Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 23 Feb 2017 15:28:43 +0100
changeset 344592 c20304c7dd0bc18f307d578969e8722900604541
parent 344591 d439fa74bf059fec9e32547d80b726a711d6f4ee (current diff)
parent 344472 c02dd6a7e9c193b488271eb53e3ea039042c9ed6 (diff)
child 344593 8fad3aa8fd4661df1fd0eb23c78849aa55dacaac
push id31414
push usercbook@mozilla.com
push dateFri, 24 Feb 2017 10:47:41 +0000
treeherdermozilla-central@be661bae6cb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone54.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 mozilla-inbound
browser/components/customizableui/test/browser_967000_button_sync.js
browser/extensions/disableSHA1rollout/README.md
browser/extensions/disableSHA1rollout/bootstrap.js
browser/extensions/disableSHA1rollout/install.rdf.in
browser/extensions/disableSHA1rollout/moz.build
gfx/thebes/gfxPrefs.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/svg/nsFilterInstance.cpp
servo/components/script/origin.rs
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -12,29 +12,42 @@ function* wait_for_tab_playing_event(tab
       is(tab.hasAttribute("soundplaying"), expectPlaying, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
       is(tab.soundPlaying, expectPlaying, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
       return true;
     }
     return false;
   });
 }
 
+function* is_audio_playing(tab) {
+  let browser = tab.linkedBrowser;
+  let isPlaying = yield ContentTask.spawn(browser, {}, function* () {
+    let audio = content.document.querySelector("audio");
+    return !audio.paused;
+  });
+  return isPlaying;
+}
+
 function* play(tab) {
   let browser = tab.linkedBrowser;
   yield ContentTask.spawn(browser, {}, function* () {
     let audio = content.document.querySelector("audio");
     audio.play();
   });
 
+  // If the tab has already be muted, it means the tab won't get soundplaying,
+  // so we don't need to check this attribute.
+  if (browser.audioMuted) {
+      return;
+  }
+
   yield wait_for_tab_playing_event(tab, true);
 }
 
 function* pause(tab, options) {
-  ok(tab.hasAttribute("soundplaying"), "The tab should have the soundplaying attribute when pause() is called");
-
   let extendedDelay = options && options.extendedDelay;
   if (extendedDelay) {
     // Use 10s to remove possibility of race condition with attr removal.
     Services.prefs.setIntPref(TABATTR_REMOVAL_PREFNAME, 10000);
   }
 
   try {
     let browser = tab.linkedBrowser;
@@ -42,16 +55,22 @@ function* pause(tab, options) {
       BrowserTestUtils.waitForEvent(browser, "DOMAudioPlaybackStopped", "DOMAudioPlaybackStopped event should get fired after pause");
     let awaitTabPausedAttrModified =
       wait_for_tab_playing_event(tab, false);
     yield ContentTask.spawn(browser, {}, function* () {
       let audio = content.document.querySelector("audio");
       audio.pause();
     });
 
+    // If the tab has already be muted, it means the tab won't have soundplaying,
+    // so we don't need to check this attribute.
+    if (browser.audioMuted) {
+      return;
+    }
+
     if (extendedDelay) {
       ok(tab.hasAttribute("soundplaying"), "The tab should still have the soundplaying attribute immediately after pausing");
 
       yield awaitDOMAudioPlaybackStopped;
       ok(tab.hasAttribute("soundplaying"), "The tab should still have the soundplaying attribute immediately after DOMAudioPlaybackStopped");
     }
 
     yield awaitTabPausedAttrModified;
@@ -136,16 +155,23 @@ function* test_mute_tab(tab, icon, expec
   let tooltip = document.getElementById("tabbrowser-tab-tooltip");
 
   yield hover_icon(icon, tooltip);
   EventUtils.synthesizeMouseAtCenter(icon, {button: 0});
   leave_icon(icon);
 
   is(gBrowser.selectedTab, activeTab, "Clicking on mute should not change the currently selected tab");
 
+  // If the audio is playing, we should check whether clicking on icon affects
+  // the media element's playing state.
+  let isAudioPlaying = yield is_audio_playing(tab);
+  if (isAudioPlaying) {
+    yield wait_for_tab_playing_event(tab, !expectMuted);
+  }
+
   return mutedPromise;
 }
 
 function get_tab_state(tab) {
   const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
   return JSON.parse(ss.getTabState(tab));
 }
 
@@ -164,17 +190,17 @@ function* test_muting_using_menu(tab, ex
   is(toggleMute.accessKey, expectedAccessKey, "Correct accessKey expected");
 
   is(toggleMute.hasAttribute("muted"), expectMuted, "Should have the correct state for the muted attribute");
   ok(!toggleMute.hasAttribute("soundplaying"), "Should not have the soundplaying attribute");
 
   yield play(tab);
 
   is(toggleMute.hasAttribute("muted"), expectMuted, "Should have the correct state for the muted attribute");
-  ok(toggleMute.hasAttribute("soundplaying"), "Should have the soundplaying attribute");
+  is(!toggleMute.hasAttribute("soundplaying"), expectMuted, "The value of soundplaying attribute is incorrect");
 
   yield pause(tab);
 
   is(toggleMute.hasAttribute("muted"), expectMuted, "Should have the correct state for the muted attribute");
   ok(!toggleMute.hasAttribute("soundplaying"), "Should not have the soundplaying attribute");
 
   // Click on the menu and wait for the tab to be muted.
   let mutedPromise = get_wait_for_mute_promise(tab, !expectMuted);
@@ -229,32 +255,32 @@ function* test_playing_icon_on_tab(tab, 
   // Make sure it's possible to mute using the context menu.
   yield test_muting_using_menu(tab, false);
 
   // Make sure it's possible to unmute using the context menu.
   yield test_muting_using_menu(tab, true);
 }
 
 function* test_swapped_browser_while_playing(oldTab, newBrowser) {
+  // The tab was muted so it won't have soundplaying attribute even it's playing.
   ok(oldTab.hasAttribute("muted"), "Expected the correct muted attribute on the old tab");
   is(oldTab.muteReason, null, "Expected the correct muteReason attribute on the old tab");
-  ok(oldTab.hasAttribute("soundplaying"), "Expected the correct soundplaying attribute on the old tab");
+  ok(!oldTab.hasAttribute("soundplaying"), "Expected the correct soundplaying attribute on the old tab");
 
   let newTab = gBrowser.getTabForBrowser(newBrowser);
   let AttrChangePromise = BrowserTestUtils.waitForEvent(newTab, "TabAttrModified", false, event => {
-    return event.detail.changed.includes("soundplaying") &&
-           event.detail.changed.includes("muted");
+    return event.detail.changed.includes("muted");
   });
 
   gBrowser.swapBrowsersAndCloseOther(newTab, oldTab);
   yield AttrChangePromise;
 
   ok(newTab.hasAttribute("muted"), "Expected the correct muted attribute on the new tab");
   is(newTab.muteReason, null, "Expected the correct muteReason property on the new tab");
-  ok(newTab.hasAttribute("soundplaying"), "Expected the correct soundplaying attribute on the new tab");
+  ok(!newTab.hasAttribute("soundplaying"), "Expected the correct soundplaying attribute on the new tab");
 
   let icon = document.getAnonymousElementByAttribute(newTab, "anonid",
                                                      "soundplaying-icon");
   yield test_tooltip(icon, "Unmute tab", true);
 }
 
 function* test_swapped_browser_while_not_playing(oldTab, newBrowser) {
   ok(oldTab.hasAttribute("muted"), "Expected the correct muted attribute on the old tab");
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -304,16 +304,18 @@ const CustomizableWidgets = [
     viewId: "PanelUI-remotetabs",
     defaultArea: CustomizableUI.AREA_PANEL,
     deckIndices: {
       DECKINDEX_TABS: 0,
       DECKINDEX_TABSDISABLED: 1,
       DECKINDEX_FETCHING: 2,
       DECKINDEX_NOCLIENTS: 3,
     },
+    TABS_PER_PAGE: 25,
+    NEXT_PAGE_MIN_TABS: 5, // Minimum number of tabs displayed when we click "Show All"
     onCreated(aNode) {
       // Add an observer to the button so we get the animation during sync.
       // (Note the observer sets many attributes, including label and
       // tooltiptext, but we only want the 'syncstatus' attribute for the
       // animation)
       let doc = aNode.ownerDocument;
       let obnode = doc.createElementNS(kNSXUL, "observes");
       obnode.setAttribute("element", "sync-status");
@@ -396,23 +398,23 @@ const CustomizableWidgets = [
       // We call setAttribute instead of relying on the XBL property setter due
       // to things going wrong when we try and set the index before the XBL
       // binding has been created - see bug 1241851 for the gory details.
       deck.setAttribute("selectedIndex", index);
     },
 
     _showTabsPromise: Promise.resolve(),
     // Update the tab list after any existing in-flight updates are complete.
-    _showTabs() {
+    _showTabs(paginationInfo) {
       this._showTabsPromise = this._showTabsPromise.then(() => {
-        return this.__showTabs();
+        return this.__showTabs(paginationInfo);
       });
     },
     // Return a new promise to update the tab list.
-    __showTabs() {
+    __showTabs(paginationInfo) {
       let doc = this._tabsList.ownerDocument;
       return SyncedTabs.getTabClients().then(clients => {
         // The view may have been hidden while the promise was resolving.
         if (!this._tabsList) {
           return;
         }
         if (clients.length === 0 && !SyncedTabs.hasSyncedThisSession) {
           // the "fetching tabs" deck is being shown - let's leave it there.
@@ -422,26 +424,30 @@ const CustomizableWidgets = [
 
         if (clients.length === 0) {
           this.setDeckIndex(this.deckIndices.DECKINDEX_NOCLIENTS);
           return;
         }
 
         this.setDeckIndex(this.deckIndices.DECKINDEX_TABS);
         this._clearTabList();
-        SyncedTabs.sortTabClientsByLastUsed(clients, 50 /* maxTabs */);
+        SyncedTabs.sortTabClientsByLastUsed(clients);
         let fragment = doc.createDocumentFragment();
 
         for (let client of clients) {
           // add a menu separator for all clients other than the first.
           if (fragment.lastChild) {
             let separator = doc.createElementNS(kNSXUL, "menuseparator");
             fragment.appendChild(separator);
           }
-          this._appendClient(client, fragment);
+          if (paginationInfo && paginationInfo.clientId == client.id) {
+            this._appendClient(client, fragment, paginationInfo.maxTabs);
+          } else {
+            this._appendClient(client, fragment);
+          }
         }
         this._tabsList.appendChild(fragment);
       }).catch(err => {
         Cu.reportError(err);
       }).then(() => {
         // an observer for tests.
         Services.obs.notifyObservers(null, "synced-tabs-menu:test:tabs-updated", null);
       });
@@ -461,36 +467,56 @@ const CustomizableWidgets = [
       }
       let message = this._tabsList.getAttribute(messageAttr);
       let doc = this._tabsList.ownerDocument;
       let messageLabel = doc.createElementNS(kNSXUL, "label");
       messageLabel.textContent = message;
       appendTo.appendChild(messageLabel);
       return messageLabel;
     },
-    _appendClient(client, attachFragment) {
+    _appendClient(client, attachFragment, maxTabs = this.TABS_PER_PAGE) {
       let doc = attachFragment.ownerDocument;
       // Create the element for the remote client.
       let clientItem = doc.createElementNS(kNSXUL, "label");
       clientItem.setAttribute("itemtype", "client");
       let window = doc.defaultView;
       clientItem.setAttribute("tooltiptext",
         window.gSyncUI.formatLastSyncDate(new Date(client.lastModified)));
       clientItem.textContent = client.name;
 
       attachFragment.appendChild(clientItem);
 
       if (client.tabs.length == 0) {
         let label = this._appendMessageLabel("notabsforclientlabel", attachFragment);
         label.setAttribute("class", "PanelUI-remotetabs-notabsforclient-label");
       } else {
+        // If this page will display all tabs, show no additional buttons.
+        // If the next page will display all the remaining tabs, show a "Show All" button
+        // Otherwise, show a "Shore More" button
+        let hasNextPage = client.tabs.length > maxTabs;
+        let nextPageIsLastPage = hasNextPage && maxTabs + this.TABS_PER_PAGE >= client.tabs.length;
+        if (nextPageIsLastPage) {
+          // When the user clicks "Show All", try to have at least NEXT_PAGE_MIN_TABS more tabs
+          // to display in order to avoid user frustration
+          maxTabs = Math.min(client.tabs.length - this.NEXT_PAGE_MIN_TABS, maxTabs);
+        }
+        if (hasNextPage) {
+          client.tabs = client.tabs.slice(0, maxTabs);
+        }
         for (let tab of client.tabs) {
           let tabEnt = this._createTabElement(doc, tab);
           attachFragment.appendChild(tabEnt);
         }
+        if (hasNextPage) {
+          let showAllEnt = this._createShowMoreElement(doc, client.id,
+                                                       nextPageIsLastPage ?
+                                                       Infinity :
+                                                       maxTabs + this.TABS_PER_PAGE);
+          attachFragment.appendChild(showAllEnt);
+        }
       }
     },
     _createTabElement(doc, tabInfo) {
       let item = doc.createElementNS(kNSXUL, "toolbarbutton");
       let tooltipText = (tabInfo.title ? tabInfo.title + "\n" : "") + tabInfo.url;
       item.setAttribute("itemtype", "tab");
       item.setAttribute("class", "subviewbutton");
       item.setAttribute("targetURI", tabInfo.url);
@@ -501,16 +527,39 @@ const CustomizableWidgets = [
       // respects different buttons (eg, to open in a new tab).
       item.addEventListener("click", e => {
         doc.defaultView.openUILink(tabInfo.url, e);
         CustomizableUI.hidePanelForNode(item);
         BrowserUITelemetry.countSyncedTabEvent("open", "toolbarbutton-subview");
       });
       return item;
     },
+    _createShowMoreElement(doc, clientId, showCount) {
+      let labelAttr, tooltipAttr;
+      if (showCount === Infinity) {
+        labelAttr = "showAllLabel";
+        tooltipAttr = "showAllTooltipText";
+      } else {
+        labelAttr = "showMoreLabel";
+        tooltipAttr = "showMoreTooltipText";
+      }
+      let showAllItem = doc.createElementNS(kNSXUL, "toolbarbutton");
+      showAllItem.setAttribute("itemtype", "showmorebutton");
+      showAllItem.setAttribute("class", "subviewbutton");
+      let label = this._tabsList.getAttribute(labelAttr);
+      showAllItem.setAttribute("label", label);
+      let tooltipText = this._tabsList.getAttribute(tooltipAttr);
+      showAllItem.setAttribute("tooltiptext", tooltipText);
+      showAllItem.addEventListener("click", e => {
+        e.preventDefault();
+        e.stopPropagation();
+        this._showTabs({ clientId, maxTabs: showCount });
+      });
+      return showAllItem;
+    }
   }, {
     id: "privatebrowsing-button",
     shortcutId: "key_privatebrowsing",
     defaultArea: CustomizableUI.AREA_PANEL,
     onCommand(e) {
       let win = e.target.ownerGlobal;
       win.OpenBrowserWindow({private: true});
     }
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -120,16 +120,20 @@
                            oncommand="gSyncUI.doSync();"
                            closemenu="none"/>
             <menuseparator id="PanelUI-remotetabs-separator"/>
           </vbox>
           <deck id="PanelUI-remotetabs-deck">
             <!-- Sync is ready to Sync and the "tabs" engine is enabled -->
             <vbox id="PanelUI-remotetabs-tabspane">
               <vbox id="PanelUI-remotetabs-tabslist"
+                    showAllLabel="&appMenuRemoteTabs.showAll.label;"
+                    showAllTooltipText="&appMenuRemoteTabs.showAll.tooltip;"
+                    showMoreLabel="&appMenuRemoteTabs.showMore.label;"
+                    showMoreTooltipText="&appMenuRemoteTabs.showMore.tooltip;"
                     notabsforclientlabel="&appMenuRemoteTabs.notabs.label;"
                     />
             </vbox>
             <!-- Sync is ready to Sync but the "tabs" engine isn't enabled-->
             <hbox id="PanelUI-remotetabs-tabsdisabledpane" pack="center" flex="1">
               <vbox class="PanelUI-remotetabs-instruction-box">
                 <hbox pack="center">
                   <html:img class="fxaSyncIllustration" src="chrome://browser/skin/fxa/sync-illustration.svg"/>
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -95,17 +95,16 @@ skip-if = os == "linux" # Intermittent f
 [browser_948985_non_removable_defaultArea.js]
 [browser_952963_areaType_getter_no_area.js]
 [browser_956602_remove_special_widget.js]
 [browser_962069_drag_to_overflow_chevron.js]
 [browser_962884_opt_in_disable_hyphens.js]
 [browser_963639_customizing_attribute_non_customizable_toolbar.js]
 [browser_967000_button_charEncoding.js]
 [browser_967000_button_feeds.js]
-[browser_967000_button_sync.js]
 [browser_968447_bookmarks_toolbar_items_in_panel.js]
 skip-if = os == "linux" # Intemittent failures - bug 979207
 [browser_968565_insert_before_hidden_items.js]
 [browser_969427_recreate_destroyed_widget_after_reset.js]
 [browser_969661_character_encoding_navbar_disabled.js]
 [browser_970511_undo_restore_default.js]
 [browser_972267_customizationchange_events.js]
 [browser_973641_button_addon.js]
@@ -146,9 +145,10 @@ skip-if = os == "mac"
 [browser_1087303_button_preferences.js]
 [browser_1089591_still_customizable_after_reset.js]
 [browser_1096763_seen_widgets_post_reset.js]
 [browser_1161838_inserted_new_default_buttons.js]
 [browser_bootstrapped_custom_toolbar.js]
 [browser_customizemode_contextmenu_menubuttonstate.js]
 [browser_panel_toggle.js]
 [browser_switch_to_customize_mode.js]
+[browser_synced_tabs_menu.js]
 [browser_check_tooltips_in_navbar.js]
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_967000_button_sync.js
+++ /dev/null
@@ -1,337 +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/. */
-
-"use strict";
-
-requestLongerTimeout(2);
-
-let {SyncedTabs} = Cu.import("resource://services-sync/SyncedTabs.jsm", {});
-
-XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
-
-// These are available on the widget implementation, but it seems impossible
-// to grab that impl at runtime.
-const DECKINDEX_TABS = 0;
-const DECKINDEX_TABSDISABLED = 1;
-const DECKINDEX_FETCHING = 2;
-const DECKINDEX_NOCLIENTS = 3;
-
-var initialLocation = gBrowser.currentURI.spec;
-var newTab = null;
-
-// A helper to notify there are new tabs. Returns a promise that is resolved
-// once the UI has been updated.
-function updateTabsPanel() {
-  let promiseTabsUpdated = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
-  Services.obs.notifyObservers(null, SyncedTabs.TOPIC_TABS_CHANGED, null);
-  return promiseTabsUpdated;
-}
-
-// This is the mock we use for SyncedTabs.jsm - tests may override various
-// functions.
-let mockedInternal = {
-  get isConfiguredToSyncTabs() { return true; },
-  getTabClients() { return []; },
-  syncTabs() {},
-  hasSyncedThisSession: false,
-};
-
-
-add_task(function* setup() {
-  let oldInternal = SyncedTabs._internal;
-  SyncedTabs._internal = mockedInternal;
-
-  // This test hacks some observer states to simulate a user being signed
-  // in to Sync - restore them when the test completes.
-  let initialObserverStates = {};
-  for (let id of ["sync-reauth-state", "sync-setup-state", "sync-syncnow-state"]) {
-    initialObserverStates[id] = document.getElementById(id).hidden;
-  }
-
-  registerCleanupFunction(() => {
-    SyncedTabs._internal = oldInternal;
-    for (let [id, initial] of Object.entries(initialObserverStates)) {
-      document.getElementById(id).hidden = initial;
-    }
-  });
-});
-
-// The test expects the about:preferences#sync page to open in the current tab
-function* openPrefsFromMenuPanel(expectedPanelId, entryPoint) {
-  info("Check Sync button functionality");
-  Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri", "http://example.com/");
-
-  // check the button's functionality
-  yield PanelUI.show();
-
-  if (entryPoint == "uitour") {
-    UITour.tourBrowsersByWindow.set(window, new Set());
-    UITour.tourBrowsersByWindow.get(window).add(gBrowser.selectedBrowser);
-  }
-
-  let syncButton = document.getElementById("sync-button");
-  ok(syncButton, "The Sync button was added to the Panel Menu");
-
-  syncButton.click();
-  let syncPanel = document.getElementById("PanelUI-remotetabs");
-  ok(syncPanel.getAttribute("current"), "Sync Panel is in view");
-
-  // Sync is not configured - verify that state is reflected.
-  let subpanel = document.getElementById(expectedPanelId)
-  ok(!subpanel.hidden, "sync setup element is visible");
-
-  // Find and click the "setup" button.
-  let setupButton = subpanel.querySelector(".PanelUI-remotetabs-prefs-button");
-  setupButton.click();
-
-  let deferred = Promise.defer();
-  let handler = (e) => {
-    if (e.originalTarget != gBrowser.selectedBrowser.contentDocument ||
-        e.target.location.href == "about:blank") {
-      info("Skipping spurious 'load' event for " + e.target.location.href);
-      return;
-    }
-    gBrowser.selectedBrowser.removeEventListener("load", handler, true);
-    deferred.resolve();
-  }
-  gBrowser.selectedBrowser.addEventListener("load", handler, true);
-
-  yield deferred.promise;
-  newTab = gBrowser.selectedTab;
-
-  is(gBrowser.currentURI.spec, "about:preferences?entrypoint=" + entryPoint + "#sync",
-    "Firefox Sync preference page opened with `menupanel` entrypoint");
-  ok(!isPanelUIOpen(), "The panel closed");
-
-  if (isPanelUIOpen()) {
-    let panelHidePromise = promisePanelHidden(window);
-    PanelUI.hide();
-    yield panelHidePromise;
-  }
-}
-
-function* asyncCleanup() {
-  Services.prefs.clearUserPref("identity.fxaccounts.remote.signup.uri");
-  // reset the panel UI to the default state
-  yield resetCustomization();
-  ok(CustomizableUI.inDefaultState, "The panel UI is in default state again.");
-
-  // restore the tabs
-  gBrowser.addTab(initialLocation);
-  gBrowser.removeTab(newTab);
-  UITour.tourBrowsersByWindow.delete(window);
-}
-
-// When Sync is not setup.
-add_task(() => openPrefsFromMenuPanel("PanelUI-remotetabs-setupsync", "synced-tabs"));
-add_task(asyncCleanup);
-
-// When Sync is configured in a "needs reauthentication" state.
-add_task(function* () {
-  // configure our broadcasters so we are in the right state.
-  document.getElementById("sync-reauth-state").hidden = false;
-  document.getElementById("sync-setup-state").hidden = true;
-  document.getElementById("sync-syncnow-state").hidden = true;
-  yield openPrefsFromMenuPanel("PanelUI-remotetabs-reauthsync", "synced-tabs")
-});
-
-// Test the mobile promo links
-add_task(function* () {
-  // change the preferences for the mobile links.
-  Services.prefs.setCharPref("identity.mobilepromo.android", "http://example.com/?os=android&tail=");
-  Services.prefs.setCharPref("identity.mobilepromo.ios", "http://example.com/?os=ios&tail=");
-
-  mockedInternal.getTabClients = () => [];
-  mockedInternal.syncTabs = () => Promise.resolve();
-
-  document.getElementById("sync-reauth-state").hidden = true;
-  document.getElementById("sync-setup-state").hidden = true;
-  document.getElementById("sync-syncnow-state").hidden = false;
-
-  let syncPanel = document.getElementById("PanelUI-remotetabs");
-  let links = syncPanel.querySelectorAll(".remotetabs-promo-link");
-
-  is(links.length, 2, "found 2 links as expected");
-
-  // test each link and left and middle mouse buttons
-  for (let link of links) {
-    for (let button = 0; button < 2; button++) {
-      yield PanelUI.show();
-      EventUtils.sendMouseEvent({ type: "click", button }, link, window);
-      // the panel should have been closed.
-      ok(!isPanelUIOpen(), "click closed the panel");
-      // should be a new tab - wait for the load.
-      is(gBrowser.tabs.length, 2, "there's a new tab");
-      yield new Promise(resolve => {
-        if (gBrowser.selectedBrowser.currentURI.spec == "about:blank") {
-          gBrowser.selectedBrowser.addEventListener("load", function(e) {
-            resolve();
-          }, {capture: true, once: true});
-          return;
-        }
-        // the new tab has already transitioned away from about:blank so we
-        // are good to go.
-        resolve();
-      });
-
-      let os = link.getAttribute("mobile-promo-os");
-      let expectedUrl = `http://example.com/?os=${os}&tail=synced-tabs`;
-      is(gBrowser.selectedBrowser.currentURI.spec, expectedUrl, "correct URL");
-      gBrowser.removeTab(gBrowser.selectedTab);
-    }
-  }
-
-  // test each link and right mouse button - should be a noop.
-  yield PanelUI.show();
-  for (let link of links) {
-    EventUtils.sendMouseEvent({ type: "click", button: 2 }, link, window);
-    // the panel should still be open
-    ok(isPanelUIOpen(), "panel remains open after right-click");
-    is(gBrowser.tabs.length, 1, "no new tab was opened");
-  }
-  PanelUI.hide();
-
-  Services.prefs.clearUserPref("identity.mobilepromo.android");
-  Services.prefs.clearUserPref("identity.mobilepromo.ios");
-});
-
-// Test the "Sync Now" button
-add_task(function* () {
-  mockedInternal.getTabClients = () => [];
-  mockedInternal.syncTabs = () => {
-    return Promise.resolve();
-  }
-
-  // configure our broadcasters so we are in the right state.
-  document.getElementById("sync-reauth-state").hidden = true;
-  document.getElementById("sync-setup-state").hidden = true;
-  document.getElementById("sync-syncnow-state").hidden = false;
-
-  yield PanelUI.show();
-  document.getElementById("sync-button").click();
-  let syncPanel = document.getElementById("PanelUI-remotetabs");
-  ok(syncPanel.getAttribute("current"), "Sync Panel is in view");
-
-  let subpanel = document.getElementById("PanelUI-remotetabs-main")
-  ok(!subpanel.hidden, "main pane is visible");
-  let deck = document.getElementById("PanelUI-remotetabs-deck");
-
-  // The widget is still fetching tabs, as we've neutered everything that
-  // provides them
-  is(deck.selectedIndex, DECKINDEX_FETCHING, "first deck entry is visible");
-
-  let syncNowButton = document.getElementById("PanelUI-remotetabs-syncnow");
-
-  let didSync = false;
-  let oldDoSync = gSyncUI.doSync;
-  gSyncUI.doSync = function() {
-    didSync = true;
-    mockedInternal.hasSyncedThisSession = true;
-    gSyncUI.doSync = oldDoSync;
-  }
-  syncNowButton.click();
-  ok(didSync, "clicking the button called the correct function");
-
-  // Tell the widget there are tabs available, but with zero clients.
-  mockedInternal.getTabClients = () => {
-    return Promise.resolve([]);
-  }
-  yield updateTabsPanel();
-  // The UI should be showing the "no clients" pane.
-  is(deck.selectedIndex, DECKINDEX_NOCLIENTS, "no-clients deck entry is visible");
-
-  // Tell the widget there are tabs available - we have 3 clients, one with no
-  // tabs.
-  mockedInternal.getTabClients = () => {
-    return Promise.resolve([
-      {
-        id: "guid_mobile",
-        type: "client",
-        name: "My Phone",
-        tabs: [],
-      },
-      {
-        id: "guid_desktop",
-        type: "client",
-        name: "My Desktop",
-        tabs: [
-          {
-            title: "http://example.com/10",
-            lastUsed: 10, // the most recent
-          },
-          {
-            title: "http://example.com/1",
-            lastUsed: 1, // the least recent.
-          },
-          {
-            title: "http://example.com/5",
-            lastUsed: 5,
-          },
-        ],
-      },
-      {
-        id: "guid_second_desktop",
-        name: "My Other Desktop",
-        tabs: [
-          {
-            title: "http://example.com/6",
-            lastUsed: 6,
-          }
-        ],
-      },
-    ]);
-  };
-  yield updateTabsPanel();
-
-  // The UI should be showing tabs!
-  is(deck.selectedIndex, DECKINDEX_TABS, "no-clients deck entry is visible");
-  let tabList = document.getElementById("PanelUI-remotetabs-tabslist");
-  let node = tabList.firstChild;
-  // First entry should be the client with the most-recent tab.
-  is(node.getAttribute("itemtype"), "client", "node is a client entry");
-  is(node.textContent, "My Desktop", "correct client");
-  // Next entry is the most-recent tab
-  node = node.nextSibling;
-  is(node.getAttribute("itemtype"), "tab", "node is a tab");
-  is(node.getAttribute("label"), "http://example.com/10");
-
-  // Next entry is the next-most-recent tab
-  node = node.nextSibling;
-  is(node.getAttribute("itemtype"), "tab", "node is a tab");
-  is(node.getAttribute("label"), "http://example.com/5");
-
-  // Next entry is the least-recent tab from the first client.
-  node = node.nextSibling;
-  is(node.getAttribute("itemtype"), "tab", "node is a tab");
-  is(node.getAttribute("label"), "http://example.com/1");
-
-  // Next is a menuseparator between the clients.
-  node = node.nextSibling;
-  is(node.nodeName, "menuseparator");
-
-  // Next is the client with 1 tab.
-  node = node.nextSibling;
-  is(node.getAttribute("itemtype"), "client", "node is a client entry");
-  is(node.textContent, "My Other Desktop", "correct client");
-  // Its single tab
-  node = node.nextSibling;
-  is(node.getAttribute("itemtype"), "tab", "node is a tab");
-  is(node.getAttribute("label"), "http://example.com/6");
-
-  // Next is a menuseparator between the clients.
-  node = node.nextSibling;
-  is(node.nodeName, "menuseparator");
-
-  // Next is the client with no tab.
-  node = node.nextSibling;
-  is(node.getAttribute("itemtype"), "client", "node is a client entry");
-  is(node.textContent, "My Phone", "correct client");
-  // There is a single node saying there's no tabs for the client.
-  node = node.nextSibling;
-  is(node.nodeName, "label", "node is a label");
-  is(node.getAttribute("itemtype"), "", "node is neither a tab nor a client");
-
-  node = node.nextSibling;
-  is(node, null, "no more entries");
-});
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/test/browser_synced_tabs_menu.js
@@ -0,0 +1,427 @@
+/* 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/. */
+
+"use strict";
+
+requestLongerTimeout(2);
+
+let {SyncedTabs} = Cu.import("resource://services-sync/SyncedTabs.jsm", {});
+
+XPCOMUtils.defineLazyModuleGetter(this, "UITour", "resource:///modules/UITour.jsm");
+
+// These are available on the widget implementation, but it seems impossible
+// to grab that impl at runtime.
+const DECKINDEX_TABS = 0;
+const DECKINDEX_TABSDISABLED = 1;
+const DECKINDEX_FETCHING = 2;
+const DECKINDEX_NOCLIENTS = 3;
+
+var initialLocation = gBrowser.currentURI.spec;
+var newTab = null;
+
+// A helper to notify there are new tabs. Returns a promise that is resolved
+// once the UI has been updated.
+function updateTabsPanel() {
+  let promiseTabsUpdated = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
+  Services.obs.notifyObservers(null, SyncedTabs.TOPIC_TABS_CHANGED, null);
+  return promiseTabsUpdated;
+}
+
+// This is the mock we use for SyncedTabs.jsm - tests may override various
+// functions.
+let mockedInternal = {
+  get isConfiguredToSyncTabs() { return true; },
+  getTabClients() { return Promise.resolve([]); },
+  syncTabs() { return Promise.resolve(); },
+  hasSyncedThisSession: false,
+};
+
+
+add_task(function* setup() {
+  let oldInternal = SyncedTabs._internal;
+  SyncedTabs._internal = mockedInternal;
+
+  // This test hacks some observer states to simulate a user being signed
+  // in to Sync - restore them when the test completes.
+  let initialObserverStates = {};
+  for (let id of ["sync-reauth-state", "sync-setup-state", "sync-syncnow-state"]) {
+    initialObserverStates[id] = document.getElementById(id).hidden;
+  }
+
+  registerCleanupFunction(() => {
+    SyncedTabs._internal = oldInternal;
+    for (let [id, initial] of Object.entries(initialObserverStates)) {
+      document.getElementById(id).hidden = initial;
+    }
+  });
+});
+
+// The test expects the about:preferences#sync page to open in the current tab
+function* openPrefsFromMenuPanel(expectedPanelId, entryPoint) {
+  info("Check Sync button functionality");
+  Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri", "http://example.com/");
+
+  // check the button's functionality
+  yield PanelUI.show();
+
+  if (entryPoint == "uitour") {
+    UITour.tourBrowsersByWindow.set(window, new Set());
+    UITour.tourBrowsersByWindow.get(window).add(gBrowser.selectedBrowser);
+  }
+
+  let syncButton = document.getElementById("sync-button");
+  ok(syncButton, "The Sync button was added to the Panel Menu");
+
+  let tabsUpdatedPromise = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
+  syncButton.click();
+  yield tabsUpdatedPromise;
+  let syncPanel = document.getElementById("PanelUI-remotetabs");
+  ok(syncPanel.getAttribute("current"), "Sync Panel is in view");
+
+  // Sync is not configured - verify that state is reflected.
+  let subpanel = document.getElementById(expectedPanelId)
+  ok(!subpanel.hidden, "sync setup element is visible");
+
+  // Find and click the "setup" button.
+  let setupButton = subpanel.querySelector(".PanelUI-remotetabs-prefs-button");
+  setupButton.click();
+
+  let deferred = Promise.defer();
+  let handler = (e) => {
+    if (e.originalTarget != gBrowser.selectedBrowser.contentDocument ||
+        e.target.location.href == "about:blank") {
+      info("Skipping spurious 'load' event for " + e.target.location.href);
+      return;
+    }
+    gBrowser.selectedBrowser.removeEventListener("load", handler, true);
+    deferred.resolve();
+  }
+  gBrowser.selectedBrowser.addEventListener("load", handler, true);
+
+  yield deferred.promise;
+  newTab = gBrowser.selectedTab;
+
+  is(gBrowser.currentURI.spec, "about:preferences?entrypoint=" + entryPoint + "#sync",
+    "Firefox Sync preference page opened with `menupanel` entrypoint");
+  ok(!isPanelUIOpen(), "The panel closed");
+
+  if (isPanelUIOpen()) {
+    yield panelUIHide();
+  }
+}
+
+function panelUIHide() {
+  let panelHidePromise = promisePanelHidden(window);
+  PanelUI.hide();
+  return panelHidePromise;
+}
+
+function* asyncCleanup() {
+  Services.prefs.clearUserPref("identity.fxaccounts.remote.signup.uri");
+  // reset the panel UI to the default state
+  yield resetCustomization();
+  ok(CustomizableUI.inDefaultState, "The panel UI is in default state again.");
+
+  // restore the tabs
+  gBrowser.addTab(initialLocation);
+  gBrowser.removeTab(newTab);
+  UITour.tourBrowsersByWindow.delete(window);
+}
+
+// When Sync is not setup.
+add_task(function* () {
+  document.getElementById("sync-reauth-state").hidden = true;
+  document.getElementById("sync-setup-state").hidden = false;
+  document.getElementById("sync-syncnow-state").hidden = true;
+  yield openPrefsFromMenuPanel("PanelUI-remotetabs-setupsync", "synced-tabs")
+});
+add_task(asyncCleanup);
+
+// When Sync is configured in a "needs reauthentication" state.
+add_task(function* () {
+  // configure our broadcasters so we are in the right state.
+  document.getElementById("sync-reauth-state").hidden = false;
+  document.getElementById("sync-setup-state").hidden = true;
+  document.getElementById("sync-syncnow-state").hidden = true;
+  yield openPrefsFromMenuPanel("PanelUI-remotetabs-reauthsync", "synced-tabs")
+});
+
+// Test the mobile promo links
+add_task(function* () {
+  // change the preferences for the mobile links.
+  Services.prefs.setCharPref("identity.mobilepromo.android", "http://example.com/?os=android&tail=");
+  Services.prefs.setCharPref("identity.mobilepromo.ios", "http://example.com/?os=ios&tail=");
+
+  document.getElementById("sync-reauth-state").hidden = true;
+  document.getElementById("sync-setup-state").hidden = true;
+  document.getElementById("sync-syncnow-state").hidden = false;
+
+  let syncPanel = document.getElementById("PanelUI-remotetabs");
+  let links = syncPanel.querySelectorAll(".remotetabs-promo-link");
+
+  is(links.length, 2, "found 2 links as expected");
+
+  // test each link and left and middle mouse buttons
+  for (let link of links) {
+    for (let button = 0; button < 2; button++) {
+      yield PanelUI.show();
+      EventUtils.sendMouseEvent({ type: "click", button }, link, window);
+      // the panel should have been closed.
+      ok(!isPanelUIOpen(), "click closed the panel");
+      // should be a new tab - wait for the load.
+      is(gBrowser.tabs.length, 2, "there's a new tab");
+      yield new Promise(resolve => {
+        if (gBrowser.selectedBrowser.currentURI.spec == "about:blank") {
+          gBrowser.selectedBrowser.addEventListener("load", function(e) {
+            resolve();
+          }, {capture: true, once: true});
+          return;
+        }
+        // the new tab has already transitioned away from about:blank so we
+        // are good to go.
+        resolve();
+      });
+
+      let os = link.getAttribute("mobile-promo-os");
+      let expectedUrl = `http://example.com/?os=${os}&tail=synced-tabs`;
+      is(gBrowser.selectedBrowser.currentURI.spec, expectedUrl, "correct URL");
+      gBrowser.removeTab(gBrowser.selectedTab);
+    }
+  }
+
+  // test each link and right mouse button - should be a noop.
+  yield PanelUI.show();
+  for (let link of links) {
+    EventUtils.sendMouseEvent({ type: "click", button: 2 }, link, window);
+    // the panel should still be open
+    ok(isPanelUIOpen(), "panel remains open after right-click");
+    is(gBrowser.tabs.length, 1, "no new tab was opened");
+  }
+  yield panelUIHide();
+
+  Services.prefs.clearUserPref("identity.mobilepromo.android");
+  Services.prefs.clearUserPref("identity.mobilepromo.ios");
+});
+
+// Test the "Sync Now" button
+add_task(function* () {
+  // configure our broadcasters so we are in the right state.
+  document.getElementById("sync-reauth-state").hidden = true;
+  document.getElementById("sync-setup-state").hidden = true;
+  document.getElementById("sync-syncnow-state").hidden = false;
+
+  yield PanelUI.show();
+  let tabsUpdatedPromise = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
+  document.getElementById("sync-button").click();
+  yield tabsUpdatedPromise;
+  let syncPanel = document.getElementById("PanelUI-remotetabs");
+  ok(syncPanel.getAttribute("current"), "Sync Panel is in view");
+
+  let subpanel = document.getElementById("PanelUI-remotetabs-main")
+  ok(!subpanel.hidden, "main pane is visible");
+  let deck = document.getElementById("PanelUI-remotetabs-deck");
+
+  // The widget is still fetching tabs, as we've neutered everything that
+  // provides them
+  is(deck.selectedIndex, DECKINDEX_FETCHING, "first deck entry is visible");
+
+  let syncNowButton = document.getElementById("PanelUI-remotetabs-syncnow");
+
+  let didSync = false;
+  let oldDoSync = gSyncUI.doSync;
+  gSyncUI.doSync = function() {
+    didSync = true;
+    mockedInternal.hasSyncedThisSession = true;
+    gSyncUI.doSync = oldDoSync;
+  }
+  syncNowButton.click();
+  ok(didSync, "clicking the button called the correct function");
+
+  // Tell the widget there are tabs available, but with zero clients.
+  mockedInternal.getTabClients = () => {
+    return Promise.resolve([]);
+  }
+  yield updateTabsPanel();
+  // The UI should be showing the "no clients" pane.
+  is(deck.selectedIndex, DECKINDEX_NOCLIENTS, "no-clients deck entry is visible");
+
+  // Tell the widget there are tabs available - we have 3 clients, one with no
+  // tabs.
+  mockedInternal.getTabClients = () => {
+    return Promise.resolve([
+      {
+        id: "guid_mobile",
+        type: "client",
+        name: "My Phone",
+        tabs: [],
+      },
+      {
+        id: "guid_desktop",
+        type: "client",
+        name: "My Desktop",
+        tabs: [
+          {
+            title: "http://example.com/10",
+            lastUsed: 10, // the most recent
+          },
+          {
+            title: "http://example.com/1",
+            lastUsed: 1, // the least recent.
+          },
+          {
+            title: "http://example.com/5",
+            lastUsed: 5,
+          },
+        ],
+      },
+      {
+        id: "guid_second_desktop",
+        name: "My Other Desktop",
+        tabs: [
+          {
+            title: "http://example.com/6",
+            lastUsed: 6,
+          }
+        ],
+      },
+    ]);
+  };
+  yield updateTabsPanel();
+
+  // The UI should be showing tabs!
+  is(deck.selectedIndex, DECKINDEX_TABS, "no-clients deck entry is visible");
+  let tabList = document.getElementById("PanelUI-remotetabs-tabslist");
+  let node = tabList.firstChild;
+  // First entry should be the client with the most-recent tab.
+  is(node.getAttribute("itemtype"), "client", "node is a client entry");
+  is(node.textContent, "My Desktop", "correct client");
+  // Next entry is the most-recent tab
+  node = node.nextSibling;
+  is(node.getAttribute("itemtype"), "tab", "node is a tab");
+  is(node.getAttribute("label"), "http://example.com/10");
+
+  // Next entry is the next-most-recent tab
+  node = node.nextSibling;
+  is(node.getAttribute("itemtype"), "tab", "node is a tab");
+  is(node.getAttribute("label"), "http://example.com/5");
+
+  // Next entry is the least-recent tab from the first client.
+  node = node.nextSibling;
+  is(node.getAttribute("itemtype"), "tab", "node is a tab");
+  is(node.getAttribute("label"), "http://example.com/1");
+
+  // Next is a menuseparator between the clients.
+  node = node.nextSibling;
+  is(node.nodeName, "menuseparator");
+
+  // Next is the client with 1 tab.
+  node = node.nextSibling;
+  is(node.getAttribute("itemtype"), "client", "node is a client entry");
+  is(node.textContent, "My Other Desktop", "correct client");
+  // Its single tab
+  node = node.nextSibling;
+  is(node.getAttribute("itemtype"), "tab", "node is a tab");
+  is(node.getAttribute("label"), "http://example.com/6");
+
+  // Next is a menuseparator between the clients.
+  node = node.nextSibling;
+  is(node.nodeName, "menuseparator");
+
+  // Next is the client with no tab.
+  node = node.nextSibling;
+  is(node.getAttribute("itemtype"), "client", "node is a client entry");
+  is(node.textContent, "My Phone", "correct client");
+  // There is a single node saying there's no tabs for the client.
+  node = node.nextSibling;
+  is(node.nodeName, "label", "node is a label");
+  is(node.getAttribute("itemtype"), "", "node is neither a tab nor a client");
+
+  node = node.nextSibling;
+  is(node, null, "no more entries");
+
+  yield panelUIHide();
+});
+
+// Test the pagination capabilities (Show More/All tabs)
+add_task(function* () {
+  mockedInternal.getTabClients = () => {
+    return Promise.resolve([
+      {
+        id: "guid_desktop",
+        type: "client",
+        name: "My Desktop",
+        tabs: function() {
+          let allTabsDesktop = [];
+          // We choose 77 tabs, because TABS_PER_PAGE is 25, which means
+          // on the second to last page we should have 22 items shown
+          // (because we have to show at least NEXT_PAGE_MIN_TABS=5 tabs on the last page)
+          for (let i = 1; i <= 77; i++) {
+            allTabsDesktop.push({ title: "Tab #" + i });
+          }
+          return allTabsDesktop;
+        }(),
+      }
+    ]);
+  };
+
+  // configure our broadcasters so we are in the right state.
+  document.getElementById("sync-reauth-state").hidden = true;
+  document.getElementById("sync-setup-state").hidden = true;
+  document.getElementById("sync-syncnow-state").hidden = false;
+
+  yield PanelUI.show();
+  let tabsUpdatedPromise = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
+  document.getElementById("sync-button").click();
+  yield tabsUpdatedPromise;
+
+  // Check pre-conditions
+  let syncPanel = document.getElementById("PanelUI-remotetabs");
+  ok(syncPanel.getAttribute("current"), "Sync Panel is in view");
+  let subpanel = document.getElementById("PanelUI-remotetabs-main")
+  ok(!subpanel.hidden, "main pane is visible");
+  let deck = document.getElementById("PanelUI-remotetabs-deck");
+  is(deck.selectedIndex, DECKINDEX_TABS, "we should be showing tabs");
+
+  function checkTabsPage(tabsShownCount, showMoreLabel) {
+    let tabList = document.getElementById("PanelUI-remotetabs-tabslist");
+    let node = tabList.firstChild;
+    is(node.getAttribute("itemtype"), "client", "node is a client entry");
+    is(node.textContent, "My Desktop", "correct client");
+    for (let i = 0; i < tabsShownCount; i++) {
+      node = node.nextSibling;
+      is(node.getAttribute("itemtype"), "tab", "node is a tab");
+      is(node.getAttribute("label"), "Tab #" + (i + 1), "the tab is the correct one");
+    }
+    let showMoreButton;
+    if (showMoreLabel) {
+      node = showMoreButton = node.nextSibling;
+      is(node.getAttribute("itemtype"), "showmorebutton", "node is a show more button");
+      is(node.getAttribute("label"), showMoreLabel);
+    }
+    node = node.nextSibling;
+    is(node, null, "no more entries");
+
+    return showMoreButton;
+  }
+
+  let showMoreButton;
+  function clickShowMoreButton() {
+    let promise = promiseObserverNotified("synced-tabs-menu:test:tabs-updated");
+    showMoreButton.click();
+    return promise;
+  }
+
+  showMoreButton = checkTabsPage(25, "Show More");
+  yield clickShowMoreButton();
+
+  showMoreButton = checkTabsPage(50, "Show More");
+  yield clickShowMoreButton();
+
+  showMoreButton = checkTabsPage(72, "Show All");
+  yield clickShowMoreButton();
+
+  checkTabsPage(77, null);
+
+  yield panelUIHide();
+});
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -33,17 +33,24 @@ function isAncestorOrSelf(target, node) 
     if (node === target) {
       return true;
     }
   }
   return false;
 }
 
 // WeakMap[Extension -> BrowserAction]
-var browserActionMap = new WeakMap();
+const browserActionMap = new WeakMap();
+
+const browserAreas = {
+  "navbar": CustomizableUI.AREA_NAVBAR,
+  "menupanel": CustomizableUI.AREA_PANEL,
+  "tabstrip": CustomizableUI.AREA_TABSTRIP,
+  "personaltoolbar": CustomizableUI.AREA_BOOKMARKS,
+};
 
 // Responsible for the browser_action section of the manifest as well
 // as the associated popup.
 function BrowserAction(options, extension) {
   this.extension = extension;
 
   let widgetId = makeWidgetId(extension.id);
   this.id = `${widgetId}-browser-action`;
@@ -57,16 +64,17 @@ function BrowserAction(options, extensio
 
   this.defaults = {
     enabled: true,
     title: options.default_title || extension.name,
     badgeText: "",
     badgeBackgroundColor: null,
     icon: IconDetails.normalize({path: options.default_icon}, extension),
     popup: options.default_popup || "",
+    area: browserAreas[options.default_area || "navbar"],
   };
 
   this.browserStyle = options.browser_style || false;
   if (options.browser_style === null) {
     this.extension.logger.warn("Please specify whether you want browser_style " +
                                "or not in your browser_action options.");
   }
 
@@ -80,17 +88,17 @@ BrowserAction.prototype = {
   build() {
     let widget = CustomizableUI.createWidget({
       id: this.id,
       viewId: this.viewId,
       type: "view",
       removable: true,
       label: this.defaults.title || this.extension.name,
       tooltiptext: this.defaults.title || "",
-      defaultArea: CustomizableUI.AREA_NAVBAR,
+      defaultArea: this.defaults.area,
 
       onBeforeCreated: document => {
         let view = document.createElementNS(XUL_NS, "panelview");
         view.id = this.viewId;
         view.setAttribute("flex", "1");
 
         document.getElementById("PanelUI-multiView").appendChild(view);
         document.addEventListener("popupshowing", this);
--- a/browser/components/extensions/schemas/browser_action.json
+++ b/browser/components/extensions/schemas/browser_action.json
@@ -26,16 +26,22 @@
                 "type": "string",
                 "format": "relativeUrl",
                 "optional": true,
                 "preprocess": "localize"
               },
               "browser_style": {
                 "type": "boolean",
                 "optional": true
+              },
+              "default_area": {
+                "description": "Defines the location the browserAction will appear by default.  The default location is navbar.",
+                "type": "string",
+                "enum": ["navbar", "menupanel", "tabstrip", "personaltoolbar"],
+                "optional": true
               }
             },
             "optional": true
           }
         }
       }
     ]
   },
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -19,16 +19,17 @@ support-files =
   file_dummy.html
   file_inspectedwindow_reload_target.sjs
   file_serviceWorker.html
   serviceWorker.js
   searchSuggestionEngine.xml
   searchSuggestionEngine.sjs
   ../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js
 
+[browser_ext_browserAction_area.js]
 [browser_ext_browserAction_context.js]
 [browser_ext_browserAction_disabled.js]
 [browser_ext_browserAction_pageAction_icon.js]
 [browser_ext_browserAction_pageAction_icon_permissions.js]
 [browser_ext_browserAction_popup.js]
 [browser_ext_browserAction_popup_preload.js]
 [browser_ext_browserAction_popup_resize.js]
 [browser_ext_browserAction_simple.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_browserAction_area.js
@@ -0,0 +1,49 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+var browserAreas = {
+  "navbar": CustomizableUI.AREA_NAVBAR,
+  "menupanel": CustomizableUI.AREA_PANEL,
+  "tabstrip": CustomizableUI.AREA_TABSTRIP,
+  "personaltoolbar": CustomizableUI.AREA_BOOKMARKS,
+};
+
+function* testInArea(area) {
+  let manifest = {
+    "browser_action": {
+      "browser_style": true,
+    },
+  };
+  if (area) {
+    manifest.browser_action.default_area = area;
+  }
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest,
+  });
+  yield extension.startup();
+  let widget = getBrowserActionWidget(extension);
+  let placement = CustomizableUI.getPlacementOfWidget(widget.id);
+  is(placement && placement.area, browserAreas[area || "navbar"], `widget located in correct area`);
+  yield extension.unload();
+}
+
+add_task(function* testBrowserActionDefaultArea() {
+  yield testInArea();
+});
+
+add_task(function* testBrowserActionInToolbar() {
+  yield testInArea("navbar");
+});
+
+add_task(function* testBrowserActionInMenuPanel() {
+  yield testInArea("menupanel");
+});
+
+add_task(function* testBrowserActionInTabStrip() {
+  yield testInArea("tabstrip");
+});
+
+add_task(function* testBrowserActionInPersonalToolbar() {
+  yield testInArea("personaltoolbar");
+});
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-This system add-on is a follow-up to the MITM prevalence experiment. The purpose
-is to facilitate rolling out the disabling of SHA-1 in signatures on
-certificates issued by publicly-trusted roots. When installed, this add-on will
-perform a number of checks to determine if it should change the preference that
-controls the SHA-1 policy. First, this should only apply to users on the beta
-update channel. It should also only apply to users who have not otherwise
-changed the policy to always allow or always forbid SHA-1. Additionally, it
-must double-check that the user is not affected by a TLS intercepting proxy
-using a publicly-trusted root. If these checks pass, the add-on will divide the
-population into a test group and a control group (starting on a 10%/90% split).
-The test group will have the policy changed. After doing this, a telemetry
-payload is reported with the following values:
-
-* cohortName -- the name of the group this user is in:
-  1. "notSafeToDisableSHA1" if the user is behind a MITM proxy using a
-     publicly-trusted root
-  2. "optedOut" if the user already set the SHA-1 policy to always allow or
-     always forbid
-  3. "optedIn" if the user already set the SHA-1 policy to only allow for
-     non-built-in roots
-  4. "test" if the user is in the test cohort (and SHA-1 will be disabled)
-  5. "control" if the user is not in the test cohort
-* errorCode -- 0 for successful connections, some PR error code otherwise
-* error -- a short description of one of four error conditions encountered, if
-  applicable, and an empty string otherwise:
-  1. "timeout" if the connection to telemetry.mozilla.org timed out
-  2. "user override" if the user has stored a permanent certificate exception
-     override for telemetry.mozilla.org (due to technical limitations, we can't
-     gather much information in this situation)
-  3. "certificate reverification" if re-building the certificate chain after
-     connecting failed for some reason (unfortunately this step is necessary
-     due to technical limitations)
-  4. "connection error" if the connection to telemetry.mozilla.org failed for
-     another reason
-* chain -- a list of dictionaries each corresponding to a certificate in the
-  verified certificate chain, if it was successfully constructed. The first
-  entry is the end-entity certificate. The last entry is the root certificate.
-  This will be empty if the connection failed or if reverification failed. Each
-  element in the list contains the following values:
-  * sha256Fingerprint -- a hex string representing the SHA-256 hash of the
-    certificate
-  * isBuiltInRoot -- true if the certificate is a trust anchor in the web PKI,
-    false otherwise
-  * signatureAlgorithm -- a description of the algorithm used to sign the
-    certificate. Will be one of "md2WithRSAEncryption", "md5WithRSAEncryption",
-    "sha1WithRSAEncryption", "sha256WithRSAEncryption",
-    "sha384WithRSAEncryption", "sha512WithRSAEncryption", "ecdsaWithSHA1",
-    "ecdsaWithSHA224", "ecdsaWithSHA256", "ecdsaWithSHA384", "ecdsaWithSHA512",
-    or "unknown".
-* disabledSHA1 -- true if SHA-1 was disabled, false otherwise
-* didNotDisableSHA1Because -- a short string describing why SHA-1 could not be
-    disabled, if applicable. Reasons are limited to:
-    1. "MITM" if the user is behind a TLS intercepting proxy using a
-       publicly-trusted root
-    2. "connection error" if there was an error connecting to
-       telemetry.mozilla.org
-    3. "code error" if some inconsistent state was detected, and it was
-       determined that the experiment should not attempt to change the
-       preference
-    4. "preference:userReset" if the user reset the SHA-1 policy after it had
-       been changed by this add-on
-    5. "preference:allow" if the user had already configured Firefox to always
-       accept SHA-1 signatures
-    6. "preference:forbid" if the user had already configured Firefox to always
-       forbid SHA-1 signatures
-
-For a connection not intercepted by a TLS proxy and where the user is in the
-test cohort, the expected result will be:
-
-    { "cohortName": "test",
-      "errorCode": 0,
-      "error": "",
-      "chain": [
-        { "sha256Fingerprint": "197feaf3faa0f0ad637a89c97cb91336bfc114b6b3018203cbd9c3d10c7fa86c",
-          "isBuiltInRoot": false,
-          "signatureAlgorithm": "sha256WithRSAEncryption"
-        },
-        { "sha256Fingerprint": "154c433c491929c5ef686e838e323664a00e6a0d822ccc958fb4dab03e49a08f",
-          "isBuiltInRoot": false,
-          "signatureAlgorithm": "sha256WithRSAEncryption"
-        },
-        { "sha256Fingerprint": "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161",
-          "isBuiltInRoot": true,
-          "signatureAlgorithm": "sha1WithRSAEncryption"
-        }
-      ],
-      "disabledSHA1": true,
-      "didNotDisableSHA1Because": ""
-    }
-
-When this result is encountered, the user's preferences are updated to disable
-SHA-1 in signatures on certificates issued by publicly-trusted roots.
-Similarly, if the user is behind a TLS intercepting proxy but the root
-certificate is not part of the public web PKI, we can also disable SHA-1 in
-signatures on certificates issued by publicly-trusted roots.
-
-If the user has already indicated in their preferences that they will always
-accept SHA-1 in signatures or that they will never accept SHA-1 in signatures,
-then the preference is not changed.
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/bootstrap.js
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -*- 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/. */
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/Preferences.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/UpdateUtils.jsm");
-Cu.import("resource://gre/modules/TelemetryController.jsm");
-
- // Percentage of the population to attempt to disable SHA-1 for, by channel.
-const TEST_THRESHOLD = {
-  beta: 0.1, // 10%
-};
-
-const PREF_COHORT_SAMPLE = "disableSHA1.rollout.cohortSample";
-const PREF_COHORT_NAME = "disableSHA1.rollout.cohort";
-const PREF_SHA1_POLICY = "security.pki.sha1_enforcement_level";
-const PREF_SHA1_POLICY_SET_BY_ADDON = "disableSHA1.rollout.policySetByAddOn";
-const PREF_SHA1_POLICY_RESET_BY_USER = "disableSHA1.rollout.userResetPref";
-
-const SHA1_MODE_ALLOW = 0;
-const SHA1_MODE_FORBID = 1;
-const SHA1_MODE_IMPORTED_ROOTS_ONLY = 3;
-const SHA1_MODE_CURRENT_DEFAULT = 4;
-
-function startup() {
-  Preferences.observe(PREF_SHA1_POLICY, policyPreferenceChanged);
-}
-
-function install() {
-  let updateChannel = UpdateUtils.getUpdateChannel(false);
-  if (updateChannel in TEST_THRESHOLD) {
-    makeRequest().then(defineCohort).catch((e) => console.error(e));
-  }
-}
-
-function policyPreferenceChanged() {
-  let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
-                                         SHA1_MODE_CURRENT_DEFAULT);
-  Preferences.reset(PREF_SHA1_POLICY_RESET_BY_USER);
-  if (currentPrefValue == SHA1_MODE_CURRENT_DEFAULT) {
-    Preferences.set(PREF_SHA1_POLICY_RESET_BY_USER, true);
-  }
-}
-
-function defineCohort(result) {
-  let userOptedOut = optedOut();
-  let userOptedIn = optedIn();
-  let shouldNotDisableSHA1Because = reasonToNotDisableSHA1(result);
-  let safeToDisableSHA1 = shouldNotDisableSHA1Because.length == 0;
-  let updateChannel = UpdateUtils.getUpdateChannel(false);
-  let testGroup = getUserSample() < TEST_THRESHOLD[updateChannel];
-
-  let cohortName;
-  if (!safeToDisableSHA1) {
-    cohortName = "notSafeToDisableSHA1";
-  } else if (userOptedOut) {
-    cohortName = "optedOut";
-  } else if (userOptedIn) {
-    cohortName = "optedIn";
-  } else if (testGroup) {
-    cohortName = "test";
-    Preferences.ignore(PREF_SHA1_POLICY, policyPreferenceChanged);
-    Preferences.set(PREF_SHA1_POLICY, SHA1_MODE_IMPORTED_ROOTS_ONLY);
-    Preferences.observe(PREF_SHA1_POLICY, policyPreferenceChanged);
-    Preferences.set(PREF_SHA1_POLICY_SET_BY_ADDON, true);
-  } else {
-    cohortName = "control";
-  }
-  Preferences.set(PREF_COHORT_NAME, cohortName);
-  reportTelemetry(result, cohortName, shouldNotDisableSHA1Because,
-                  cohortName == "test");
-}
-
-function shutdown(data, reason) {
-  Preferences.ignore(PREF_SHA1_POLICY, policyPreferenceChanged);
-}
-
-function uninstall() {
-}
-
-function getUserSample() {
-  let prefValue = Preferences.get(PREF_COHORT_SAMPLE, undefined);
-  let value = 0.0;
-
-  if (typeof(prefValue) == "string") {
-    value = parseFloat(prefValue, 10);
-    return value;
-  }
-
-  value = Math.random();
-
-  Preferences.set(PREF_COHORT_SAMPLE, value.toString().substr(0, 8));
-  return value;
-}
-
-function reportTelemetry(result, cohortName, didNotDisableSHA1Because,
-                         disabledSHA1) {
-  result.cohortName = cohortName;
-  result.disabledSHA1 = disabledSHA1;
-  if (cohortName == "optedOut") {
-    let userResetPref = Preferences.get(PREF_SHA1_POLICY_RESET_BY_USER, false);
-    let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
-                                           SHA1_MODE_CURRENT_DEFAULT);
-    if (userResetPref) {
-      didNotDisableSHA1Because = "preference:userReset";
-    } else if (currentPrefValue == SHA1_MODE_ALLOW) {
-      didNotDisableSHA1Because = "preference:allow";
-    } else {
-      didNotDisableSHA1Because = "preference:forbid";
-    }
-  }
-  result.didNotDisableSHA1Because = didNotDisableSHA1Because;
-  return TelemetryController.submitExternalPing("disableSHA1rollout", result,
-                                                {});
-}
-
-function optedIn() {
-  let policySetByAddOn = Preferences.get(PREF_SHA1_POLICY_SET_BY_ADDON, false);
-  let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
-                                         SHA1_MODE_CURRENT_DEFAULT);
-  return currentPrefValue == SHA1_MODE_IMPORTED_ROOTS_ONLY && !policySetByAddOn;
-}
-
-function optedOut() {
-  // Users can also opt-out by setting the policy to always allow or always
-  // forbid SHA-1, or by resetting the preference after this add-on has changed
-  // it (in that case, this will be reported the next time this add-on is
-  // updated).
-  let currentPrefValue = Preferences.get(PREF_SHA1_POLICY,
-                                         SHA1_MODE_CURRENT_DEFAULT);
-  let userResetPref = Preferences.get(PREF_SHA1_POLICY_RESET_BY_USER, false);
-  return currentPrefValue == SHA1_MODE_ALLOW ||
-         currentPrefValue == SHA1_MODE_FORBID ||
-         userResetPref;
-}
-
-function delocalizeAlgorithm(localizedString) {
-  let bundle = Services.strings.createBundle(
-    "chrome://pipnss/locale/pipnss.properties");
-  let algorithmStringIdsToOIDDescriptionMap = {
-    "CertDumpMD2WithRSA":                       "md2WithRSAEncryption",
-    "CertDumpMD5WithRSA":                       "md5WithRSAEncryption",
-    "CertDumpSHA1WithRSA":                      "sha1WithRSAEncryption",
-    "CertDumpSHA256WithRSA":                    "sha256WithRSAEncryption",
-    "CertDumpSHA384WithRSA":                    "sha384WithRSAEncryption",
-    "CertDumpSHA512WithRSA":                    "sha512WithRSAEncryption",
-    "CertDumpAnsiX962ECDsaSignatureWithSha1":   "ecdsaWithSHA1",
-    "CertDumpAnsiX962ECDsaSignatureWithSha224": "ecdsaWithSHA224",
-    "CertDumpAnsiX962ECDsaSignatureWithSha256": "ecdsaWithSHA256",
-    "CertDumpAnsiX962ECDsaSignatureWithSha384": "ecdsaWithSHA384",
-    "CertDumpAnsiX962ECDsaSignatureWithSha512": "ecdsaWithSHA512",
-  };
-
-  let description;
-  Object.keys(algorithmStringIdsToOIDDescriptionMap).forEach((l10nID) => {
-    let candidateLocalizedString = bundle.GetStringFromName(l10nID);
-    if (localizedString == candidateLocalizedString) {
-      description = algorithmStringIdsToOIDDescriptionMap[l10nID];
-    }
-  });
-  if (!description) {
-    return "unknown";
-  }
-  return description;
-}
-
-function getSignatureAlgorithm(cert) {
-  // Certificate  ::=  SEQUENCE  {
-  //      tbsCertificate       TBSCertificate,
-  //      signatureAlgorithm   AlgorithmIdentifier,
-  //      signatureValue       BIT STRING  }
-  let certificate = cert.ASN1Structure.QueryInterface(Ci.nsIASN1Sequence);
-  let signatureAlgorithm = certificate.ASN1Objects
-                                      .queryElementAt(1, Ci.nsIASN1Sequence);
-  // AlgorithmIdentifier  ::=  SEQUENCE  {
-  //      algorithm               OBJECT IDENTIFIER,
-  //      parameters              ANY DEFINED BY algorithm OPTIONAL  }
-
-  // If parameters is NULL (or empty), signatureAlgorithm won't be a container
-  // under this implementation. Just get its displayValue.
-  if (!signatureAlgorithm.isValidContainer) {
-    return signatureAlgorithm.displayValue;
-  }
-  let oid = signatureAlgorithm.ASN1Objects.queryElementAt(0, Ci.nsIASN1Object);
-  return oid.displayValue;
-}
-
-function processCertChain(chain) {
-  let output = [];
-  let enumerator = chain.getEnumerator();
-  while (enumerator.hasMoreElements()) {
-    let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
-    output.push({
-      sha256Fingerprint: cert.sha256Fingerprint.replace(/:/g, "").toLowerCase(),
-      isBuiltInRoot: cert.isBuiltInRoot,
-      signatureAlgorithm: delocalizeAlgorithm(getSignatureAlgorithm(cert)),
-    });
-  }
-  return output;
-}
-
-class CertificateVerificationResult {
-  constructor(resolve) {
-    this.resolve = resolve;
-  }
-
-  verifyCertFinished(aPRErrorCode, aVerifiedChain, aEVStatus) {
-    let result = { errorCode: aPRErrorCode, error: "", chain: [] };
-    if (aPRErrorCode == 0) {
-      result.chain = processCertChain(aVerifiedChain);
-    } else {
-      result.error = "certificate reverification";
-    }
-    this.resolve(result);
-  }
-}
-
-function makeRequest() {
-  return new Promise((resolve) => {
-    let hostname = "telemetry.mozilla.org";
-    let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
-                .createInstance(Ci.nsIXMLHttpRequest);
-    req.open("GET", "https://" + hostname);
-    req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
-    req.timeout = 30000;
-    req.addEventListener("error", (evt) => {
-      // If we can't connect to telemetry.mozilla.org, then how did we even
-      // download the experiment? In any case, we may still be able to get some
-      // information.
-      let result = { error: "connection error" };
-      if (evt.target.channel && evt.target.channel.securityInfo) {
-        let securityInfo = evt.target.channel.securityInfo
-                             .QueryInterface(Ci.nsITransportSecurityInfo);
-        if (securityInfo) {
-          result.errorCode = securityInfo.errorCode;
-        }
-        if (securityInfo && securityInfo.failedCertChain) {
-          result.chain = processCertChain(securityInfo.failedCertChain);
-        }
-      }
-      resolve(result);
-    });
-    req.addEventListener("timeout", (evt) => {
-      resolve({ error: "timeout" });
-    });
-    req.addEventListener("load", (evt) => {
-      let securityInfo = evt.target.channel.securityInfo
-                           .QueryInterface(Ci.nsITransportSecurityInfo);
-      if (securityInfo.securityState &
-          Ci.nsIWebProgressListener.STATE_CERT_USER_OVERRIDDEN) {
-        resolve({ error: "user override" });
-        return;
-      }
-      let sslStatus = securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
-                        .SSLStatus;
-      let certdb = Cc["@mozilla.org/security/x509certdb;1"]
-                     .getService(Ci.nsIX509CertDB);
-      let result = new CertificateVerificationResult(resolve);
-      // Unfortunately, we don't have direct access to the verified certificate
-      // chain as built by the AuthCertificate hook, so we have to re-build it
-      // here. In theory we are likely to get the same result.
-      certdb.asyncVerifyCertAtTime(sslStatus.serverCert,
-                                   2, // certificateUsageSSLServer
-                                   0, // flags
-                                   hostname,
-                                   Date.now() / 1000,
-                                   result);
-    });
-    req.send();
-  });
-}
-
-// As best we know, it is safe to disable SHA1 if the connection was successful
-// and either the connection was MITM'd by a root not in the public PKI or the
-// chain is part of the public PKI and is the one served by the real
-// telemetry.mozilla.org.
-// This will return a short string description of why it might not be safe to
-// disable SHA1 or an empty string if it is safe to disable SHA1.
-function reasonToNotDisableSHA1(result) {
-  if (!("errorCode" in result) || result.errorCode != 0) {
-    return "connection error";
-  }
-  if (!("chain" in result)) {
-    return "code error";
-  }
-  if (!result.chain[result.chain.length - 1].isBuiltInRoot) {
-    return "";
-  }
-  if (result.chain.length != 3) {
-    return "MITM";
-  }
-  const kEndEntityFingerprint = "197feaf3faa0f0ad637a89c97cb91336bfc114b6b3018203cbd9c3d10c7fa86c";
-  const kIntermediateFingerprint = "154c433c491929c5ef686e838e323664a00e6a0d822ccc958fb4dab03e49a08f";
-  const kRootFingerprint = "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161";
-  if (result.chain[0].sha256Fingerprint != kEndEntityFingerprint ||
-      result.chain[1].sha256Fingerprint != kIntermediateFingerprint ||
-      result.chain[2].sha256Fingerprint != kRootFingerprint) {
-    return "MITM";
-  }
-  return "";
-}
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/install.rdf.in
+++ /dev/null
@@ -1,32 +0,0 @@
-<?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/. -->
-
-#filter substitution
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>disableSHA1rollout@mozilla.org</em:id>
-    <em:version>1.0</em:version>
-    <em:type>2</em:type>
-    <em:bootstrap>true</em:bootstrap>
-    <em:multiprocessCompatible>true</em:multiprocessCompatible>
-
-    <!-- Target Application this theme can install into,
-        with minimum and maximum supported versions. -->
-    <em:targetApplication>
-      <Description>
-        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-        <em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
-        <em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-    <!-- Front End MetaData -->
-    <em:name>SHA-1 deprecation staged rollout</em:name>
-    <em:description>Staged rollout deprecating SHA-1 in certificate signatures.</em:description>
-  </Description>
-</RDF>
deleted file mode 100644
--- a/browser/extensions/disableSHA1rollout/moz.build
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
-DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
-
-FINAL_TARGET_FILES.features['disableSHA1rollout@mozilla.org'] += [
-  'bootstrap.js'
-]
-
-FINAL_TARGET_PP_FILES.features['disableSHA1rollout@mozilla.org'] += [
-  'install.rdf.in'
-]
--- a/browser/extensions/moz.build
+++ b/browser/extensions/moz.build
@@ -1,17 +1,16 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += [
     'aushelper',
-    'disableSHA1rollout',
     'e10srollout',
     'pdfjs',
     'pocket',
     'webcompat',
     'shield-recipe-client',
 ]
 
 # Only include the following system add-ons if building Aurora or Nightly
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -353,16 +353,24 @@ These should match what Safari and other
 <!ENTITY appMenuHistory.restoreSession.label "Restore Previous Session">
 <!ENTITY appMenuHistory.viewSidebar.label "View History Sidebar">
 <!ENTITY appMenuHelp.tooltip "Open Help Menu">
 
 <!ENTITY appMenuRemoteTabs.label "Synced Tabs">
 <!-- LOCALIZATION NOTE (appMenuRemoteTabs.notabs.label): This is shown beneath
      the name of a device when that device has no open tabs -->
 <!ENTITY appMenuRemoteTabs.notabs.label "No open tabs">
+<!-- LOCALIZATION NOTE (appMenuRemoteTabs.showMore.label, appMenuRemoteTabs.showMore.tooltip):
+     This is shown after the tabs list if we can display more tabs by clicking on the button -->
+<!ENTITY appMenuRemoteTabs.showMore.label "Show More">
+<!ENTITY appMenuRemoteTabs.showMore.tooltip "Show more tabs from this device">
+<!-- LOCALIZATION NOTE (appMenuRemoteTabs.showAll.label, appMenuRemoteTabs.showAll.tooltip):
+     This is shown after the tabs list if we can all the remaining tabs by clicking on the button -->
+<!ENTITY appMenuRemoteTabs.showAll.label "Show All">
+<!ENTITY appMenuRemoteTabs.showAll.tooltip "Show all tabs from this device">
 <!-- LOCALIZATION NOTE (appMenuRemoteTabs.tabsnotsyncing.label): This is shown
      when Sync is configured but syncing tabs is disabled. -->
 <!ENTITY appMenuRemoteTabs.tabsnotsyncing.label "Turn on tab syncing to view a list of tabs from your other devices.">
 <!-- LOCALIZATION NOTE (appMenuRemoteTabs.noclients.label): This is shown
      when Sync is configured but this appears to be the only device attached to
      the account. We also show links to download Firefox for android/ios. -->
 <!ENTITY appMenuRemoteTabs.noclients.title "No synced tabs… yet!">
 <!ENTITY appMenuRemoteTabs.noclients.subtitle "Want to see your tabs from other devices here?">
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -1238,29 +1238,29 @@ menuitem.panel-subview-footer@menuStateA
 
 .subviewbutton > .menu-accel-container {
   -moz-box-pack: start;
   margin-inline-start: 10px;
   margin-inline-end: auto;
   color: GrayText;
 }
 
-#PanelUI-remotetabs-tabslist > toolbarbutton,
+#PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"],
 #PanelUI-historyItems > toolbarbutton {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
 }
 
 @media (min-resolution: 1.1dppx) {
-  #PanelUI-remotetabs-tabslist > toolbarbutton,
+  #PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"],
   #PanelUI-historyItems > toolbarbutton {
     list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
   }
 }
 
-#PanelUI-remotetabs-tabslist > toolbarbutton > .toolbarbutton-icon,
+#PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"] > .toolbarbutton-icon,
 #PanelUI-recentlyClosedWindows > toolbarbutton > .toolbarbutton-icon,
 #PanelUI-recentlyClosedTabs > toolbarbutton > .toolbarbutton-icon,
 #PanelUI-historyItems > toolbarbutton > .toolbarbutton-icon {
   width: 16px;
   height: 16px;
 }
 
 toolbarbutton[panel-multiview-anchor="true"],
--- a/build/moz.configure/warnings.configure
+++ b/build/moz.configure/warnings.configure
@@ -73,19 +73,16 @@ check_and_add_gcc_warning('-Wimplicit-fa
 # --enable-warnings-as-errors is specified so that no unexpected fatal
 # warnings are produced.
 check_and_add_gcc_warning('-Werror=non-literal-null-conversion',
                           when='--enable-warnings-as-errors')
 
 # catches string literals used in boolean expressions
 check_and_add_gcc_warning('-Wstring-conversion')
 
-# catches inconsistent use of mutexes
-check_and_add_gcc_warning('-Wthread-safety')
-
 # we inline 'new' and 'delete' in mozalloc
 check_and_add_gcc_warning('-Wno-inline-new-delete', cxx_compiler)
 
 # Prevent the following GCC warnings from being treated as errors:
 # too many false positives
 check_and_add_gcc_warning('-Wno-error=maybe-uninitialized')
 
 # we don't want our builds held hostage when a platform-specific API
--- a/dom/base/GroupedSHistory.cpp
+++ b/dom/base/GroupedSHistory.cpp
@@ -1,15 +1,17 @@
 /* -*- 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 "GroupedSHistory.h"
+
+#include "mozilla/dom/Promise.h"
 #include "TabParent.h"
 #include "PartialSHistory.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(GroupedSHistory)
 
--- a/dom/base/GroupedSHistory.h
+++ b/dom/base/GroupedSHistory.h
@@ -6,16 +6,19 @@
 
 #ifndef GroupedSHistory_h
 #define GroupedSHistory_h
 
 #include "nsIFrameLoader.h"
 #include "nsIGroupedSHistory.h"
 #include "nsIPartialSHistory.h"
 #include "nsTArray.h"
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
 
 
 /**
  * GroupedSHistory connects session histories across multiple frameloaders.
--- a/dom/canvas/test/reftest/filters/reftest-stylo.list
+++ b/dom/canvas/test/reftest/filters/reftest-stylo.list
@@ -1,13 +1,13 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 default-preferences pref(canvas.filters.enabled,true)
 
 fails asserts-if(stylo,2) == default-color.html default-color.html # bug 1324700
-# == drop-shadow.html drop-shadow.html
+fails asserts-if(stylo,2) == drop-shadow.html drop-shadow.html # bug 1324700
 fails asserts-if(stylo,2) == drop-shadow-transformed.html drop-shadow-transformed.html # bug 1324700
 fails asserts-if(stylo,2) == global-alpha.html global-alpha.html # bug 1324700
 fails asserts-if(stylo,2) == global-composite-operation.html global-composite-operation.html # bug 1324700
 fails asserts-if(stylo,1) == liveness.html liveness.html # bug 1324700
 fails asserts-if(stylo,2) == multiple-drop-shadows.html multiple-drop-shadows.html # bug 1324700
 fails asserts-if(stylo,2) == shadow.html shadow.html # bug 1324700
 fails asserts-if(stylo,2) == subregion-fill-paint.html subregion-fill-paint.html # bug 1324700
 fails asserts-if(stylo,2) == subregion-stroke-paint.html subregion-stroke-paint.html # bug 1324700
--- a/dom/canvas/test/reftest/reftest-stylo.list
+++ b/dom/canvas/test/reftest/reftest-stylo.list
@@ -54,17 +54,17 @@ fuzzy(1,30000) fails-if(winWidget&&layer
 fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&aa&________&_______&alpha webgl-color-test.html?frame=1&aa&________&_______&alpha
 fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&__&preserve&_______&alpha webgl-color-test.html?frame=1&__&preserve&_______&alpha
 fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=1&aa&preserve&_______&alpha webgl-color-test.html?frame=1&aa&preserve&_______&alpha
 skip-if(Android) == webgl-color-test.html?frame=1&__&________&premult&alpha webgl-color-test.html?frame=1&__&________&premult&alpha
 skip-if(Android) == webgl-color-test.html?frame=1&aa&________&premult&alpha webgl-color-test.html?frame=1&aa&________&premult&alpha
 skip-if(Android) == webgl-color-test.html?frame=1&__&preserve&premult&alpha webgl-color-test.html?frame=1&__&preserve&premult&alpha
 skip-if(Android) == webgl-color-test.html?frame=1&aa&preserve&premult&alpha webgl-color-test.html?frame=1&aa&preserve&premult&alpha
 
-# == webgl-color-test.html?frame=6&__&________&_______&_____ webgl-color-test.html?frame=6&__&________&_______&_____
+== webgl-color-test.html?frame=6&__&________&_______&_____ webgl-color-test.html?frame=6&__&________&_______&_____
 skip-if(Android) == webgl-color-test.html?frame=6&aa&________&_______&_____ webgl-color-test.html?frame=6&aa&________&_______&_____
 skip-if(Android) == webgl-color-test.html?frame=6&__&preserve&_______&_____ webgl-color-test.html?frame=6&__&preserve&_______&_____
 skip-if(Android) == webgl-color-test.html?frame=6&aa&preserve&_______&_____ webgl-color-test.html?frame=6&aa&preserve&_______&_____
 == webgl-color-test.html?frame=6&__&________&premult&_____ webgl-color-test.html?frame=6&__&________&premult&_____
 skip-if(Android) == webgl-color-test.html?frame=6&aa&________&premult&_____ webgl-color-test.html?frame=6&aa&________&premult&_____
 skip-if(Android) == webgl-color-test.html?frame=6&__&preserve&premult&_____ webgl-color-test.html?frame=6&__&preserve&premult&_____
 skip-if(Android) == webgl-color-test.html?frame=6&aa&preserve&premult&_____ webgl-color-test.html?frame=6&aa&preserve&premult&_____
 fuzzy(1,30000) fails-if(winWidget&&layersGPUAccelerated&&!d3d11) skip-if(Android) == webgl-color-test.html?frame=6&__&________&_______&alpha webgl-color-test.html?frame=6&__&________&_______&alpha
--- a/dom/encoding/test/reftest/reftest-stylo.list
+++ b/dom/encoding/test/reftest/reftest-stylo.list
@@ -1,6 +1,6 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# == bug863728-1.html bug863728-1.html
+== bug863728-1.html bug863728-1.html
 == bug863728-2.html bug863728-2.html
 == bug863728-3.html bug863728-3.html
-# == bug945215-1.html bug945215-1.html
+== bug945215-1.html bug945215-1.html
 == bug945215-2.html bug945215-2.html
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -991,17 +991,17 @@ private:
             mSuspended == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE ||
             mSuspended == nsISuspendedTypes::SUSPENDED_BLOCK);
   }
 
   AudibleState
   IsOwnerAudible() const
   {
     // Muted or the volume should not be ~0
-    if (mOwner->Muted() || (std::fabs(mOwner->Volume()) <= 1e-7)) {
+    if (mOwner->mMuted || (std::fabs(mOwner->Volume()) <= 1e-7)) {
       return AudioChannelService::AudibleState::eNotAudible;
     }
 
     // No audio track.
     if (!mOwner->HasAudio()) {
       return AudioChannelService::AudibleState::eNotAudible;
     }
 
@@ -2034,25 +2034,29 @@ void HTMLMediaElement::NotifyMediaTrackD
                         this, aTrack->AsAudioTrack() ? "Audio" : "Video",
                         NS_ConvertUTF16toUTF8(id).get()));
 #endif
 
   MOZ_ASSERT((!aTrack->AsAudioTrack() || !aTrack->AsAudioTrack()->Enabled()) &&
              (!aTrack->AsVideoTrack() || !aTrack->AsVideoTrack()->Selected()));
 
   if (aTrack->AsAudioTrack()) {
-    bool shouldMute = true;
-    for (uint32_t i = 0; i < AudioTracks()->Length(); ++i) {
-      if ((*AudioTracks())[i]->Enabled()) {
-        shouldMute = false;
-        break;
+    // If we don't have any alive track , we don't need to mute MediaElement.
+    if (AudioTracks()->Length() > 0) {
+      bool shouldMute = true;
+      for (uint32_t i = 0; i < AudioTracks()->Length(); ++i) {
+        if ((*AudioTracks())[i]->Enabled()) {
+          shouldMute = false;
+          break;
+        }
       }
-    }
-    if (shouldMute) {
-      SetMutedInternal(mMuted | MUTED_BY_AUDIO_TRACK);
+
+      if (shouldMute) {
+        SetMutedInternal(mMuted | MUTED_BY_AUDIO_TRACK);
+      }
     }
   } else if (aTrack->AsVideoTrack()) {
     if (mSrcStream) {
       MOZ_ASSERT(mSelectedVideoStreamTrack);
       if (mSelectedVideoStreamTrack && mMediaStreamSizeListener) {
         mSelectedVideoStreamTrack->RemoveDirectListener(mMediaStreamSizeListener);
         mMediaStreamSizeListener->Forget();
         mMediaStreamSizeListener = nullptr;
--- a/dom/html/reftests/reftest-stylo.list
+++ b/dom/html/reftests/reftest-stylo.list
@@ -1,66 +1,65 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # autofocus attribute (we can't test with mochitests)
 include autofocus/reftest-stylo.list
 include toblob-todataurl/reftest-stylo.list
 
 fails == 41464-1a.html 41464-1a.html
 fails == 41464-1b.html 41464-1b.html
 fails == 52019-1.html 52019-1.html
-fails == 82711-1.html 82711-1.html
+fails == 82711-1.html 82711-1.html # Bug 1341637
 fails == 82711-2.html 82711-2.html
-# == 82711-1-ref.html 82711-1-ref.html
+fails == 82711-1-ref.html 82711-1-ref.html
 == 468263-1a.html 468263-1a.html
 == 468263-1b.html 468263-1b.html
 == 468263-1c.html 468263-1c.html
-# == 468263-1d.html 468263-1d.html
-# == 468263-2.html 468263-2.html
-# == 468263-2.html 468263-2.html
+== 468263-1d.html 468263-1d.html
+fails == 468263-2.html 468263-2.html # Bug 1341642
 fails == 484200-1.html 484200-1.html
-# == 485377.html 485377.html
+== 485377.html 485377.html
 == 557840.html 557840.html
 == 560059-video-dimensions.html 560059-video-dimensions.html
 fails == 573322-quirks.html 573322-quirks.html
 fails == 573322-no-quirks.html 573322-no-quirks.html
 fails == 596455-1a.html 596455-1a.html
 fails == 596455-1b.html 596455-1b.html
 fails == 596455-2a.html 596455-2a.html
 fails == 596455-2b.html 596455-2b.html
 fails == 610935.html 610935.html
 == 649134-1.html 649134-1.html
-# == 649134-2.html 649134-2.html
+== 649134-2.html 649134-2.html
 fails == 741776-1.vtt 741776-1.vtt
 
-# == bug448564-1_malformed.html bug448564-1_malformed.html
-# == bug448564-1_malformed.html bug448564-1_malformed.html
+== bug448564-1_malformed.html bug448564-1_malformed.html
+== bug448564-1_malformed.html bug448564-1_malformed.html
 
-# == bug448564-4a.html bug448564-4a.html
-# == bug502168-1_malformed.html bug502168-1_malformed.html
+== bug448564-4a.html bug448564-4a.html
+== bug502168-1_malformed.html bug502168-1_malformed.html
 
-# == responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit.html
+fails == responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit.html
 == image-load-shortcircuit-1.html image-load-shortcircuit-1.html
 == image-load-shortcircuit-2.html image-load-shortcircuit-2.html
 
 # Test that image documents taken into account CSS properties like
 # image-orientation when determining the size of the image.
 # (Fuzzy necessary due to pixel-wise comparison of different JPEGs.
 # The vast majority of the fuzziness comes from Linux and WinXP.)
-# == bug917595-iframe-1.html bug917595-iframe-1.html
+fails == bug917595-iframe-1.html bug917595-iframe-1.html # Bug 1341647
 fails == bug917595-exif-rotated.jpg bug917595-exif-rotated.jpg
 
 # Test support for SVG-as-image in <picture> elements.
 == bug1106522-1.html bug1106522-1.html
 == bug1106522-2.html bug1106522-2.html
 
 fails == href-attr-change-restyles.html href-attr-change-restyles.html
-# == figure.html figure.html
+== figure.html figure.html
 fails == pre-1.html pre-1.html
-# == table-border-1.html table-border-1.html
-# == table-border-2.html table-border-2.html
-# == table-border-2.html table-border-2.html
+fails == table-border-1.html table-border-1.html # Bug 1341651
+== table-border-2.html table-border-2.html
+== table-border-2.html table-border-2.html
 
 # Test imageset is using permissions.default.image
 # pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html
 # pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html
 
 # Test video with rotation information can be rotated.
 == bug1228601-video-rotation-90.html bug1228601-video-rotation-90.html
--- a/dom/media/MediaResult.h
+++ b/dom/media/MediaResult.h
@@ -2,16 +2,18 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MediaResult_h_
 #define MediaResult_h_
 
+#include "nsString.h" // Required before 'mozilla/ErrorNames.h'!?
+#include "mozilla/ErrorNames.h"
 #include "nsError.h"
 #include "nsPrintfCString.h"
 
 // MediaResult can be used interchangeably with nsresult.
 // It allows to store extra information such as where the error occurred.
 // While nsresult is typically passed by value; due to its potential size, using
 // MediaResult const references is recommended.
 namespace mozilla {
@@ -46,20 +48,30 @@ public:
   bool operator!=(nsresult aResult) const { return aResult != mCode; }
   operator nsresult () const { return mCode; }
 
   nsCString Description() const
   {
     if (NS_SUCCEEDED(mCode)) {
       return nsCString();
     }
-    return nsPrintfCString("0x%08" PRIx32 ": %s", static_cast<uint32_t>(mCode), mMessage.get());
+    nsCString name;
+    GetErrorName(mCode, static_cast<nsACString&>(name));
+    return nsPrintfCString("%s (0x%08" PRIx32 ")%s%s",
+                           name.get(),
+                           static_cast<uint32_t>(mCode),
+                           mMessage.IsEmpty() ? "" : " - ",
+                           mMessage.get());
   }
 
 private:
   nsresult mCode;
   nsCString mMessage;
 };
 
-#define RESULT_DETAIL(arg, ...) nsPrintfCString("%s: " arg, __func__, ##__VA_ARGS__)
+#ifdef _MSC_VER
+#define RESULT_DETAIL(arg, ...) nsPrintfCString("%s: " arg, __FUNCSIG__, ##__VA_ARGS__)
+#else
+#define RESULT_DETAIL(arg, ...) nsPrintfCString("%s: " arg, __PRETTY_FUNCTION__, ##__VA_ARGS__)
+#endif
 
 } // namespace mozilla
 #endif // MediaResult_h_
--- a/dom/media/gmp/GMPVideoDecoderParent.cpp
+++ b/dom/media/gmp/GMPVideoDecoderParent.cpp
@@ -10,16 +10,17 @@
 #include "nsAutoRef.h"
 #include "nsThreadUtils.h"
 #include "GMPUtils.h"
 #include "GMPVideoEncodedFrameImpl.h"
 #include "GMPVideoi420FrameImpl.h"
 #include "GMPContentParent.h"
 #include "GMPMessageUtils.h"
 #include "mozilla/gmp/GMPTypes.h"
+#include "nsPrintfCString.h"
 
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
 
 extern LogModule* GetGMPLog();
--- a/dom/plugins/test/reftest/reftest-stylo.list
+++ b/dom/plugins/test/reftest/reftest-stylo.list
@@ -1,26 +1,26 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # basic sanity checking
-# == plugin-sanity.html plugin-sanity.html
-# == plugin-sanity.html plugin-sanity.html
+fails == plugin-sanity.html plugin-sanity.html # Bug 1341095
+fails == plugin-sanity.html plugin-sanity.html # Bug 1341095
 == plugin-alpha-zindex.html plugin-alpha-zindex.html
 == plugin-alpha-opacity.html plugin-alpha-opacity.html
 == windowless-clipping-1.html windowless-clipping-1.html
 # fuzzy because of anti-aliasing in dashed border
 == border-padding-1.html border-padding-1.html
 == border-padding-2.html border-padding-2.html
 == border-padding-3.html border-padding-3.html
 # The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
 #random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-1.html pluginproblemui-direction-1.html
 #random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-2.html pluginproblemui-direction-2.html
 == plugin-canvas-alpha-zindex.html plugin-canvas-alpha-zindex.html
 fails == plugin-transform-alpha-zindex.html plugin-transform-alpha-zindex.html
 == plugin-busy-alpha-zindex.html plugin-busy-alpha-zindex.html
-# == plugin-background.html plugin-background.html
+== plugin-background.html plugin-background.html
 == plugin-background-1-step.html plugin-background-1-step.html
 == plugin-background-2-step.html plugin-background-2-step.html
 == plugin-background-5-step.html plugin-background-5-step.html
 == plugin-background-10-step.html plugin-background-10-step.html
 == plugin-transform-1.html plugin-transform-1.html
 fails == plugin-transform-2.html plugin-transform-2.html
 fails == shrink-1.html shrink-1.html
 == update-1.html update-1.html
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -56,17 +56,17 @@ bool nsMixedContentBlocker::sBlockMixedS
 // Is mixed display content blocking (images, audio, video, <a ping>) enabled?
 bool nsMixedContentBlocker::sBlockMixedDisplay = false;
 
 // Do we move HSTS before mixed-content
 bool nsMixedContentBlocker::sUseHSTS = false;
 // Do we send an HSTS priming request
 bool nsMixedContentBlocker::sSendHSTSPriming = false;
 // Default HSTS Priming failure timeout to 7 days, in seconds
-uint32_t nsMixedContentBlocker::sHSTSPrimingCacheTimeout = (60 * 24 * 7);
+uint32_t nsMixedContentBlocker::sHSTSPrimingCacheTimeout = (60 * 60 * 24 * 7);
 
 bool
 IsEligibleForHSTSPriming(nsIURI* aContentLocation) {
   bool isHttpScheme = false;
   nsresult rv = aContentLocation->SchemeIs("http", &isHttpScheme);
   NS_ENSURE_SUCCESS(rv, false);
   if (!isHttpScheme) {
     return false;
--- a/editor/reftests/reftest-stylo.list
+++ b/editor/reftests/reftest-stylo.list
@@ -14,41 +14,41 @@ fails == dynamic-type-4.html dynamic-typ
 fails == passwd-1.html passwd-1.html
 fails == passwd-2.html passwd-2.html
 fails == passwd-3.html passwd-3.html
 fails needs-focus == passwd-4.html passwd-4.html
 fails == emptypasswd-1.html emptypasswd-1.html
 fails == emptypasswd-2.html emptypasswd-2.html
 fails == caret_on_positioned.html caret_on_positioned.html
 fails == spellcheck-input-disabled.html spellcheck-input-disabled.html
-# == spellcheck-input-attr-before.html spellcheck-input-attr-before.html
-# == spellcheck-input-attr-before.html spellcheck-input-attr-before.html
-# == spellcheck-input-attr-after.html spellcheck-input-attr-after.html
-# == spellcheck-input-attr-after.html spellcheck-input-attr-after.html
-# == spellcheck-input-attr-inherit.html spellcheck-input-attr-inherit.html
-# == spellcheck-input-attr-inherit.html spellcheck-input-attr-inherit.html
-# == spellcheck-input-attr-dynamic.html spellcheck-input-attr-dynamic.html
-# == spellcheck-input-attr-dynamic.html spellcheck-input-attr-dynamic.html
-# == spellcheck-input-attr-dynamic-inherit.html spellcheck-input-attr-dynamic-inherit.html
-# == spellcheck-input-attr-dynamic-inherit.html spellcheck-input-attr-dynamic-inherit.html
-# == spellcheck-input-property-dynamic.html spellcheck-input-property-dynamic.html
-# == spellcheck-input-property-dynamic.html spellcheck-input-property-dynamic.html
-# == spellcheck-input-property-dynamic-inherit.html spellcheck-input-property-dynamic-inherit.html
-# == spellcheck-input-property-dynamic-inherit.html spellcheck-input-property-dynamic-inherit.html
-# == spellcheck-input-attr-dynamic-override.html spellcheck-input-attr-dynamic-override.html
-# == spellcheck-input-attr-dynamic-override.html spellcheck-input-attr-dynamic-override.html
-# == spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-attr-dynamic-override-inherit.html
-# == spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-attr-dynamic-override-inherit.html
-# == spellcheck-input-property-dynamic-override.html spellcheck-input-property-dynamic-override.html
-# == spellcheck-input-property-dynamic-override.html spellcheck-input-property-dynamic-override.html
-# == spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-property-dynamic-override-inherit.html
-# == spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-property-dynamic-override-inherit.html
-# == spellcheck-textarea-attr.html spellcheck-textarea-attr.html
+fails == spellcheck-input-attr-before.html spellcheck-input-attr-before.html
+fails == spellcheck-input-attr-before.html spellcheck-input-attr-before.html
+fails == spellcheck-input-attr-after.html spellcheck-input-attr-after.html
+fails == spellcheck-input-attr-after.html spellcheck-input-attr-after.html
+fails == spellcheck-input-attr-inherit.html spellcheck-input-attr-inherit.html
+fails == spellcheck-input-attr-inherit.html spellcheck-input-attr-inherit.html
+fails == spellcheck-input-attr-dynamic.html spellcheck-input-attr-dynamic.html
+fails == spellcheck-input-attr-dynamic.html spellcheck-input-attr-dynamic.html
+fails == spellcheck-input-attr-dynamic-inherit.html spellcheck-input-attr-dynamic-inherit.html
+fails == spellcheck-input-attr-dynamic-inherit.html spellcheck-input-attr-dynamic-inherit.html
+fails == spellcheck-input-property-dynamic.html spellcheck-input-property-dynamic.html
+fails == spellcheck-input-property-dynamic.html spellcheck-input-property-dynamic.html
+fails == spellcheck-input-property-dynamic-inherit.html spellcheck-input-property-dynamic-inherit.html
+fails == spellcheck-input-property-dynamic-inherit.html spellcheck-input-property-dynamic-inherit.html
+fails == spellcheck-input-attr-dynamic-override.html spellcheck-input-attr-dynamic-override.html
+fails == spellcheck-input-attr-dynamic-override.html spellcheck-input-attr-dynamic-override.html
+fails == spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-attr-dynamic-override-inherit.html
+fails == spellcheck-input-attr-dynamic-override-inherit.html spellcheck-input-attr-dynamic-override-inherit.html
+fails == spellcheck-input-property-dynamic-override.html spellcheck-input-property-dynamic-override.html
+fails == spellcheck-input-property-dynamic-override.html spellcheck-input-property-dynamic-override.html
+fails == spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-property-dynamic-override-inherit.html
+fails == spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-property-dynamic-override-inherit.html
+fails == spellcheck-textarea-attr.html spellcheck-textarea-attr.html
 #the random-if(Android) tests pass on android native, but fail on android-xul, see bug 728942
-# == spellcheck-textarea-attr.html spellcheck-textarea-attr.html
+fails == spellcheck-textarea-attr.html spellcheck-textarea-attr.html
 fails needs-focus == spellcheck-textarea-focused.html spellcheck-textarea-focused.html
 fails needs-focus == spellcheck-textarea-focused-reframe.html spellcheck-textarea-focused-reframe.html
 fails needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-focused-notreadonly.html
 fails == spellcheck-textarea-nofocus.html spellcheck-textarea-nofocus.html
 fails == spellcheck-textarea-disabled.html spellcheck-textarea-disabled.html
 fails == spellcheck-textarea-attr-inherit.html spellcheck-textarea-attr-inherit.html
 fails == spellcheck-textarea-attr-dynamic.html spellcheck-textarea-attr-dynamic.html
 fails == spellcheck-textarea-attr-dynamic-inherit.html spellcheck-textarea-attr-dynamic-inherit.html
@@ -58,18 +58,18 @@ fails == spellcheck-textarea-attr-dynami
 fails == spellcheck-textarea-attr-dynamic-override-inherit.html spellcheck-textarea-attr-dynamic-override-inherit.html
 fails == spellcheck-textarea-property-dynamic-override.html spellcheck-textarea-property-dynamic-override.html
 fails == spellcheck-textarea-property-dynamic-override-inherit.html spellcheck-textarea-property-dynamic-override-inherit.html
 fails needs-focus == caret_on_focus.html caret_on_focus.html
 fails needs-focus == caret_on_textarea_lastline.html caret_on_textarea_lastline.html
 fails needs-focus == input-text-onfocus-reframe.html input-text-onfocus-reframe.html
 fails needs-focus == input-text-notheme-onfocus-reframe.html input-text-notheme-onfocus-reframe.html
 fails needs-focus == caret_after_reframe.html caret_after_reframe.html
-# == nobogusnode-1.html nobogusnode-1.html
-# == nobogusnode-2.html nobogusnode-2.html
+== nobogusnode-1.html nobogusnode-1.html
+== nobogusnode-2.html nobogusnode-2.html
 fails == spellcheck-hyphen-valid.html spellcheck-hyphen-valid.html
 fails == spellcheck-hyphen-invalid.html spellcheck-hyphen-invalid.html
 fails == spellcheck-slash-valid.html spellcheck-slash-valid.html
 fails == spellcheck-period-valid.html spellcheck-period-valid.html
 fails == spellcheck-space-valid.html spellcheck-space-valid.html
 fails == spellcheck-comma-valid.html spellcheck-comma-valid.html
 fails == spellcheck-hyphen-multiple-valid.html spellcheck-hyphen-multiple-valid.html
 fails == spellcheck-hyphen-multiple-invalid.html spellcheck-hyphen-multiple-invalid.html
@@ -77,18 +77,18 @@ fails == spellcheck-dotafterquote-valid.
 fails == spellcheck-url-valid.html spellcheck-url-valid.html
 fails needs-focus == spellcheck-non-latin-arabic.html spellcheck-non-latin-arabic.html
 fails needs-focus == spellcheck-non-latin-chinese-simplified.html spellcheck-non-latin-chinese-simplified.html
 fails needs-focus == spellcheck-non-latin-chinese-traditional.html spellcheck-non-latin-chinese-traditional.html
 fails needs-focus == spellcheck-non-latin-hebrew.html spellcheck-non-latin-hebrew.html
 fails needs-focus == spellcheck-non-latin-japanese.html spellcheck-non-latin-japanese.html
 fails needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean.html
 fails == unneeded_scroll.html unneeded_scroll.html
-# == caret_on_presshell_reinit.html caret_on_presshell_reinit.html
-# == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-2.html
+== caret_on_presshell_reinit.html caret_on_presshell_reinit.html
+== caret_on_presshell_reinit-2.html caret_on_presshell_reinit-2.html
 fails == 642800.html 642800.html
 fails == selection_visibility_after_reframe.html selection_visibility_after_reframe.html
 fails == selection_visibility_after_reframe-2.html selection_visibility_after_reframe-2.html
 fails == selection_visibility_after_reframe-3.html selection_visibility_after_reframe-3.html
 == 672709.html 672709.html
 fails == 338427-1.html 338427-1.html
 fails == 674212-spellcheck.html 674212-spellcheck.html
 fails == 338427-2.html 338427-2.html
@@ -101,38 +101,38 @@ fails == readonly-editable.html readonly
 fails == dynamic-overflow-change.html dynamic-overflow-change.html
 fails == 694880-1.html 694880-1.html
 fails == 694880-2.html 694880-2.html
 fails == 694880-3.html 694880-3.html
 fails == 388980-1.html 388980-1.html
 fails needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1.html
 fails == spellcheck-superscript-2.html spellcheck-superscript-2.html
 == 824080-1.html 824080-1.html
-# == 824080-2.html 824080-2.html
-# == 824080-3.html 824080-3.html
+== 824080-2.html 824080-2.html
+== 824080-3.html 824080-3.html
 # needs-focus == 824080-2.html 824080-2.html
-# == 824080-4.html 824080-4.html
-# == 824080-5.html 824080-5.html
+== 824080-4.html 824080-4.html
+== 824080-5.html 824080-5.html
 # needs-focus == 824080-4.html 824080-4.html
 # needs-focus == 824080-6.html 824080-6.html
 fails needs-focus pref(layout.accessiblecaret.enabled,false) pref(layout.accessiblecaret.enabled_on_touch,false) == 824080-7.html 824080-7.html
 # needs-focus == 824080-6.html 824080-6.html
 # Bug 674927: copy spellcheck-textarea tests to contenteditable
-# == spellcheck-contenteditable-attr.html spellcheck-contenteditable-attr.html
-# == spellcheck-contenteditable-attr.html spellcheck-contenteditable-attr.html
+== spellcheck-contenteditable-attr.html spellcheck-contenteditable-attr.html
+== spellcheck-contenteditable-attr.html spellcheck-contenteditable-attr.html
 # needs-focus == spellcheck-contenteditable-focused.html spellcheck-contenteditable-focused.html
 # needs-focus == spellcheck-contenteditable-focused-reframe.html spellcheck-contenteditable-focused-reframe.html
 == spellcheck-contenteditable-nofocus.html spellcheck-contenteditable-nofocus.html
-# == spellcheck-contenteditable-disabled.html spellcheck-contenteditable-disabled.html
-# == spellcheck-contenteditable-disabled-partial.html spellcheck-contenteditable-disabled-partial.html
-# == spellcheck-contenteditable-attr-inherit.html spellcheck-contenteditable-attr-inherit.html
-# == spellcheck-contenteditable-attr-dynamic.html spellcheck-contenteditable-attr-dynamic.html
-# == spellcheck-contenteditable-attr-dynamic-inherit.html spellcheck-contenteditable-attr-dynamic-inherit.html
+== spellcheck-contenteditable-disabled.html spellcheck-contenteditable-disabled.html
+== spellcheck-contenteditable-disabled-partial.html spellcheck-contenteditable-disabled-partial.html
+== spellcheck-contenteditable-attr-inherit.html spellcheck-contenteditable-attr-inherit.html
+== spellcheck-contenteditable-attr-dynamic.html spellcheck-contenteditable-attr-dynamic.html
+== spellcheck-contenteditable-attr-dynamic-inherit.html spellcheck-contenteditable-attr-dynamic-inherit.html
 == spellcheck-contenteditable-property-dynamic.html spellcheck-contenteditable-property-dynamic.html
-# == spellcheck-contenteditable-property-dynamic-inherit.html spellcheck-contenteditable-property-dynamic-inherit.html
-# == spellcheck-contenteditable-attr-dynamic-override.html spellcheck-contenteditable-attr-dynamic-override.html
+== spellcheck-contenteditable-property-dynamic-inherit.html spellcheck-contenteditable-property-dynamic-inherit.html
+== spellcheck-contenteditable-attr-dynamic-override.html spellcheck-contenteditable-attr-dynamic-override.html
 == spellcheck-contenteditable-attr-dynamic-override-inherit.html spellcheck-contenteditable-attr-dynamic-override-inherit.html
-# == spellcheck-contenteditable-property-dynamic-override.html spellcheck-contenteditable-property-dynamic-override.html
+== spellcheck-contenteditable-property-dynamic-override.html spellcheck-contenteditable-property-dynamic-override.html
 == spellcheck-contenteditable-property-dynamic-override-inherit.html spellcheck-contenteditable-property-dynamic-override-inherit.html
-# == 911201.html 911201.html
+== 911201.html 911201.html
 fails needs-focus == 969773.html 969773.html
 fails == 997805.html 997805.html
 fails == 1088158.html 1088158.html
--- a/gfx/layers/LayerAttributes.h
+++ b/gfx/layers/LayerAttributes.h
@@ -87,21 +87,22 @@ public:
     {
       return false;
     }
     mScrollbarTargetContainerId = aScrollId;
     mScrollbarDirection = aDir;
     mScrollbarThumbRatio = aThumbRatio;
     return true;
   }
-  bool SetIsScrollbarContainer() {
-    if (mIsScrollbarContainer) {
+  bool SetIsScrollbarContainer(FrameMetrics::ViewID aScrollId) {
+    if (mIsScrollbarContainer && mScrollbarTargetContainerId == aScrollId) {
       return false;
     }
     mIsScrollbarContainer = true;
+    mScrollbarTargetContainerId = aScrollId;
     return true;
   }
   bool SetMixBlendMode(gfx::CompositionOp aMixBlendMode) {
     if (mMixBlendMode == aMixBlendMode) {
       return false;
     }
     mMixBlendMode = aMixBlendMode;
     return true;
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1292,19 +1292,21 @@ public:
   {
     if (mSimpleAttrs.SetScrollbarData(aScrollId, aDir, aThumbRatio)) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollbarData", this));
       MutatedSimple();
     }
   }
 
   // Set during construction for the container layer of scrollbar components.
-  void SetIsScrollbarContainer()
+  // |aScrollId| holds the scroll identifier of the scrollable content that
+  // the scrollbar is for.
+  void SetIsScrollbarContainer(FrameMetrics::ViewID aScrollId)
   {
-    if (mSimpleAttrs.SetIsScrollbarContainer()) {
+    if (mSimpleAttrs.SetIsScrollbarContainer(aScrollId)) {
       MutatedSimple();
     }
   }
 
   // Used when forwarding transactions. Do not use at any other time.
   void SetSimpleAttributes(const SimpleLayerAttributes& aAttrs) {
     mSimpleAttrs = aAttrs;
   }
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1788,21 +1788,30 @@ APZCTreeManager::GetAPZCAtPoint(HitTesti
           return TraversalFlag::Abort;
         }
         return TraversalFlag::Continue;
       }
   );
 
   if (*aOutHitResult != HitNothing) {
       MOZ_ASSERT(resultNode);
-      if (aOutHitScrollbar) {
-        for (HitTestingTreeNode* n = resultNode; n; n = n->GetParent()) {
-          if (n->IsScrollbarNode()) {
+      for (HitTestingTreeNode* n = resultNode; n; n = n->GetParent()) {
+        if (n->IsScrollbarNode()) {
+          if (aOutHitScrollbar) {
             *aOutHitScrollbar = true;
           }
+          // If we hit a scrollbar, target the APZC for the content scrolled
+          // by the scrollbar. (The scrollbar itself doesn't scroll with the
+          // scrolled content, so it doesn't carry the scrolled content's
+          // scroll metadata).
+          ScrollableLayerGuid guid(n->GetLayersId(), 0, n->GetScrollTargetId());
+          if (RefPtr<HitTestingTreeNode> scrollTarget = GetTargetNode(guid, &GuidComparatorIgnoringPresShell)) {
+            MOZ_ASSERT(scrollTarget->GetApzc());
+            return scrollTarget->GetApzc();
+          }
         }
       }
 
       AsyncPanZoomController* result = GetTargetApzcForNode(resultNode);
       if (!result) {
         result = FindRootApzcForLayersId(resultNode->GetLayersId());
         MOZ_ASSERT(result);
         APZCTM_LOG("Found target %p using root lookup\n", result);
--- a/gfx/layers/apz/src/HitTestingTreeNode.cpp
+++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp
@@ -123,16 +123,22 @@ HitTestingTreeNode::GetScrollThumbLength
 }
 
 bool
 HitTestingTreeNode::IsScrollbarNode() const
 {
   return mIsScrollbarContainer || (mScrollDir != ScrollDirection::NONE);
 }
 
+FrameMetrics::ViewID
+HitTestingTreeNode::GetScrollTargetId() const
+{
+  return mScrollViewId;
+}
+
 void
 HitTestingTreeNode::SetFixedPosData(FrameMetrics::ViewID aFixedPosTarget)
 {
   mFixedPosTarget = aFixedPosTarget;
 }
 
 FrameMetrics::ViewID
 HitTestingTreeNode::GetFixedPosTarget() const
--- a/gfx/layers/apz/src/HitTestingTreeNode.h
+++ b/gfx/layers/apz/src/HitTestingTreeNode.h
@@ -93,16 +93,17 @@ public:
 
   void SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
                         ScrollDirection aDir,
                         int32_t aScrollThumbLength,
                         bool aIsScrollContainer);
   bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
   LayerIntCoord GetScrollThumbLength() const;
   bool IsScrollbarNode() const;
+  FrameMetrics::ViewID GetScrollTargetId() const;
 
   /* Fixed pos info */
 
   void SetFixedPosData(FrameMetrics::ViewID aFixedPosTarget);
   FrameMetrics::ViewID GetFixedPosTarget() const;
 
   /* Convert aPoint into the LayerPixel space for the layer corresponding to
    * this node. */
@@ -123,19 +124,25 @@ private:
   RefPtr<HitTestingTreeNode> mPrevSibling;
   RefPtr<HitTestingTreeNode> mParent;
 
   RefPtr<AsyncPanZoomController> mApzc;
   bool mIsPrimaryApzcHolder;
 
   uint64_t mLayersId;
 
+  // This is set for both scroll track and scroll thumb Container layers, and
+  // represents the scroll id of the scroll frame scrolled by the scrollbar.
   FrameMetrics::ViewID mScrollViewId;
+
+  // This is set for scroll thumb Container layers only.
   ScrollDirection mScrollDir;
   int32_t mScrollThumbLength;
+
+  // This is set for scroll track Container layers only.
   bool mIsScrollbarContainer;
 
   FrameMetrics::ViewID mFixedPosTarget;
 
   /* Let {L,M} be the {layer, scrollable metrics} pair that this node
    * corresponds to in the layer tree. mEventRegions contains the event regions
    * from L, in the case where event-regions are enabled. If event-regions are
    * disabled, it will contain the visible region of L, which we use as an
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_scroll_over_scrollbar.html
@@ -0,0 +1,42 @@
+<head>
+  <meta name="viewport" content="width=device-width; initial-scale=1.0">
+  <title>Wheel-scrolling over scrollbar</title>
+  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+  <script type="application/javascript">
+
+function* test(testDriver) {
+  var subframe = document.getElementById('scroll');
+
+  // scroll over the scrollbar, and make sure the subframe scrolls
+  var scrollPos = subframe.scrollTop;
+  var scrollbarX = (200 + subframe.clientWidth) / 2;
+  yield moveMouseAndScrollWheelOver(subframe, scrollbarX, 100, testDriver);
+  ok(subframe.scrollTop > scrollPos, "subframe scrolled after wheeling over scrollbar");
+}
+
+waitUntilApzStable()
+.then(runContinuation(test))
+.then(subtestDone);
+
+  </script>
+  <style>
+    #scroll {
+      width: 200px;
+      height: 200px;
+      overflow: scroll;
+    }
+    #scrolled {
+      width: 200px;
+      height: 1000px; /* so the subframe has room to scroll */
+      will-change: transform; /* to force active layers */
+    }
+  </style>
+</head>
+<body>
+  <div id="scroll">
+    <div id="scrolled"></div>
+  </div>
+</body>
+</head>
--- a/gfx/layers/apz/test/mochitest/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest/mochitest.ini
@@ -16,16 +16,17 @@
     helper_drag_scroll.html
     helper_iframe_pan.html
     helper_iframe1.html
     helper_iframe2.html
     helper_long_tap.html
     helper_scroll_inactive_perspective.html
     helper_scroll_inactive_zindex.html
     helper_scroll_on_position_fixed.html
+    helper_scroll_over_scrollbar.html
     helper_scrollto_tap.html
     helper_subframe_style.css
     helper_tall.html
     helper_tap.html
     helper_tap_fullzoom.html
     helper_tap_passive.html
     helper_touch_action.html
     helper_touch_action_regions.html
--- a/gfx/layers/apz/test/mochitest/test_group_wheelevents.html
+++ b/gfx/layers/apz/test/mochitest/test_group_wheelevents.html
@@ -14,21 +14,29 @@ var prefs = [
   ['general.smoothScroll', false],
   // ensure that any mouse movement will trigger a new wheel transaction,
   // because in this test we move the mouse a bunch and want to recalculate
   // the target APZC after each such movement.
   ['mousewheel.transaction.ignoremovedelay', 0],
   ['mousewheel.transaction.timeout', 0]
 ]
 
+// For helper_scroll_over_scrollbar, we need to set a pref to force
+// layerization of the scrollbar track to reproduce the bug being fixed.
+// Otherwise, the bug only manifests with overlay scrollbars on macOS,
+// or in a XUL RCD, both of which are hard to materialize in a test.
+var scrollbar_prefs = prefs.slice();  // make a copy
+scrollbar_prefs.push(["layout.scrollbars.always-layerize-track", true]);
+
 var subtests = [
   {'file': 'helper_scroll_on_position_fixed.html', 'prefs': prefs},
   {'file': 'helper_bug1271432.html', 'prefs': prefs},
   {'file': 'helper_scroll_inactive_perspective.html', 'prefs': prefs},
-  {'file': 'helper_scroll_inactive_zindex.html', 'prefs': prefs}
+  {'file': 'helper_scroll_inactive_zindex.html', 'prefs': prefs},
+  {'file': 'helper_scroll_over_scrollbar.html', 'prefs': scrollbar_prefs}
 ];
 
 if (isApzEnabled()) {
   SimpleTest.waitForExplicitFinish();
   window.onload = function() {
     runSubtestsSeriallyInFreshWindows(subtests)
     .then(SimpleTest.finish);
   };
--- a/gfx/layers/apz/test/reftest/reftest-stylo.list
+++ b/gfx/layers/apz/test/reftest/reftest-stylo.list
@@ -1,20 +1,20 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # The following tests test the async positioning of the scrollbars.
 # Basic root-frame scrollbar with async scrolling
 fuzzy-if(Android,1,2) skip-if(!Android) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v.html
 fuzzy-if(Android,4,5) skip-if(!Android) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h.html
 fuzzy-if(Android,3,5) skip-if(!Android) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh.html
-# == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl.html
-# == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl.html
-# == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl.html
+fuzzy-if(Android,1,2) skip-if(!Android) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl.html
+fuzzy-if(Android,4,5) skip-if(!Android) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl.html
+fuzzy-if(Android,3,7) skip-if(!Android) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl.html
 
 # Different async zoom levels. Since the scrollthumb gets async-scaled in the
 # compositor, the border-radius ends of the scrollthumb are going to be a little
 # off, hence the fuzzy-if clauses.
 fails == async-scrollbar-zoom-1.html async-scrollbar-zoom-1.html
 fails == async-scrollbar-zoom-2.html async-scrollbar-zoom-2.html
 
 # Meta-viewport tag support
-# == initial-scale-1.html initial-scale-1.html
+skip-if(!Android) pref(apz.allow_zooming,true) == initial-scale-1.html initial-scale-1.html
 
 skip-if(!asyncPan) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping.html
--- a/gfx/tests/reftest/reftest-stylo.list
+++ b/gfx/tests/reftest/reftest-stylo.list
@@ -1,10 +1,10 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # 468496-1 will also detect bugs in video drivers.
 == 468496-1.html 468496-1.html
-# == 611498-1.html 611498-1.html
+skip-if(stylo) == 611498-1.html 611498-1.html # Bug 1302946
 fails == 709477-1.html 709477-1.html
 skip-if(!asyncPan) == 1086723.html 1086723.html
 fails == 853889-1.html 853889-1.html
 skip-if(Android) fuzzy-if(skiaContent,1,587) == 1143303-1.svg 1143303-1.svg
 fuzzy(100,30) == 1149923.html 1149923.html
 == 1131264-1.svg 1131264-1.svg
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -557,16 +557,18 @@ private:
   DECL_GFX_PREF(Live, "layout.display-list.dump-content",      LayoutDumpDisplayListContent, bool, false);
   DECL_GFX_PREF(Live, "layout.event-regions.enabled",          LayoutEventRegionsEnabledDoNotUseDirectly, bool, false);
   DECL_GFX_PREF(Once, "layout.frame_rate",                     LayoutFrameRate, int32_t, -1);
   DECL_GFX_PREF(Live, "layout.min-active-layer-size",          LayoutMinActiveLayerSize, int, 64);
   DECL_GFX_PREF(Once, "layout.paint_rects_separately",         LayoutPaintRectsSeparately, bool, true);
 
   // This and code dependent on it should be removed once containerless scrolling looks stable.
   DECL_GFX_PREF(Once, "layout.scroll.root-frame-containers",   LayoutUseContainersForRootFrames, bool, true);
+  // This pref is to be set by test code only.
+  DECL_GFX_PREF(Live, "layout.scrollbars.always-layerize-track", AlwaysLayerizeScrollbarTrackTestOnly, bool, false);
   DECL_GFX_PREF(Live, "layout.smaller-painted-layers",         LayoutSmallerPaintedLayers, bool, false);
 
   DECL_GFX_PREF(Once, "media.hardware-video-decoding.force-enabled",
                                                                HardwareVideoDecodingForceEnabled, bool, false);
 #ifdef XP_WIN
   DECL_GFX_PREF(Live, "media.windows-media-foundation.allow-d3d11-dxva", PDMWMFAllowD3D11, bool, true);
   DECL_GFX_PREF(Live, "media.windows-media-foundation.max-dxva-videos", PDMWMFMaxDXVAVideos, uint32_t, 8);
   DECL_GFX_PREF(Live, "media.wmf.low-latency.enabled", PDMWMFLowLatencyEnabled, bool, false);
--- a/image/test/reftest/bmp/bmpsuite/g/reftest-stylo.list
+++ b/image/test/reftest/bmp/bmpsuite/g/reftest-stylo.list
@@ -72,28 +72,28 @@
 # "A v5 bitmap. Version 5 has additional colorspace options over v4, so it is
 # easier to create, and ought to be more portable."
 == pal8v5.bmp pal8v5.bmp
 
 # BMP: bihsize=40, 127 x 64, bpp=16, compression=0, colors=0
 # "A 16-bit image with the default color format: 5 bits each for red, green, and
 # blue, and 1 unused bit. The whitest colors should (I assume) be displayed as
 # pure white: (255,255,255), not (248,248,248)."
-# == rgb16.bmp rgb16.bmp
+== rgb16.bmp rgb16.bmp
 
 # BMP: bihsize=40, 127 x 64, bpp=16, compression=3, colors=0
 # "A 16-bit image with a BITFIELDS segment indicating 5 red, 6 green, and 5 blue
 # bits. This is a standard 16-bit format, even supported by old versions of
 # Windows that don’t support any other non-default 16-bit formats. The whitest
 # colors should be displayed as pure white: (255,255,255), not (248,252,248)."
-# == rgb16.bmp rgb16.bmp
+== rgb16.bmp rgb16.bmp
 
 # BMP: bihsize=40, 127 x 64, bpp=16, compression=3, colors=256
 # "A 16-bit image with both a BITFIELDS segment and a palette."
-# == rgb16.bmp rgb16.bmp
+== rgb16.bmp rgb16.bmp
 
 # BMP: bihsize=40, 127 x 64, bpp=24, compression=0, colors=0
 # "A perfectly ordinary 24-bit (truecolor) image."
 == rgb24.bmp rgb24.bmp
 
 # BMP: bihsize=40, 127 x 64, bpp=24, compression=0, colors=256
 # "A 24-bit image, with a palette containing 256 colors. There is little if any
 # reason for a truecolor image to contain a palette, but it is legal."
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/AgileReference.cpp
@@ -0,0 +1,152 @@
+/* -*- 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/mscom/AgileReference.h"
+
+#include "DynamicallyLinkedFunctionPtr.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Move.h"
+
+#if NTDDI_VERSION < NTDDI_WINBLUE
+
+// Declarations from Windows SDK specific to Windows 8.1
+
+enum AgileReferenceOptions
+{
+    AGILEREFERENCE_DEFAULT        = 0,
+    AGILEREFERENCE_DELAYEDMARSHAL = 1,
+};
+
+HRESULT WINAPI RoGetAgileReference(AgileReferenceOptions options,
+                                   REFIID riid, IUnknown* pUnk,
+                                   IAgileReference** ppAgileReference);
+
+#endif // NTDDI_VERSION < NTDDI_WINBLUE
+
+namespace mozilla {
+namespace mscom {
+
+AgileReference::AgileReference(REFIID aIid, IUnknown* aObject)
+  : mIid(aIid)
+  , mGitCookie(0)
+{
+  /*
+   * There are two possible techniques for creating agile references. Starting
+   * with Windows 8.1, we may use the RoGetAgileReference API, which is faster.
+   * If that API is not available, we fall back to using the Global Interface
+   * Table.
+   */
+  static const DynamicallyLinkedFunctionPtr<decltype(&::RoGetAgileReference)>
+    pRoGetAgileReference(L"ole32.dll", "RoGetAgileReference");
+
+  MOZ_ASSERT(aObject);
+
+  if (pRoGetAgileReference &&
+      SUCCEEDED(pRoGetAgileReference(AGILEREFERENCE_DEFAULT, aIid, aObject,
+                                     getter_AddRefs(mAgileRef)))) {
+    return;
+  }
+
+  IGlobalInterfaceTable* git = ObtainGit();
+  MOZ_ASSERT(git);
+  if (!git) {
+    return;
+  }
+
+  DebugOnly<HRESULT> hr = git->RegisterInterfaceInGlobal(aObject, aIid,
+                                                         &mGitCookie);
+  MOZ_ASSERT(SUCCEEDED(hr));
+}
+
+AgileReference::AgileReference(AgileReference&& aOther)
+  : mIid(aOther.mIid)
+  , mAgileRef(Move(aOther.mAgileRef))
+  , mGitCookie(aOther.mGitCookie)
+{
+  aOther.mGitCookie = 0;
+}
+
+AgileReference::~AgileReference()
+{
+  if (!mGitCookie) {
+    return;
+  }
+
+  IGlobalInterfaceTable* git = ObtainGit();
+  MOZ_ASSERT(git);
+  if (!git) {
+    return;
+  }
+
+  DebugOnly<HRESULT> hr = git->RevokeInterfaceFromGlobal(mGitCookie);
+  MOZ_ASSERT(SUCCEEDED(hr));
+}
+
+HRESULT
+AgileReference::Resolve(REFIID aIid, void** aOutInterface)
+{
+  MOZ_ASSERT(aOutInterface);
+  MOZ_ASSERT(mAgileRef || mGitCookie);
+
+  if (!aOutInterface) {
+    return E_INVALIDARG;
+  }
+
+  *aOutInterface = nullptr;
+
+  if (mAgileRef) {
+    // IAgileReference lets you directly resolve the interface you want...
+    return mAgileRef->Resolve(aIid, aOutInterface);
+  }
+
+  if (!mGitCookie) {
+    return E_UNEXPECTED;
+  }
+
+  IGlobalInterfaceTable* git = ObtainGit();
+  MOZ_ASSERT(git);
+  if (!git) {
+    return E_UNEXPECTED;
+  }
+
+  RefPtr<IUnknown> originalInterface;
+  HRESULT hr = git->GetInterfaceFromGlobal(mGitCookie, mIid,
+                                           getter_AddRefs(originalInterface));
+  if (FAILED(hr)) {
+    return hr;
+  }
+
+  if (aIid == mIid) {
+    originalInterface.forget(aOutInterface);
+    return S_OK;
+  }
+
+  // ...Whereas the GIT requires us to obtain the same interface that we
+  // requested and then QI for the desired interface afterward.
+  return originalInterface->QueryInterface(aIid, aOutInterface);
+}
+
+IGlobalInterfaceTable*
+AgileReference::ObtainGit()
+{
+  // Internally to COM, the Global Interface Table is a singleton, therefore we
+  // don't worry about holding onto this reference indefinitely.
+  static IGlobalInterfaceTable * const sGit = []() -> IGlobalInterfaceTable * const {
+    IGlobalInterfaceTable* result = nullptr;
+    DebugOnly<HRESULT> hr =
+      ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr,
+                         CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable,
+                         reinterpret_cast<void**>(&result));
+    MOZ_ASSERT(SUCCEEDED(hr));
+    return result;
+  }();
+
+  return sGit;
+}
+
+} // namespace mscom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/AgileReference.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_mscom_AgileReference_h
+#define mozilla_mscom_AgileReference_h
+
+#include "mozilla/RefPtr.h"
+
+#include <objidl.h>
+
+namespace mozilla {
+namespace mscom {
+
+/**
+ * This class encapsulates an "agile reference." These are references that
+ * allow you to pass COM interfaces between apartments. When you have an
+ * interface that you would like to pass between apartments, you wrap that
+ * interface in an AgileReference and pass the agile reference instead. Then
+ * you unwrap the interface by calling AgileReference::Resolve.
+ *
+ * Sample usage:
+ *
+ * // In the multithreaded apartment, foo is an IFoo*
+ * auto myAgileRef = MakeUnique<AgileReference>(IID_IFoo, foo);
+ *
+ * // myAgileRef is passed to our main thread, which runs in a single-threaded
+ * // apartment:
+ *
+ * RefPtr<IFoo> foo;
+ * HRESULT hr = myAgileRef->Resolve(IID_IFoo, getter_AddRefs(foo));
+ * // Now foo may be called from the main thread
+ */
+class AgileReference
+{
+public:
+  AgileReference(REFIID aIid, IUnknown* aObject);
+  AgileReference(AgileReference&& aOther);
+
+  ~AgileReference();
+
+  explicit operator bool() const
+  {
+    return mAgileRef || mGitCookie;
+  }
+
+  HRESULT Resolve(REFIID aIid, void** aOutInterface);
+
+  AgileReference(const AgileReference& aOther) = delete;
+  AgileReference& operator=(const AgileReference& aOther) = delete;
+  AgileReference& operator=(AgileReference&& aOther) = delete;
+
+private:
+  IGlobalInterfaceTable* ObtainGit();
+
+private:
+  REFIID                  mIid;
+  RefPtr<IAgileReference> mAgileRef;
+  DWORD                   mGitCookie;
+};
+
+} // namespace mscom
+} // namespace mozilla
+
+#endif // mozilla_mscom_AgileReference_h
--- a/ipc/mscom/DynamicallyLinkedFunctionPtr.h
+++ b/ipc/mscom/DynamicallyLinkedFunctionPtr.h
@@ -25,33 +25,40 @@ public:
   DynamicallyLinkedFunctionPtr(const wchar_t* aLibName, const char* aFuncName)
     : mModule(NULL)
     , mFunction(nullptr)
   {
     mModule = ::LoadLibraryW(aLibName);
     if (mModule) {
       mFunction = reinterpret_cast<FunctionPtrT>(
                     ::GetProcAddress(mModule, aFuncName));
+
+      if (!mFunction) {
+        // Since the function doesn't exist, there is no point in holding a
+        // reference to mModule anymore.
+        ::FreeLibrary(mModule);
+        mModule = NULL;
+      }
     }
   }
 
   DynamicallyLinkedFunctionPtr(const DynamicallyLinkedFunctionPtr&) = delete;
   DynamicallyLinkedFunctionPtr& operator=(const DynamicallyLinkedFunctionPtr&) = delete;
 
   DynamicallyLinkedFunctionPtr(DynamicallyLinkedFunctionPtr&&) = delete;
   DynamicallyLinkedFunctionPtr& operator=(DynamicallyLinkedFunctionPtr&&) = delete;
 
   ~DynamicallyLinkedFunctionPtr()
   {
     if (mModule) {
       ::FreeLibrary(mModule);
     }
   }
 
-  R operator()(Args... args)
+  R operator()(Args... args) const
   {
     return mFunction(mozilla::Forward<Args>(args)...);
   }
 
   explicit operator bool() const
   {
     return !!mFunction;
   }
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/StructStream.cpp
@@ -0,0 +1,29 @@
+/* -*- 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 <malloc.h>
+#include <rpc.h>
+
+/**
+ * These functions need to be defined in order for the types that use
+ * mozilla::mscom::StructToStream and mozilla::mscom::StructFromStream to work.
+ */
+extern "C" {
+
+void __RPC_FAR* __RPC_USER
+midl_user_allocate(size_t aNumBytes)
+{
+  const unsigned long kRpcReqdBufAlignment = 8;
+  return _aligned_malloc(aNumBytes, kRpcReqdBufAlignment);
+}
+
+void __RPC_USER
+midl_user_free(void* aBuffer)
+{
+  _aligned_free(aBuffer);
+}
+
+} // extern "C"
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/StructStream.h
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_mscom_StructStream_h
+#define mozilla_mscom_StructStream_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/UniquePtr.h"
+#include "nscore.h"
+
+#include <memory.h>
+#include <midles.h>
+#include <objidl.h>
+#include <rpc.h>
+
+/**
+ * This code is used for (de)serializing data structures that have been
+ * declared using midl, thus allowing us to use Microsoft RPC for marshaling
+ * data for our COM handlers that may run in other processes that are not ours.
+ */
+
+namespace mozilla {
+namespace mscom {
+
+namespace detail {
+
+typedef ULONG EncodedLenT;
+
+} // namespace detail
+
+class MOZ_NON_TEMPORARY_CLASS StructToStream
+{
+public:
+  /**
+   * This constructor variant represents an empty/null struct to be serialized.
+   */
+  StructToStream()
+    : mStatus(RPC_S_OK)
+    , mHandle(nullptr)
+    , mBuffer(nullptr)
+    , mEncodedLen(0)
+  {
+  }
+
+  template <typename StructT>
+  StructToStream(StructT& aSrcStruct, void (*aEncodeFnPtr)(handle_t, StructT*))
+    : mStatus(RPC_X_INVALID_BUFFER)
+    , mHandle(nullptr)
+    , mBuffer(nullptr)
+    , mEncodedLen(0)
+  {
+    mStatus = ::MesEncodeDynBufferHandleCreate(&mBuffer, &mEncodedLen,
+                                               &mHandle);
+    if (mStatus != RPC_S_OK) {
+      return;
+    }
+
+    MOZ_SEH_TRY {
+      aEncodeFnPtr(mHandle, &aSrcStruct);
+    } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+      mStatus = ::RpcExceptionCode();
+      return;
+    }
+
+    if (!mBuffer || !mEncodedLen) {
+      mStatus = RPC_X_NO_MEMORY;
+      return;
+    }
+  }
+
+  ~StructToStream()
+  {
+    if (mHandle) {
+      ::MesHandleFree(mHandle);
+    }
+  }
+
+  static unsigned long GetEmptySize()
+  {
+    return sizeof(detail::EncodedLenT);
+  }
+
+  static HRESULT WriteEmpty(IStream* aDestStream)
+  {
+    StructToStream emptyStruct;
+    return emptyStruct.Write(aDestStream);
+  }
+
+  explicit operator bool() const
+  {
+    return mStatus == RPC_S_OK;
+  }
+
+  bool IsEmpty() const
+  {
+    return mStatus == RPC_S_OK && !mEncodedLen;
+  }
+
+  unsigned long GetSize() const
+  {
+    return sizeof(mEncodedLen) + mEncodedLen;
+  }
+
+  HRESULT Write(IStream* aDestStream)
+  {
+    if (!aDestStream) {
+      return E_INVALIDARG;
+    }
+    if (mStatus != RPC_S_OK) {
+      return E_FAIL;
+    }
+
+    ULONG bytesWritten;
+    HRESULT hr = aDestStream->Write(&mEncodedLen, sizeof(mEncodedLen),
+                                    &bytesWritten);
+    if (FAILED(hr)) {
+      return hr;
+    }
+    if (bytesWritten != sizeof(mEncodedLen)) {
+      return E_UNEXPECTED;
+    }
+
+    if (mBuffer && mEncodedLen) {
+      hr = aDestStream->Write(mBuffer, mEncodedLen, &bytesWritten);
+      if (FAILED(hr)) {
+        return hr;
+      }
+      if (bytesWritten != mEncodedLen) {
+        return E_UNEXPECTED;
+      }
+    }
+
+    return hr;
+  }
+
+  StructToStream(const StructToStream&) = delete;
+  StructToStream(StructToStream&&) = delete;
+  StructToStream& operator=(const StructToStream&) = delete;
+  StructToStream& operator=(StructToStream&&) = delete;
+
+private:
+  RPC_STATUS          mStatus;
+  handle_t            mHandle;
+  char*               mBuffer;
+  detail::EncodedLenT mEncodedLen;
+};
+
+class MOZ_NON_TEMPORARY_CLASS StructFromStream
+{
+  struct AlignedFreeDeleter
+  {
+    void operator()(void* aPtr)
+    {
+      ::_aligned_free(aPtr);
+    }
+  };
+
+  static const detail::EncodedLenT kRpcReqdBufAlignment = 8;
+
+public:
+  explicit StructFromStream(IStream* aStream)
+    : mStatus(RPC_X_INVALID_BUFFER)
+    , mHandle(nullptr)
+  {
+    MOZ_ASSERT(aStream);
+
+    // Read the length of the encoded data first
+    detail::EncodedLenT encodedLen = 0;
+    ULONG bytesRead = 0;
+    HRESULT hr = aStream->Read(&encodedLen, sizeof(encodedLen), &bytesRead);
+    if (FAILED(hr)) {
+      return;
+    }
+
+    // NB: Some implementations of IStream return S_FALSE to indicate EOF,
+    // other implementations return S_OK and set the number of bytes read to 0.
+    // We must handle both.
+    if (hr == S_FALSE || !bytesRead) {
+      mStatus = RPC_S_OBJECT_NOT_FOUND;
+      return;
+    }
+
+    if (bytesRead != sizeof(encodedLen)) {
+      return;
+    }
+
+    if (!encodedLen) {
+      mStatus = RPC_S_OBJECT_NOT_FOUND;
+      return;
+    }
+
+    MOZ_ASSERT(encodedLen % kRpcReqdBufAlignment == 0);
+    if (encodedLen % kRpcReqdBufAlignment) {
+      return;
+    }
+
+    // This memory allocation is fallible
+    mEncodedBuffer.reset(static_cast<char*>(
+          ::_aligned_malloc(encodedLen, kRpcReqdBufAlignment)));
+    if (!mEncodedBuffer) {
+      return;
+    }
+
+    ULONG bytesReadFromStream = 0;
+    hr = aStream->Read(mEncodedBuffer.get(), encodedLen, &bytesReadFromStream);
+    if (FAILED(hr) || bytesReadFromStream != encodedLen) {
+      return;
+    }
+
+    mStatus = ::MesDecodeBufferHandleCreate(mEncodedBuffer.get(), encodedLen,
+                                            &mHandle);
+  }
+
+  ~StructFromStream()
+  {
+    if (mHandle) {
+      ::MesHandleFree(mHandle);
+    }
+  }
+
+  explicit operator bool() const
+  {
+    return mStatus == RPC_S_OK || IsEmpty();
+  }
+
+  bool IsEmpty() const { return mStatus == RPC_S_OBJECT_NOT_FOUND; }
+
+  template <typename StructT>
+  bool Read(StructT* aDestStruct, void (*aDecodeFnPtr)(handle_t, StructT*))
+  {
+    if (!aDestStruct || !aDecodeFnPtr || mStatus != RPC_S_OK) {
+      return false;
+    }
+
+    // NB: Deserialization will fail with BSTRs unless the destination data
+    //     is zeroed out!
+    ZeroMemory(aDestStruct, sizeof(StructT));
+
+    MOZ_SEH_TRY {
+      aDecodeFnPtr(mHandle, aDestStruct);
+    } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+      mStatus = ::RpcExceptionCode();
+      return false;
+    }
+
+    return true;
+  }
+
+  StructFromStream(const StructFromStream&) = delete;
+  StructFromStream(StructFromStream&&) = delete;
+  StructFromStream& operator=(const StructFromStream&) = delete;
+  StructFromStream& operator=(StructFromStream&&) = delete;
+
+private:
+  RPC_STATUS                          mStatus;
+  handle_t                            mHandle;
+  UniquePtr<char, AlignedFreeDeleter> mEncodedBuffer;
+};
+
+} // namespace mscom
+} // namespace mozilla
+
+#endif // mozilla_mscom_StructStream_h
--- a/ipc/mscom/moz.build
+++ b/ipc/mscom/moz.build
@@ -1,62 +1,66 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.mscom += [
     'Aggregation.h',
+    'AgileReference.h',
     'AsyncInvoker.h',
     'COMApartmentRegion.h',
     'COMPtrHolder.h',
     'EnsureMTA.h',
     'MainThreadRuntime.h',
     'ProxyStream.h',
     'Ptr.h',
     'Utils.h',
 ]
 
 UNIFIED_SOURCES += [
+    'AgileReference.cpp',
     'EnsureMTA.cpp',
     'MainThreadRuntime.cpp',
     'ProxyStream.cpp',
     'Utils.cpp',
 ]
 
 if CONFIG['ACCESSIBILITY']:
     EXPORTS.mozilla.mscom += [
         'ActivationContext.h',
         'DispatchForwarder.h',
         'Interceptor.h',
         'InterceptorLog.h',
         'MainThreadHandoff.h',
         'MainThreadInvoker.h',
         'Registration.h',
+        'StructStream.h',
         'WeakRef.h',
     ]
 
     SOURCES += [
         'Interceptor.cpp',
         'Registration.cpp',
         'WeakRef.cpp',
     ]
 
     UNIFIED_SOURCES += [
         'ActivationContext.cpp',
         'DispatchForwarder.cpp',
         'InterceptorLog.cpp',
         'MainThreadHandoff.cpp',
         'MainThreadInvoker.cpp',
+        'StructStream.cpp',
     ]
 
 LOCAL_INCLUDES += [
     '/xpcom/base',
     '/xpcom/build',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
-with Files("**"):
-    BUG_COMPONENT = ("Core", "Disability Access APIs")
+with Files("**"):
+    BUG_COMPONENT = ("Core", "Disability Access APIs")
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -9212,17 +9212,17 @@ PresShell::DoReflow(nsIFrame* target, bo
                "non-root frame's desired size changed during an "
                "incremental reflow");
   NS_ASSERTION(target == rootFrame ||
                desiredSize.VisualOverflow().IsEqualInterior(boundsRelativeToTarget),
                "non-root reflow roots must not have visible overflow");
   NS_ASSERTION(target == rootFrame ||
                desiredSize.ScrollableOverflow().IsEqualEdges(boundsRelativeToTarget),
                "non-root reflow roots must not have scrollable overflow");
-  NS_ASSERTION(status == NS_FRAME_COMPLETE,
+  NS_ASSERTION(status.IsEmpty(),
                "reflow roots should never split");
 
   target->SetSize(boundsRelativeToTarget.Size());
 
   // Always use boundsRelativeToTarget here, not desiredSize.GetVisualOverflowArea(),
   // because for root frames (where they could be different, since root frames
   // are allowed to have overflow) the root view bounds need to match the
   // viewport bounds; the view manager "window dimensions" code depends on it.
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -892,21 +892,21 @@ nsComboboxControlFrame::Reflow(nsPresCon
   buttonRect.ISize(wm) = buttonISize;
 
   buttonRect.BStart(wm) = this->GetLogicalUsedBorder(wm).BStart(wm);
   buttonRect.BSize(wm) = mDisplayFrame->BSize(wm) +
                          this->GetLogicalUsedPadding(wm).BStartEnd(wm);
 
   mButtonFrame->SetRect(buttonRect, containerSize);
 
-  if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) &&
-      !NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
+  if (!aStatus.IsInlineBreakBefore() &&
+      !aStatus.IsFullyComplete()) {
     // This frame didn't fit inside a fragmentation container.  Splitting
     // a nsComboboxControlFrame makes no sense, so we override the status here.
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
   }
 }
 
 //--------------------------------------------------------------
 
 nsIAtom*
 nsComboboxControlFrame::GetType() const
 {
@@ -1323,17 +1323,17 @@ nsComboboxDisplayFrame::Reflow(nsPresCon
   WritingMode wm = aReflowInput.GetWritingMode();
   nscoord computedISize = mComboBox->mDisplayISize -
     state.ComputedLogicalBorderPadding().IStartEnd(wm);
   if (computedISize < 0) {
     computedISize = 0;
   }
   state.SetComputedISize(computedISize);
   nsBlockFrame::Reflow(aPresContext, aDesiredSize, state, aStatus);
-  aStatus = NS_FRAME_COMPLETE; // this type of frame can't be split
+  aStatus.Reset(); // this type of frame can't be split
 }
 
 void
 nsComboboxDisplayFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                          const nsRect&           aDirtyRect,
                                          const nsDisplayListSet& aLists)
 {
   nsDisplayListCollection set;
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -230,17 +230,17 @@ nsDateTimeControlFrame::Reflow(nsPresCon
 
     nsReflowStatus childStatus;
     // We initially reflow the child with a dummy containerSize; positioning
     // will be fixed later.
     const nsSize dummyContainerSize;
     ReflowChild(inputAreaFrame, aPresContext, childDesiredSize,
                 childReflowOuput, myWM, childOffset, dummyContainerSize, 0,
                 childStatus);
-    MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus),
+    MOZ_ASSERT(childStatus.IsFullyComplete(),
                "We gave our child unconstrained available block-size, "
                "so it should be complete");
 
     nscoord childMarginBoxBSize =
       childDesiredSize.BSize(myWM) + childMargin.BStartEnd(myWM);
 
     if (contentBoxBSize == NS_INTRINSICSIZE) {
       // We are intrinsically sized -- we should shrinkwrap the input area's
@@ -288,17 +288,17 @@ nsDateTimeControlFrame::Reflow(nsPresCon
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   if (inputAreaFrame) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inputAreaFrame);
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("exit nsDateTimeControlFrame::Reflow: size=%d,%d",
                   aDesiredSize.Width(), aDesiredSize.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 nsresult
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -334,20 +334,20 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
 
   NS_PRECONDITION(aReflowInput.ComputedISize() != NS_INTRINSICSIZE,
                   "Should have a precomputed inline-size!");
 
   // Initialize OUT parameter
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   nsOverflowAreas ocBounds;
-  nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus ocStatus;
   if (GetPrevInFlow()) {
     ReflowOverflowContainerChildren(aPresContext, aReflowInput, ocBounds, 0,
                                     ocStatus);
   }
 
   //------------ Handle Incremental Reflow -----------------
   bool reflowInner;
   bool reflowLegend;
@@ -569,17 +569,17 @@ nsFieldSetFrame::Reflow(nsPresContext*  
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
   }
   if (inner) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner);
   }
 
   // Merge overflow container bounds and status.
   aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
-  NS_MergeReflowStatusInto(&aStatus, ocStatus);
+  aStatus.MergeCompletionStatusFrom(ocStatus);
 
   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, aStatus);
 
   InvalidateFrame();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -126,17 +126,17 @@ nsFormControlFrame::Reflow(nsPresContext
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("enter nsFormControlFrame::Reflow: aMaxSize=%d,%d",
                   aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
 
   if (mState & NS_FRAME_FIRST_REFLOW) {
     RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
   }
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
                        aReflowInput.ComputedSizeWithBorderPadding());
 
   if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
     float inflation = nsLayoutUtils::FontSizeInflationFor(this);
     aDesiredSize.Width() *= inflation;
     aDesiredSize.Height() *= inflation;
   }
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -209,23 +209,23 @@ nsHTMLButtonControlFrame::Reflow(nsPresC
                        aReflowInput, firstKid);
 
   if (!ShouldClipPaintingToBorderBox()) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, firstKid);
   }
   // else, we ignore child overflow -- anything that overflows beyond our
   // own border-box will get clipped when painting.
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize,
                                  aReflowInput, aStatus);
 
   // We're always complete and we don't support overflow containers
   // so we shouldn't have a next-in-flow ever.
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   MOZ_ASSERT(!GetNextInFlow());
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
                                                ReflowOutput& aButtonDesiredSize,
@@ -252,17 +252,17 @@ nsHTMLButtonControlFrame::ReflowButtonCo
                       // child to determine its size.
 
   // We just pass a dummy containerSize here, as the child will be
   // repositioned later by FinishReflowChild.
   nsSize dummyContainerSize;
   ReflowChild(aFirstKid, aPresContext,
               contentsDesiredSize, contentsReflowInput,
               wm, childPos, dummyContainerSize, 0, contentsReflowStatus);
-  MOZ_ASSERT(NS_FRAME_IS_COMPLETE(contentsReflowStatus),
+  MOZ_ASSERT(contentsReflowStatus.IsComplete(),
              "We gave button-contents frame unconstrained available height, "
              "so it should be complete");
 
   // Compute the button's content-box size:
   LogicalSize buttonContentBox(wm);
   if (aButtonReflowInput.ComputedBSize() != NS_INTRINSICSIZE) {
     // Button has a fixed block-size -- that's its content-box bSize.
     buttonContentBox.BSize(wm) = aButtonReflowInput.ComputedBSize();
--- a/layout/forms/nsMeterFrame.cpp
+++ b/layout/forms/nsMeterFrame.cpp
@@ -123,17 +123,17 @@ nsMeterFrame::Reflow(nsPresContext*     
 
   aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
                        aReflowInput.ComputedSizeWithBorderPadding());
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
   FinishAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsMeterFrame::ReflowBarFrame(nsIFrame*                aBarFrame,
                              nsPresContext*           aPresContext,
                              const ReflowInput& aReflowInput,
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -178,17 +178,17 @@ nsNumberControlFrame::Reflow(nsPresConte
 
     nsReflowStatus childStatus;
     // We initially reflow the child with a dummy containerSize; positioning
     // will be fixed later.
     const nsSize dummyContainerSize;
     ReflowChild(outerWrapperFrame, aPresContext, wrappersDesiredSize,
                 wrapperReflowInput, myWM, wrapperOffset, dummyContainerSize, 0,
                 childStatus);
-    MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(childStatus),
+    MOZ_ASSERT(childStatus.IsFullyComplete(),
                "We gave our child unconstrained available block-size, "
                "so it should be complete");
 
     nscoord wrappersMarginBoxBSize =
       wrappersDesiredSize.BSize(myWM) + wrapperMargin.BStartEnd(myWM);
 
     if (contentBoxBSize == NS_INTRINSICSIZE) {
       // We are intrinsically sized -- we should shrinkwrap the outer wrapper's
@@ -237,17 +237,17 @@ nsNumberControlFrame::Reflow(nsPresConte
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   if (outerWrapperFrame) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, outerWrapperFrame);
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsNumberControlFrame::SyncDisabledState()
 {
   EventStates eventStates = mContent->AsElement()->State();
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -132,17 +132,17 @@ nsProgressFrame::Reflow(nsPresContext*  
 
   for (auto childFrame : PrincipalChildList()) {
     ReflowChildFrame(childFrame, aPresContext, aReflowInput, aStatus);
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, childFrame);
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsProgressFrame::ReflowChildFrame(nsIFrame*          aChild,
                                   nsPresContext*     aPresContext,
                                   const ReflowInput& aReflowInput,
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -358,17 +358,17 @@ nsRangeFrame::Reflow(nsPresContext*     
 
   nsIFrame* thumbFrame = mThumbDiv->GetPrimaryFrame();
   if (thumbFrame) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, thumbFrame);
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsRangeFrame::ReflowAnonymousContent(nsPresContext*           aPresContext,
                                      ReflowOutput&     aDesiredSize,
                                      const ReflowInput& aReflowInput)
@@ -413,17 +413,17 @@ nsRangeFrame::ReflowAnonymousContent(nsP
     // Make relative to our border box instead of our content box:
     trackX += aReflowInput.ComputedPhysicalBorderPadding().left;
     trackY += aReflowInput.ComputedPhysicalBorderPadding().top;
 
     nsReflowStatus frameStatus;
     ReflowOutput trackDesiredSize(aReflowInput);
     ReflowChild(trackFrame, aPresContext, trackDesiredSize,
                 trackReflowInput, trackX, trackY, 0, frameStatus);
-    MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus),
+    MOZ_ASSERT(frameStatus.IsFullyComplete(),
                "We gave our child unconstrained height, so it should be complete");
     FinishReflowChild(trackFrame, aPresContext, trackDesiredSize,
                       &trackReflowInput, trackX, trackY, 0);
   }
 
   nsIFrame* thumbFrame = mThumbDiv->GetPrimaryFrame();
 
   if (thumbFrame) { // display:none?
@@ -435,17 +435,17 @@ nsRangeFrame::ReflowAnonymousContent(nsP
 
     // Where we position the thumb depends on its size, so we first reflow
     // the thumb at {0,0} to obtain its size, then position it afterwards.
 
     nsReflowStatus frameStatus;
     ReflowOutput thumbDesiredSize(aReflowInput);
     ReflowChild(thumbFrame, aPresContext, thumbDesiredSize,
                 thumbReflowInput, 0, 0, 0, frameStatus);
-    MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus),
+    MOZ_ASSERT(frameStatus.IsFullyComplete(),
                "We gave our child unconstrained height, so it should be complete");
     FinishReflowChild(thumbFrame, aPresContext, thumbDesiredSize,
                       &thumbReflowInput, 0, 0, 0);
     DoUpdateThumbPosition(thumbFrame, nsSize(aDesiredSize.Width(),
                                              aDesiredSize.Height()));
   }
 
   nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
@@ -461,17 +461,17 @@ nsRangeFrame::ReflowAnonymousContent(nsP
     // unadjusted dimensions, then we adjust it to so that the appropriate edge
     // ends at the thumb.
 
     nsReflowStatus frameStatus;
     ReflowOutput progressDesiredSize(aReflowInput);
     ReflowChild(rangeProgressFrame, aPresContext,
                 progressDesiredSize, progressReflowInput, 0, 0,
                 0, frameStatus);
-    MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus),
+    MOZ_ASSERT(frameStatus.IsFullyComplete(),
                "We gave our child unconstrained height, so it should be complete");
     FinishReflowChild(rangeProgressFrame, aPresContext,
                       progressDesiredSize, &progressReflowInput, 0, 0, 0);
     DoUpdateRangeProgressFrame(rangeProgressFrame, nsSize(aDesiredSize.Width(),
                                                           aDesiredSize.Height()));
   }
 }
 
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -536,17 +536,17 @@ nsTextControlFrame::Reflow(nsPresContext
   while (kid) {
     ReflowTextControlChild(kid, aPresContext, aReflowInput, aStatus, aDesiredSize);
     kid = kid->GetNextSibling();
   }
 
   // take into account css properties that affect overflow handling
   FinishAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsTextControlFrame::ReflowTextControlChild(nsIFrame*                aKid,
                                            nsPresContext*           aPresContext,
                                            const ReflowInput& aReflowInput,
                                            nsReflowStatus&          aStatus,
--- a/layout/generic/BRFrame.cpp
+++ b/layout/generic/BRFrame.cpp
@@ -149,22 +149,22 @@ BRFrame::Reflow(nsPresContext* aPresCont
     }
 
     // Return our reflow status
     StyleClear breakType = aReflowInput.mStyleDisplay->PhysicalBreakType(wm);
     if (StyleClear::None == breakType) {
       breakType = StyleClear::Line;
     }
 
-    aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
-      NS_INLINE_MAKE_BREAK_TYPE(breakType);
+    aStatus.Reset();
+    aStatus.SetInlineLineBreakAfter(breakType);
     ll->SetLineEndsInBR(true);
   }
   else {
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
   }
 
   aMetrics.SetSize(wm, finalSize);
   aMetrics.SetOverflowAreasToDesiredBounds();
 
   mAscent = aMetrics.BlockStartAscent();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
--- a/layout/generic/BlockReflowInput.cpp
+++ b/layout/generic/BlockReflowInput.cpp
@@ -99,17 +99,17 @@ BlockReflowInput::BlockReflowInput(const
 
   MOZ_ASSERT(FloatManager(),
              "Float manager should be valid when creating BlockReflowInput!");
 
   // Save the coordinate system origin for later.
   FloatManager()->GetTranslation(mFloatManagerI, mFloatManagerB);
   FloatManager()->PushState(&mFloatManagerStateBefore); // never popped
 
-  mReflowStatus = NS_FRAME_COMPLETE;
+  mReflowStatus.Reset();
 
   mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
 
   LAYOUT_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowInput.ComputedISize(),
                        "have unconstrained width; this should only result "
                        "from very large sizes, not attempts at intrinsic "
                        "width calculation");
   mContentArea.ISize(wm) = aReflowInput.ComputedISize();
@@ -770,17 +770,17 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
   // orthogonal writing mode and 'auto' block-size (in its mode).
   bool earlyFloatReflow =
     aFloat->GetType() == nsGkAtoms::letterFrame ||
     floatMarginISize == NS_UNCONSTRAINEDSIZE;
   if (earlyFloatReflow) {
     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin,
                         floatOffsets, false, reflowStatus);
     floatMarginISize = aFloat->ISize(wm) + floatMargin.IStartEnd(wm);
-    NS_ASSERTION(NS_FRAME_IS_COMPLETE(reflowStatus),
+    NS_ASSERTION(reflowStatus.IsComplete(),
                  "letter frames and orthogonal floats with auto block-size "
                  "shouldn't break, and if they do now, then they're breaking "
                  "at the wrong point");
   }
 
   // Find a place to place the float. The CSS2 spec doesn't want
   // floats overlapping each other or sticking out of the containing
   // block if possible (CSS2 spec section 9.5.1, see the rule list).
@@ -907,46 +907,46 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
   // where to break.
   if (!earlyFloatReflow) {
     bool pushedDown = mBCoord != restoreBCoord.SavedValue();
     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin,
                         floatOffsets, pushedDown, reflowStatus);
   }
   if (aFloat->GetPrevInFlow())
     floatMargin.BStart(wm) = 0;
-  if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus))
+  if (reflowStatus.IsIncomplete())
     floatMargin.BEnd(wm) = 0;
 
   // In the case that we're in columns and not splitting floats, we need
   // to check here that the float's height fit, and if it didn't, bail.
   // (controlled by the pref "layout.float-fragments-inside-column.enabled")
   //
   // Likewise, if none of the float fit, and it needs to be pushed in
-  // its entirety to the next page (NS_FRAME_IS_TRUNCATED or
-  // NS_INLINE_IS_BREAK_BEFORE), we need to do the same.
+  // its entirety to the next page (IsTruncated() or IsInlineBreakBefore()),
+  // we need to do the same.
   if ((ContentBSize() != NS_UNCONSTRAINEDSIZE &&
        !mFlags.mFloatFragmentsInsideColumnEnabled &&
        adjustedAvailableSpace.BSize(wm) == NS_UNCONSTRAINEDSIZE &&
        !mustPlaceFloat &&
        aFloat->BSize(wm) + floatMargin.BStartEnd(wm) >
        ContentBEnd() - floatPos.B(wm)) ||
-      NS_FRAME_IS_TRUNCATED(reflowStatus) ||
-      NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
+      reflowStatus.IsTruncated() ||
+      reflowStatus.IsInlineBreakBefore()) {
     PushFloatPastBreak(aFloat);
     return false;
   }
 
   // We can't use aFloat->ShouldAvoidBreakInside(mReflowInput) here since
   // its mIsTopOfPage may be true even though the float isn't at the
   // top when floatPos.B(wm) > 0.
   if (ContentBSize() != NS_UNCONSTRAINEDSIZE &&
       !mustPlaceFloat &&
       (!mReflowInput.mFlags.mIsTopOfPage || floatPos.B(wm) > 0) &&
       NS_STYLE_PAGE_BREAK_AVOID == aFloat->StyleDisplay()->mBreakInside &&
-      (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus) ||
+      (!reflowStatus.IsFullyComplete() ||
        aFloat->BSize(wm) + floatMargin.BStartEnd(wm) >
        ContentBEnd() - floatPos.B(wm)) &&
       !aFloat->GetPrevInFlow()) {
     PushFloatPastBreak(aFloat);
     return false;
   }
 
   // Calculate the actual origin of the float frame's border rect
@@ -975,17 +975,17 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
                                 aFloat->GetPosition());
 
   // Place the float in the float manager
   // calculate region
   LogicalRect region =
     nsFloatManager::CalculateRegionFor(wm, aFloat, floatMargin,
                                        ContainerSize());
   // if the float split, then take up all of the vertical height
-  if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
+  if (reflowStatus.IsIncomplete() &&
       (NS_UNCONSTRAINEDSIZE != ContentBSize())) {
     region.BSize(wm) = std::max(region.BSize(wm),
                                 ContentBSize() - floatPos.B(wm));
   }
   FloatManager()->AddFloat(aFloat, region, wm, ContainerSize());
 
   // store region
   nsFloatManager::StoreRegionFor(wm, aFloat, region, ContainerSize());
@@ -997,17 +997,17 @@ BlockReflowInput::FlowAndPlaceFloat(nsIF
     // less damage; e.g., if only height has changed, then only note the
     // area into which the float has grown or from which the float has
     // shrunk.
     nscoord blockStart = std::min(region.BStart(wm), oldRegion.BStart(wm));
     nscoord blockEnd = std::max(region.BEnd(wm), oldRegion.BEnd(wm));
     FloatManager()->IncludeInDamage(blockStart, blockEnd);
   }
 
-  if (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus)) {
+  if (!reflowStatus.IsFullyComplete()) {
     mBlock->SplitFloat(*this, aFloat, reflowStatus);
   } else {
     MOZ_ASSERT(!aFloat->GetNextInFlow());
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyFloatManager) {
     nscoord tI, tB;
@@ -1048,17 +1048,17 @@ BlockReflowInput::PushFloatPastBreak(nsI
     FloatManager()->SetPushedRightFloatPastBreak();
   }
 
   // Put the float on the pushed floats list, even though it
   // isn't actually a continuation.
   DebugOnly<nsresult> rv = mBlock->StealFrame(aFloat);
   NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame should succeed");
   AppendPushedFloatChain(aFloat);
-  NS_FRAME_SET_OVERFLOW_INCOMPLETE(mReflowStatus);
+  mReflowStatus.SetOverflowIncomplete();
 }
 
 /**
  * Place below-current-line floats.
  */
 void
 BlockReflowInput::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList,
                                                 nsLineBox* aLine)
--- a/layout/generic/ReflowInput.cpp
+++ b/layout/generic/ReflowInput.cpp
@@ -3036,34 +3036,16 @@ ReflowInput::ComputeMinMaxValues(const L
 
   // If the computed value of 'min-height' is greater than the value of
   // 'max-height', 'max-height' is set to the value of 'min-height'
   if (ComputedMinBSize() > ComputedMaxBSize()) {
     ComputedMaxBSize() = ComputedMinBSize();
   }
 }
 
-void
-ReflowInput::SetTruncated(const ReflowOutput& aMetrics,
-                                nsReflowStatus* aStatus) const
-{
-  const WritingMode containerWM = aMetrics.GetWritingMode();
-  if (GetWritingMode().IsOrthogonalTo(containerWM)) {
-    // Orthogonal flows are always reflowed with an unconstrained dimension,
-    // so should never end up truncated (see ReflowInput::Init()).
-    *aStatus &= ~NS_FRAME_TRUNCATED;
-  } else if (AvailableBSize() != NS_UNCONSTRAINEDSIZE &&
-             AvailableBSize() < aMetrics.BSize(containerWM) &&
-             !mFlags.mIsTopOfPage) {
-    *aStatus |= NS_FRAME_TRUNCATED;
-  } else {
-    *aStatus &= ~NS_FRAME_TRUNCATED;
-  }
-}
-
 bool
 ReflowInput::IsFloating() const
 {
   return mStyleDisplay->IsFloating(mFrame);
 }
 
 mozilla::StyleDisplay
 ReflowInput::GetDisplay() const
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -285,17 +285,17 @@ ViewportFrame::Reflow(nsPresContext*    
                       nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("ViewportFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
   NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow");
 
   // Initialize OUT parameters
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   // Because |Reflow| sets ComputedBSize() on the child to our
   // ComputedBSize().
   AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
 
   // Set our size up front, since some parts of reflow depend on it
   // being already set.  Note that the computed height may be
   // unconstrained; that's ok.  Consumers should watch out for that.
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -114,49 +114,49 @@ void
 nsAbsoluteContainingBlock::Reflow(nsContainerFrame*        aDelegatingFrame,
                                   nsPresContext*           aPresContext,
                                   const ReflowInput& aReflowInput,
                                   nsReflowStatus&          aReflowStatus,
                                   const nsRect&            aContainingBlock,
                                   AbsPosReflowFlags        aFlags,
                                   nsOverflowAreas*         aOverflowAreas)
 {
-  nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus reflowStatus;
 
   const bool reflowAll = aReflowInput.ShouldReflowAllKids();
   const bool isGrid = !!(aFlags & AbsPosReflowFlags::eIsGridContainerCB);
   nsIFrame* kidFrame;
   nsOverflowContinuationTracker tracker(aDelegatingFrame, true);
   for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
     bool kidNeedsReflow = reflowAll || NS_SUBTREE_DIRTY(kidFrame) ||
       FrameDependsOnContainer(kidFrame,
                               !!(aFlags & AbsPosReflowFlags::eCBWidthChanged),
                               !!(aFlags & AbsPosReflowFlags::eCBHeightChanged));
     if (kidNeedsReflow && !aPresContext->HasPendingInterrupt()) {
       // Reflow the frame
-      nsReflowStatus  kidStatus = NS_FRAME_COMPLETE;
+      nsReflowStatus kidStatus;
       const nsRect& cb = isGrid ? nsGridContainerFrame::GridItemCB(kidFrame)
                                 : aContainingBlock;
       ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowInput, cb,
                           aFlags, kidFrame, kidStatus, aOverflowAreas);
       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
-      if (!NS_FRAME_IS_FULLY_COMPLETE(kidStatus) &&
+      if (!kidStatus.IsFullyComplete() &&
           aDelegatingFrame->IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
         // Need a continuation
         if (!nextFrame) {
           nextFrame =
             aPresContext->PresShell()->FrameConstructor()->
               CreateContinuingFrame(aPresContext, kidFrame, aDelegatingFrame);
         }
         // Add it as an overflow container.
         //XXXfr This is a hack to fix some of our printing dataloss.
         // See bug 154892. Not sure how to do it "right" yet; probably want
         // to keep continuations within an nsAbsoluteContainingBlock eventually.
         tracker.Insert(nextFrame, kidStatus);
-        NS_MergeReflowStatusInto(&reflowStatus, kidStatus);
+        reflowStatus.MergeCompletionStatusFrom(kidStatus);
       }
       else {
         // Delete any continuations
         if (nextFrame) {
           nsOverflowContinuationTracker::AutoFinish fini(&tracker, kidFrame);
           nextFrame->GetParent()->DeleteNextInFlowChild(nextFrame, true);
         }
       }
@@ -186,20 +186,20 @@ nsAbsoluteContainingBlock::Reflow(nsCont
       } else {
         kidFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
       }
     }
   }
 
   // Abspos frames can't cause their parent to be incomplete,
   // only overflow incomplete.
-  if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus))
-    NS_FRAME_SET_OVERFLOW_INCOMPLETE(reflowStatus);
+  if (reflowStatus.IsIncomplete())
+    reflowStatus.SetOverflowIncomplete();
 
-  NS_MergeReflowStatusInto(&aReflowStatus, reflowStatus);
+  aReflowStatus.MergeCompletionStatusFrom(reflowStatus);
 }
 
 static inline bool IsFixedPaddingSize(const nsStyleCoord& aCoord)
   { return aCoord.ConvertsToLength(); }
 static inline bool IsFixedMarginSize(const nsStyleCoord& aCoord)
   { return aCoord.ConvertsToLength(); }
 static inline bool IsFixedOffset(const nsStyleCoord& aCoord)
   { return aCoord.ConvertsToLength(); }
--- a/layout/generic/nsBackdropFrame.cpp
+++ b/layout/generic/nsBackdropFrame.cpp
@@ -87,10 +87,10 @@ nsBackdropFrame::Reflow(nsPresContext* a
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
 
   // Note that this frame is a child of the viewport frame.
   WritingMode wm = aReflowInput.GetWritingMode();
   LogicalMargin borderPadding = aReflowInput.ComputedLogicalBorderPadding();
   nscoord isize = aReflowInput.ComputedISize() + borderPadding.IStartEnd(wm);
   nscoord bsize = aReflowInput.ComputedBSize() + borderPadding.BStartEnd(wm);
   aDesiredSize.SetSize(wm, LogicalSize(wm, isize, bsize));
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 }
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -254,28 +254,28 @@ RecordReflowStatus(bool aChildIsBlock, n
 
   // 0: child-is-block
   // 1: child-is-inline
   int index = 0;
   if (!aChildIsBlock) index |= 1;
 
   // Compute new status
   uint32_t newS = record[index];
-  if (NS_INLINE_IS_BREAK(aFrameReflowStatus)) {
-    if (NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
+  if (aFrameReflowStatus.IsInlineBreak()) {
+    if (aFrameReflowStatus.IsInlineBreakBefore()) {
       newS |= 1;
     }
-    else if (NS_FRAME_IS_NOT_COMPLETE(aFrameReflowStatus)) {
+    else if (aFrameReflowStatus.IsIncomplete()) {
       newS |= 2;
     }
     else {
       newS |= 4;
     }
   }
-  else if (NS_FRAME_IS_NOT_COMPLETE(aFrameReflowStatus)) {
+  else if (aFrameReflowStatus.IsIncomplete()) {
     newS |= 8;
   }
   else {
     newS |= 16;
   }
 
   // Log updates to the status that yield different values
   if (record[index] != newS) {
@@ -1190,31 +1190,31 @@ nsBlockFrame::Reflow(nsPresContext*     
     static_cast<nsBlockFrame*>(FirstContinuation())->ResolveBidi();
 
   if (RenumberList()) {
     AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
   }
 
   // Handle paginated overflow (see nsContainerFrame.h)
   nsOverflowAreas ocBounds;
-  nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus ocStatus;
   if (GetPrevInFlow()) {
     ReflowOverflowContainerChildren(aPresContext, *reflowInput, ocBounds, 0,
                                     ocStatus);
   }
 
   // Now that we're done cleaning up our overflow container lists, we can
   // give |state| its nsOverflowContinuationTracker.
   nsOverflowContinuationTracker tracker(this, false);
   state.mOverflowTracker = &tracker;
 
   // Drain & handle pushed floats
   DrainPushedFloats();
   nsOverflowAreas fcBounds;
-  nsReflowStatus fcStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus fcStatus;
   ReflowPushedFloats(state, fcBounds, fcStatus);
 
   // If we're not dirty (which means we'll mark everything dirty later)
   // and our inline-size has changed, mark the lines dirty that we need to
   // mark dirty for a resize reflow.
   if (!(GetStateBits() & NS_FRAME_IS_DIRTY) && reflowInput->IsIResize()) {
     PrepareResizeReflow(state);
   }
@@ -1233,53 +1233,55 @@ nsBlockFrame::Reflow(nsPresContext*     
 
   mState &= ~NS_FRAME_FIRST_REFLOW;
 
   // Now reflow...
   ReflowDirtyLines(state);
 
   // If we have a next-in-flow, and that next-in-flow has pushed floats from
   // this frame from a previous iteration of reflow, then we should not return
-  // a status of NS_FRAME_IS_FULLY_COMPLETE, since we actually have overflow,
-  // it's just already been handled.
+  // a status with IsFullyComplete() equals to true, since we actually have
+  // overflow, it's just already been handled.
 
   // NOTE: This really shouldn't happen, since we _should_ pull back our floats
   // and reflow them, but just in case it does, this is a safety precaution so
   // we don't end up with a placeholder pointing to frames that have already
   // been deleted as part of removing our next-in-flow.
   // XXXmats maybe this code isn't needed anymore?
   // XXXmats (layout/generic/crashtests/600100.xhtml doesn't crash without it)
-  if (NS_FRAME_IS_FULLY_COMPLETE(state.mReflowStatus)) {
+  if (state.mReflowStatus.IsFullyComplete()) {
     nsBlockFrame* nif = static_cast<nsBlockFrame*>(GetNextInFlow());
     while (nif) {
       if (nif->HasPushedFloatsFromPrevContinuation()) {
-        bool oc = nif->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER;
-        NS_MergeReflowStatusInto(&state.mReflowStatus,
-            oc ? NS_FRAME_OVERFLOW_INCOMPLETE : NS_FRAME_NOT_COMPLETE);
+        if (nif->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
+          state.mReflowStatus.SetOverflowIncomplete();
+        } else {
+          state.mReflowStatus.SetIncomplete();
+        }
         break;
       }
 
       nif = static_cast<nsBlockFrame*>(nif->GetNextInFlow());
     }
   }
 
-  NS_MergeReflowStatusInto(&state.mReflowStatus, ocStatus);
-  NS_MergeReflowStatusInto(&state.mReflowStatus, fcStatus);
+  state.mReflowStatus.MergeCompletionStatusFrom(ocStatus);
+  state.mReflowStatus.MergeCompletionStatusFrom(fcStatus);
 
   // If we end in a BR with clear and affected floats continue,
   // we need to continue, too.
   if (NS_UNCONSTRAINEDSIZE != reflowInput->AvailableBSize() &&
-      NS_FRAME_IS_COMPLETE(state.mReflowStatus) &&
+      state.mReflowStatus.IsComplete() &&
       state.FloatManager()->ClearContinues(FindTrailingClear())) {
-    NS_FRAME_SET_INCOMPLETE(state.mReflowStatus);
-  }
-
-  if (!NS_FRAME_IS_FULLY_COMPLETE(state.mReflowStatus)) {
+    state.mReflowStatus.SetIncomplete();
+  }
+
+  if (!state.mReflowStatus.IsFullyComplete()) {
     if (HasOverflowLines() || HasPushedFloats()) {
-      state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+      state.mReflowStatus.SetNextInFlowNeedsReflow();
     }
 
 #ifdef DEBUG_kipp
     ListTag(stdout); printf(": block is not fully complete\n");
 #endif
   }
 
   // Place the "marker" (bullet) frame if it is placed next to a block
@@ -1466,18 +1468,18 @@ nsBlockFrame::Reflow(nsPresContext*     
   // our floats list, since a first-in-flow might get pushed to a later
   // continuation of its containing block.  But it's not permitted
   // outside that time.
   nsLayoutUtils::AssertNoDuplicateContinuations(this, mFloats);
 
   if (gNoisyReflow) {
     IndentBy(stdout, gNoiseIndent);
     ListTag(stdout);
-    printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d",
-           aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ",
+    printf(": status=%s metrics=%d,%d carriedMargin=%d",
+           ToString(aStatus).c_str(),
            aMetrics.ISize(parentWM), aMetrics.BSize(parentWM),
            aMetrics.mCarriedOutBEndMargin.get());
     if (HasOverflowAreas()) {
       printf(" overflow-vis={%d,%d,%d,%d}",
              aMetrics.VisualOverflow().x,
              aMetrics.VisualOverflow().y,
              aMetrics.VisualOverflow().width,
              aMetrics.VisualOverflow().height);
@@ -1608,17 +1610,17 @@ nsBlockFrame::ComputeFinalSize(const Ref
   }
 
   if (NS_UNCONSTRAINEDSIZE != aReflowInput.ComputedBSize()
       && (GetParent()->GetType() != nsGkAtoms::columnSetFrame ||
           aReflowInput.mParentReflowInput->AvailableBSize() == NS_UNCONSTRAINEDSIZE)) {
     ComputeFinalBSize(aReflowInput, &aState.mReflowStatus,
                       aState.mBCoord + nonCarriedOutBDirMargin,
                       borderPadding, finalSize, aState.mConsumedBSize);
-    if (!NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
+    if (!aState.mReflowStatus.IsComplete()) {
       // Use the current height; continuations will take up the rest.
       // Do extend the height to at least consume the available
       // height, otherwise our left/right borders (for example) won't
       // extend all the way to the break.
       finalSize.BSize(wm) = std::max(aReflowInput.AvailableBSize(),
                                      aState.mBCoord + nonCarriedOutBDirMargin);
       // ... but don't take up more block size than is available
       nscoord effectiveComputedBSize =
@@ -1630,17 +1632,17 @@ nsBlockFrame::ComputeFinalSize(const Ref
       // on its own on the last-in-flow, even if we ran out of height
       // here. We need GetSkipSides to check whether we ran out of content
       // height in the current frame, not whether it's last-in-flow.
     }
 
     // Don't carry out a block-end margin when our BSize is fixed.
     aMetrics.mCarriedOutBEndMargin.Zero();
   }
-  else if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
+  else if (aState.mReflowStatus.IsComplete()) {
     nscoord contentBSize = blockEndEdgeOfChildren - borderPadding.BStart(wm);
     nscoord autoBSize = aReflowInput.ApplyMinMaxBSize(contentBSize);
     if (autoBSize != contentBSize) {
       // Our min- or max-bsize value made our bsize change.  Don't carry out
       // our kids' block-end margins.
       aMetrics.mCarriedOutBEndMargin.Zero();
     }
     autoBSize += borderPadding.BStart(wm) + borderPadding.BEnd(wm);
@@ -1653,43 +1655,43 @@ nsBlockFrame::ComputeFinalSize(const Ref
                                    aReflowInput.AvailableBSize());
     if (aReflowInput.AvailableBSize() == NS_UNCONSTRAINEDSIZE) {
       // This should never happen, but it does. See bug 414255
       finalSize.BSize(wm) = aState.mBCoord;
     }
   }
 
   if (IS_TRUE_OVERFLOW_CONTAINER(this)) {
-    if (NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
+    if (aState.mReflowStatus.IsIncomplete()) {
       // Overflow containers can only be overflow complete.
       // Note that auto height overflow containers have no normal children
       NS_ASSERTION(finalSize.BSize(wm) == 0,
                    "overflow containers must be zero-block-size");
-      NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
+      aState.mReflowStatus.SetOverflowIncomplete();
     }
   } else if (aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE &&
-             !NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus) &&
-             NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
+             !aState.mReflowStatus.IsInlineBreakBefore() &&
+             aState.mReflowStatus.IsComplete()) {
     // Currently only used for grid items, but could be used in other contexts.
     // The FragStretchBSizeProperty is our expected non-fragmented block-size
     // we should stretch to (for align-self:stretch etc).  In some fragmentation
     // cases though, the last fragment (this frame since we're complete), needs
     // to have extra size applied because earlier fragments consumed too much of
     // our computed size due to overflowing their containing block.  (E.g. this
     // ensures we fill the last row when a multi-row grid item is fragmented).
     bool found;
     nscoord bSize = Properties().Get(FragStretchBSizeProperty(), &found);
     if (found) {
       finalSize.BSize(wm) = std::max(bSize, finalSize.BSize(wm));
     }
   }
 
   // Clamp the content size to fit within the margin-box clamp size, if any.
   if (MOZ_UNLIKELY(aReflowInput.mFlags.mBClampMarginBoxMinSize) &&
-      NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
+      aState.mReflowStatus.IsComplete()) {
     bool found;
     nscoord cbSize = Properties().Get(BClampMarginBoxMinSizeProperty(), &found);
     if (found) {
       auto marginBoxBSize = finalSize.BSize(wm) +
                             aReflowInput.ComputedLogicalMargin().BStartEnd(wm);
       auto overflow = marginBoxBSize - cbSize;
       if (overflow > 0) {
         auto contentBSize = finalSize.BSize(wm) - borderPadding.BStartEnd(wm);
@@ -2571,19 +2573,19 @@ nsBlockFrame::ReflowDirtyLines(BlockRefl
         skipPull=true;
       }
     }
   }
 
   if (skipPull && aState.mNextInFlow) {
     NS_ASSERTION(heightConstrained, "Height should be constrained here\n");
     if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow))
-      NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
+      aState.mReflowStatus.SetOverflowIncomplete();
     else
-      NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+      aState.mReflowStatus.SetIncomplete();
   }
 
   if (!skipPull && aState.mNextInFlow) {
     // Pull data from a next-in-flow if there's still room for more
     // content here.
     while (keepGoing && aState.mNextInFlow) {
       // Grab first line from our next-in-flow
       nsBlockFrame* nextInFlow = aState.mNextInFlow;
@@ -2650,17 +2652,17 @@ nsBlockFrame::ReflowDirtyLines(BlockRefl
         // line to be created; see SplitLine's callers for examples of
         // when this happens).
         while (line != LinesEnd()) {
           ReflowLine(aState, line, &keepGoing);
 
           if (aState.mReflowInput.WillReflowAgainForClearance()) {
             line->MarkDirty();
             keepGoing = false;
-            NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+            aState.mReflowStatus.SetIncomplete();
             break;
           }
 
           DumpLine(aState, line, deltaBCoord, -1);
           if (!keepGoing) {
             if (0 == line->GetChildCount()) {
               DeleteLine(aState, line, line_end);
             }
@@ -2678,18 +2680,18 @@ nsBlockFrame::ReflowDirtyLines(BlockRefl
 
           // If this is an inline frame then its time to stop
           ++line;
           aState.AdvanceToNextLine();
         }
       }
     }
 
-    if (NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
-      aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+    if (aState.mReflowStatus.IsIncomplete()) {
+      aState.mReflowStatus.SetNextInFlowNeedsReflow();
     } //XXXfr shouldn't set this flag when nextinflow has no lines
   }
 
   // Handle an odd-ball case: a list-item with no lines
   if (HasOutsideBullet() && mLines.empty()) {
     ReflowOutput metrics(aState.mReflowInput);
     nsIFrame* bullet = GetOutsideBullet();
     WritingMode wm = aState.mReflowInput.GetWritingMode();
@@ -2738,18 +2740,18 @@ nsBlockFrame::ReflowDirtyLines(BlockRefl
   }
 
 #ifdef DEBUG
   VerifyLines(true);
   VerifyOverflowSituation();
   if (gNoisyReflow) {
     IndentBy(stdout, gNoiseIndent - 1);
     ListTag(stdout);
-    printf(": done reflowing dirty lines (status=%x)\n",
-           aState.mReflowStatus);
+    printf(": done reflowing dirty lines (status=%s)\n",
+           ToString(aState.mReflowStatus).c_str());
   }
 #endif
 }
 
 void
 nsBlockFrame::MarkLineDirtyForInterrupt(nsLineBox* aLine)
 {
   aLine->MarkDirty();
@@ -3399,20 +3401,20 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
       // Doing this means that we also don't need to worry about the
       // |availSpace.BSize(wm) += bStartMargin| below interacting with
       // pushed floats (which force nscoord_MAX clearance) to cause a
       // constrained block size to turn into an unconstrained one.
       aState.mBCoord = startingBCoord;
       aState.mPrevBEndMargin = incomingMargin;
       *aKeepReflowGoing = false;
       if (ShouldAvoidBreakInside(aState.mReflowInput)) {
-        aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
       } else {
         PushLines(aState, aLine.prev());
-        NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+        aState.mReflowStatus.SetIncomplete();
       }
       return;
     }
 
     // Now put the block-dir coordinate back to the start of the
     // block-start-margin + clearance.
     aState.mBCoord -= bStartMargin;
     availSpace.BStart(wm) -= bStartMargin;
@@ -3451,17 +3453,17 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
 
       if (mayNeedRetry) {
         blockHtmlRI->mDiscoveredClearance = &clearanceFrame;
       } else if (!applyBStartMargin) {
         blockHtmlRI->mDiscoveredClearance =
           aState.mReflowInput.mDiscoveredClearance;
       }
 
-      frameReflowStatus = NS_FRAME_COMPLETE;
+      frameReflowStatus.Reset();
       brc.ReflowBlock(availSpace, applyBStartMargin, aState.mPrevBEndMargin,
                       clearance, aState.IsAdjacentWithTop(),
                       aLine.get(), *blockHtmlRI, frameReflowStatus, aState);
 
       // Now the block has a height.  Using that height, get the
       // available space again and call ComputeBlockAvailSpace again.
       // If ComputeBlockAvailSpace gives a different result, we need to
       // reflow again.
@@ -3572,24 +3574,24 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
                    "we need to call PositionChildViews");
       return;
     }
 
 #if defined(REFLOW_STATUS_COVERAGE)
     RecordReflowStatus(true, frameReflowStatus);
 #endif
 
-    if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {
+    if (frameReflowStatus.IsInlineBreakBefore()) {
       // None of the child block fits.
       *aKeepReflowGoing = false;
       if (ShouldAvoidBreakInside(aState.mReflowInput)) {
-        aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
       } else {
         PushLines(aState, aLine.prev());
-        NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+        aState.mReflowStatus.SetIncomplete();
       }
     }
     else {
       // Note: line-break-after a block is a nop
 
       // Try to place the child block.
       // Don't force the block to fit if we have positive clearance, because
       // pushing it to the next page would give it more room.
@@ -3599,17 +3601,17 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
       bool forceFit = aState.IsAdjacentWithTop() && clearance <= 0 &&
         !floatAvailableSpace.mHasFloats;
       nsCollapsingMargin collapsedBEndMargin;
       nsOverflowAreas overflowAreas;
       *aKeepReflowGoing = brc.PlaceBlock(*blockHtmlRI, forceFit, aLine.get(),
                                          collapsedBEndMargin,
                                          overflowAreas,
                                          frameReflowStatus);
-      if (!NS_FRAME_IS_FULLY_COMPLETE(frameReflowStatus) &&
+      if (!frameReflowStatus.IsFullyComplete() &&
           ShouldAvoidBreakInside(aState.mReflowInput)) {
         *aKeepReflowGoing = false;
       }
 
       if (aLine->SetCarriedOutBEndMargin(collapsedBEndMargin)) {
         LineIterator nextLine = aLine;
         ++nextLine;
         if (nextLine != LinesEnd()) {
@@ -3623,54 +3625,54 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
 
         // Advance to new Y position
         nscoord newBCoord = aLine->BEnd();
         aState.mBCoord = newBCoord;
 
 
         // Continue the block frame now if it didn't completely fit in
         // the available space.
-        if (!NS_FRAME_IS_FULLY_COMPLETE(frameReflowStatus)) {
+        if (!frameReflowStatus.IsFullyComplete()) {
           bool madeContinuation =
             CreateContinuationFor(aState, nullptr, frame);
 
           nsIFrame* nextFrame = frame->GetNextInFlow();
           NS_ASSERTION(nextFrame, "We're supposed to have a next-in-flow by now");
 
-          if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {
+          if (frameReflowStatus.IsIncomplete()) {
             // If nextFrame used to be an overflow container, make it a normal block
             if (!madeContinuation &&
                 (NS_FRAME_IS_OVERFLOW_CONTAINER & nextFrame->GetStateBits())) {
               nsOverflowContinuationTracker::AutoFinish fini(aState.mOverflowTracker, frame);
               nsContainerFrame* parent = nextFrame->GetParent();
               nsresult rv = parent->StealFrame(nextFrame);
               if (NS_FAILED(rv)) {
                 return;
               }
               if (parent != this)
                 ReparentFrame(nextFrame, parent, this);
               mFrames.InsertFrame(nullptr, frame, nextFrame);
               madeContinuation = true; // needs to be added to mLines
               nextFrame->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
-              frameReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+              frameReflowStatus.SetNextInFlowNeedsReflow();
             }
 
             // Push continuation to a new line, but only if we actually made one.
             if (madeContinuation) {
               nsLineBox* line = NewLineBox(nextFrame, true);
               mLines.after_insert(aLine, line);
             }
 
             PushLines(aState, aLine);
-            NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+            aState.mReflowStatus.SetIncomplete();
 
             // If we need to reflow the continuation of the block child,
             // then we'd better reflow our continuation
-            if (frameReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
-              aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+            if (frameReflowStatus.NextInFlowNeedsReflow()) {
+              aState.mReflowStatus.SetNextInFlowNeedsReflow();
               // We also need to make that continuation's line dirty so
               // it gets reflowed when we reflow our next in flow. The
               // nif's line must always be either a line of the nif's
               // parent block (only if we didn't make a continuation) or
               // else one of our own overflow lines. In the latter case
               // the line is already marked dirty, so just handle the
               // first case.
               if (!madeContinuation) {
@@ -3714,17 +3716,17 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
               }
             }
             else if (madeContinuation) {
               mFrames.RemoveFrame(nextFrame);
             }
 
             // Put it in our overflow list
             aState.mOverflowTracker->Insert(nextFrame, frameReflowStatus);
-            NS_MergeReflowStatusInto(&aState.mReflowStatus, frameReflowStatus);
+            aState.mReflowStatus.MergeCompletionStatusFrom(frameReflowStatus);
 
 #ifdef NOISY_BLOCK_DIR_MARGINS
             ListTag(stdout);
             printf(": reflow complete but overflow incomplete for ");
             nsFrame::ListTag(stdout, mFrame);
             printf(" prevBEndMargin=%d collapsedBEndMargin=%d\n",
                    aState.mPrevBEndMargin.get(), collapsedBEndMargin.get());
 #endif
@@ -3750,22 +3752,22 @@ nsBlockFrame::ReflowBlockFrame(BlockRefl
                aState.mPrevBEndMargin.get());
 #endif
       } else {
         if ((aLine == mLines.front() && !GetPrevInFlow()) ||
             ShouldAvoidBreakInside(aState.mReflowInput)) {
           // If it's our very first line *or* we're not at the top of the page
           // and we have page-break-inside:avoid, then we need to be pushed to
           // our parent's next-in-flow.
-          aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+          aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
         } else {
           // Push the line that didn't fit and any lines that follow it
           // to our next-in-flow.
           PushLines(aState, aLine.prev());
-          NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+          aState.mReflowStatus.SetIncomplete();
         }
       }
     }
     break; // out of the reflow retry loop
   }
 
   // Now that we've got its final position all figured out, position any child
   // views it may have.  Note that the case when frame has a view got handled
@@ -3858,17 +3860,17 @@ nsBlockFrame::ReflowInlineFrames(BlockRe
 
 void
 nsBlockFrame::PushTruncatedLine(BlockReflowInput& aState,
                                 LineIterator       aLine,
                                 bool*               aKeepReflowGoing)
 {
   PushLines(aState, aLine.prev());
   *aKeepReflowGoing = false;
-  NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
+  aState.mReflowStatus.SetIncomplete();
 }
 
 void
 nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
                                    nsLineLayout& aLineLayout,
                                    LineIterator aLine,
                                    nsFlowAreaRect& aFloatAvailableSpace,
                                    nscoord& aAvailableSpaceBSize,
@@ -4071,17 +4073,17 @@ nsBlockFrame::DoReflowInlineFrames(Block
     // if the new Y coordinate is past the end of the block then
     // push the line and return now instead of later on after we are
     // past the float.
   }
   else if (LineReflowStatus::Truncated != lineReflowStatus &&
            LineReflowStatus::RedoNoPull != lineReflowStatus) {
     // If we are propagating out a break-before status then there is
     // no point in placing the line.
-    if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
+    if (!aState.mReflowStatus.IsInlineBreakBefore()) {
       if (!PlaceLine(aState, aLineLayout, aLine, aFloatStateBeforeLine,
                      aFloatAvailableSpace.mRect, aAvailableSpaceBSize,
                      aKeepReflowGoing)) {
         lineReflowStatus = LineReflowStatus::RedoMoreFloats;
         // PlaceLine already called GetAvailableSpaceForBSize for us.
       }
     }
   }
@@ -4102,17 +4104,17 @@ nsBlockFrame::DoReflowInlineFrames(Block
       // aLine is stale, it's associated with the main line list but it should
       // be associated with the overflow line list now
       aLine = overflowLines->mLines.begin();
     }
     nsBlockInFlowLineIterator iter(this, aLine, pushedToOverflowLines);
     if (iter.Next() && iter.GetLine()->IsInline()) {
       iter.GetLine()->MarkDirty();
       if (iter.GetContainer() != this) {
-        aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+        aState.mReflowStatus.SetNextInFlowNeedsReflow();
       }
     }
   }
 
   *aLineReflowStatus = lineReflowStatus;
 }
 
 /**
@@ -4145,17 +4147,17 @@ nsBlockFrame::ReflowInlineFrame(BlockRef
          aLineLayout.GetFirstLetterStyleOK() ? "on" : "off");
 #endif
 
   // Reflow the inline frame
   nsReflowStatus frameReflowStatus;
   bool           pushedFrame;
   aLineLayout.ReflowFrame(aFrame, frameReflowStatus, nullptr, pushedFrame);
 
-  if (frameReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
+  if (frameReflowStatus.NextInFlowNeedsReflow()) {
     aLineLayout.SetDirtyNextLine();
   }
 
 #ifdef REALLY_NOISY_REFLOW
   nsFrame::ListTag(stdout, aFrame);
   printf(": status=%x\n", frameReflowStatus);
 #endif
 
@@ -4174,28 +4176,28 @@ nsBlockFrame::ReflowInlineFrame(BlockRef
    */
 
   // Process the child frames reflow status. There are 5 cases:
   // complete, not-complete, break-before, break-after-complete,
   // break-after-not-complete. There are two situations: we are a
   // block or we are an inline. This makes a total of 10 cases
   // (fortunately, there is some overlap).
   aLine->SetBreakTypeAfter(StyleClear::None);
-  if (NS_INLINE_IS_BREAK(frameReflowStatus) ||
+  if (frameReflowStatus.IsInlineBreak() ||
       StyleClear::None != aState.mFloatBreakType) {
     // Always abort the line reflow (because a line break is the
     // minimal amount of break we do).
     *aLineReflowStatus = LineReflowStatus::Stop;
 
     // XXX what should aLine's break-type be set to in all these cases?
-    StyleClear breakType = NS_INLINE_GET_BREAK_TYPE(frameReflowStatus);
+    StyleClear breakType = frameReflowStatus.BreakType();
     MOZ_ASSERT(StyleClear::None != breakType ||
                StyleClear::None != aState.mFloatBreakType, "bad break type");
 
-    if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {
+    if (frameReflowStatus.IsInlineBreakBefore()) {
       // Break-before cases.
       if (aFrame == aLine->mFirstChild) {
         // If we break before the first frame on the line then we must
         // be trying to place content where there's no room (e.g. on a
         // line with wide floats). Inform the caller to reflow the
         // line after skipping past a float.
         *aLineReflowStatus = LineReflowStatus::RedoNextBand;
       }
@@ -4223,42 +4225,42 @@ nsBlockFrame::ReflowInlineFrame(BlockRef
       }
       // Break-after cases
       if (breakType == StyleClear::Line) {
         if (!aLineLayout.GetLineEndsInBR()) {
           breakType = StyleClear::None;
         }
       }
       aLine->SetBreakTypeAfter(breakType);
-      if (NS_FRAME_IS_COMPLETE(frameReflowStatus)) {
+      if (frameReflowStatus.IsComplete()) {
         // Split line, but after the frame just reflowed
         SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
 
-        if (NS_INLINE_IS_BREAK_AFTER(frameReflowStatus) &&
+        if (frameReflowStatus.IsInlineBreakAfter() &&
             !aLineLayout.GetLineEndsInBR()) {
           aLineLayout.SetDirtyNextLine();
         }
       }
     }
   }
 
-  if (!NS_FRAME_IS_FULLY_COMPLETE(frameReflowStatus)) {
+  if (!frameReflowStatus.IsFullyComplete()) {
     // Create a continuation for the incomplete frame. Note that the
     // frame may already have a continuation.
     CreateContinuationFor(aState, aLine, aFrame);
 
     // Remember that the line has wrapped
     if (!aLineLayout.GetLineEndsInBR()) {
       aLine->SetLineWrapped(true);
     }
 
     // If we just ended a first-letter frame or reflowed a placeholder then
     // don't split the line and don't stop the line reflow...
     // But if we are going to stop anyways we'd better split the line.
-    if ((!(frameReflowStatus & NS_INLINE_BREAK_FIRST_LETTER_COMPLETE) &&
+    if ((!frameReflowStatus.FirstLetterComplete() &&
          nsGkAtoms::placeholderFrame != aFrame->GetType()) ||
         *aLineReflowStatus == LineReflowStatus::Stop) {
       // Split line after the current frame
       *aLineReflowStatus = LineReflowStatus::Stop;
       SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
     }
   }
 }
@@ -4286,50 +4288,50 @@ nsBlockFrame::CreateContinuationFor(Bloc
   return !!newFrame;
 }
 
 nsresult
 nsBlockFrame::SplitFloat(BlockReflowInput& aState,
                          nsIFrame*           aFloat,
                          nsReflowStatus      aFloatStatus)
 {
-  MOZ_ASSERT(!NS_FRAME_IS_FULLY_COMPLETE(aFloatStatus),
+  MOZ_ASSERT(!aFloatStatus.IsFullyComplete(),
              "why split the frame if it's fully complete?");
   MOZ_ASSERT(aState.mBlock == this);
 
   nsIFrame* nextInFlow = aFloat->GetNextInFlow();
   if (nextInFlow) {
     nsContainerFrame *oldParent = nextInFlow->GetParent();
     DebugOnly<nsresult> rv = oldParent->StealFrame(nextInFlow);
     NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame failed");
     if (oldParent != this) {
       ReparentFrame(nextInFlow, oldParent, this);
     }
-    if (!NS_FRAME_OVERFLOW_IS_INCOMPLETE(aFloatStatus)) {
+    if (!aFloatStatus.IsOverflowIncomplete()) {
       nextInFlow->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
     }
   } else {
     nextInFlow = aState.mPresContext->PresShell()->FrameConstructor()->
       CreateContinuingFrame(aState.mPresContext, aFloat, this);
   }
-  if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aFloatStatus)) {
+  if (aFloatStatus.IsOverflowIncomplete()) {
     nextInFlow->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
   }
 
   StyleFloat floatStyle =
     aFloat->StyleDisplay()->PhysicalFloats(aState.mReflowInput.GetWritingMode());
   if (floatStyle == StyleFloat::Left) {
     aState.FloatManager()->SetSplitLeftFloatAcrossBreak();
   } else {
     MOZ_ASSERT(floatStyle == StyleFloat::Right, "Unexpected float side!");
     aState.FloatManager()->SetSplitRightFloatAcrossBreak();
   }
 
   aState.AppendPushedFloatChain(nextInFlow);
-  NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
+  aState.mReflowStatus.SetOverflowIncomplete();
   return NS_OK;
 }
 
 static nsFloatCache*
 GetLastFloat(nsLineBox* aLine)
 {
   nsFloatCache* fc = aLine->GetFirstFloat();
   while (fc && fc->Next()) {
@@ -4634,31 +4636,31 @@ nsBlockFrame::PlaceLine(BlockReflowInput
     // since the line is empty.
     // We already called |ShouldApplyBStartMargin|, and if we applied it
     // then mShouldApplyBStartMargin is set.
     nscoord dy = aState.mFlags.mShouldApplyBStartMargin
                    ? -aState.mPrevBEndMargin.get() : 0;
     newBCoord = aState.mBCoord + dy;
   }
 
-  if (!NS_FRAME_IS_FULLY_COMPLETE(aState.mReflowStatus) &&
+  if (!aState.mReflowStatus.IsFullyComplete() &&
       ShouldAvoidBreakInside(aState.mReflowInput)) {
     aLine->AppendFloats(aState.mCurrentLineFloats);
-    aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
     return true;
   }
 
   // See if the line fit (our first line always does).
   if (mLines.front() != aLine &&
       newBCoord > aState.mBEndEdge &&
       aState.mBEndEdge != NS_UNCONSTRAINEDSIZE) {
     NS_ASSERTION(aState.mCurrentLine == aLine, "oops");
     if (ShouldAvoidBreakInside(aState.mReflowInput)) {
       // All our content doesn't fit, start on the next page.
-      aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      aState.mReflowStatus.SetInlineLineBreakBeforeAndReset();
     } else {
       // Push aLine and all of its children and anything else that
       // follows to our next-in-flow.
       PushTruncatedLine(aState, aLine, aKeepReflowGoing);
     }
     return true;
   }
 
@@ -6208,17 +6210,17 @@ nsBlockFrame::ReflowFloat(BlockReflowInp
                           LogicalMargin&      aFloatMargin,
                           LogicalMargin&      aFloatOffsets,
                           bool                aFloatPushedDown,
                           nsReflowStatus&     aReflowStatus)
 {
   NS_PRECONDITION(aFloat->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                   "aFloat must be an out-of-flow frame");
   // Reflow the float.
-  aReflowStatus = NS_FRAME_COMPLETE;
+  aReflowStatus.Reset();
 
   WritingMode wm = aState.mReflowInput.GetWritingMode();
 #ifdef NOISY_FLOAT
   printf("Reflow Float %p in parent %p, availSpace(%d,%d,%d,%d)\n",
          aFloat, this,
          aAdjustedAvailableSpace.IStart(wm), aAdjustedAvailableSpace.BStart(wm),
          aAdjustedAvailableSpace.ISize(wm), aAdjustedAvailableSpace.BSize(wm)
   );
@@ -6268,36 +6270,36 @@ nsBlockFrame::ReflowFloat(BlockReflowInp
     }
 
     brc.ReflowBlock(aAdjustedAvailableSpace, true, margin,
                     0, isAdjacentWithTop,
                     nullptr, floatRS,
                     aReflowStatus, aState);
   } while (clearanceFrame);
 
-  if (!NS_FRAME_IS_FULLY_COMPLETE(aReflowStatus) &&
+  if (!aReflowStatus.IsFullyComplete() &&
       ShouldAvoidBreakInside(floatRS)) {
-    aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
-  } else if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
+    aReflowStatus.SetInlineLineBreakBeforeAndReset();
+  } else if (aReflowStatus.IsIncomplete() &&
              (NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.BSize(wm))) {
     // An incomplete reflow status means we should split the float
     // if the height is constrained (bug 145305).
-    aReflowStatus = NS_FRAME_COMPLETE;
-  }
-
-  if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
-    aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+    aReflowStatus.Reset();
+  }
+
+  if (aReflowStatus.NextInFlowNeedsReflow()) {
+    aState.mReflowStatus.SetNextInFlowNeedsReflow();
   }
 
   if (aFloat->GetType() == nsGkAtoms::letterFrame) {
     // We never split floating first letters; an incomplete state for
     // such frames simply means that there is more content to be
     // reflowed on the line.
-    if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus))
-      aReflowStatus = NS_FRAME_COMPLETE;
+    if (aReflowStatus.IsIncomplete())
+      aReflowStatus.Reset();
   }
 
   // Capture the margin and offsets information for the caller
   aFloatMargin =
     // float margins don't collapse
     floatRS.ComputedLogicalMargin().ConvertTo(wm, floatRS.GetWritingMode());
   aFloatOffsets =
     floatRS.ComputedLogicalOffsets().ConvertTo(wm, floatRS.GetWritingMode());
@@ -7403,42 +7405,42 @@ nsBlockFrame::ComputeFinalBSize(const Re
                   && computedBSizeLeftOver ),
                "overflow container must not have computedBSizeLeftOver");
 
   aFinalSize.BSize(wm) =
     NSCoordSaturatingAdd(NSCoordSaturatingAdd(aBorderPadding.BStart(wm),
                                               computedBSizeLeftOver),
                          aBorderPadding.BEnd(wm));
 
-  if (NS_FRAME_IS_NOT_COMPLETE(*aStatus) &&
+  if (aStatus->IsIncomplete() &&
       aFinalSize.BSize(wm) < aReflowInput.AvailableBSize()) {
     // We fit in the available space - change status to OVERFLOW_INCOMPLETE.
     // XXXmats why didn't Reflow report OVERFLOW_INCOMPLETE in the first place?
     // XXXmats and why exclude the case when our size == AvailableBSize?
-    NS_FRAME_SET_OVERFLOW_INCOMPLETE(*aStatus);
-  }
-
-  if (NS_FRAME_IS_COMPLETE(*aStatus)) {
+    aStatus->SetOverflowIncomplete();
+  }
+
+  if (aStatus->IsComplete()) {
     if (computedBSizeLeftOver > 0 &&
         NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableBSize() &&
         aFinalSize.BSize(wm) > aReflowInput.AvailableBSize()) {
       if (ShouldAvoidBreakInside(aReflowInput)) {
-        *aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aStatus->SetInlineLineBreakBeforeAndReset();
         return;
       }
       // We don't fit and we consumed some of the computed height,
       // so we should consume all the available height and then
       // break.  If our bottom border/padding straddles the break
       // point, then this will increase our height and push the
       // border/padding to the next page/column.
       aFinalSize.BSize(wm) = std::max(aReflowInput.AvailableBSize(),
                                       aContentBSize);
-      NS_FRAME_SET_INCOMPLETE(*aStatus);
+      aStatus->SetIncomplete();
       if (!GetNextInFlow())
-        *aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+        aStatus->SetNextInFlowNeedsReflow();
     }
   }
 }
 
 nsresult
 nsBlockFrame::ResolveBidi()
 {
   NS_ASSERTION(!GetPrevInFlow(),
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -302,17 +302,17 @@ nsBlockReflowContext::ReflowBlock(const 
   mMetrics.BSize(mWritingMode) = nscoord(0xdeadbeef);
 #endif
 
   mOuterReflowInput.mFloatManager->Translate(tI, tB);
   mFrame->Reflow(mPresContext, mMetrics, aFrameRI, aFrameReflowStatus);
   mOuterReflowInput.mFloatManager->Translate(-tI, -tB);
 
 #ifdef DEBUG
-  if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
+  if (!aFrameReflowStatus.IsInlineBreakBefore()) {
     if ((CRAZY_SIZE(mMetrics.ISize(mWritingMode)) ||
          CRAZY_SIZE(mMetrics.BSize(mWritingMode))) &&
         !mFrame->GetParent()->IsCrazySizeAssertSuppressed()) {
       printf("nsBlockReflowContext: ");
       nsFrame::ListTag(stdout, mFrame);
       printf(" metrics=%d,%d!\n",
              mMetrics.ISize(mWritingMode), mMetrics.BSize(mWritingMode));
     }
@@ -325,23 +325,23 @@ nsBlockReflowContext::ReflowBlock(const 
     }
   }
 #endif
 
   if (!mFrame->HasOverflowAreas()) {
     mMetrics.SetOverflowAreasToDesiredBounds();
   }
 
-  if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus) ||
+  if (!aFrameReflowStatus.IsInlineBreakBefore() ||
       (mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
     // If frame is complete and has a next-in-flow, we need to delete
     // them now. Do not do this when a break-before is signaled because
     // the frame is going to get reflowed again (and may end up wanting
     // a next-in-flow where it ends up), unless it is an out of flow frame.
-    if (NS_FRAME_IS_FULLY_COMPLETE(aFrameReflowStatus)) {
+    if (aFrameReflowStatus.IsFullyComplete()) {
       nsIFrame* kidNextInFlow = mFrame->GetNextInFlow();
       if (nullptr != kidNextInFlow) {
         // Remove all of the childs next-in-flows. Make sure that we ask
         // the right parent to do the removal (it's possible that the
         // parent is not this because we are executing pullup code).
         // Floats will eventually be removed via nsBlockFrame::RemoveFloat
         // which detaches the placeholder from the float.
         nsOverflowContinuationTracker::AutoFinish fini(aState.mOverflowTracker, mFrame);
@@ -362,17 +362,17 @@ nsBlockReflowContext::PlaceBlock(const R
                                  nsLineBox*                aLine,
                                  nsCollapsingMargin&       aBEndMarginResult,
                                  nsOverflowAreas&          aOverflowAreas,
                                  nsReflowStatus            aReflowStatus)
 {
   // Compute collapsed block-end margin value.
   WritingMode wm = aReflowInput.GetWritingMode();
   WritingMode parentWM = mMetrics.GetWritingMode();
-  if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
+  if (aReflowStatus.IsComplete()) {
     aBEndMarginResult = mMetrics.mCarriedOutBEndMargin;
     aBEndMarginResult.Include(aReflowInput.ComputedLogicalMargin().
       ConvertTo(parentWM, wm).BEnd(parentWM));
   } else {
     // The used block-end-margin is set to zero before a break.
     aBEndMarginResult.Zero();
   }
 
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -1058,17 +1058,17 @@ nsBulletFrame::Reflow(nsPresContext* aPr
                                linePadding.BStart(lineWM));
 
   // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
   // overflow their font-boxes. It'll do for now; to fix it for real, we really
   // should rewrite all the text-handling code here to use gfxTextRun (bug
   // 397294).
   aMetrics.SetOverflowAreasToDesiredBounds();
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
 }
 
 /* virtual */ nscoord
 nsBulletFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   WritingMode wm = GetWritingMode();
   ReflowOutput reflowOutput(wm);
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -644,17 +644,17 @@ nsCanvasFrame::Reflow(nsPresContext*    
                       nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
   NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow");
 
   // Initialize OUT parameter
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*>
                                                (GetPrevInFlow());
   if (prevCanvasFrame) {
     AutoFrameListPtr overflow(aPresContext,
                               prevCanvasFrame->StealOverflowFrames());
     if (overflow) {
       NS_ASSERTION(overflow->OnlyChild(),
@@ -710,30 +710,30 @@ nsCanvasFrame::Reflow(nsPresContext*    
     // Reflow the frame
     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowInput,
                 kidWM, kidPt, containerSize, 0, aStatus);
 
     // Complete the reflow and position and size the child frame
     FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowInput,
                       kidWM, kidPt, containerSize, 0);
 
-    if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
+    if (!aStatus.IsFullyComplete()) {
       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
-      NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
+      NS_ASSERTION(nextFrame || aStatus.NextInFlowNeedsReflow(),
         "If it's incomplete and has no nif yet, it must flag a nif reflow.");
       if (!nextFrame) {
         nextFrame = aPresContext->PresShell()->FrameConstructor()->
           CreateContinuingFrame(aPresContext, kidFrame, this);
         SetOverflowFrames(nsFrameList(nextFrame, nextFrame));
         // Root overflow containers will be normal children of
         // the canvas frame, but that's ok because there
         // aren't any other frames we need to isolate them from
         // during reflow.
       }
-      if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
+      if (aStatus.IsOverflowIncomplete()) {
         nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
       }
     }
 
     // If the child frame was just inserted, then we're responsible for making sure
     // it repaints
     if (kidDirty) {
       // But we have a new child, which will affect our background, so
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -27,18 +27,18 @@ NS_NewColumnSetFrame(nsIPresShell* aPres
   nsColumnSetFrame* it = new (aPresShell) nsColumnSetFrame(aContext);
   it->AddStateBits(aStateFlags | NS_BLOCK_MARGIN_ROOT);
   return it;
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsColumnSetFrame)
 
 nsColumnSetFrame::nsColumnSetFrame(nsStyleContext* aContext)
-  : nsContainerFrame(aContext), mLastBalanceBSize(NS_INTRINSICSIZE),
-    mLastFrameStatus(NS_FRAME_COMPLETE)
+  : nsContainerFrame(aContext)
+  , mLastBalanceBSize(NS_INTRINSICSIZE)
 {
 }
 
 nsIAtom*
 nsColumnSetFrame::GetType() const
 {
   return nsGkAtoms::columnSetFrame;
 }
@@ -579,19 +579,22 @@ nsColumnSetFrame::ReflowChildren(ReflowO
     nscoord childContentBEnd = 0;
     if (!reflowNext && (skipIncremental || skipResizeBSizeShrink)) {
       // This child does not need to be reflowed, but we may need to move it
       MoveChildTo(child, childOrigin, wm, containerSize);
 
       // If this is the last frame then make sure we get the right status
       nsIFrame* kidNext = child->GetNextSibling();
       if (kidNext) {
-        aStatus = (kidNext->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)
-                  ? NS_FRAME_OVERFLOW_INCOMPLETE
-                  : NS_FRAME_NOT_COMPLETE;
+        aStatus.Reset();
+        if (kidNext->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
+          aStatus.SetOverflowIncomplete();
+        } else {
+          aStatus.SetIncomplete();
+        }
       } else {
         aStatus = mLastFrameStatus;
       }
       childContentBEnd = nsLayoutUtils::CalculateContentBEnd(wm, child);
 #ifdef DEBUG_roc
       printf("*** Skipping child #%d %p (incremental %d, resize block-size shrink %d): status = %d\n",
              columnCount, (void*)child, skipIncremental, skipResizeBSizeShrink, aStatus);
 #endif
@@ -643,17 +646,17 @@ nsColumnSetFrame::ReflowChildren(ReflowO
       LogicalPoint origin(wm,
                           childOrigin.I(wm) +
                           kidReflowInput.ComputedLogicalMargin().IStart(wm),
                           childOrigin.B(wm) +
                           kidReflowInput.ComputedLogicalMargin().BStart(wm));
       ReflowChild(child, PresContext(), kidDesiredSize, kidReflowInput,
                   wm, origin, containerSize, 0, aStatus);
 
-      reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0;
+      reflowNext = aStatus.NextInFlowNeedsReflow();
 
 #ifdef DEBUG_roc
       printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d CarriedOutBEndMargin=%d\n",
              columnCount, (void*)child, aStatus, kidDesiredSize.Width(), kidDesiredSize.Height(),
              kidDesiredSize.mCarriedOutBEndMargin.get());
 #endif
 
       NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus);
@@ -678,61 +681,61 @@ nsColumnSetFrame::ReflowChildren(ReflowO
     ConsiderChildOverflow(overflowRects, child);
     contentBEnd = std::max(contentBEnd, childContentBEnd);
     aColData.mLastBSize = childContentBEnd;
     aColData.mSumBSize += childContentBEnd;
 
     // Build a continuation column if necessary
     nsIFrame* kidNextInFlow = child->GetNextInFlow();
 
-    if (NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus)) {
+    if (aStatus.IsFullyComplete() && !aStatus.IsTruncated()) {
       NS_ASSERTION(!kidNextInFlow, "next in flow should have been deleted");
       child = nullptr;
       break;
     } else {
       ++columnCount;
       // Make sure that the column has a next-in-flow. If not, we must
       // create one to hold the overflowing stuff, even if we're just
       // going to put it on our overflow list and let *our*
       // next in flow handle it.
       if (!kidNextInFlow) {
-        NS_ASSERTION(aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
+        NS_ASSERTION(aStatus.NextInFlowNeedsReflow(),
                      "We have to create a continuation, but the block doesn't want us to reflow it?");
 
         // We need to create a continuing column
         kidNextInFlow = CreateNextInFlow(child);
       }
 
       // Make sure we reflow a next-in-flow when it switches between being
       // normal or overflow container
-      if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
+      if (aStatus.IsOverflowIncomplete()) {
         if (!(kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
-          aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+          aStatus.SetNextInFlowNeedsReflow();
           reflowNext = true;
           kidNextInFlow->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
         }
       }
       else if (kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
-        aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+        aStatus.SetNextInFlowNeedsReflow();
         reflowNext = true;
         kidNextInFlow->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
       }
 
       if ((contentBEnd > aReflowInput.ComputedMaxBSize() ||
            contentBEnd > aReflowInput.ComputedBSize()) &&
            aConfig.mBalanceColCount < INT32_MAX) {
         // We overflowed vertically, but have not exceeded the number of
         // columns. We're going to go into overflow columns now, so balancing
         // no longer applies.
         aColData.mHasExcessBSize = true;
       }
 
       if (columnCount >= aConfig.mBalanceColCount) {
         // No more columns allowed here. Stop.
-        aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+        aStatus.SetNextInFlowNeedsReflow();
         kidNextInFlow->AddStateBits(NS_FRAME_IS_DIRTY);
         // Move any of our leftover columns to our overflow list. Our
         // next-in-flow will eventually pick them up.
         const nsFrameList& continuationColumns = mFrames.RemoveFramesAfter(child);
         if (continuationColumns.NotEmpty()) {
           SetOverflowFrames(continuationColumns);
         }
         child = nullptr;
@@ -823,21 +826,21 @@ nsColumnSetFrame::ReflowChildren(ReflowO
       // Get the logical position as set previously using a provisional or
       // dummy containerSize, and reset with the correct container size.
       child->SetPosition(wm, child->GetLogicalPosition(wm, containerSize),
                          finalContainerSize);
     }
   }
 
 #ifdef DEBUG_roc
-  printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
-         && !NS_FRAME_IS_TRUNCATED(aStatus));
+  printf("*** DONE PASS feasible=%d\n", allFit && aStatus.IsFullyComplete()
+         && !aStatus.IsTruncated());
 #endif
-  return allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
-    && !NS_FRAME_IS_TRUNCATED(aStatus);
+  return allFit && aStatus.IsFullyComplete()
+    && !aStatus.IsTruncated();
 }
 
 void
 nsColumnSetFrame::DrainOverflowColumns()
 {
   // First grab the prev-in-flows overflows and reparent them to this
   // frame.
   nsPresContext* presContext = PresContext();
@@ -1028,17 +1031,17 @@ nsColumnSetFrame::Reflow(nsPresContext* 
   MarkInReflow();
   // Don't support interruption in columns
   nsPresContext::InterruptPreventer noInterrupts(aPresContext);
 
   DO_GLOBAL_REFLOW_COUNT("nsColumnSetFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
 
   // Initialize OUT parameter
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   // Our children depend on our block-size if we have a fixed block-size.
   if (aReflowInput.ComputedBSize() != NS_AUTOHEIGHT) {
     AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
   } else {
     RemoveStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
   }
 
@@ -1049,17 +1052,17 @@ nsColumnSetFrame::Reflow(nsPresContext* 
   }
   nsFrameList::Enumerator eoc(GetChildList(kExcessOverflowContainersList));
   for (; !eoc.AtEnd(); eoc.Next()) {
     MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(eoc.get()));
   }
 #endif
 
   nsOverflowAreas ocBounds;
-  nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus ocStatus;
   if (GetPrevInFlow()) {
     ReflowOverflowContainerChildren(aPresContext, aReflowInput, ocBounds, 0,
                                     ocStatus);
   }
 
   //------------ Handle Incremental Reflow -----------------
 
   // If inline size is unconstrained, set aForceAuto to true to allow
@@ -1094,26 +1097,26 @@ nsColumnSetFrame::Reflow(nsPresContext* 
                           aDesiredSize, carriedOutBottomMargin,
                           unboundedLastColumn, feasible, aStatus);
   }
 
   if (aPresContext->HasPendingInterrupt() &&
       aReflowInput.AvailableBSize() == NS_UNCONSTRAINEDSIZE) {
     // In this situation, we might be lying about our reflow status, because
     // our last kid (the one that got interrupted) was incomplete.  Fix that.
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
   }
 
-  NS_ASSERTION(NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
+  NS_ASSERTION(aStatus.IsFullyComplete() ||
                aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE,
                "Column set should be complete if the available block-size is unconstrained");
 
   // Merge overflow container bounds and status.
   aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
-  NS_MergeReflowStatusInto(&aStatus, ocStatus);
+  aStatus.MergeCompletionStatusFrom(ocStatus);
 
   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, aStatus, false);
 
   aDesiredSize.mCarriedOutBEndMargin = carriedOutBottomMargin;
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1024,18 +1024,18 @@ nsContainerFrame::ReflowChild(nsIFrame* 
     PositionChildViews(aKidFrame);
   }
 
   // Reflow the child frame
   aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
 
   // If the child frame is complete, delete any next-in-flows,
   // but only if the NO_DELETE_NEXT_IN_FLOW flag isn't set.
-  if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) &&
-      NS_FRAME_IS_FULLY_COMPLETE(aStatus) &&
+  if (!aStatus.IsInlineBreakBefore() &&
+      aStatus.IsFullyComplete() &&
       !(aFlags & NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD)) {
     nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
     if (kidNextInFlow) {
       // Remove all of the childs next-in-flows. Make sure that we ask
       // the right parent to do the removal (it's possible that the
       // parent is not this because we are executing pullup code)
       nsOverflowContinuationTracker::AutoFinish fini(aTracker, aKidFrame);
       kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
@@ -1068,17 +1068,17 @@ nsContainerFrame::ReflowChild(nsIFrame* 
     PositionChildViews(aKidFrame);
   }
 
   // Reflow the child frame
   aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
 
   // If the child frame is complete, delete any next-in-flows,
   // but only if the NO_DELETE_NEXT_IN_FLOW flag isn't set.
-  if (NS_FRAME_IS_FULLY_COMPLETE(aStatus) &&
+  if (aStatus.IsFullyComplete() &&
       !(aFlags & NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD)) {
     nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
     if (kidNextInFlow) {
       // Remove all of the childs next-in-flows. Make sure that we ask
       // the right parent to do the removal (it's possible that the
       // parent is not this because we are executing pullup code)
       nsOverflowContinuationTracker::AutoFinish fini(aTracker, aKidFrame);
       kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
@@ -1275,46 +1275,46 @@ nsContainerFrame::ReflowOverflowContaine
       ReflowChild(frame, aPresContext, desiredSize, frameState,
                   wm, pos, containerSize, aFlags, frameStatus, &tracker);
       //XXXfr Do we need to override any shrinkwrap effects here?
       // e.g. desiredSize.Width() = prevRect.width;
       FinishReflowChild(frame, aPresContext, desiredSize, &frameState,
                         wm, pos, containerSize, aFlags);
 
       // Handle continuations
-      if (!NS_FRAME_IS_FULLY_COMPLETE(frameStatus)) {
+      if (!frameStatus.IsFullyComplete()) {
         if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
           // Abspos frames can't cause their parent to be incomplete,
           // only overflow incomplete.
-          NS_FRAME_SET_OVERFLOW_INCOMPLETE(frameStatus);
+          frameStatus.SetOverflowIncomplete();
         }
         else {
-          NS_ASSERTION(NS_FRAME_IS_COMPLETE(frameStatus),
+          NS_ASSERTION(frameStatus.IsComplete(),
                        "overflow container frames can't be incomplete, only overflow-incomplete");
         }
 
         // Acquire a next-in-flow, creating it if necessary
         nsIFrame* nif = frame->GetNextInFlow();
         if (!nif) {
-          NS_ASSERTION(frameStatus & NS_FRAME_REFLOW_NEXTINFLOW,
-                       "Someone forgot a REFLOW_NEXTINFLOW flag");
+          NS_ASSERTION(frameStatus.NextInFlowNeedsReflow(),
+                       "Someone forgot a NextInFlowNeedsReflow flag");
           nif = aPresContext->PresShell()->FrameConstructor()->
             CreateContinuingFrame(aPresContext, frame, this);
         }
         else if (!(nif->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
           // used to be a normal next-in-flow; steal it from the child list
           nsresult rv = nif->GetParent()->StealFrame(nif);
           if (NS_FAILED(rv)) {
             return;
           }
         }
 
         tracker.Insert(nif, frameStatus);
       }
-      NS_MergeReflowStatusInto(&aStatus, frameStatus);
+      aStatus.MergeCompletionStatusFrom(frameStatus);
       // At this point it would be nice to assert !frame->GetOverflowRect().IsEmpty(),
       // but we have some unsplittable frames that, when taller than
       // availableHeight will push zero-height content into a next-in-flow.
     }
     else {
       tracker.Skip(frame, aStatus);
       if (aReflowInput.mFloatManager) {
         nsBlockFrame::RecoverFloatsFor(frame, *aReflowInput.mFloatManager,
@@ -2190,21 +2190,21 @@ nsOverflowContinuationTracker::Insert(ns
         if (f == nif) {
           mPrevOverflowCont = f->GetPrevSibling();
           break;
         }
       }
     }
 
     mOverflowContList->InsertFrame(mParent, mPrevOverflowCont, aOverflowCont);
-    aReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+    aReflowStatus.SetNextInFlowNeedsReflow();
   }
 
   // If we need to reflow it, mark it dirty
-  if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW)
+  if (aReflowStatus.NextInFlowNeedsReflow())
     aOverflowCont->AddStateBits(NS_FRAME_IS_DIRTY);
 
   // It's in our list, just step forward
   StepForward();
   NS_ASSERTION(mPrevOverflowCont == aOverflowCont ||
                (mSkipOverflowContainerChildren &&
                 (mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
                 (aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -323,17 +323,17 @@ public:
    * are created when the frame runs out of computed height, but still has
    * too much content to fit in the availableHeight. The parent creates a
    * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
    * and adds it to its next-in-flow's overflow container list, either by
    * adding it directly or by putting it in its own excess overflow containers
    * list (to be drained by the next-in-flow when it calls
    * ReflowOverflowContainerChildren). The parent continues reflow as if
    * the frame was complete once it ran out of computed height, but returns
-   * either an NS_FRAME_NOT_COMPLETE or NS_FRAME_OVERFLOW_INCOMPLETE reflow
+   * with either the mIncomplete or mOverflowIncomplete bit set in reflow
    * status to request a next-in-flow. The parent's next-in-flow is then
    * responsible for calling ReflowOverflowContainerChildren to (drain and)
    * reflow these overflow continuations. Overflow containers do not affect
    * other frames' size or position during reflow (but do affect their
    * parent's overflow area).
    *
    * Overflow container continuations are different from normal continuations
    * in that
@@ -371,18 +371,18 @@ public:
    * (i.e. don't affect sizing or placement of other children) and inherit
    * width and horizontal position from their prev-in-flow.
    *
    * This method
    *   1. Pulls excess overflow containers from the prev-in-flow and adds
    *      them to our overflow container list
    *   2. Reflows all our overflow container kids
    *   3. Expands aOverflowRect as necessary to accomodate these children.
-   *   4. Sets aStatus's NS_FRAME_OVERFLOW_IS_INCOMPLETE flag (along with
-   *      NS_FRAME_REFLOW_NEXTINFLOW as necessary) if any overflow children
+   *   4. Sets aStatus's mOverflowIncomplete flag (along with
+   *      mNextInFlowNeedsReflow as necessary) if any overflow children
    *      are incomplete and
    *   5. Prepends a list of their continuations to our excess overflow
    *      container list, to be drained into our next-in-flow when it is
    *      reflowed.
    *
    * The caller is responsible for tracking any new overflow container
    * continuations it makes, removing them from its child list, and
    * making sure they are stored properly in the overflow container lists.
@@ -834,29 +834,31 @@ public:
     }
   private:
     nsOverflowContinuationTracker* mTracker;
     nsIFrame* mChild;
   };
 
   /**
    * This function should be called for each child that isn't reflowed.
-   * It increments our walker and sets the NS_FRAME_OVERFLOW_INCOMPLETE
+   * It increments our walker and sets the mOverflowIncomplete
    * reflow flag if it encounters an overflow continuation so that our
    * next-in-flow doesn't get prematurely deleted. It MUST be called on
    * each unreflowed child that has an overflow container continuation;
    * it MAY be called on other children, but it isn't necessary (doesn't
    * do anything).
    */
   void Skip(nsIFrame* aChild, nsReflowStatus& aReflowStatus)
   {
     NS_PRECONDITION(aChild, "null ptr");
     if (aChild == mSentry) {
       StepForward();
-      NS_MergeReflowStatusInto(&aReflowStatus, NS_FRAME_OVERFLOW_INCOMPLETE);
+      if (aReflowStatus.IsComplete()) {
+        aReflowStatus.SetOverflowIncomplete();
+      }
     }
   }
 
 private:
 
   /**
    * @see class AutoFinish
    */
--- a/layout/generic/nsFirstLetterFrame.cpp
+++ b/layout/generic/nsFirstLetterFrame.cpp
@@ -260,20 +260,20 @@ nsFirstLetterFrame::Reflow(nsPresContext
       aMetrics.SetBlockStartAscent(kidMetrics.BlockStartAscent() +
                                    bp.BStart(wm));
       aMetrics.BSize(lineWM) = kidMetrics.BSize(lineWM) + bp.BStartEnd(wm);
     } else {
       nsLayoutUtils::SetBSizeFromFontMetrics(this, aMetrics, bp, lineWM, wm);
     }
   }
 
-  if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
+  if (!aReflowStatus.IsInlineBreakBefore()) {
     // Create a continuation or remove existing continuations based on
     // the reflow completion status.
-    if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
+    if (aReflowStatus.IsComplete()) {
       if (aReflowInput.mLineLayout) {
         aReflowInput.mLineLayout->SetFirstLetterStyleOK(false);
       }
       nsIFrame* kidNextInFlow = kid->GetNextInFlow();
       if (kidNextInFlow) {
         // Remove all of the childs next-in-flows
         kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
       }
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -1841,17 +1841,17 @@ nsFlexContainerFrame::MeasureAscentAndHe
   ReflowChild(aItem.Frame(), aPresContext,
               childDesiredSize, aChildReflowInput,
               0, 0, flags, childReflowStatus);
   aItem.SetHadMeasuringReflow();
 
   // XXXdholbert Once we do pagination / splitting, we'll need to actually
   // handle incomplete childReflowStatuses. But for now, we give our kids
   // unconstrained available height, which means they should always complete.
-  MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
+  MOZ_ASSERT(childReflowStatus.IsComplete(),
              "We gave flex item unconstrained available height, so it "
              "should be complete");
 
   // Tell the child we're done with its initial reflow.
   // (Necessary for e.g. GetBaseline() to work below w/out asserting)
   FinishReflowChild(aItem.Frame(), aPresContext,
                     childDesiredSize, &aChildReflowInput, 0, 0, flags);
 
@@ -3898,17 +3898,17 @@ ResolveFlexContainerMainSize(const Reflo
 
     // Fragmenting *and* our fixed BSize is larger than available BSize:
     // Mark incomplete so we get a next-in-flow, and take up all of the
     // available BSize (or the amount of BSize required by our children, if
     // that's larger; but of course not more than our own computed BSize).
     // XXXdholbert For now, we don't support pushing children to our next
     // continuation or splitting children, so "amount of BSize required by
     // our children" is just the main-size (BSize) of our longest flex line.
-    NS_FRAME_SET_INCOMPLETE(aStatus);
+    aStatus.SetIncomplete();
     nscoord largestLineOuterSize = GetLargestLineMainSize(aFirstLine);
 
     if (largestLineOuterSize <= aAvailableBSizeForContent) {
       return aAvailableBSizeForContent;
     }
     return std::min(aTentativeMainSize, largestLineOuterSize);
   }
 
@@ -3958,17 +3958,17 @@ nsFlexContainerFrame::ComputeCrossSize(c
 
     // Fragmenting *and* our fixed BSize is too tall for available BSize:
     // Mark incomplete so we get a next-in-flow, and take up all of the
     // available BSize (or the amount of BSize required by our children, if
     // that's larger; but of course not more than our own computed BSize).
     // XXXdholbert For now, we don't support pushing children to our next
     // continuation or splitting children, so "amount of BSize required by
     // our children" is just the sum of our FlexLines' BSizes (cross sizes).
-    NS_FRAME_SET_INCOMPLETE(aStatus);
+    aStatus.SetIncomplete();
     if (aSumLineCrossSizes <= aAvailableBSizeForContent) {
       return aAvailableBSizeForContent;
     }
     return std::min(effectiveComputedBSize, aSumLineCrossSizes);
   }
 
   // Row-oriented case (cross axis is block axis), with auto BSize:
   // Shrink-wrap our line(s), subject to our min-size / max-size
@@ -4324,17 +4324,17 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
                                    ReflowOutput&     aDesiredSize,
                                    const ReflowInput& aReflowInput,
                                    nsReflowStatus&          aStatus,
                                    nscoord aContentBoxMainSize,
                                    nscoord aAvailableBSizeForContent,
                                    nsTArray<StrutInfo>& aStruts,
                                    const FlexboxAxisTracker& aAxisTracker)
 {
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   LinkedList<FlexLine> lines;
   nsTArray<nsIFrame*> placeholderKids;
   AutoFlexLineListClearer cleanupLines(lines);
 
   GenerateFlexLines(aPresContext, aReflowInput,
                     aContentBoxMainSize,
                     aAvailableBSizeForContent,
@@ -4621,29 +4621,29 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
 
   // Now: If we're complete, add bottom border/padding to desired height (which
   // we skipped via skipSides) -- unless that pushes us over available height,
   // in which case we become incomplete (unless we already weren't asking for
   // any height, in which case we stay complete to avoid looping forever).
   // NOTE: If we're auto-height, we allow our bottom border/padding to push us
   // over the available height without requesting a continuation, for
   // consistency with the behavior of "display:block" elements.
-  if (NS_FRAME_IS_COMPLETE(aStatus)) {
+  if (aStatus.IsComplete()) {
     nscoord desiredBSizeWithBEndBP =
       desiredSizeInFlexWM.BSize(flexWM) + blockEndContainerBP;
 
     if (aReflowInput.AvailableBSize() == NS_UNCONSTRAINEDSIZE ||
         desiredSizeInFlexWM.BSize(flexWM) == 0 ||
         desiredBSizeWithBEndBP <= aReflowInput.AvailableBSize() ||
         aReflowInput.ComputedBSize() == NS_INTRINSICSIZE) {
       // Update desired height to include block-end border/padding
       desiredSizeInFlexWM.BSize(flexWM) = desiredBSizeWithBEndBP;
     } else {
       // We couldn't fit bottom border/padding, so we'll need a continuation.
-      NS_FRAME_SET_INCOMPLETE(aStatus);
+      aStatus.SetIncomplete();
     }
   }
 
   // Calculate the container baselines so that our parent can baseline-align us.
   mBaselineFromLastReflow = flexContainerAscent;
   mLastBaselineFromLastReflow = lines.getLast()->GetLastBaselineOffset();
   if (mLastBaselineFromLastReflow == nscoord_MIN) {
     // XXX we fall back to a mirrored first baseline here for now, but this
@@ -4775,17 +4775,17 @@ nsFlexContainerFrame::ReflowFlexItem(nsP
               childDesiredSize, childReflowInput,
               outerWM, aFramePos, aContainerSize,
               0, childReflowStatus);
 
   // XXXdholbert Once we do pagination / splitting, we'll need to actually
   // handle incomplete childReflowStatuses. But for now, we give our kids
   // unconstrained available height, which means they should always
   // complete.
-  MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
+  MOZ_ASSERT(childReflowStatus.IsComplete(),
              "We gave flex item unconstrained available height, so it "
              "should be complete");
 
   LogicalMargin offsets =
     childReflowInput.ComputedLogicalOffsets().ConvertTo(outerWM, wm);
   ReflowInput::ApplyRelativePositioning(aItem.Frame(), outerWM,
                                               offsets, &aFramePos,
                                               aContainerSize);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -183,19 +183,64 @@ InitBoxMetrics(nsIFrame* aFrame, bool aC
 static bool
 IsXULBoxWrapped(const nsIFrame* aFrame)
 {
   return aFrame->GetParent() &&
          aFrame->GetParent()->IsXULBoxFrame() &&
          !aFrame->IsXULBoxFrame();
 }
 
+void
+nsReflowStatus::UpdateTruncated(const ReflowInput& aReflowInput,
+                                const ReflowOutput& aMetrics)
+{
+  const WritingMode containerWM = aMetrics.GetWritingMode();
+  if (aReflowInput.GetWritingMode().IsOrthogonalTo(containerWM)) {
+    // Orthogonal flows are always reflowed with an unconstrained dimension,
+    // so should never end up truncated (see ReflowInput::Init()).
+    mTruncated = false;
+  } else if (aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE &&
+             aReflowInput.AvailableBSize() < aMetrics.BSize(containerWM) &&
+             !aReflowInput.mFlags.mIsTopOfPage) {
+    mTruncated = true;
+  } else {
+    mTruncated = false;
+  }
+}
+
 // Formerly the nsIFrameDebug interface
 
 #ifdef DEBUG
+std::ostream& operator<<(std::ostream& aStream,
+                         const nsReflowStatus& aStatus)
+{
+  char complete = 'Y';
+  if (aStatus.IsIncomplete()) {
+    complete = 'N';
+  } else if (aStatus.IsOverflowIncomplete()) {
+    complete = 'O';
+  }
+
+  char brk = 'N';
+  if (aStatus.IsInlineBreakBefore()) {
+    brk = 'B';
+  } else if (aStatus.IsInlineBreakAfter()) {
+    brk = 'A';
+  }
+
+  aStream << "["
+          << "Complete=" << complete << ","
+          << "NIF=" << (aStatus.NextInFlowNeedsReflow() ? 'Y' : 'N') << ","
+          << "Truncated=" << (aStatus.IsTruncated() ? 'Y' : 'N') << ","
+          << "Break=" << brk << ","
+          << "FirstLetter=" << (aStatus.FirstLetterComplete() ? 'Y' : 'N')
+          << "]";
+  return aStream;
+}
+
 static bool gShowFrameBorders = false;
 
 void nsFrame::ShowFrameBorders(bool aEnable)
 {
   gShowFrameBorders = aEnable;
 }
 
 bool nsFrame::GetShowFrameBorders()
@@ -357,27 +402,16 @@ nsIFrame::FindCloserFrameForSelection(
 }
 
 void
 nsIFrame::ContentStatesChanged(mozilla::EventStates aStates)
 {
 }
 
 void
-NS_MergeReflowStatusInto(nsReflowStatus* aPrimary, nsReflowStatus aSecondary)
-{
-  *aPrimary |= aSecondary &
-    (NS_FRAME_NOT_COMPLETE | NS_FRAME_OVERFLOW_INCOMPLETE |
-     NS_FRAME_TRUNCATED | NS_FRAME_REFLOW_NEXTINFLOW);
-  if (*aPrimary & NS_FRAME_NOT_COMPLETE) {
-    *aPrimary &= ~NS_FRAME_OVERFLOW_INCOMPLETE;
-  }
-}
-
-void
 nsWeakFrame::Init(nsIFrame* aFrame)
 {
   Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
   mFrame = aFrame;
   if (mFrame) {
     nsIPresShell* shell = mFrame->PresContext()->GetPresShell();
     NS_WARNING_ASSERTION(shell, "Null PresShell in nsWeakFrame!");
     if (shell) {
@@ -4934,17 +4968,17 @@ nsFrame::ComputeSize(nsRenderingContext*
     // flex items. However, we don't need to worry about that here, because
     // flex items' min-sizes are intentionally ignored until the flex
     // container explicitly considers them during space distribution.
     minISize = 0;
   }
   result.ISize(aWM) = std::max(minISize, result.ISize(aWM));
 
   // Compute block-axis size
-  // (but not if we have auto bsize or if we recieved the "eUseAutoBSize"
+  // (but not if we have auto bsize or if we received the "eUseAutoBSize"
   // flag -- then, we'll just stick with the bsize that we already calculated
   // in the initial ComputeAutoSize() call.)
   if (!(aFlags & nsIFrame::eUseAutoBSize)) {
     if (!nsLayoutUtils::IsAutoBSize(*blockStyleCoord, aCBSize.BSize(aWM))) {
       result.BSize(aWM) =
         nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
                                          boxSizingAdjust.BSize(aWM),
                                          *blockStyleCoord);
@@ -5712,17 +5746,17 @@ void
 nsFrame::Reflow(nsPresContext*          aPresContext,
                 ReflowOutput&     aDesiredSize,
                 const ReflowInput& aReflowInput,
                 nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsFrame");
   aDesiredSize.ClearSize();
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 nsresult
 nsFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
 {
   NS_NOTREACHED("should only be called for text frames");
   return NS_OK;
@@ -6747,23 +6781,22 @@ nsFrame::IsFrameTreeTooDeep(const Reflow
     NS_WARNING("frame tree too deep; setting zero size and returning");
     mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
     ClearOverflowRects();
     aMetrics.ClearSize();
     aMetrics.SetBlockStartAscent(0);
     aMetrics.mCarriedOutBEndMargin.Zero();
     aMetrics.mOverflowAreas.Clear();
 
+    aStatus.Reset();
     if (GetNextInFlow()) {
       // Reflow depth might vary between reflows, so we might have
       // successfully reflowed and split this frame before.  If so, we
       // shouldn't delete its continuations.
-      aStatus = NS_FRAME_NOT_COMPLETE;
-    } else {
-      aStatus = NS_FRAME_COMPLETE;
+      aStatus.SetIncomplete();
     }
 
     return true;
   }
   mState &= ~NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
   return false;
 }
 
@@ -9729,17 +9762,17 @@ nsFrame::DoXULLayout(nsBoxLayoutState& a
                                   aState.GetRenderingContext(),
                                   LogicalSize(ourWM, ISize(),
                                               NS_UNCONSTRAINEDSIZE),
                                   ReflowInput::DUMMY_PARENT_REFLOW_STATE);
 
     AddStateBits(NS_FRAME_IN_REFLOW);
     // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
     // (just a dummy value; hopefully that's OK)
-    nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
+    nsReflowStatus reflowStatus;
     ReflowAbsoluteFrames(aState.PresContext(), desiredSize,
                          reflowInput, reflowStatus);
     RemoveStateBits(NS_FRAME_IN_REFLOW);
   }
 
   nsSize oldSize(ourRect.Size());
   FinishAndStoreOverflow(desiredSize.mOverflowAreas,
                          size.GetPhysicalSize(outerWM), &oldSize);
@@ -9766,17 +9799,17 @@ nsFrame::BoxReflow(nsBoxLayoutState&    
   nsAdaptorAddIndents();
   printf("Reflowing: ");
   nsFrame::ListTag(stdout, mFrame);
   printf("\n");
   gIndent2++;
 #endif
 
   nsBoxLayoutMetrics *metrics = BoxMetrics();
-  nsReflowStatus status = NS_FRAME_COMPLETE;
+  nsReflowStatus status;
   WritingMode wm = aDesiredSize.GetWritingMode();
 
   bool needsReflow = NS_SUBTREE_DIRTY(this);
 
   // if we don't need a reflow then 
   // lets see if we are already that size. Yes? then don't even reflow. We are done.
   if (!needsReflow) {
       
@@ -9941,17 +9974,17 @@ nsFrame::BoxReflow(nsBoxLayoutState&    
       nsAdaptorPrintReason(reflowInput);
       printf("\n");
     #endif
 
        // place the child and reflow
 
     Reflow(aPresContext, aDesiredSize, reflowInput, status);
 
-    NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
+    NS_ASSERTION(status.IsComplete(), "bad status");
 
     uint32_t layoutFlags = aState.LayoutFlags();
     nsContainerFrame::FinishReflowChild(this, aPresContext, aDesiredSize,
                                         &reflowInput, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME);
 
     // Save the ascent.  (bug 103925)
     if (IsXULCollapsed()) {
       metrics->mAscent = 0;
@@ -10335,18 +10368,18 @@ nsFrame::Trace(const char* aMethod, bool
 void
 nsFrame::Trace(const char* aMethod, bool aEnter, nsReflowStatus aStatus)
 {
   if (NS_FRAME_LOG_TEST(sFrameLogModule, NS_FRAME_TRACE_CALLS)) {
     char tagbuf[40];
     GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
     PR_LogPrint("%s: %s %s, status=%scomplete%s",
                 tagbuf, aEnter ? "enter" : "exit", aMethod,
-                NS_FRAME_IS_NOT_COMPLETE(aStatus) ? "not" : "",
-                (NS_FRAME_REFLOW_NEXTINFLOW & aStatus) ? "+reflow" : "");
+                aStatus.IsIncomplete() ? "not" : "",
+                (aStatus.NextInFlowNeedsReflow()) ? "+reflow" : "");
   }
 }
 
 void
 nsFrame::TraceMsg(const char* aFormatString, ...)
 {
   if (NS_FRAME_LOG_TEST(sFrameLogModule, NS_FRAME_TRACE_CALLS)) {
     // Format arguments into a buffer
@@ -11197,21 +11230,21 @@ void* nsFrame::DisplayIntrinsicSizeEnter
   DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, nullptr);
   if (treeNode && treeNode->mDisplay) {
     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
     printf("Get%sSize\n", aType);
   }
   return treeNode;
 }
 
-void nsFrame::DisplayReflowExit(nsPresContext*      aPresContext,
-                                nsIFrame*            aFrame,
+void nsFrame::DisplayReflowExit(nsPresContext* aPresContext,
+                                nsIFrame* aFrame,
                                 ReflowOutput& aMetrics,
-                                nsReflowStatus       aStatus,
-                                void*                aFrameTreeNode)
+                                const nsReflowStatus& aStatus,
+                                void* aFrameTreeNode)
 {
   if (!DR_state->mActive) return;
 
   NS_ASSERTION(aFrame, "DisplayReflowExit - invalid call");
   if (!aFrameTreeNode) return;
 
   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
   if (treeNode->mDisplay) {
@@ -11220,18 +11253,18 @@ void nsFrame::DisplayReflowExit(nsPresCo
     char width[16];
     char height[16];
     char x[16];
     char y[16];
     DR_state->PrettyUC(aMetrics.Width(), width, 16);
     DR_state->PrettyUC(aMetrics.Height(), height, 16);
     printf("Reflow d=%s,%s", width, height);
 
-    if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
-      printf(" status=0x%x", aStatus);
+    if (!aStatus.IsFullyComplete()) {
+      printf(" status=%s", ToString(aStatus).c_str());
     }
     if (aFrame->HasOverflowAreas()) {
       DR_state->PrettyUC(aMetrics.VisualOverflow().x, x, 16);
       DR_state->PrettyUC(aMetrics.VisualOverflow().y, y, 16);
       DR_state->PrettyUC(aMetrics.VisualOverflow().width, width, 16);
       DR_state->PrettyUC(aMetrics.VisualOverflow().height, height, 16);
       printf(" vis-o=(%s,%s) %s x %s", x, y, width, height);
 
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -502,21 +502,21 @@ public:
   static void* DisplayReflowEnter(nsPresContext*          aPresContext,
                                   nsIFrame*                aFrame,
                                   const ReflowInput& aReflowInput);
   static void* DisplayLayoutEnter(nsIFrame* aFrame);
   static void* DisplayIntrinsicISizeEnter(nsIFrame* aFrame,
                                           const char* aType);
   static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
                                          const char* aType);
-  static void DisplayReflowExit(nsPresContext*      aPresContext,
-                                 nsIFrame*            aFrame,
-                                 ReflowOutput& aMetrics,
-                                 uint32_t             aStatus,
-                                 void*                aFrameTreeNode);
+  static void DisplayReflowExit(nsPresContext* aPresContext,
+                                nsIFrame* aFrame,
+                                ReflowOutput& aMetrics,
+                                const nsReflowStatus& aStatus,
+                                void* aFrameTreeNode);
   static void DisplayLayoutExit(nsIFrame* aFrame,
                                  void* aFrameTreeNode);
   static void DisplayIntrinsicISizeExit(nsIFrame* aFrame,
                                          const char* aType,
                                          nscoord aResult,
                                          void* aFrameTreeNode);
   static void DisplayIntrinsicSizeExit(nsIFrame* aFrame,
                                         const char* aType,
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -700,17 +700,17 @@ nsHTMLFramesetFrame::ReflowPlaceChild(ns
   reflowInput.SetComputedHeight(std::max(0, aSize.height - reflowInput.ComputedPhysicalBorderPadding().TopBottom()));
   ReflowOutput reflowOutput(aReflowInput);
   reflowOutput.Width() = aSize.width;
   reflowOutput.Height() = aSize.height;
   nsReflowStatus status;
 
   ReflowChild(aChild, aPresContext, reflowOutput, reflowInput, aOffset.x,
               aOffset.y, 0, status);
-  NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
+  NS_ASSERTION(status.IsComplete(), "bad status");
 
   // Place and size the child
   reflowOutput.Width() = aSize.width;
   reflowOutput.Height() = aSize.height;
   FinishReflowChild(aChild, aPresContext, reflowOutput, nullptr, aOffset.x, aOffset.y, 0);
 }
 
 static
@@ -844,17 +844,17 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
   const nsFramesetSpec* colSpecs = nullptr;
   int32_t rows = 0;
   int32_t cols = 0;
   ourContent->GetRowSpec(&rows, &rowSpecs);
   ourContent->GetColSpec(&cols, &colSpecs);
   // If the number of cols or rows has changed, the frame for the frameset
   // will be re-created.
   if (mNumRows != rows || mNumCols != cols) {
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     mDrag.UnSet();
     NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     return;
   }
 
   CalculateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes.get());
   CalculateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes.get());
 
@@ -1079,17 +1079,17 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
         mHorBorders[horX]->SetColor(childColor);
       }
     }
 
     mChildFrameborder.reset();
     mChildBorderColors.reset();
   }
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   mDrag.UnSet();
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
@@ -1389,17 +1389,17 @@ nsHTMLFramesetBorderFrame::Reflow(nsPres
   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
 
   // Override Reflow(), since we don't want to deal with what our
   // computed values are.
   SizeToAvailSize(aReflowInput, aDesiredSize);
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 }
 
 class nsDisplayFramesetBorder : public nsDisplayItem {
 public:
   nsDisplayFramesetBorder(nsDisplayListBuilder* aBuilder,
                           nsHTMLFramesetBorderFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFramesetBorder);
@@ -1604,17 +1604,17 @@ nsHTMLFramesetBlankFrame::Reflow(nsPresC
 {
   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame");
 
   // Override Reflow(), since we don't want to deal with what our
   // computed values are.
   SizeToAvailSize(aReflowInput, aDesiredSize);
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 }
 
 class nsDisplayFramesetBlank : public nsDisplayItem {
 public:
   nsDisplayFramesetBlank(nsDisplayListBuilder* aBuilder,
                          nsIFrame* aFrame) :
     nsDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFramesetBlank);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1101,17 +1101,17 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
   }
 
   if (mHelper.mIsRoot && !oldScrolledAreaBounds.IsEqualEdges(newScrolledAreaBounds)) {
     mHelper.PostScrolledAreaEvent();
   }
 
   mHelper.UpdatePrevScrolledRect();
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
   mHelper.PostOverflowEvent();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 
 #ifdef DEBUG_FRAME_DUMP
@@ -2986,17 +2986,20 @@ AppendToTop(nsDisplayListBuilder* aBuild
     return;
 
   nsDisplayWrapList* newItem;
   const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot();
   if (aFlags & APPEND_OWN_LAYER) {
     uint32_t flags = (aFlags & APPEND_SCROLLBAR_CONTAINER)
                      ? nsDisplayOwnLayer::SCROLLBAR_CONTAINER
                      : 0;
-    newItem = new (aBuilder) nsDisplayOwnLayer(aBuilder, aSourceFrame, aSource, asr, flags);
+    FrameMetrics::ViewID scrollTarget = (aFlags & APPEND_SCROLLBAR_CONTAINER)
+                                        ? aBuilder->GetCurrentScrollbarTarget()
+                                        : FrameMetrics::NULL_SCROLL_ID;
+    newItem = new (aBuilder) nsDisplayOwnLayer(aBuilder, aSourceFrame, aSource, asr, flags, scrollTarget);
   } else {
     newItem = new (aBuilder) nsDisplayWrapList(aBuilder, aSourceFrame, aSource, asr);
   }
 
   if (aFlags & APPEND_POSITIONED) {
     // We want overlay scrollbars to always be on top of the scrolled content,
     // but we don't want them to unnecessarily cover overlapping elements from
     // outside our scroll frame.
@@ -3092,17 +3095,18 @@ ScrollFrameHelper::AppendScrollPartsTo(n
                    : aDirtyRect;
     nsDisplayListBuilder::AutoBuildingDisplayList
       buildingForChild(aBuilder, scrollParts[i],
                        dirty + mOuter->GetOffsetTo(scrollParts[i]), true);
 
     // Always create layers for overlay scrollbars so that we don't create a
     // giant layer covering the whole scrollport if both scrollbars are visible.
     bool isOverlayScrollbar = (flags != 0) && overlayScrollbars;
-    bool createLayer = aCreateLayer || isOverlayScrollbar;
+    bool createLayer = aCreateLayer || isOverlayScrollbar ||
+        gfxPrefs::AlwaysLayerizeScrollbarTrackTestOnly();
 
     nsDisplayListBuilder::AutoCurrentScrollbarInfoSetter
       infoSetter(aBuilder, scrollTargetId, flags, createLayer);
     nsDisplayListCollection partList;
     mOuter->BuildDisplayListForChild(
       aBuilder, scrollParts[i], dirty, partList,
       nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
 
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -95,22 +95,22 @@ ClampToCSSMaxBSize(nscoord aSize, const 
 static nscoord
 ClampToCSSMaxBSize(nscoord aSize, const ReflowInput* aReflowInput,
                    nsReflowStatus* aStatus)
 {
   auto maxSize = aReflowInput->ComputedMaxBSize();
   if (MOZ_UNLIKELY(maxSize != NS_UNCONSTRAINEDSIZE)) {
     MOZ_ASSERT(aReflowInput->ComputedMinBSize() <= maxSize);
     if (aSize < maxSize) {
-      NS_FRAME_SET_INCOMPLETE(*aStatus);
+      aStatus->SetIncomplete();
     } else {
       aSize = maxSize;
     }
   } else {
-    NS_FRAME_SET_INCOMPLETE(*aStatus);
+    aStatus->SetIncomplete();
   }
   return aSize;
 }
 
 static bool
 IsPercentOfIndefiniteSize(const nsStyleCoord& aCoord, nscoord aPercentBasis)
 {
   return aPercentBasis == NS_UNCONSTRAINEDSIZE && aCoord.HasPercent();
@@ -5282,17 +5282,17 @@ nsGridContainerFrame::ReflowInFlowChild(
   ReflowChild(aChild, pc, childSize, childRI, childWM, LogicalPoint(childWM),
               dummyContainerSize, 0, aStatus);
   LogicalPoint childPos =
     cb.Origin(wm).ConvertTo(childWM, wm,
                             aContainerSize - childSize.PhysicalSize());
   // Apply align/justify-self and reflow again if that affects the size.
   if (MOZ_LIKELY(isGridItem)) {
     LogicalSize size = childSize.Size(childWM); // from the ReflowChild()
-    if (NS_FRAME_IS_COMPLETE(aStatus)) {
+    if (aStatus.IsComplete()) {
       auto align = childRI.mStylePosition->UsedAlignSelf(containerSC);
       auto state = aGridItemInfo->mState[eLogicalAxisBlock];
       if (state & ItemState::eContentBaseline) {
         align = (state & ItemState::eFirstBaseline) ? NS_STYLE_ALIGN_SELF_START
                                                     : NS_STYLE_ALIGN_SELF_END;
       }
       nscoord cbsz = cb.BSize(wm) - consumedGridAreaBSize;
       AlignSelf(*aGridItemInfo, align, cbsz, wm, childRI, size, &childPos);
@@ -5316,17 +5316,17 @@ nsGridContainerFrame::ReflowInFlowChild(
 nscoord
 nsGridContainerFrame::ReflowInFragmentainer(GridReflowInput&     aState,
                                             const LogicalRect&   aContentArea,
                                             ReflowOutput& aDesiredSize,
                                             nsReflowStatus&      aStatus,
                                             Fragmentainer&       aFragmentainer,
                                             const nsSize&        aContainerSize)
 {
-  MOZ_ASSERT(aStatus == NS_FRAME_COMPLETE);
+  MOZ_ASSERT(aStatus.IsEmpty());
   MOZ_ASSERT(aState.mReflowInput);
 
   // Collect our grid items and sort them in row order.  Collect placeholders
   // and put them in a separate array.
   nsTArray<const GridItemInfo*> sortedItems(aState.mGridItems.Length());
   nsTArray<nsIFrame*> placeholders(aState.mAbsPosItems.Length());
   aState.mIter.Reset(GridItemCSSOrderIterator::eIncludeAll);
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
@@ -5343,17 +5343,17 @@ nsGridContainerFrame::ReflowInFragmentai
   std::sort(sortedItems.begin(), sortedItems.end(),
             GridItemInfo::IsStartRowLessThan);
 
   // Reflow our placeholder children; they must all be complete.
   for (auto child : placeholders) {
     nsReflowStatus childStatus;
     ReflowInFlowChild(child, nullptr, aContainerSize, Nothing(), &aFragmentainer,
                       aState, aContentArea, aDesiredSize, childStatus);
-    MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childStatus),
+    MOZ_ASSERT(childStatus.IsComplete(),
                "nsPlaceholderFrame should never need to be fragmented");
   }
 
   // The available size for children - we'll set this to the edge of the last
   // row in most cases below, but for now use the full size.
   nscoord childAvailableSize = aFragmentainer.mToFragmentainerEnd;
   const uint32_t startRow = aState.mStartRow;
   const uint32_t numRows = aState.mRows.mSizes.Length();
@@ -5383,56 +5383,56 @@ nsGridContainerFrame::ReflowInFragmentai
     if (itemStartRow == endRow) {
       break;
     }
     auto disp = info->mFrame->StyleDisplay();
     if (disp->mBreakBefore) {
       // Propagate break-before on the first row to the container unless we're
       // already at top-of-page.
       if ((itemStartRow == 0 && !isTopOfPage) || avoidBreakInside) {
-        aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+        aStatus.SetInlineLineBreakBeforeAndReset();
         return aState.mFragBStart;
       }
       if ((itemStartRow > startRow ||
            (itemStartRow == startRow && !isTopOfPage)) &&
           itemStartRow < endRow) {
         endRow = itemStartRow;
         isForcedBreak = true;
         // reset any BREAK_AFTER we found on an earlier item
-        aStatus = NS_FRAME_COMPLETE;
+        aStatus.Reset();
         break;  // we're done since the items are sorted in row order
       }
     }
     uint32_t itemEndRow = info->mArea.mRows.mEnd;
     if (disp->mBreakAfter) {
       if (itemEndRow != numRows) {
         if (itemEndRow > startRow && itemEndRow < endRow) {
           endRow = itemEndRow;
           isForcedBreak = true;
           // No "break;" here since later items with break-after may have
           // a shorter span.
         }
       } else {
         // Propagate break-after on the last row to the container, we may still
         // find a break-before on this row though (and reset aStatus).
-        aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus); // tentative
+        aStatus.SetInlineLineBreakAfter(); // tentative
       }
     }
   }
 
   // Consume at least one row in each fragment until we have consumed them all.
   // Except for the first row if there's a break opportunity before it.
   if (startRow == endRow && startRow != numRows &&
       (startRow != 0 || !aFragmentainer.mCanBreakAtStart)) {
     ++endRow;
   }
 
   // Honor break-inside:avoid if we can't fit all rows.
   if (avoidBreakInside && endRow < numRows) {
-    aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aStatus.SetInlineLineBreakBeforeAndReset();
     return aState.mFragBStart;
   }
 
   // Calculate the block-size including this fragment.
   nscoord bEndRow =
     aState.mRows.GridLineEdge(endRow, GridLineSide::eBeforeGridGap);
   nscoord bSize;
   if (aFragmentainer.mIsAutoBSize) {
@@ -5458,17 +5458,17 @@ nsGridContainerFrame::ReflowInFragmentai
                           aState.mReflowInput->ComputedMinBSize(),
                           aState.mReflowInput->ComputedMaxBSize());
   }
 
   // Check for overflow and set aStatus INCOMPLETE if so.
   bool overflow = bSize + bpBEnd > childAvailableSize;
   if (overflow) {
     if (avoidBreakInside) {
-      aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      aStatus.SetInlineLineBreakBeforeAndReset();
       return aState.mFragBStart;
     }
     bool breakAfterLastRow = endRow == numRows && aFragmentainer.mCanBreakAtEnd;
     if (breakAfterLastRow) {
       MOZ_ASSERT(bEndRow < bSize, "bogus aFragmentainer.mCanBreakAtEnd");
       nscoord availableSize = childAvailableSize;
       if (isBDBClone) {
         availableSize -= bpBEnd;
@@ -5480,50 +5480,50 @@ nsGridContainerFrame::ReflowInFragmentai
       // Fill the fragmentainer, but not more than our desired block-size and
       // at least to the size of the last row (even if that overflows).
       nscoord newBSize = std::min(bSize, availableSize);
       newBSize = std::max(newBSize, bEndRow);
       // If it's just the border+padding that is overflowing and we have
       // box-decoration-break:clone then we are technically COMPLETE.  There's
       // no point in creating another zero-bsize fragment in this case.
       if (newBSize < bSize || !isBDBClone) {
-        NS_FRAME_SET_INCOMPLETE(aStatus);
+        aStatus.SetIncomplete();
       }
       bSize = newBSize;
     } else if (bSize <= bEndRow && startRow + 1 < endRow) {
       if (endRow == numRows) {
         // We have more than one row in this fragment, so we can break before
         // the last row instead.
         --endRow;
         bEndRow = aState.mRows.GridLineEdge(endRow, GridLineSide::eBeforeGridGap);
         bSize = bEndRow;
         if (aFragmentainer.mIsAutoBSize) {
           bSize = ClampToCSSMaxBSize(bSize, aState.mReflowInput);
         }
       }
-      NS_FRAME_SET_INCOMPLETE(aStatus);
+      aStatus.SetIncomplete();
     } else if (endRow < numRows) {
       bSize = ClampToCSSMaxBSize(bEndRow, aState.mReflowInput, &aStatus);
     } // else - no break opportunities.
   } else {
     // Even though our block-size fits we need to honor forced breaks, or if
     // a row doesn't fit in an auto-sized container (unless it's constrained
     // by a max-bsize which make us overflow-incomplete).
     if (endRow < numRows && (isForcedBreak ||
                              (aFragmentainer.mIsAutoBSize && bEndRow == bSize))) {
       bSize = ClampToCSSMaxBSize(bEndRow, aState.mReflowInput, &aStatus);
     }
   }
 
   // If we can't fit all rows then we're at least overflow-incomplete.
   if (endRow < numRows) {
     childAvailableSize = bEndRow;
-    if (NS_FRAME_IS_COMPLETE(aStatus)) {
-      NS_FRAME_SET_OVERFLOW_INCOMPLETE(aStatus);
-      aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+    if (aStatus.IsComplete()) {
+      aStatus.SetOverflowIncomplete();
+      aStatus.SetNextInFlowNeedsReflow();
     }
   } else {
     // Children always have the full size of the rows in this fragment.
     childAvailableSize = std::max(childAvailableSize, bEndRow);
   }
 
   return ReflowRowsInFragmentainer(aState, aContentArea, aDesiredSize, aStatus,
                                    aFragmentainer, aContainerSize, sortedItems,
@@ -5620,26 +5620,26 @@ nsGridContainerFrame::ReflowRowsInFragme
     // Pass along how much to stretch this fragment, in case it's needed.
     nscoord bSize =
       aState.mRows.GridLineEdge(std::min(aEndRow, info->mArea.mRows.mEnd),
                                 GridLineSide::eBeforeGridGap) -
       aState.mRows.GridLineEdge(std::max(aStartRow, row),
                                 GridLineSide::eAfterGridGap);
     ReflowInFlowChild(child, info, aContainerSize, Some(bSize), &aFragmentainer,
                       aState, aContentArea, aDesiredSize, childStatus);
-    MOZ_ASSERT(NS_INLINE_IS_BREAK_BEFORE(childStatus) ||
-               !NS_FRAME_IS_FULLY_COMPLETE(childStatus) ||
+    MOZ_ASSERT(childStatus.IsInlineBreakBefore() ||
+               !childStatus.IsFullyComplete() ||
                !child->GetNextInFlow(),
                "fully-complete reflow should destroy any NIFs");
 
-    if (NS_INLINE_IS_BREAK_BEFORE(childStatus)) {
+    if (childStatus.IsInlineBreakBefore()) {
       MOZ_ASSERT(!child->GetPrevInFlow(),
                  "continuations should never report BREAK_BEFORE status");
       MOZ_ASSERT(!aFragmentainer.mIsTopOfPage,
-                 "got NS_INLINE_IS_BREAK_BEFORE at top of page");
+                 "got IsInlineBreakBefore() at top of page");
       if (!didGrowRow) {
         if (rowCanGrow) {
           // Grow this row and restart with the next row as |aEndRow|.
           aState.mRows.ResizeRow(row, maxRowSize);
           if (aState.mSharedGridData) {
             aState.mSharedGridData->mRows.ResizeRow(row, maxRowSize);
           }
           didGrowRow = true;
@@ -5648,68 +5648,68 @@ nsGridContainerFrame::ReflowRowsInFragme
           isRowTopOfPage = isStartRowTopOfPage;
           overflowIncompleteItems.Clear();
           incompleteItems.Clear();
           nscoord bEndRow =
             aState.mRows.GridLineEdge(aEndRow, GridLineSide::eBeforeGridGap);
           aFragmentainer.mToFragmentainerEnd = bEndRow;
           if (aFragmentainer.mIsAutoBSize) {
             aBSize = ClampToCSSMaxBSize(bEndRow, aState.mReflowInput, &aStatus);
-          } else if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
+          } else if (aStatus.IsIncomplete()) {
             aBSize = NS_CSS_MINMAX(aState.mReflowInput->ComputedBSize(),
                                    aState.mReflowInput->ComputedMinBSize(),
                                    aState.mReflowInput->ComputedMaxBSize());
             aBSize = std::min(bEndRow, aBSize);
           }
           continue;
         }
 
         if (!isRowTopOfPage) {
           // We can break before this row - restart with it as the new end row.
           aEndRow = row;
           aBSize = aState.mRows.GridLineEdge(aEndRow, GridLineSide::eBeforeGridGap);
           i = -1;  // i == 0 after the next loop increment
           isRowTopOfPage = isStartRowTopOfPage;
           overflowIncompleteItems.Clear();
           incompleteItems.Clear();
-          NS_FRAME_SET_INCOMPLETE(aStatus);
+          aStatus.SetIncomplete();
           continue;
         }
         NS_ERROR("got BREAK_BEFORE at top-of-page");
-        childStatus = NS_FRAME_COMPLETE;
+        childStatus.Reset();
       } else {
         NS_ERROR("got BREAK_BEFORE again after growing the row?");
-        NS_FRAME_SET_INCOMPLETE(childStatus);
+        childStatus.SetIncomplete();
       }
-    } else if (NS_INLINE_IS_BREAK_AFTER(childStatus)) {
+    } else if (childStatus.IsInlineBreakAfter()) {
       MOZ_ASSERT_UNREACHABLE("unexpected child reflow status");
     }
 
-    if (NS_FRAME_IS_NOT_COMPLETE(childStatus)) {
+    if (childStatus.IsIncomplete()) {
       incompleteItems.PutEntry(child);
-    } else if (!NS_FRAME_IS_FULLY_COMPLETE(childStatus)) {
+    } else if (!childStatus.IsFullyComplete()) {
       overflowIncompleteItems.PutEntry(child);
     }
   }
 
   // Record a break before |aEndRow|.
   aState.mNextFragmentStartRow = aEndRow;
   if (aEndRow < aState.mRows.mSizes.Length()) {
     aState.mRows.BreakBeforeRow(aEndRow);
     if (aState.mSharedGridData) {
       aState.mSharedGridData->mRows.BreakBeforeRow(aEndRow);
     }
   }
 
   if (!pushedItems.IsEmpty() ||
       !incompleteItems.IsEmpty() ||
       !overflowIncompleteItems.IsEmpty()) {
-    if (NS_FRAME_IS_COMPLETE(aStatus)) {
-      NS_FRAME_SET_OVERFLOW_INCOMPLETE(aStatus);
-      aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+    if (aStatus.IsComplete()) {
+      aStatus.SetOverflowIncomplete();
+      aStatus.SetNextInFlowNeedsReflow();
     }
     // Iterate the children in normal document order and append them (or a NIF)
     // to one of the following frame lists according to their status.
     nsFrameList pushedList;
     nsFrameList incompleteList;
     nsFrameList overflowIncompleteList;
     auto* pc = PresContext();
     auto* fc = pc->PresShell()->FrameConstructor();
@@ -5819,19 +5819,19 @@ nsGridContainerFrame::ReflowRowsInFragme
 nscoord
 nsGridContainerFrame::ReflowChildren(GridReflowInput&     aState,
                                      const LogicalRect&   aContentArea,
                                      ReflowOutput& aDesiredSize,
                                      nsReflowStatus&      aStatus)
 {
   MOZ_ASSERT(aState.mReflowInput);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   nsOverflowAreas ocBounds;
-  nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus ocStatus;
   if (GetPrevInFlow()) {
     ReflowOverflowContainerChildren(PresContext(), *aState.mReflowInput,
                                     ocBounds, 0, ocStatus,
                                     MergeSortedFrameListsFor);
   }
 
   WritingMode wm = aState.mReflowInput->GetWritingMode();
   const nsSize containerSize =
@@ -5848,24 +5848,24 @@ nsGridContainerFrame::ReflowChildren(Gri
     for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
       nsIFrame* child = *aState.mIter;
       const GridItemInfo* info = nullptr;
       if (child->GetType() != nsGkAtoms::placeholderFrame) {
         info = &aState.mGridItems[aState.mIter.GridItemIndex()];
       }
       ReflowInFlowChild(*aState.mIter, info, containerSize, Nothing(), nullptr,
                         aState, aContentArea, aDesiredSize, aStatus);
-      MOZ_ASSERT(NS_FRAME_IS_COMPLETE(aStatus), "child should be complete "
+      MOZ_ASSERT(aStatus.IsComplete(), "child should be complete "
                  "in unconstrained reflow");
     }
   }
 
   // Merge overflow container bounds and status.
   aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
-  NS_MergeReflowStatusInto(&aStatus, ocStatus);
+  aStatus.MergeCompletionStatusFrom(ocStatus);
 
   if (IsAbsoluteContainer()) {
     nsFrameList children(GetChildList(GetAbsoluteListID()));
     if (!children.IsEmpty()) {
       // 'gridOrigin' is the origin of the grid (the start of the first track),
       // with respect to the grid container's padding-box (CB).
       LogicalMargin pad(aState.mReflowInput->ComputedLogicalPadding());
       const LogicalPoint gridOrigin(wm, pad.IStart(wm), pad.BStart(wm));
@@ -6152,34 +6152,34 @@ nsGridContainerFrame::Reflow(nsPresConte
     // CalculateTrackSizes did the columns.
     gridReflowInput.mRows.AlignJustifyContent(stylePos, wm, contentArea.Size(wm));
   }
 
   bSize = ReflowChildren(gridReflowInput, contentArea, aDesiredSize, aStatus);
   bSize = std::max(bSize - consumedBSize, 0);
 
   // Skip our block-end border if we're INCOMPLETE.
-  if (!NS_FRAME_IS_COMPLETE(aStatus) &&
+  if (!aStatus.IsComplete() &&
       !gridReflowInput.mSkipSides.BEnd() &&
       StyleBorder()->mBoxDecorationBreak !=
         StyleBoxDecorationBreak::Clone) {
     bp.BEnd(wm) = nscoord(0);
   }
 
   LogicalSize desiredSize(wm, computedISize + bp.IStartEnd(wm),
                               bSize         + bp.BStartEnd(wm));
   aDesiredSize.SetSize(wm, desiredSize);
   nsRect frameRect(0, 0, aDesiredSize.Width(), aDesiredSize.Height());
   aDesiredSize.mOverflowAreas.UnionAllWith(frameRect);
 
   // Convert INCOMPLETE -> OVERFLOW_INCOMPLETE and zero bsize if we're an OC.
   if (HasAnyStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER)) {
-    if (!NS_FRAME_IS_COMPLETE(aStatus)) {
-      NS_FRAME_SET_OVERFLOW_INCOMPLETE(aStatus);
-      aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
+    if (!aStatus.IsComplete()) {
+      aStatus.SetOverflowIncomplete();
+      aStatus.SetNextInFlowNeedsReflow();
     }
     bSize = 0;
     desiredSize.BSize(wm) = bSize + bp.BStartEnd(wm);
     aDesiredSize.SetSize(wm, desiredSize);
   }
 
   if (!gridReflowInput.mInFragmentainer) {
     MOZ_ASSERT(gridReflowInput.mIter.IsValid());
@@ -6410,17 +6410,17 @@ nsGridContainerFrame::Reflow(nsPresConte
       Properties().Set(ExplicitNamedAreasProperty(), areas);
     } else {
       Properties().Delete(ExplicitNamedAreasProperty());
     }
   }
 
   if (!prevInFlow) {
     SharedGridData* sharedGridData = Properties().Get(SharedGridData::Prop());
-    if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
+    if (!aStatus.IsFullyComplete()) {
       if (!sharedGridData) {
         sharedGridData = new SharedGridData;
         Properties().Set(SharedGridData::Prop(), sharedGridData);
       }
       sharedGridData->mCols.mSizes.Clear();
       sharedGridData->mCols.mSizes.SwapElements(gridReflowInput.mCols.mSizes);
       sharedGridData->mCols.mContentBoxSize = gridReflowInput.mCols.mContentBoxSize;
       sharedGridData->mCols.mBaselineSubtreeAlign[0] =
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -252,17 +252,17 @@ nsHTMLCanvasFrame::Reflow(nsPresContext*
   DO_GLOBAL_REFLOW_COUNT("nsHTMLCanvasFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("enter nsHTMLCanvasFrame::Reflow: availSize=%d,%d",
                   aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   WritingMode wm = aReflowInput.GetWritingMode();
   LogicalSize finalSize(wm,
                         aReflowInput.ComputedISize(),
                         aReflowInput.ComputedBSize());
 
   // stash this away so we can compute our inner area later
   mBorderPadding   = aReflowInput.ComputedLogicalBorderPadding();
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -190,142 +190,169 @@ enum nsSpread {
   eSpreadDown   = 2
 };
 
 // Carried out margin flags
 #define NS_CARRIED_TOP_MARGIN_IS_AUTO    0x1
 #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
 
 //----------------------------------------------------------------------
-
-/**
- * Reflow status returned by the reflow methods. There are three
- * completion statuses, represented by two bit flags.
- *
- * NS_FRAME_COMPLETE means the frame is fully complete.
- *
- * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its
- * content, and that the parent frame should create a continuing frame.
- * If this bit isn't set it means the frame does map all its content.
- * This bit is mutually exclusive with NS_FRAME_OVERFLOW_INCOMPLETE.
- *
- * NS_FRAME_OVERFLOW_INCOMPLETE bit flag means that the frame has
- * overflow that is not complete, but its own box is complete.
- * (This happens when content overflows a fixed-height box.)
- * The reflower should place and size the frame and continue its reflow,
- * but needs to create an overflow container as a continuation for this
- * frame. See nsContainerFrame.h for more information.
- * This bit is mutually exclusive with NS_FRAME_NOT_COMPLETE.
- * 
- * Please use the SET macro for handling
- * NS_FRAME_NOT_COMPLETE and NS_FRAME_OVERFLOW_INCOMPLETE.
- *
- * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is
- * dirty, and also needs to be reflowed. This status only makes sense
- * for a frame that is not complete, i.e. you wouldn't set both
- * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW.
- *
- * The low 8 bits of the nsReflowStatus are reserved for future extensions;
- * the remaining 24 bits are zero (and available for extensions; however
- * API's that accept/return nsReflowStatus must not receive/return any
- * extension bits).
- *
- * @see #Reflow()
- */
-typedef uint32_t nsReflowStatus;
-
-#define NS_FRAME_COMPLETE             0       // Note: not a bit!
-#define NS_FRAME_NOT_COMPLETE         0x1
-#define NS_FRAME_REFLOW_NEXTINFLOW    0x2
-#define NS_FRAME_OVERFLOW_INCOMPLETE  0x4
-
-#define NS_FRAME_IS_COMPLETE(status) \
-  (0 == ((status) & NS_FRAME_NOT_COMPLETE))
-
-#define NS_FRAME_IS_NOT_COMPLETE(status) \
-  (0 != ((status) & NS_FRAME_NOT_COMPLETE))
-
-#define NS_FRAME_OVERFLOW_IS_INCOMPLETE(status) \
-  (0 != ((status) & NS_FRAME_OVERFLOW_INCOMPLETE))
-
-#define NS_FRAME_IS_FULLY_COMPLETE(status) \
-  (NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status))
-
-// These macros set or switch incomplete statuses without touching the
-// NS_FRAME_REFLOW_NEXTINFLOW bit.
-#define NS_FRAME_SET_INCOMPLETE(status) \
-  status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE
-
-#define NS_FRAME_SET_OVERFLOW_INCOMPLETE(status) \
-  status = (status & ~NS_FRAME_NOT_COMPLETE) | NS_FRAME_OVERFLOW_INCOMPLETE
-
-// This bit is set, when a break is requested. This bit is orthogonal
-// to the nsIFrame::nsReflowStatus completion bits.
-#define NS_INLINE_BREAK              0x0100
-
-// When a break is requested, this bit when set indicates that the
-// break should occur after the frame just reflowed; when the bit is
-// clear the break should occur before the frame just reflowed.
-#define NS_INLINE_BREAK_BEFORE       0x0000
-#define NS_INLINE_BREAK_AFTER        0x0200
-
-// The type of break requested can be found in these bits.
-#define NS_INLINE_BREAK_TYPE_MASK    0xF000
-
-// Set when a break was induced by completion of a first-letter
-#define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000
-
-//----------------------------------------
-// Macros that use those bits
-
-#define NS_INLINE_IS_BREAK(_status) \
-  (0 != ((_status) & NS_INLINE_BREAK))
-
-#define NS_INLINE_IS_BREAK_AFTER(_status) \
-  (0 != ((_status) & NS_INLINE_BREAK_AFTER))
-
-#define NS_INLINE_IS_BREAK_BEFORE(_status) \
-  (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER)))
-
-#define NS_INLINE_GET_BREAK_TYPE(_status) \
-  (static_cast<StyleClear>(((_status) >> 12) & 0xF))
-
-#define NS_INLINE_MAKE_BREAK_TYPE(_type)  (static_cast<int>(_type) << 12)
-
-// Construct a line-break-before status. Note that there is no
-// completion status for a line-break before because we *know* that
-// the frame will be reflowed later and hence its current completion
-// status doesn't matter.
-#define NS_INLINE_LINE_BREAK_BEFORE()                                   \
-  (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE |                           \
-   NS_INLINE_MAKE_BREAK_TYPE(StyleClear::Line))
-
-// Take a completion status and add to it the desire to have a
-// line-break after. For this macro we do need the completion status
-// because the user of the status will need to know whether to
-// continue the frame or not.
-#define NS_INLINE_LINE_BREAK_AFTER(_completionStatus)                   \
-  ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |      \
-   NS_INLINE_MAKE_BREAK_TYPE(StyleClear::Line))
-
-// A frame is "truncated" if the part of the frame before the first
-// possible break point was unable to fit in the available vertical
-// space.  Therefore, the entire frame should be moved to the next page.
-// A frame that begins at the top of the page must never be "truncated".
-// Doing so would likely cause an infinite loop.
-#define NS_FRAME_TRUNCATED  0x0010
-#define NS_FRAME_IS_TRUNCATED(status) \
-  (0 != ((status) & NS_FRAME_TRUNCATED))
-#define NS_FRAME_SET_TRUNCATION(status, aReflowInput, aMetrics) \
-  aReflowInput.SetTruncated(aMetrics, &status);
-
-// Merge the incompleteness, truncation and NS_FRAME_REFLOW_NEXTINFLOW
-// status from aSecondary into aPrimary.
-void NS_MergeReflowStatusInto(nsReflowStatus* aPrimary,
-                              nsReflowStatus aSecondary);
+// Reflow status returned by the Reflow() methods.
+class nsReflowStatus final {
+  using StyleClear = mozilla::StyleClear;
+
+public:
+  nsReflowStatus()
+    : mBreakType(StyleClear::None)
+    , mIncomplete(false)
+    , mOverflowIncomplete(false)
+    , mNextInFlowNeedsReflow(false)
+    , mTruncated(false)
+    , mInlineBreak(false)
+    , mInlineBreakAfter(false)
+    , mFirstLetterComplete(false)
+  {}
+
+  // Reset all the bit-fields.
+  void Reset() {
+    mBreakType = StyleClear::None;
+    mIncomplete = false;
+    mOverflowIncomplete = false;
+    mNextInFlowNeedsReflow = false;
+    mTruncated = false;
+    mInlineBreak = false;
+    mInlineBreakAfter = false;
+    mFirstLetterComplete = false;
+  }
+
+  // Return true if all flags are cleared.
+  bool IsEmpty() const {
+    return (!mIncomplete &&
+            !mOverflowIncomplete &&
+            !mNextInFlowNeedsReflow &&
+            !mTruncated &&
+            !mInlineBreak &&
+            !mInlineBreakAfter &&
+            !mFirstLetterComplete);
+  }
+
+  // mIncomplete bit flag means the frame does not map all its content, and
+  // that the parent frame should create a continuing frame. If this bit
+  // isn't set, it means the frame does map all its content. This bit is
+  // mutually exclusive with mOverflowIncomplete.
+  //
+  // mOverflowIncomplete bit flag means that the frame has overflow that is
+  // not complete, but its own box is complete. (This happens when content
+  // overflows a fixed-height box.) The reflower should place and size the
+  // frame and continue its reflow, but needs to create an overflow
+  // container as a continuation for this frame. See nsContainerFrame.h for
+  // more information. This bit is mutually exclusive with mIncomplete.
+  //
+  // If both mIncomplete and mOverflowIncomplete are not set, the frame is
+  // fully complete.
+  bool IsComplete() const { return !mIncomplete; }
+  bool IsIncomplete() const { return mIncomplete; }
+  bool IsOverflowIncomplete() const { return mOverflowIncomplete; }
+  bool IsFullyComplete() const {
+    return !IsIncomplete() && !IsOverflowIncomplete();
+  }
+
+  void SetIncomplete() {
+    mIncomplete = true;
+    mOverflowIncomplete = false;
+  }
+  void SetOverflowIncomplete() {
+    mIncomplete = false;
+    mOverflowIncomplete = true;
+  }
+
+  // mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
+  // and also needs to be reflowed. This status only makes sense for a frame
+  // that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
+  // IsComplete() is true.
+  bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
+  void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
+
+  // mTruncated bit flag means that the part of the frame before the first
+  // possible break point was unable to fit in the available space.
+  // Therefore, the entire frame should be moved to the next continuation of
+  // the parent frame. A frame that begins at the top of the page must never
+  // be truncated. Doing so would likely cause an infinite loop.
+  bool IsTruncated() const { return mTruncated; }
+  void UpdateTruncated(const mozilla::ReflowInput& aReflowInput,
+                       const mozilla::ReflowOutput& aMetrics);
+
+  // Merge the frame completion status bits from aStatus into this.
+  void MergeCompletionStatusFrom(const nsReflowStatus& aStatus)
+  {
+    mIncomplete |= aStatus.mIncomplete;
+    mOverflowIncomplete |= aStatus.mOverflowIncomplete;
+    mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
+    mTruncated |= aStatus.mTruncated;
+    if (mIncomplete) {
+      mOverflowIncomplete = false;
+    }
+  }
+
+  // mInlineBreak bit flag means a break is requested.
+  bool IsInlineBreak() const { return mInlineBreak; }
+
+  // Suppose a break is requested. When mInlineBreakAfter is set, the break
+  // should occur after the frame just reflowed; when mInlineBreakAfter is
+  // clear, the break should occur before the frame just reflowed.
+  bool IsInlineBreakBefore() const { return mInlineBreak && !mInlineBreakAfter; }
+  bool IsInlineBreakAfter() const { return mInlineBreak && mInlineBreakAfter; }
+  StyleClear BreakType() const { return mBreakType; }
+
+  // Set the inline line-break-before status, and reset other bit flags. The
+  // break type is StyleClear::Line. Note that other frame completion status
+  // isn't expected to matter after calling this method.
+  void SetInlineLineBreakBeforeAndReset() {
+    Reset();
+    mBreakType = StyleClear::Line;
+    mInlineBreak = true;
+    mInlineBreakAfter = false;
+  }
+
+  // Set the inline line-break-after status. The break type can be changed
+  // via the optional aBreakType param.
+  void SetInlineLineBreakAfter(StyleClear aBreakType = StyleClear::Line) {
+    mBreakType = aBreakType;
+    mInlineBreak = true;
+    mInlineBreakAfter = true;
+  }
+
+  // mFirstLetterComplete bit flag means the break was induced by
+  // completion of a first-letter.
+  bool FirstLetterComplete() const { return mFirstLetterComplete; }
+  void SetFirstLetterComplete() { mFirstLetterComplete = true; }
+
+private:
+  StyleClear mBreakType;
+
+  // Frame completion status bit flags.
+  bool mIncomplete : 1;
+  bool mOverflowIncomplete : 1;
+  bool mNextInFlowNeedsReflow : 1;
+  bool mTruncated : 1;
+
+  // Inline break status bit flags.
+  bool mInlineBreak : 1;
+  bool mInlineBreakAfter : 1;
+  bool mFirstLetterComplete : 1;
+};
+
+#define NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics) \
+  aStatus.UpdateTruncated(aReflowInput, aMetrics);
+
+#ifdef DEBUG
+// Convert nsReflowStatus to a human-readable string.
+std::ostream&
+operator<<(std::ostream& aStream, const nsReflowStatus& aStatus);
+#endif
 
 //----------------------------------------------------------------------
 
 /**
  * DidReflow status values.
  */
 enum class nsDidReflowStatus : uint32_t {
   NOT_FINISHED,
@@ -2291,17 +2318,17 @@ public:
    * frame the status returned by the Reflow member function.
    *
    * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
    * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
    * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
    * frame state will be cleared.
    *
    * XXX This doesn't make sense. If the frame is reflowed but not complete, then
-   * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE
+   * the status should have mIncomplete bit set.
    * XXX Don't we want the semantics to dictate that we only call this once for
    * a given reflow?
    */
   virtual void DidReflow(nsPresContext*           aPresContext,
                          const ReflowInput* aReflowInput,
                          nsDidReflowStatus        aStatus) = 0;
 
   /**
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -954,17 +954,17 @@ nsImageFrame::Reflow(nsPresContext*     
   DO_GLOBAL_REFLOW_COUNT("nsImageFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("enter nsImageFrame::Reflow: availSize=%d,%d",
                   aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   // see if we have a frozen size (i.e. a fixed width and height)
   if (HaveFixedSize(aReflowInput)) {
     mState |= IMAGE_SIZECONSTRAINED;
   } else {
     mState &= ~IMAGE_SIZECONSTRAINED;
   }
 
@@ -1007,17 +1007,18 @@ nsImageFrame::Reflow(nsPresContext*     
   }
   if (aPresContext->IsPaginated() &&
       ((loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (mState & IMAGE_SIZECONSTRAINED)) &&
       NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableHeight() && 
       aMetrics.Height() > aReflowInput.AvailableHeight()) { 
     // our desired height was greater than 0, so to avoid infinite
     // splitting, use 1 pixel as the min
     aMetrics.Height() = std::max(nsPresContext::CSSPixelsToAppUnits(1), aReflowInput.AvailableHeight());
-    aStatus = NS_FRAME_NOT_COMPLETE;
+    aStatus.Reset();
+    aStatus.SetIncomplete();
   }
 
   aMetrics.SetOverflowAreasToDesiredBounds();
   EventStates contentState = mContent->AsElement()->State();
   bool imageOK = IMAGE_OK(contentState, true);
 
   // Determine if the size is available
   bool haveSize = false;
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -569,17 +569,17 @@ nsInlineFrame::PullOverflowsFromPrevInFl
 
 void
 nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
                             const ReflowInput& aReflowInput,
                             InlineReflowInput& irs,
                             ReflowOutput& aMetrics,
                             nsReflowStatus& aStatus)
 {
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   nsLineLayout* lineLayout = aReflowInput.mLineLayout;
   bool inFirstLine = aReflowInput.mLineLayout->GetInFirstLine();
   RestyleManager* restyleManager = aPresContext->RestyleManager();
   WritingMode frameWM = aReflowInput.GetWritingMode();
   WritingMode lineWM = aReflowInput.mLineLayout->mRootSpan->mWritingMode;
   LogicalMargin framePadding = aReflowInput.ComputedLogicalBorderPadding();
   nscoord startEdge = 0;
@@ -682,18 +682,18 @@ nsInlineFrame::ReflowFrames(nsPresContex
         }
       }
     }
     MOZ_ASSERT(frame->GetParent() == this);
 
     if (!done) {
       bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
       ReflowInlineFrame(aPresContext, aReflowInput, irs, frame, aStatus);
-      done = NS_INLINE_IS_BREAK(aStatus) || 
-             (!reflowingFirstLetter && NS_FRAME_IS_NOT_COMPLETE(aStatus));
+      done = aStatus.IsInlineBreak() ||
+             (!reflowingFirstLetter && aStatus.IsIncomplete());
       if (done) {
         if (!irs.mSetParentPointer) {
           break;
         }
         // Keep reparenting the remaining siblings, but don't reflow them.
         nsFrameList* pushedFrames = GetOverflowFrames();
         if (pushedFrames && pushedFrames->FirstChild() == frame) {
           // Don't bother if |frame| was pushed to our overflow list.
@@ -715,31 +715,32 @@ nsInlineFrame::ReflowFrames(nsPresContex
                     // it created a continuation, since we don't push those.
         frame = PullOneFrame(aPresContext, irs, &isComplete);
       }
 #ifdef NOISY_PUSHING
       printf("%p pulled up %p\n", this, frame);
 #endif
       if (nullptr == frame) {
         if (!isComplete) {
-          aStatus = NS_FRAME_NOT_COMPLETE;
+          aStatus.Reset();
+          aStatus.SetIncomplete();
         }
         break;
       }
       ReflowInlineFrame(aPresContext, aReflowInput, irs, frame, aStatus);
-      if (NS_INLINE_IS_BREAK(aStatus) || 
-          (!reflowingFirstLetter && NS_FRAME_IS_NOT_COMPLETE(aStatus))) {
+      if (aStatus.IsInlineBreak() ||
+          (!reflowingFirstLetter && aStatus.IsIncomplete())) {
         break;
       }
       irs.mPrevFrame = frame;
       frame = frame->GetNextSibling();
     }
   }
 
-  NS_ASSERTION(!NS_FRAME_IS_COMPLETE(aStatus) || !GetOverflowFrames(),
+  NS_ASSERTION(!aStatus.IsComplete() || !GetOverflowFrames(),
                "We can't be complete AND have overflow frames!");
 
   // If after reflowing our children they take up no area then make
   // sure that we don't either.
   //
   // Note: CSS demands that empty inline elements still affect the
   // line-height calculations. However, continuations of an inline
   // that are empty we force to empty so that things like collapsed
@@ -766,17 +767,17 @@ nsInlineFrame::ReflowFrames(nsPresContex
   /*
    * We want to only apply the end border and padding if we're the last
    * continuation and either not in an {ib} split or the last part of it.  To
    * be the last continuation we have to be complete (so that we won't get a
    * next-in-flow) and have no non-fluid continuations on our continuation
    * chain.  For box-decoration-break:clone we always apply the end border and
    * padding since all continuations have them.
    */
-  if ((NS_FRAME_IS_COMPLETE(aStatus) &&
+  if ((aStatus.IsComplete() &&
        !LastInFlow()->GetNextContinuation() &&
        !FrameIsNonLastInIBSplit()) ||
       boxDecorationBreakClone) {
     aMetrics.ISize(lineWM) += framePadding.IEnd(frameWM);
   }
 
   nsLayoutUtils::SetBSizeFromFontMetrics(this, aMetrics,
                                          framePadding, lineWM, frameWM);
@@ -798,61 +799,62 @@ nsInlineFrame::ReflowInlineFrame(nsPresC
                                  InlineReflowInput& irs,
                                  nsIFrame* aFrame,
                                  nsReflowStatus& aStatus)
 {
   nsLineLayout* lineLayout = aReflowInput.mLineLayout;
   bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
   bool pushedFrame;
   lineLayout->ReflowFrame(aFrame, aStatus, nullptr, pushedFrame);
-  
-  if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
+
+  if (aStatus.IsInlineBreakBefore()) {
     if (aFrame != mFrames.FirstChild()) {
       // Change break-before status into break-after since we have
       // already placed at least one child frame. This preserves the
       // break-type so that it can be propagated upward.
-      aStatus = NS_FRAME_NOT_COMPLETE |
-        NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
-        (aStatus & NS_INLINE_BREAK_TYPE_MASK);
+      StyleClear oldBreakType = aStatus.BreakType();
+      aStatus.Reset();
+      aStatus.SetIncomplete();
+      aStatus.SetInlineLineBreakAfter(oldBreakType);
       PushFrames(aPresContext, aFrame, irs.mPrevFrame, irs);
     }
     else {
       // Preserve reflow status when breaking-before our first child
       // and propagate it upward without modification.
     }
     return;
   }
 
   // Create a next-in-flow if needed.
-  if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
+  if (!aStatus.IsFullyComplete()) {
     CreateNextInFlow(aFrame);
   }
 
-  if (NS_INLINE_IS_BREAK_AFTER(aStatus)) {
+  if (aStatus.IsInlineBreakAfter()) {
     nsIFrame* nextFrame = aFrame->GetNextSibling();
     if (nextFrame) {
-      NS_FRAME_SET_INCOMPLETE(aStatus);
+      aStatus.SetIncomplete();
       PushFrames(aPresContext, nextFrame, aFrame, irs);
     }
     else {
       // We must return an incomplete status if there are more child
       // frames remaining in a next-in-flow that follows this frame.
       nsInlineFrame* nextInFlow = static_cast<nsInlineFrame*>(GetNextInFlow());
       while (nextInFlow) {
         if (nextInFlow->mFrames.NotEmpty()) {
-          NS_FRAME_SET_INCOMPLETE(aStatus);
+          aStatus.SetIncomplete();
           break;
         }
         nextInFlow = static_cast<nsInlineFrame*>(nextInFlow->GetNextInFlow());
       }
     }
     return;
   }
 
-  if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !reflowingFirstLetter) {
+  if (!aStatus.IsFullyComplete() && !reflowingFirstLetter) {
     nsIFrame* nextFrame = aFrame->GetNextSibling();
     if (nextFrame) {
       PushFrames(aPresContext, nextFrame, aFrame, irs);
     }
   }
 }
 
 nsIFrame*
--- a/layout/generic/nsLeafFrame.cpp
+++ b/layout/generic/nsLeafFrame.cpp
@@ -80,17 +80,17 @@ nsLeafFrame::DoReflow(nsPresContext* aPr
                "Shouldn't have unconstrained stuff here "
                "thanks to ComputeAutoSize");
 
   // XXX how should border&padding effect baseline alignment?
   // => descent = borderPadding.bottom for example
   WritingMode wm = aReflowInput.GetWritingMode();
   aMetrics.SetSize(wm, aReflowInput.ComputedSizeWithBorderPadding());
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("exit nsLeafFrame::DoReflow: size=%d,%d",
                   aMetrics.ISize(wm), aMetrics.BSize(wm)));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
 
   aMetrics.SetOverflowAreasToDesiredBounds();
 }
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1023,17 +1023,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   }
   if (reflowOutput.BSize(lineWM) < 0) {
     reflowOutput.BSize(lineWM) = 0;
   }
 
 #ifdef DEBUG
   // Note: break-before means ignore the reflow metrics since the
   // frame will be reflowed another time.
-  if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
+  if (!aReflowStatus.IsInlineBreakBefore()) {
     if ((CRAZY_SIZE(reflowOutput.ISize(lineWM)) ||
          CRAZY_SIZE(reflowOutput.BSize(lineWM))) &&
         !LineContainerFrame()->GetParent()->IsCrazySizeAssertSuppressed()) {
       printf("nsLineLayout: ");
       nsFrame::ListTag(stdout, aFrame);
       printf(" metrics=%d,%d!\n", reflowOutput.Width(), reflowOutput.Height());
     }
     if ((reflowOutput.Width() == nscoord(0xdeadbeef)) ||
@@ -1062,22 +1062,22 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   aFrame->DidReflow(mPresContext,
                     isText ? nullptr : reflowInputHolder.ptr(),
                     nsDidReflowStatus::FINISHED);
 
   if (aMetrics) {
     *aMetrics = reflowOutput;
   }
 
-  if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
+  if (!aReflowStatus.IsInlineBreakBefore()) {
     // If frame is complete and has a next-in-flow, we need to delete
     // them now. Do not do this when a break-before is signaled because
     // the frame is going to get reflowed again (and may end up wanting
     // a next-in-flow where it ends up).
-    if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
+    if (aReflowStatus.IsComplete()) {
       nsIFrame* kidNextInFlow = aFrame->GetNextInFlow();
       if (nullptr != kidNextInFlow) {
         // Remove all of the childs next-in-flows. Make sure that we ask
         // the right parent to do the removal (it's possible that the
         // parent is not this because we are executing pullup code)
         kidNextInFlow->GetParent()->
           DeleteNextInFlowChild(kidNextInFlow, true);
       }
@@ -1131,17 +1131,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
         if (!psd->mNoWrap && (!LineIsEmpty() || placedFloat)) {
           // record soft break opportunity after this content that can't be
           // part of a text run. This is not a text frame so we know
           // that offset INT32_MAX means "after the content".
           if (NotifyOptionalBreakPosition(aFrame, INT32_MAX,
                                           optionalBreakAfterFits,
                                           gfxBreakPriority::eNormalBreak)) {
             // If this returns true then we are being told to actually break here.
-            aReflowStatus = NS_INLINE_LINE_BREAK_AFTER(aReflowStatus);
+            aReflowStatus.SetInlineLineBreakAfter();
           }
         }
       }
     }
     else {
       PushFrame(aFrame);
       aPushedFrame = true;
       // Undo any saved break positions that the frame might have told us about,
@@ -1288,17 +1288,17 @@ nsLineLayout::CanPlaceFrame(PerFrameData
    *    end-margin in that case.
    * 3) The frame is in an {ib} split and is not the last part.
    *
    * However, none of that applies if this is a letter frame (XXXbz why?)
    *
    * For box-decoration-break:clone we apply the end margin on all
    * continuations (that are not letter frames).
    */
-  if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
+  if ((aStatus.IsIncomplete() ||
        pfd->mFrame->LastInFlow()->GetNextContinuation() ||
        pfd->mFrame->FrameIsNonLastInIBSplit()) &&
       !pfd->mIsLetterFrame &&
       pfd->mFrame->StyleBorder()->mBoxDecorationBreak ==
         StyleBoxDecorationBreak::Slice) {
     pfd->mMargin.IEnd(lineWM) = 0;
   }
 
@@ -1413,17 +1413,17 @@ nsLineLayout::CanPlaceFrame(PerFrameData
     // We will want to try backup.
     mNeedBackup = true;
     return true;
   }
 
 #ifdef NOISY_CAN_PLACE_FRAME
   printf("   ==> didn't fit\n");
 #endif
-  aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+  aStatus.SetInlineLineBreakBeforeAndReset();
   return false;
 }
 
 /**
  * Place the frame. Update running counters.
  */
 void
 nsLineLayout::PlaceFrame(PerFrameData* pfd, ReflowOutput& aMetrics)
--- a/layout/generic/nsPageContentFrame.cpp
+++ b/layout/generic/nsPageContentFrame.cpp
@@ -23,17 +23,17 @@ void
 nsPageContentFrame::Reflow(nsPresContext*           aPresContext,
                            ReflowOutput&     aDesiredSize,
                            const ReflowInput& aReflowInput,
                            nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
-  aStatus = NS_FRAME_COMPLETE;  // initialize out parameter
+  aStatus.Reset();  // initialize out parameter
 
   if (GetPrevInFlow() && (GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     nsresult rv = aPresContext->PresShell()->FrameConstructor()
                     ->ReplicateFixedFrames(this);
     if (NS_FAILED(rv)) {
       return;
     }
   }
@@ -83,24 +83,24 @@ nsPageContentFrame::Reflow(nsPresContext
         NS_ASSERTION(ratio >= 0.0 && ratio < 1.0, "invalid shrink-to-fit ratio");
         mPD->mShrinkToFitRatio = std::min(mPD->mShrinkToFitRatio, ratio);
       }
     }
 
     // Place and size the child
     FinishReflowChild(frame, aPresContext, aDesiredSize, &kidReflowInput, 0, 0, 0);
 
-    NS_ASSERTION(aPresContext->IsDynamic() || !NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
+    NS_ASSERTION(aPresContext->IsDynamic() || !aStatus.IsFullyComplete() ||
                   !frame->GetNextInFlow(), "bad child flow list");
   }
 
   // Reflow our fixed frames
-  nsReflowStatus fixedStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus fixedStatus;
   ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, fixedStatus);
-  NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete");
+  NS_ASSERTION(fixedStatus.IsComplete(), "fixed frames can be truncated, but not incomplete");
 
   // Return our desired size
   WritingMode wm = aReflowInput.GetWritingMode();
   aDesiredSize.ISize(wm) = aReflowInput.ComputedISize();
   if (aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
     aDesiredSize.BSize(wm) = aReflowInput.ComputedBSize();
   }
   FinishAndStoreOverflow(&aDesiredSize);
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -53,17 +53,17 @@ void
 nsPageFrame::Reflow(nsPresContext*           aPresContext,
                                   ReflowOutput&     aDesiredSize,
                                   const ReflowInput& aReflowInput,
                                   nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
-  aStatus = NS_FRAME_COMPLETE;  // initialize out parameter
+  aStatus.Reset();  // initialize out parameter
 
   NS_ASSERTION(mFrames.FirstChild() &&
                nsGkAtoms::pageContentFrame == mFrames.FirstChild()->GetType(),
                "pageFrame must have a pageContentFrame child");
 
   // Resize our frame allowing it only to be as big as we are
   // XXX Pay attention to the page's border and padding...
   if (mFrames.NotEmpty()) {
@@ -141,17 +141,17 @@ nsPageFrame::Reflow(nsPresContext*      
     nscoord yc = mPageContentMargin.top;
 
     // Get the child's desired size
     ReflowChild(frame, aPresContext, aDesiredSize, kidReflowInput, xc, yc, 0, aStatus);
 
     // Place and size the child
     FinishReflowChild(frame, aPresContext, aDesiredSize, &kidReflowInput, xc, yc, 0);
 
-    NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
+    NS_ASSERTION(!aStatus.IsFullyComplete() ||
                  !frame->GetNextInFlow(), "bad child flow list");
   }
   PR_PL(("PageFrame::Reflow %p ", this));
   PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.Width(), aDesiredSize.Height(),
          aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
 
   // Return our desired size
   WritingMode wm = aReflowInput.GetWritingMode();
@@ -726,17 +726,17 @@ nsPageBreakFrame::Reflow(nsPresContext* 
   // round the height down to the nearest pixel
   finalSize.BSize(wm) -=
     finalSize.BSize(wm) % nsPresContext::CSSPixelsToAppUnits(1);
   aDesiredSize.SetSize(wm, finalSize);
 
   // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
   // DidReflow will always get called before the next Reflow() call.
   mHaveReflowed = true;
-  aStatus = NS_FRAME_COMPLETE; 
+  aStatus.Reset(); 
 }
 
 nsIAtom*
 nsPageBreakFrame::GetType() const
 {
   return nsGkAtoms::pageBreakFrame;
 }
 
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -142,17 +142,17 @@ nsPlaceholderFrame::Reflow(nsPresContext
   }
 #endif
 
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
   aDesiredSize.ClearSize();
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 void
 nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   nsIFrame* oof = mOutOfFlowFrame;
   if (oof) {
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -501,23 +501,23 @@ nsPluginFrame::Reflow(nsPresContext*    
   GetDesiredSize(aPresContext, aReflowInput, aMetrics);
   aMetrics.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aMetrics);
 
   // delay plugin instantiation until all children have
   // arrived. Otherwise there may be PARAMs or other stuff that the
   // plugin needs to see that haven't arrived yet.
   if (!GetContent()->IsDoneAddingChildren()) {
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     return;
   }
 
   // if we are printing or print previewing, bail for now
   if (aPresContext->Medium() == nsGkAtoms::print) {
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     return;
   }
 
   nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
   r.Deflate(aReflowInput.ComputedPhysicalBorderPadding());
 
   if (mInnerView) {
     nsViewManager* vm = mInnerView->GetViewManager();
@@ -526,17 +526,17 @@ nsPluginFrame::Reflow(nsPresContext*    
   }
 
   FixupWindow(r.Size());
   if (!mReflowCallbackPosted) {
     mReflowCallbackPosted = true;
     aPresContext->PresShell()->PostReflowCallback(this);
   }
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
 }
 
 ///////////// nsIReflowCallback ///////////////
 
 bool
 nsPluginFrame::ReflowFinished()
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -302,17 +302,17 @@ struct nsRubyBaseContainerFrame::RubyRef
 nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext,
                                  ReflowOutput& aDesiredSize,
                                  const ReflowInput& aReflowInput,
                                  nsReflowStatus& aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsRubyBaseContainerFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   if (!aReflowInput.mLineLayout) {
     NS_ASSERTION(
       aReflowInput.mLineLayout,
       "No line layout provided to RubyBaseContainerFrame reflow method.");
     return;
   }
 
@@ -394,25 +394,25 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
   isize = ReflowColumns(reflowInput, aStatus);
   DebugOnly<nscoord> lineSpanSize = aReflowInput.mLineLayout->EndSpan(this);
   aDesiredSize.ISize(lineWM) = isize;
   // When there are no frames inside the ruby base container, EndSpan
   // will return 0. However, in this case, the actual width of the
   // container could be non-zero because of non-empty ruby annotations.
   // XXX When bug 765861 gets fixed, this warning should be upgraded.
   NS_WARNING_ASSERTION(
-    NS_INLINE_IS_BREAK(aStatus) || isize == lineSpanSize || mFrames.IsEmpty(),
+    aStatus.IsInlineBreak() || isize == lineSpanSize || mFrames.IsEmpty(),
     "bad isize");
 
   // If there exists any span, the columns must either be completely
   // reflowed, or be not reflowed at all.
-  MOZ_ASSERT(NS_INLINE_IS_BREAK_BEFORE(aStatus) ||
-             NS_FRAME_IS_COMPLETE(aStatus) || !hasSpan);
-  if (!NS_INLINE_IS_BREAK_BEFORE(aStatus) &&
-      NS_FRAME_IS_COMPLETE(aStatus) && hasSpan) {
+  MOZ_ASSERT(aStatus.IsInlineBreakBefore() ||
+             aStatus.IsComplete() || !hasSpan);
+  if (!aStatus.IsInlineBreakBefore() &&
+      aStatus.IsComplete() && hasSpan) {
     // Reflow spans
     RubyReflowInput reflowInput = {
       false, false, textContainers, aReflowInput, reflowInputs
     };
     nscoord spanISize = ReflowSpans(reflowInput);
     isize = std::max(isize, spanISize);
   }
 
@@ -465,75 +465,75 @@ struct MOZ_STACK_CLASS nsRubyBaseContain
 nscoord
 nsRubyBaseContainerFrame::ReflowColumns(const RubyReflowInput& aReflowInput,
                                         nsReflowStatus& aStatus)
 {
   nsLineLayout* lineLayout = aReflowInput.mBaseReflowInput.mLineLayout;
   const uint32_t rtcCount = aReflowInput.mTextContainers.Length();
   nscoord icoord = lineLayout->GetCurrentICoord();
   MOZ_ASSERT(icoord == 0, "border/padding of rbc should have been suppressed");
-  nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
-  aStatus = NS_FRAME_COMPLETE;
+  nsReflowStatus reflowStatus;
+  aStatus.Reset();
 
   uint32_t columnIndex = 0;
   RubyColumn column;
   column.mTextFrames.SetCapacity(rtcCount);
   RubyColumnEnumerator e(this, aReflowInput.mTextContainers);
   for (; !e.AtEnd(); e.Next()) {
     e.GetColumn(column);
     icoord += ReflowOneColumn(aReflowInput, columnIndex, column, reflowStatus);
-    if (!NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
+    if (!reflowStatus.IsInlineBreakBefore()) {
       columnIndex++;
     }
-    if (NS_INLINE_IS_BREAK(reflowStatus)) {
+    if (reflowStatus.IsInlineBreak()) {
       break;
     }
     // We are not handling overflow here.
-    MOZ_ASSERT(reflowStatus == NS_FRAME_COMPLETE);
+    MOZ_ASSERT(reflowStatus.IsEmpty());
   }
 
   bool isComplete = false;
   PullFrameState pullFrameState(this, aReflowInput.mTextContainers);
-  while (!NS_INLINE_IS_BREAK(reflowStatus)) {
+  while (!reflowStatus.IsInlineBreak()) {
     // We are not handling overflow here.
-    MOZ_ASSERT(reflowStatus == NS_FRAME_COMPLETE);
+    MOZ_ASSERT(reflowStatus.IsEmpty());
 
     // Try pull some frames from next continuations. This call replaces
     // frames in |column| with the frame pulled in each level.
     PullOneColumn(lineLayout, pullFrameState, column, isComplete);
     if (isComplete) {
       // No more frames can be pulled.
       break;
     }
     icoord += ReflowOneColumn(aReflowInput, columnIndex, column, reflowStatus);
-    if (!NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
+    if (!reflowStatus.IsInlineBreakBefore()) {
       columnIndex++;
     }
   }
 
-  if (!e.AtEnd() && NS_INLINE_IS_BREAK_AFTER(reflowStatus)) {
+  if (!e.AtEnd() && reflowStatus.IsInlineBreakAfter()) {
     // The current column has been successfully placed.
     // Skip to the next column and mark break before.
     e.Next();
     e.GetColumn(column);
-    reflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    reflowStatus.SetInlineLineBreakBeforeAndReset();
   }
   if (!e.AtEnd() || (GetNextInFlow() && !isComplete)) {
-    NS_FRAME_SET_INCOMPLETE(aStatus);
+    aStatus.SetIncomplete();
   }
 
-  if (NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
+  if (reflowStatus.IsInlineBreakBefore()) {
     if (!columnIndex || !aReflowInput.mAllowLineBreak) {
       // If no column has been placed yet, or we have any span,
       // the whole container should be in the next line.
-      aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+      aStatus.SetInlineLineBreakBeforeAndReset();
       return 0;
     }
-    aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
-    MOZ_ASSERT(NS_FRAME_IS_COMPLETE(aStatus) || aReflowInput.mAllowLineBreak);
+    aStatus.SetInlineLineBreakAfter();
+    MOZ_ASSERT(aStatus.IsComplete() || aReflowInput.mAllowLineBreak);
 
     // If we are on an intra-level whitespace column, null values in
     // column.mBaseFrame and column.mTextFrames don't represent the
     // end of the frame-sibling-chain at that level -- instead, they
     // represent an anonymous empty intra-level whitespace box. It is
     // likely that there are frames in the next column (which can't be
     // intra-level whitespace). Those frames should be pushed as well.
     Maybe<RubyColumn> nextColumn;
@@ -554,23 +554,23 @@ nsRubyBaseContainerFrame::ReflowColumns(
       if (!textFrame && nextColumn.isSome()) {
         textFrame = nextColumn->mTextFrames[i];
       }
       if (textFrame) {
         aReflowInput.mTextContainers[i]->PushChildren(
           textFrame, textFrame->GetPrevSibling());
       }
     }
-  } else if (NS_INLINE_IS_BREAK_AFTER(reflowStatus)) {
+  } else if (reflowStatus.IsInlineBreakAfter()) {
     // |reflowStatus| being break after here may only happen when
     // there is a break after the column just pulled, or the whole
     // segment has been completely reflowed. In those cases, we do
     // not need to push anything.
     MOZ_ASSERT(e.AtEnd());
-    aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
+    aStatus.SetInlineLineBreakAfter();
   }
 
   return icoord;
 }
 
 nscoord
 nsRubyBaseContainerFrame::ReflowOneColumn(const RubyReflowInput& aReflowInput,
                                           uint32_t aColumnIndex,
@@ -593,17 +593,17 @@ nsRubyBaseContainerFrame::ReflowOneColum
         gfxBreakPriority lastBreakPriority =
           baseReflowInput.mLineLayout->LastOptionalBreakPriority();
         if (breakPriority >= lastBreakPriority) {
           // Either we have been overflow, or we are forced
           // to break here, do break before.
           if (istart > baseReflowInput.AvailableISize() ||
               baseReflowInput.mLineLayout->NotifyOptionalBreakPosition(
                 aColumn.mBaseFrame, 0, true, breakPriority)) {
-            aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+            aStatus.SetInlineLineBreakBeforeAndReset();
             return 0;
           }
         }
       }
     }
   }
 
   const uint32_t rtcCount = aReflowInput.mTextContainers.Length();
@@ -635,17 +635,17 @@ nsRubyBaseContainerFrame::ReflowOneColum
       }
       RubyUtils::ClearReservedISize(textFrame);
 
       bool pushedFrame;
       nsReflowStatus reflowStatus;
       nsLineLayout* lineLayout = textReflowInputs[i]->mLineLayout;
       nscoord textIStart = lineLayout->GetCurrentICoord();
       lineLayout->ReflowFrame(textFrame, reflowStatus, nullptr, pushedFrame);
-      if (MOZ_UNLIKELY(NS_INLINE_IS_BREAK(reflowStatus) || pushedFrame)) {
+      if (MOZ_UNLIKELY(reflowStatus.IsInlineBreak() || pushedFrame)) {
         MOZ_ASSERT_UNREACHABLE(
             "Any line break inside ruby box should have been suppressed");
         // For safety, always drain the overflow list, so that
         // no frames are left there after reflow.
         textFrame->DrainSelfOverflowList();
       }
       nscoord textISize = lineLayout->GetCurrentICoord() - textIStart;
       columnISize = std::max(columnISize, textISize);
@@ -657,17 +657,17 @@ nsRubyBaseContainerFrame::ReflowOneColum
     RubyUtils::ClearReservedISize(aColumn.mBaseFrame);
 
     bool pushedFrame;
     nsReflowStatus reflowStatus;
     nsLineLayout* lineLayout = baseReflowInput.mLineLayout;
     nscoord baseIStart = lineLayout->GetCurrentICoord();
     lineLayout->ReflowFrame(aColumn.mBaseFrame, reflowStatus,
                             nullptr, pushedFrame);
-    if (MOZ_UNLIKELY(NS_INLINE_IS_BREAK(reflowStatus) || pushedFrame)) {
+    if (MOZ_UNLIKELY(reflowStatus.IsInlineBreak() || pushedFrame)) {
       MOZ_ASSERT_UNREACHABLE(
         "Any line break inside ruby box should have been suppressed");
       // For safety, always drain the overflow list, so that
       // no frames are left there after reflow.
       aColumn.mBaseFrame->DrainSelfOverflowList();
     }
     nscoord baseISize = lineLayout->GetCurrentICoord() - baseIStart;
     columnISize = std::max(columnISize, baseISize);
@@ -823,14 +823,14 @@ nsRubyBaseContainerFrame::ReflowSpans(co
 
     nsIFrame* rtFrame = container->PrincipalChildList().FirstChild();
     nsReflowStatus reflowStatus;
     bool pushedFrame;
     nsLineLayout* lineLayout = aReflowInput.mTextReflowInputs[i]->mLineLayout;
     MOZ_ASSERT(lineLayout->GetCurrentICoord() == 0,
                "border/padding of rtc should have been suppressed");
     lineLayout->ReflowFrame(rtFrame, reflowStatus, nullptr, pushedFrame);
-    MOZ_ASSERT(!NS_INLINE_IS_BREAK(reflowStatus) && !pushedFrame,
+    MOZ_ASSERT(!reflowStatus.IsInlineBreak() && !pushedFrame,
                "Any line break inside ruby box should has been suppressed");
     spanISize = std::max(spanISize, lineLayout->GetCurrentICoord());
   }
   return spanISize;
 }
--- a/layout/generic/nsRubyFrame.cpp
+++ b/layout/generic/nsRubyFrame.cpp
@@ -111,17 +111,17 @@ nsRubyFrame::Reflow(nsPresContext* aPres
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsRubyFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
   
   if (!aReflowInput.mLineLayout) {
     NS_ASSERTION(aReflowInput.mLineLayout,
                  "No line layout provided to RubyFrame reflow method.");
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     return;
   }
 
   // Grab overflow frames from prev-in-flow and its own.
   MoveOverflowToChildList();
 
   // Clear leadings
   mLeadings.Reset();
@@ -138,45 +138,45 @@ nsRubyFrame::Reflow(nsPresContext* aPres
   }
   NS_ASSERTION(aReflowInput.AvailableISize() != NS_UNCONSTRAINEDSIZE,
                "should no longer use available widths");
   nscoord availableISize = aReflowInput.AvailableISize();
   availableISize -= startEdge + borderPadding.IEnd(frameWM);
   aReflowInput.mLineLayout->BeginSpan(this, &aReflowInput,
                                       startEdge, availableISize, &mBaseline);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   for (RubySegmentEnumerator e(this); !e.AtEnd(); e.Next()) {
     ReflowSegment(aPresContext, aReflowInput, e.GetBaseContainer(), aStatus);
 
-    if (NS_INLINE_IS_BREAK(aStatus)) {
+    if (aStatus.IsInlineBreak()) {
       // A break occurs when reflowing the segment.
       // Don't continue reflowing more segments.
       break;
     }
   }
 
   ContinuationTraversingState pullState(this);
-  while (aStatus == NS_FRAME_COMPLETE) {
+  while (aStatus.IsEmpty()) {
     nsRubyBaseContainerFrame* baseContainer =
       PullOneSegment(aReflowInput.mLineLayout, pullState);
     if (!baseContainer) {
       // No more continuations after, finish now.
       break;
     }
     ReflowSegment(aPresContext, aReflowInput, baseContainer, aStatus);
   }
   // We never handle overflow in ruby.
-  MOZ_ASSERT(!NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus));
+  MOZ_ASSERT(!aStatus.IsOverflowIncomplete());
 
   aDesiredSize.ISize(lineWM) = aReflowInput.mLineLayout->EndSpan(this);
   if (boxDecorationBreakClone || !GetPrevContinuation()) {
     aDesiredSize.ISize(lineWM) += borderPadding.IStart(frameWM);
   }
-  if (boxDecorationBreakClone || NS_FRAME_IS_COMPLETE(aStatus)) {
+  if (boxDecorationBreakClone || aStatus.IsComplete()) {
     aDesiredSize.ISize(lineWM) += borderPadding.IEnd(frameWM);
   }
 
   // Update descendant leadings of ancestor ruby base container.
   if (nsRubyBaseContainerFrame* rbc = FindRubyBaseContainerAncestor(this)) {
     rbc->UpdateDescendantLeadings(mLeadings);
   }
 
@@ -200,34 +200,36 @@ nsRubyFrame::ReflowSegment(nsPresContext
   AutoRubyTextContainerArray textContainers(aBaseContainer);
   const uint32_t rtcCount = textContainers.Length();
 
   ReflowOutput baseMetrics(aReflowInput);
   bool pushedFrame;
   aReflowInput.mLineLayout->ReflowFrame(aBaseContainer, aStatus,
                                         &baseMetrics, pushedFrame);
 
-  if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
+  if (aStatus.IsInlineBreakBefore()) {
     if (aBaseContainer != mFrames.FirstChild()) {
       // Some segments may have been reflowed before, hence it is not
       // a break-before for the ruby container.
-      aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_NOT_COMPLETE);
+      aStatus.Reset();
+      aStatus.SetInlineLineBreakAfter();
+      aStatus.SetIncomplete();
       PushChildren(aBaseContainer, aBaseContainer->GetPrevSibling());
       aReflowInput.mLineLayout->SetDirtyNextLine();
     }
     // This base container is not placed at all, we can skip all
     // text containers paired with it.
     return;
   }
-  if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
+  if (aStatus.IsIncomplete()) {
     // It always promise that if the status is incomplete, there is a
     // break occurs. Break before has been processed above. However,
     // it is possible that break after happens with the frame reflow
     // completed. It happens if there is a force break at the end.
-    MOZ_ASSERT(NS_INLINE_IS_BREAK_AFTER(aStatus));
+    MOZ_ASSERT(aStatus.IsInlineBreakAfter());
     // Find the previous sibling which we will
     // insert new continuations after.
     nsIFrame* lastChild;
     if (rtcCount > 0) {
       lastChild = textContainers.LastElement();
     } else {
       lastChild = aBaseContainer;
     }
@@ -298,20 +300,20 @@ nsRubyFrame::ReflowSegment(nsPresContext
                                       availSize.ConvertTo(rtcWM, lineWM));
     // FIXME We probably shouldn't be using the same nsLineLayout for
     //       the text containers. But it should be fine now as we are
     //       not actually using this line layout to reflow something,
     //       but just read the writing mode from it.
     textReflowInput.mLineLayout = aReflowInput.mLineLayout;
     textContainer->Reflow(aPresContext, textMetrics,
                           textReflowInput, textReflowStatus);
-    // Ruby text containers always return NS_FRAME_COMPLETE even when
+    // Ruby text containers always return complete reflow status even when
     // they have continuations, because the breaking has already been
     // handled when reflowing the base containers.
-    NS_ASSERTION(textReflowStatus == NS_FRAME_COMPLETE,
+    NS_ASSERTION(textReflowStatus.IsEmpty(),
                  "Ruby text container must not break itself inside");
     // The metrics is initialized with reflow state of this ruby frame,
     // hence the writing-mode is tied to rubyWM instead of rtcWM.
     LogicalSize size = textMetrics.Size(rubyWM).ConvertTo(lineWM, rubyWM);
     textContainer->SetSize(lineWM, size);
 
     nscoord reservedISize = RubyUtils::GetReservedISize(textContainer);
     segmentISize = std::max(segmentISize, size.ISize(lineWM) + reservedISize);
--- a/layout/generic/nsRubyTextContainerFrame.cpp
+++ b/layout/generic/nsRubyTextContainerFrame.cpp
@@ -125,20 +125,20 @@ nsRubyTextContainerFrame::Reflow(nsPresC
                                  const ReflowInput& aReflowInput,
                                  nsReflowStatus& aStatus)
 {
   MarkInReflow();
   DO_GLOBAL_REFLOW_COUNT("nsRubyTextContainerFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
 
   // Although a ruby text container may have continuations, returning
-  // NS_FRAME_COMPLETE here is still safe, since its parent, ruby frame,
+  // complete reflow status is still safe, since its parent, ruby frame,
   // ignores the status, and continuations of the ruby base container
   // will take care of our continuations.
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   WritingMode lineWM = aReflowInput.mLineLayout->GetWritingMode();
 
   nscoord minBCoord = nscoord_MAX;
   nscoord maxBCoord = nscoord_MIN;
   // The container size is not yet known, so we use a dummy (0, 0) size.
   // The block-dir position will be corrected below after containerSize
   // is finalized.
   const nsSize dummyContainerSize;
--- a/layout/generic/nsSimplePageSequenceFrame.cpp
+++ b/layout/generic/nsSimplePageSequenceFrame.cpp
@@ -151,17 +151,17 @@ nsSimplePageSequenceFrame::Reflow(nsPres
 {
   MarkInReflow();
   NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(),
                   "A Page Sequence is only for real pages");
   DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
   NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");
 
-  aStatus = NS_FRAME_COMPLETE;  // we're always complete
+  aStatus.Reset();  // we're always complete
 
   // Don't do incremental reflow until we've taught tables how to do
   // it right in paginated mode.
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     // Return our desired size
     SetDesiredSize(aDesiredSize, aReflowInput, mSize.width, mSize.height);
     aDesiredSize.SetOverflowAreasToDesiredBounds();
     FinishAndStoreOverflow(&aDesiredSize);
@@ -278,17 +278,17 @@ nsSimplePageSequenceFrame::Reflow(nsPres
     y += kidSize.Height();
     y += pageCSSMargin.bottom;
 
     maxXMost = std::max(maxXMost, x + kidSize.Width() + pageCSSMargin.right);
 
     // Is the page complete?
     nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
 
-    if (NS_FRAME_IS_FULLY_COMPLETE(status)) {
+    if (status.IsFullyComplete()) {
       NS_ASSERTION(!kidNextInFlow, "bad child flow list");
     } else if (!kidNextInFlow) {
       // The page isn't complete and it doesn't have a next-in-flow, so
       // create a continuing page.
       nsIFrame* continuingPage = aPresContext->PresShell()->FrameConstructor()->
         CreateContinuingFrame(aPresContext, kidFrame, this);
 
       // Add it to our child list
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -747,17 +747,17 @@ nsSubDocumentFrame::Reflow(nsPresContext
 
   NS_ASSERTION(aReflowInput.ComputedWidth() != NS_UNCONSTRAINEDSIZE,
                "Shouldn't have unconstrained stuff here "
                "thanks to the rules of reflow");
   NS_ASSERTION(NS_INTRINSICSIZE != aReflowInput.ComputedHeight(),
                "Shouldn't have unconstrained stuff here "
                "thanks to ComputeAutoSize");
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   NS_ASSERTION(mContent->GetPrimaryFrame() == this,
                "Shouldn't happen");
 
   // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed>
   aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
                        aReflowInput.ComputedSizeWithBorderPadding());
 
@@ -800,18 +800,18 @@ nsSubDocumentFrame::Reflow(nsPresContext
   FinishAndStoreOverflow(&aDesiredSize);
 
   if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
     PresContext()->PresShell()->PostReflowCallback(this);
     mPostedReflowCallback = true;
   }
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
-     ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x",
-      aDesiredSize.Width(), aDesiredSize.Height(), aStatus));
+     ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%s",
+      aDesiredSize.Width(), aDesiredSize.Height(), ToString(aStatus).c_str()));
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 bool
 nsSubDocumentFrame::ReflowFinished()
 {
   if (mFrameLoader) {
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -8979,17 +8979,17 @@ nsTextFrame::Reflow(nsPresContext*      
   DO_GLOBAL_REFLOW_COUNT("nsTextFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
 
   // XXX If there's no line layout, we shouldn't even have created this
   // frame. This may happen if, for example, this is text inside a table
   // but not inside a cell. For now, just don't reflow.
   if (!aReflowInput.mLineLayout) {
     ClearMetrics(aMetrics);
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     return;
   }
 
   ReflowText(*aReflowInput.mLineLayout, aReflowInput.AvailableWidth(),
              aReflowInput.mRenderingContext->GetDrawTarget(), aMetrics, aStatus);
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
 }
@@ -9055,17 +9055,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
   // so that when doing reflow our styles prevail over any part of the
   // textrun we look at. Note that next-in-flows may be mapping the same
   // content; gfxTextRun construction logic will ensure that we take priority.
   int32_t maxContentLength = GetInFlowContentLength();
 
   // We don't need to reflow if there is no content.
   if (!maxContentLength) {
     ClearMetrics(aMetrics);
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     return;
   }
 
 #ifdef NOISY_BIDI
     printf("Reflowed textframe\n");
 #endif
 
   const nsStyleText* textStyle = StyleText();
@@ -9212,17 +9212,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
     ClearTextRuns();
     iter = EnsureTextRun(nsTextFrame::eInflated, aDrawTarget,
                          lineContainer, aLineLayout.GetLine(),
                          &flowEndInTextRun);
   }
 
   if (!mTextRun) {
     ClearMetrics(aMetrics);
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     return;
   }
 
   NS_ASSERTION(gfxSkipCharsIterator(iter).ConvertOriginalToSkipped(offset + length)
                     <= mTextRun->GetLength(),
                "Text run does not map enough text for our reflow");
 
   /////////////////////////////////////////////////////////////////////
@@ -9540,32 +9540,34 @@ nsTextFrame::ReflowText(nsLineLayout& aL
       } else {
         aLineLayout.NotifyOptionalBreakPosition(this, length, true,
                                                 gfxBreakPriority::eNormalBreak);
       }
     }
   }
 
   // Compute reflow status
-  aStatus = contentLength == maxContentLength
-    ? NS_FRAME_COMPLETE : NS_FRAME_NOT_COMPLETE;
+  aStatus.Reset();
+  if (contentLength != maxContentLength) {
+    aStatus.SetIncomplete();
+  }
 
   if (charsFit == 0 && length > 0 && !usedHyphenation) {
     // Couldn't place any text
-    aStatus = NS_INLINE_LINE_BREAK_BEFORE();
+    aStatus.SetInlineLineBreakBeforeAndReset();
   } else if (contentLength > 0 && mContentOffset + contentLength - 1 == newLineOffset) {
     // Ends in \n
-    aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
+    aStatus.SetInlineLineBreakAfter();
     aLineLayout.SetLineEndsInBR(true);
   } else if (breakAfter) {
-    aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus);
+    aStatus.SetInlineLineBreakAfter();
   }
   if (completedFirstLetter) {
     aLineLayout.SetFirstLetterStyleOK(false);
-    aStatus |= NS_INLINE_BREAK_FIRST_LETTER_COMPLETE;
+    aStatus.SetFirstLetterComplete();
   }
 
   // Updated the cached NewlineProperty, or delete it.
   if (contentLength < maxContentLength &&
       textStyle->NewlineIsSignificant(this) &&
       (contentNewLineOffset < 0 ||
        mContentOffset + contentLength <= contentNewLineOffset)) {
     if (!cachedNewlineOffset) {
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -291,17 +291,17 @@ nsVideoFrame::Reflow(nsPresContext* aPre
   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("enter nsVideoFrame::Reflow: availSize=%d,%d",
                   aReflowInput.AvailableWidth(),
                   aReflowInput.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
 
   const WritingMode myWM = aReflowInput.GetWritingMode();
   nscoord contentBoxBSize = aReflowInput.ComputedBSize();
   const nscoord borderBoxISize = aReflowInput.ComputedISize() +
     aReflowInput.ComputedLogicalBorderPadding().IStartEnd(myWM);
   const bool isBSizeShrinkWrapping = (contentBoxBSize == NS_INTRINSICSIZE);
 
   nscoord borderBoxBSize;
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -889,17 +889,17 @@ nsMathMLContainerFrame::Reflow(nsPresCon
                                          aDesiredSize.mFlags);
     WritingMode wm = childFrame->GetWritingMode();
     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
     ReflowInput childReflowInput(aPresContext, aReflowInput,
                                        childFrame, availSize);
     ReflowChild(childFrame, aPresContext, childDesiredSize,
                 childReflowInput, childStatus);
-    //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
+    //NS_ASSERTION(childStatus.IsComplete(), "bad status");
     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                     childDesiredSize.mBoundingMetrics);
     childFrame = childFrame->GetNextSibling();
   }
 
   /////////////
   // If we are a container which is entitled to stretch its children, then we
   // ask our stretchy children to stretch themselves
@@ -945,17 +945,17 @@ nsMathMLContainerFrame::Reflow(nsPresCon
       childFrame = childFrame->GetNextSibling();
     }
   }
 
   /////////////
   // Place children now by re-adjusting the origins to align the baselines
   FinalizeReflow(drawTarget, aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 static nscoord AddInterFrameSpacingToSize(ReflowOutput&    aDesiredSize,
                                           nsMathMLContainerFrame* aFrame);
 
 /* virtual */ void
 nsMathMLContainerFrame::MarkIntrinsicISizesDirty()
--- a/layout/mathml/nsMathMLSelectedFrame.cpp
+++ b/layout/mathml/nsMathMLSelectedFrame.cpp
@@ -135,17 +135,17 @@ nsMathMLSelectedFrame::ComputeSize(nsRen
 void
 nsMathMLSelectedFrame::Reflow(nsPresContext*          aPresContext,
                               ReflowOutput&     aDesiredSize,
                               const ReflowInput& aReflowInput,
                               nsReflowStatus&          aStatus)
 {
   MarkInReflow();
   mPresentationData.flags &= ~NS_MATHML_ERROR;
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   aDesiredSize.ClearSize();
   aDesiredSize.SetBlockStartAscent(0);
   mBoundingMetrics = nsBoundingMetrics();
   nsIFrame* childFrame = GetSelectedFrame();
   if (childFrame) {
     WritingMode wm = childFrame->GetWritingMode();
     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -139,25 +139,25 @@ nsMathMLTokenFrame::Reflow(nsPresContext
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     WritingMode wm = childFrame->GetWritingMode();
     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
     ReflowInput childReflowInput(aPresContext, aReflowInput,
                                        childFrame, availSize);
     ReflowChild(childFrame, aPresContext, childDesiredSize,
                 childReflowInput, aStatus);
-    //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
+    //NS_ASSERTION(aStatus.IsComplete(), "bad status");
     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                     childDesiredSize.mBoundingMetrics);
   }
 
   // place and size children
   FinalizeReflow(aReflowInput.mRenderingContext->GetDrawTarget(), aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 // For token elements, mBoundingMetrics is computed at the ReflowToken
 // pass, it is not computed here because our children may be text frames
 // that do not implement the GetBoundingMetrics() interface.
 /* virtual */ nsresult
 nsMathMLTokenFrame::Place(DrawTarget*          aDrawTarget,
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -260,17 +260,17 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     WritingMode wm = childFrame->GetWritingMode();
     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
     ReflowInput childReflowInput(aPresContext, aReflowInput,
                                        childFrame, availSize);
     ReflowChild(childFrame, aPresContext, childDesiredSize,
                 childReflowInput, childStatus);
-    //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
+    //NS_ASSERTION(childStatus.IsComplete(), "bad status");
     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                     childDesiredSize.mBoundingMetrics);
 
     mozilla::WritingMode outerWM = aReflowInput.GetWritingMode();
     nscoord childDescent = childDesiredSize.BSize(outerWM) -
                            childDesiredSize.BlockStartAscent();
     if (descent < childDescent)
       descent = childDescent;
@@ -441,17 +441,17 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   FixInterFrameSpacing(aDesiredSize);
 
   // Finished with these:
   ClearSavedChildMetrics();
 
   // Set our overflow area
   GatherAndStoreOverflow(&aDesiredSize);
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 static void
 GetCharSpacing(nsMathMLChar*        aMathMLChar,
                nsOperatorFlags      aForm,
                int32_t              aScriptLevel,
                nscoord              em,
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -310,17 +310,17 @@ nsMathMLmpaddedFrame::Reflow(nsPresConte
 {
   mPresentationData.flags &= ~NS_MATHML_ERROR;
   ProcessAttributes();
 
   ///////////////
   // Let the base class format our content like an inferred mrow
   nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize,
                                  aReflowInput, aStatus);
-  //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
+  //NS_ASSERTION(aStatus.IsComplete(), "bad status");
 }
 
 /* virtual */ nsresult
 nsMathMLmpaddedFrame::Place(DrawTarget*          aDrawTarget,
                             bool                 aPlaceOrigin,
                             ReflowOutput& aDesiredSize)
 {
   nsresult rv =
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -191,17 +191,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     WritingMode wm = childFrame->GetWritingMode();
     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
     ReflowInput childReflowInput(aPresContext, aReflowInput,
                                        childFrame, availSize);
     ReflowChild(childFrame, aPresContext,
                      childDesiredSize, childReflowInput, childStatus);
-    //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
+    //NS_ASSERTION(childStatus.IsComplete(), "bad status");
     if (0 == count) {
       // base 
       baseFrame = childFrame;
       baseSize = childDesiredSize;
       bmBase = childDesiredSize.mBoundingMetrics;
     }
     else if (1 == count) {
       // index
@@ -211,17 +211,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
     }
     count++;
     childFrame = childFrame->GetNextSibling();
   }
   if (2 != count) {
     // report an error, encourage people to get their markups in order
     ReportChildCountError();
     ReflowError(drawTarget, aDesiredSize);
-    aStatus = NS_FRAME_COMPLETE;
+    aStatus.Reset();
     NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     // Call DidReflow() for the child frames we successfully did reflow.
     DidReflowChildren(mFrames.FirstChild(), childFrame);
     return;
   }
 
   ////////////
   // Prepare the radical symbol and the overline bar
@@ -349,17 +349,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
   dy = aDesiredSize.BlockStartAscent() - baseSize.BlockStartAscent();
   FinishReflowChild(baseFrame, aPresContext, baseSize, nullptr,
                     MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx),
                     dy, 0);
 
   mReference.x = 0;
   mReference.y = aDesiredSize.BlockStartAscent();
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 /* virtual */ void
 nsMathMLmrootFrame::GetIntrinsicISizeMetrics(nsRenderingContext* aRenderingContext, ReflowOutput& aDesiredSize)
 {
   nsIFrame* baseFrame = mFrames.FirstChild();
   nsIFrame* indexFrame = nullptr;
--- a/layout/mathml/nsMathMLmspaceFrame.cpp
+++ b/layout/mathml/nsMathMLmspaceFrame.cpp
@@ -110,17 +110,17 @@ nsMathMLmspaceFrame::Reflow(nsPresContex
   mBoundingMetrics.rightBearing = mBoundingMetrics.width;
 
   aDesiredSize.SetBlockStartAscent(mHeight);
   aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
   aDesiredSize.Height() = aDesiredSize.BlockStartAscent() + mDepth;
   // Also return our bounding metrics
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
-  aStatus = NS_FRAME_COMPLETE;
+  aStatus.Reset();
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
 }
 
 /* virtual */ nsresult
 nsMathMLmspaceFrame::MeasureForWidth(DrawTarget* aDrawTarget,
                                      ReflowOutput& aDesiredSize)
 {
   ProcessAttributes(PresContext());
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -5632,17 +5632,17 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayL
                            FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR);
   if (mFlags & VERTICAL_SCROLLBAR) {
     layer->SetScrollbarData(mScrollTarget, ScrollDirection::VERTICAL, mScrollbarThumbRatio);
   }
   if (mFlags & HORIZONTAL_SCROLLBAR) {
     layer->SetScrollbarData(mScrollTarget, ScrollDirection::HORIZONTAL, mScrollbarThumbRatio);
   }
   if (mFlags & SCROLLBAR_CONTAINER) {
-    layer->SetIsScrollbarContainer();
+    layer->SetIsScrollbarContainer(mScrollTarget);
   }
 
   if (mFlags & GENERATE_SUBDOC_INVALIDATIONS) {
     mFrame->PresContext()->SetNotifySubDocInvalidationData(layer);
   }
   return layer.forget();
 }
 
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -444,21 +444,18 @@ public:
    * a displayport, and for scroll handoff to work properly the ancestor
    * scrollframes should also get their own scrollable layers.
    */
   void ForceLayerForScrollParent() { mForceLayerForScrollParent = true; }
   /**
    * Get the ViewID and the scrollbar flags corresponding to the scrollbar for
    * which we are building display items at the moment.
    */
-  void GetScrollbarInfo(ViewID* aOutScrollbarTarget, uint32_t* aOutScrollbarFlags)
-  {
-    *aOutScrollbarTarget = mCurrentScrollbarTarget;
-    *aOutScrollbarFlags = mCurrentScrollbarFlags;
-  }
+  ViewID GetCurrentScrollbarTarget() const { return mCurrentScrollbarTarget; }
+  uint32_t GetCurrentScrollbarFlags() const { return mCurrentScrollbarFlags; }
   /**
    * Returns true if building a scrollbar, and the scrollbar will not be
    * layerized.
    */
   bool IsBuildingNonLayerizedScrollbar() const {
     return mIsBuildingScrollbar && !mCurrentScrollbarWillHaveLayer;
   }
   /**
--- a/layout/reftests/async-scrolling/reftest-stylo.list
+++ b/layout/reftests/async-scrolling/reftest-stylo.list
@@ -7,17 +7,17 @@ skip-if(!asyncPan) == bg-fixed-child.htm
 fails == bg-fixed-child-clip-1.html bg-fixed-child-clip-1.html
 fails == bg-fixed-child-clip-2.html bg-fixed-child-clip-2.html
 fuzzy(1,246) fuzzy-if(skiaContent,2,160) fuzzy-if(browserIsRemote&&d2d,53,185) skip-if(!asyncPan) == bg-fixed-child-mask.html bg-fixed-child-mask.html
 == bg-fixed-in-opacity.html bg-fixed-in-opacity.html
 fails == bg-fixed-child-no-culling-1.html bg-fixed-child-no-culling-1.html
 == bg-fixed-child-no-culling-2.html bg-fixed-child-no-culling-2.html
 fuzzy-if(Android,2,4000) fuzzy-if(browserIsRemote&&cocoaWidget,2,179524) fuzzy-if(browserIsRemote&&winWidget,1,74590) fuzzy-if(gtkWidget&&layersGPUAccelerated,1,3528) skip-if(!asyncPan) == bg-fixed-transformed-image.html bg-fixed-transformed-image.html
 == element-1.html element-1.html
-# == iframe-1.html iframe-1.html
+== iframe-1.html iframe-1.html
 == nested-1.html nested-1.html
 == nested-2.html nested-2.html
 == position-fixed-1.html position-fixed-1.html
 == position-fixed-2.html position-fixed-2.html
 skip-if(!asyncPan) == position-fixed-body.html position-fixed-body.html
 == position-fixed-cover-1.html position-fixed-cover-1.html
 == position-fixed-cover-2.html position-fixed-cover-2.html
 skip-if(!asyncPan) == position-fixed-cover-3.html position-fixed-cover-3.html
@@ -25,17 +25,17 @@ fails == position-fixed-transformed-1.ht
 == split-layers-1.html split-layers-1.html
 == split-layers-multi-scrolling-1.html split-layers-multi-scrolling-1.html
 == split-opacity-layers-1.html split-opacity-layers-1.html
 == sticky-pos-scrollable-1.html sticky-pos-scrollable-1.html
 == sticky-pos-scrollable-2.html sticky-pos-scrollable-2.html
 skip-if(!asyncPan) == sticky-pos-scrollable-3.html sticky-pos-scrollable-3.html
 fails == fixed-pos-scrollable-1.html fixed-pos-scrollable-1.html
 == culling-1.html culling-1.html
-# == position-fixed-iframe-1.html position-fixed-iframe-1.html
+== position-fixed-iframe-1.html position-fixed-iframe-1.html
 == position-fixed-iframe-2.html position-fixed-iframe-2.html
 fuzzy-if(skiaContent,1,11300) skip-if(!asyncPan) == position-fixed-in-scroll-container.html position-fixed-in-scroll-container.html
 == position-fixed-inside-sticky-1.html position-fixed-inside-sticky-1.html
 == position-fixed-inside-sticky-2.html position-fixed-inside-sticky-2.html
 == group-opacity-surface-size-1.html group-opacity-surface-size-1.html
 skip-if(!asyncPan) == position-sticky-transformed.html position-sticky-transformed.html
 == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity.html
 fails == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-1.html
--- a/layout/reftests/backgrounds/reftest-stylo.list
+++ b/layout/reftests/backgrounds/reftest-stylo.list
@@ -11,17 +11,17 @@ fails == layers-layer-count-inheritance-
 fails == viewport-translucent-color-2.html viewport-translucent-color-2.html
 fails == viewport-translucent-color-3.html viewport-translucent-color-3.html
 == viewport-translucent-color-ref.html viewport-translucent-color-ref.html
 == iframe-translucent-color-1.html iframe-translucent-color-1.html
 == translucent-color-1.html translucent-color-1.html
 fails == translucent-color-2.html translucent-color-2.html
 fuzzy-if(skiaContent,1,1024) == translucent-color-3.html translucent-color-3.html
 == translucent-color-ref.html translucent-color-ref.html
-# == root-element-display-none-1.html root-element-display-none-1.html
+== root-element-display-none-1.html root-element-display-none-1.html
 fails == continuous-inline-1a.html continuous-inline-1a.html
 fails == continuous-inline-1b.html continuous-inline-1b.html
 fails == continuous-inline-1c.html continuous-inline-1c.html
 fails == continuous-inline-1d.html continuous-inline-1d.html
 fails == continuous-inline-2a.html continuous-inline-2a.html
 fails == continuous-inline-2b.html continuous-inline-2b.html
 fails == continuous-inline-3.html continuous-inline-3.html
 fails == continuous-inline-4a.html continuous-inline-4a.html
@@ -36,18 +36,18 @@ fails == continuous-inline-5b.html conti
 == background-position-1a.html background-position-1a.html
 == background-position-1b.html background-position-1b.html
 == background-position-1c.html background-position-1c.html
 == background-position-1d.html background-position-1d.html
 == background-position-1e.html background-position-1e.html
 == background-position-1f.html background-position-1f.html
 == background-position-2a.html background-position-2a.html
 == background-position-2b.html background-position-2b.html
-# == background-position-2c.html background-position-2c.html
-# == background-position-2d.html background-position-2d.html
+== background-position-2c.html background-position-2c.html
+== background-position-2d.html background-position-2d.html
 == background-position-3a.html background-position-3a.html
 == background-position-3b.html background-position-3b.html
 == background-position-3c.html background-position-3c.html
 == background-position-3d.html background-position-3d.html
 == background-position-4a.html background-position-4a.html
 == background-position-4b.html background-position-4b.html
 == background-position-4c.html background-position-4c.html
 == background-position-4d.html background-position-4d.html
@@ -87,21 +87,21 @@ fails == continuous-inline-5b.html conti
 == background-size-body-contain-no-repeat.html background-size-body-contain-no-repeat.html
 == background-size-body-contain-not-fixed.html background-size-body-contain-not-fixed.html
 == background-size-body-cover-not-fixed.html background-size-body-cover-not-fixed.html
 
 == background-size-body-percent-percent-overflow.html background-size-body-percent-percent-overflow.html
 
 == background-size-zoom-no-repeat.html background-size-zoom-no-repeat.html
 
-# == background-size-contain-clip-padding.html background-size-contain-clip-padding.html
+== background-size-contain-clip-padding.html background-size-contain-clip-padding.html
 == background-size-contain-clip-border.html background-size-contain-clip-border.html
 == background-size-contain-position-fifty-fifty.html background-size-contain-position-fifty-fifty.html
 == background-size-contain-clip-padding-origin-border.html background-size-contain-clip-padding-origin-border.html
-# == background-size-contain-clip-padding-origin-border-padding.html background-size-contain-clip-padding-origin-border-padding.html
+== background-size-contain-clip-padding-origin-border-padding.html background-size-contain-clip-padding-origin-border-padding.html
 
 == background-layers-1a.html background-layers-1a.html
 == background-layers-1b.html background-layers-1b.html
 
 # box-decoration-break's effect on backgrounds is touchy and hard to test due to stretching
 # artifacts and the difficulty of covering exact lines, so just make sure
 # background-size results in a different rendering when present.
 fails pref(layout.css.box-decoration-break.enabled,true) == background-size-cover-slice.html background-size-cover-slice.html
@@ -133,21 +133,21 @@ fails == background-size-monster-rem.htm
 fails == background-moz-default-background-color.html background-moz-default-background-color.html
 
 fails == fixed-bg-with-transform-outside-viewport-1.html fixed-bg-with-transform-outside-viewport-1.html
 fuzzy(2,83) == fixed-bg-border-radius.html fixed-bg-border-radius.html
 
 fails HTTP == root-background-1.html root-background-1.html
 fails HTTP == root-background-1.html root-background-1.html
 
-# == really-big-background.html really-big-background.html
-# == body-background.html body-background.html
-# == table-background.html table-background.html
+fails == really-big-background.html really-big-background.html # Bug 1341690
+fails == body-background.html body-background.html # Bug 1339711
+fails == table-background.html table-background.html # Bug 1339711
 fails == table-background-print.html table-background-print.html
-# == div-background.html div-background.html
+== div-background.html div-background.html
 
 == background-repeat-1-ref.html background-repeat-1-ref.html
 
 == multi-background-clip-content-border.html multi-background-clip-content-border.html
 
 fails HTTP == background-referrer.html background-referrer.html
 
 == attachment-scroll-positioning-1.html attachment-scroll-positioning-1.html
@@ -174,16 +174,16 @@ fails == attachment-local-positioning-4.
 
 fuzzy-if(skiaContent,1,8) == background-multiple-with-border-radius.html background-multiple-with-border-radius.html
 == background-repeat-large-area.html background-repeat-large-area.html
 
 fails == background-tiling-zoom-1.html background-tiling-zoom-1.html
 
 skip-if(!cocoaWidget) == background-repeat-resampling.html background-repeat-resampling.html
 
-# == background-clip-text-1a.html background-clip-text-1a.html
-# == background-clip-text-1b.html background-clip-text-1b.html
-# == background-clip-text-1c.html background-clip-text-1c.html
-# == background-clip-text-1d.html background-clip-text-1d.html
-# == background-clip-text-1e.html background-clip-text-1e.html
+== background-clip-text-1a.html background-clip-text-1a.html
+== background-clip-text-1b.html background-clip-text-1b.html
+== background-clip-text-1c.html background-clip-text-1c.html
+== background-clip-text-1d.html background-clip-text-1d.html
+== background-clip-text-1e.html background-clip-text-1e.html
 # pref(layout.css.background-clip-text.enabled,false) == background-clip-text-1a.html background-clip-text-1a.html
 
 # pref(layout.css.background-clip-text.enabled,true) == background-clip-text-2.html background-clip-text-2.html
--- a/layout/reftests/backgrounds/vector/reftest-stylo.list
+++ b/layout/reftests/backgrounds/vector/reftest-stylo.list
@@ -196,10 +196,10 @@ include empty/reftest-stylo.list
 == wide--cover--omitted-width-percent-height-viewbox.html wide--cover--omitted-width-percent-height-viewbox.html
 == wide--cover--percent-width-nonpercent-height.html wide--cover--percent-width-nonpercent-height.html
 == wide--cover--percent-width-nonpercent-height-viewbox.html wide--cover--percent-width-nonpercent-height-viewbox.html
 == wide--cover--percent-width-omitted-height.html wide--cover--percent-width-omitted-height.html
 == wide--cover--percent-width-omitted-height-viewbox.html wide--cover--percent-width-omitted-height-viewbox.html
 == wide--cover--percent-width-percent-height.html wide--cover--percent-width-percent-height.html
 == wide--cover--percent-width-percent-height-viewbox.html wide--cover--percent-width-percent-height-viewbox.html
 
-# == diagonal-percentage-vector-background.html diagonal-percentage-vector-background.html
+== diagonal-percentage-vector-background.html diagonal-percentage-vector-background.html
 == no-aspect-ratio-wide.html no-aspect-ratio-wide.html
--- a/layout/reftests/bidi/dirAuto/reftest-stylo.list
+++ b/layout/reftests/bidi/dirAuto/reftest-stylo.list
@@ -37,18 +37,18 @@ fails == dynamicDirAuto-setLTR-NoDir6.ht
 fails == dynamicDirAuto-setLTR-NoDir7.html dynamicDirAuto-setLTR-NoDir7.html
 fails == dynamicDirAuto-setLTR-NoDir8.html dynamicDirAuto-setLTR-NoDir8.html
 fails == dynamicDirAuto-setLTR-InvalidDir1.html dynamicDirAuto-setLTR-InvalidDir1.html
 fails == dynamicDirAuto-setLTR-InvalidDir2.html dynamicDirAuto-setLTR-InvalidDir2.html
 fails == dynamicDirAuto-setLTR-InvalidDir3.html dynamicDirAuto-setLTR-InvalidDir3.html
 fails == dynamicDirAuto-setLTR-InvalidDir4.html dynamicDirAuto-setLTR-InvalidDir4.html
 fails == dynamicDirAuto-setLTR-InvalidDir5.html dynamicDirAuto-setLTR-InvalidDir5.html
 fails == dynamicDirAuto-setLTR-InvalidDir6.html dynamicDirAuto-setLTR-InvalidDir6.html
-# == dynamicDirAuto-setLTR-InvalidDir7.html dynamicDirAuto-setLTR-InvalidDir7.html
-# == dynamicDirAuto-setLTR-InvalidDir7.html dynamicDirAuto-setLTR-InvalidDir7.html
+fails == dynamicDirAuto-setLTR-InvalidDir7.html dynamicDirAuto-setLTR-InvalidDir7.html # Bug 1340696, bug 1341086
+fails == dynamicDirAuto-setLTR-InvalidDir7.html dynamicDirAuto-setLTR-InvalidDir7.html # Bug 1340696, bug 1341086
 fails == dynamicDirAuto-setRTL-Auto1.html dynamicDirAuto-setRTL-Auto1.html
 fails == dynamicDirAuto-setRTL-Auto2.html dynamicDirAuto-setRTL-Auto2.html
 fails == dynamicDirAuto-setRTL-Auto3.html dynamicDirAuto-setRTL-Auto3.html
 fails == dynamicDirAuto-setRTL-Auto4.html dynamicDirAuto-setRTL-Auto4.html
 fails == dynamicDirAuto-setRTL-Auto5.html dynamicDirAuto-setRTL-Auto5.html
 fails == dynamicDirAuto-setRTL-Auto6.html dynamicDirAuto-setRTL-Auto6.html
 fails == dynamicDirAuto-setRTL-LTR1.html dynamicDirAuto-setRTL-LTR1.html
 fails == dynamicDirAuto-setRTL-LTR2.html dynamicDirAuto-setRTL-LTR2.html
--- a/layout/reftests/bidi/numeral/reftest-stylo.list
+++ b/layout/reftests/bidi/numeral/reftest-stylo.list
@@ -30,19 +30,19 @@ pref(bidi.numeral,2) == bug441782-1.html
 pref(bidi.numeral,3) == bug441782-1.html bug441782-1.html
 pref(bidi.numeral,4) == bug441782-1.html bug441782-1.html
 pref(bidi.numeral,0) == bug441782-2.html bug441782-2.html
 pref(bidi.numeral,1) == bug441782-2.html bug441782-2.html
 pref(bidi.numeral,2) == bug441782-2.html bug441782-2.html
 pref(bidi.numeral,3) == bug441782-2.html bug441782-2.html
 pref(bidi.numeral,4) == bug441782-2.html bug441782-2.html
 # pref(bidi.numeral,0) == bug441782-3.html bug441782-3.html
-# == bug441782-3.html bug441782-3.html
-# == bug441782-3.html bug441782-3.html
-# == bug441782-3.html bug441782-3.html
+== bug441782-3.html bug441782-3.html
+== bug441782-3.html bug441782-3.html
+== bug441782-3.html bug441782-3.html
 # pref(bidi.numeral,4) == bug441782-3.html bug441782-3.html
 pref(bidi.numeral,0) == bug441782-4.html bug441782-4.html
 pref(bidi.numeral,1) == bug441782-4.html bug441782-4.html
 pref(bidi.numeral,2) == bug441782-4.html bug441782-4.html
 pref(bidi.numeral,3) == bug441782-4.html bug441782-4.html
 pref(bidi.numeral,4) == bug441782-4.html bug441782-4.html
 pref(bidi.numeral,0) == bug441782-5.html bug441782-5.html
 pref(bidi.numeral,1) == bug441782-5.html bug441782-5.html
--- a/layout/reftests/bidi/reftest-stylo.list
+++ b/layout/reftests/bidi/reftest-stylo.list
@@ -52,53 +52,53 @@ fails == 83958-1a.html 83958-1a.html
 fails == 83958-1b.html 83958-1b.html
 fails == 83958-1c.html 83958-1c.html
 fails == 83958-2a.html 83958-2a.html
 fails == 83958-2b.html 83958-2b.html
 == 115921-1.html 115921-1.html
 fails == 115921-2.html 115921-2.html
 == 151407-1.html 151407-1.html
 == 151407-1a.html 151407-1a.html
-# == 151407-2-ltr.html 151407-2-ltr.html
-# == 151407-2-rtl.html 151407-2-rtl.html
+== 151407-2-ltr.html 151407-2-ltr.html
+== 151407-2-rtl.html 151407-2-rtl.html
 == 151407-2-auto.html 151407-2-auto.html
 == 151407-2-empty.html 151407-2-empty.html
 == 151407-2-foopy.html 151407-2-foopy.html
-# == 151407-3-ltr.html 151407-3-ltr.html
-# == 151407-3-rtl.html 151407-3-rtl.html
+== 151407-3-ltr.html 151407-3-ltr.html
+== 151407-3-rtl.html 151407-3-rtl.html
 == 151407-3-auto.html 151407-3-auto.html
 == 151407-3-foopy.html 151407-3-foopy.html
 == 229367-1.html 229367-1.html
 fails == 229367-2.html 229367-2.html
 == 229367-3.html 229367-3.html
 fails == 258928-1.html 258928-1.html
 fails == 263359-1.html 263359-1.html
 fails == 263359-1a.html 263359-1a.html
 fails == 263359-1b.html 263359-1b.html
 fails == 263359-2.html 263359-2.html
 == 263359-3.html 263359-3.html
 fails == 263359-4.html 263359-4.html
 fails == 267459-1.html 267459-1.html
 fails == 267459-2.html 267459-2.html
 == 299065-1.html 299065-1.html
-# == 305643-1.html 305643-1.html
+== 305643-1.html 305643-1.html
 fails asserts-if(stylo,7) == 332655-1.html 332655-1.html # bug 1335314
 fails asserts-if(stylo,7) == 332655-2.html 332655-2.html # bug 1335314
 fails == 381279-1.html 381279-1.html
 fails == 386339.html 386339.html
 fails == 409375.html 409375.html
 == 413542-1.html 413542-1.html
 == 413542-2.html 413542-2.html
 fails == 413928-1.html 413928-1.html
 fails == 413928-2.html 413928-2.html
 == 425338-1a.html 425338-1a.html
 == 425338-1b.html 425338-1b.html
 == 489517-1.html 489517-1.html
 == 489887-1.html 489887-1.html
-# == 492231-1.html 492231-1.html
+== 492231-1.html 492231-1.html
 == 496006-1.html 496006-1.html
 == 503269-1.html 503269-1.html
 == 503957-1.html 503957-1.html
 == 525740-1.html 525740-1.html
 fails == 536963-1.html 536963-1.html
 fails == 562169-1.html 562169-1.html
 fails == 562169-1a.html 562169-1a.html
 fails == 562169-2.html 562169-2.html
@@ -143,33 +143,33 @@ fails == 726420-1.html 726420-1.html
 == 817406-2.html 817406-2.html
 == 817406-3.html 817406-3.html
 == 817406-4.html 817406-4.html
 == 847242-1.html 847242-1.html
 fuzzy-if(xulRuntime.widgetToolkit=="gtk3",1,11) == 869833-1.xul 869833-1.xul
 == 922530-1.html 922530-1.html
 == 922550-1.html 922550-1.html
 == 1067268-1.html 1067268-1.html
-# == 1069941-inline-bidi-border-1.html 1069941-inline-bidi-border-1.html
+== 1069941-inline-bidi-border-1.html 1069941-inline-bidi-border-1.html
 == 1069941-inline-bidi-margin-1.html 1069941-inline-bidi-margin-1.html
 == 1155359-1.xul 1155359-1.xul
 == 1157726-1.html 1157726-1.html
 == 1161752.html 1161752.html
 == 1161752-5-embed.html 1161752-5-embed.html
-# == brackets-1a-ltr.html brackets-1a-ltr.html
-# == brackets-1a-rtl.html brackets-1a-rtl.html
-# == brackets-1b-ltr.html brackets-1b-ltr.html
-# == brackets-1b-rtl.html brackets-1b-rtl.html
-# == brackets-1c-ltr.html brackets-1c-ltr.html
-# == brackets-1c-rtl.html brackets-1c-rtl.html
-# == brackets-2a-ltr.html brackets-2a-ltr.html
-# == brackets-2a-rtl.html brackets-2a-rtl.html
-# == brackets-2b-ltr.html brackets-2b-ltr.html
-# == brackets-2b-rtl.html brackets-2b-rtl.html
-# == brackets-2c-ltr.html brackets-2c-ltr.html
-# == brackets-2c-rtl.html brackets-2c-rtl.html
-# == brackets-3a-ltr.html brackets-3a-ltr.html
-# == brackets-3a-rtl.html brackets-3a-rtl.html
-# == brackets-3b-ltr.html brackets-3b-ltr.html
-# == brackets-3b-rtl.html brackets-3b-rtl.html
+== brackets-1a-ltr.html brackets-1a-ltr.html
+== brackets-1a-rtl.html brackets-1a-rtl.html
+== brackets-1b-ltr.html brackets-1b-ltr.html
+== brackets-1b-rtl.html brackets-1b-rtl.html
+== brackets-1c-ltr.html brackets-1c-ltr.html
+== brackets-1c-rtl.html brackets-1c-rtl.html
+== brackets-2a-ltr.html brackets-2a-ltr.html
+== brackets-2a-rtl.html brackets-2a-rtl.html
+== brackets-2b-ltr.html brackets-2b-ltr.html
+== brackets-2b-rtl.html brackets-2b-rtl.html
+== brackets-2c-ltr.html brackets-2c-ltr.html
+== brackets-2c-rtl.html brackets-2c-rtl.html
+== brackets-3a-ltr.html brackets-3a-ltr.html
+== brackets-3a-rtl.html brackets-3a-rtl.html
+== brackets-3b-ltr.html brackets-3b-ltr.html
+== brackets-3b-rtl.html brackets-3b-rtl.html
 fails == 1217833-1.html 1217833-1.html
 fails == 1217833-2.html 1217833-2.html
 == 1231175-1.html 1231175-1.html
--- a/layout/reftests/border-image/reftest-stylo.list
+++ b/layout/reftests/border-image/reftest-stylo.list
@@ -9,19 +9,19 @@ fails == multicolor-image-1.html multico
 fails == multicolor-image-2.html multicolor-image-2.html
 fails == multicolor-image-3.html multicolor-image-3.html
 fails == multicolor-image-4.html multicolor-image-4.html
 fails == multicolor-image-5.html multicolor-image-5.html
 fails == transparent-image-1.html transparent-image-1.html
 fails == repeat-image-1.html repeat-image-1.html
 fails == 470250-1.html 470250-1.html
 fails == 470250-2.html 470250-2.html
-# == different-h-v-1.html different-h-v-1.html
+fails == different-h-v-1.html different-h-v-1.html # Bug 1341703
 fails == different-h-v-2.html different-h-v-2.html
-# == different-h-v-1.html different-h-v-1.html
+fails == different-h-v-1.html different-h-v-1.html # Bug 1341703
 fails == center-scaling-1.html center-scaling-1.html
 fails == center-scaling-2.html center-scaling-2.html
 fails == center-scaling-3.html center-scaling-3.html
 fails == center-scaling-4t.html center-scaling-4t.html
 fails == center-scaling-4r.html center-scaling-4r.html
 fails == center-scaling-4b.html center-scaling-4b.html
 fails == center-scaling-4l.html center-scaling-4l.html
 fails == center-scaling-4tb.html center-scaling-4tb.html
--- a/layout/reftests/border-radius/reftest-stylo.list
+++ b/layout/reftests/border-radius/reftest-stylo.list
@@ -60,17 +60,17 @@ fuzzy-if(cocoaWidget,1,4) == intersectin
 == intersecting-clipping-1-overflow-hidden.html intersecting-clipping-1-overflow-hidden.html
 fuzzy-if(Android,5,105) fuzzy-if(d2d,1,20) fuzzy-if(skiaContent,1,250) == intersecting-clipping-1-refi.html intersecting-clipping-1-refi.html
 fuzzy-if(true,1,33) fuzzy-if(d2d,48,350) fuzzy-if(cocoaWidget,1,332) fuzzy-if(Android,124,440) fuzzy-if(skiaContent,1,135) == intersecting-clipping-1-refc.html intersecting-clipping-1-refc.html
 
 # Inheritance
 == inherit-1.html inherit-1.html
 
 # Table elements
-# == table-collapse-1.html table-collapse-1.html
+== table-collapse-1.html table-collapse-1.html
 # when border-collapse: collapse
 
 fuzzy-if(skiaContent,1,116) == invalidate-1a.html invalidate-1a.html
 fuzzy-if(skiaContent,1,117) == invalidate-1b.html invalidate-1b.html
 
 # test that border-radius is reduced for scrollbars
 fails == scrollbar-clamping-1.html scrollbar-clamping-1.html
 fails == scrollbar-clamping-2.html scrollbar-clamping-2.html
@@ -80,16 +80,16 @@ fails == corner-joins-1.xhtml corner-joi
 == corner-joins-2.xhtml corner-joins-2.xhtml
 
 == scroll-1.html scroll-1.html
 
 == transforms-1.html transforms-1.html
 
 == zero-radius-clip-1.html zero-radius-clip-1.html
 
-# == iframe-1.html iframe-1.html
+== iframe-1.html iframe-1.html
 
 # Test for antialiasing gaps between background and border
 fuzzy-if(gtkWidget,1,9) fuzzy-if(winWidget&&!d2d,1,9) fuzzy-if(d2d,5,40) fuzzy-if(Android||skiaContent,1,9) == curved-border-background-nogap.html curved-border-background-nogap.html
 
 == color-layer-1a.html color-layer-1a.html
 
 fails == corner-split.html corner-split.html
--- a/layout/reftests/box-properties/reftest-stylo.list
+++ b/layout/reftests/box-properties/reftest-stylo.list
@@ -12,19 +12,19 @@ fails == width-special-values-block-intr
 fails == width-special-values-float-intrinsic.html width-special-values-float-intrinsic.html
 fails == minmax-width-special-values-block-intrinsic.html minmax-width-special-values-block-intrinsic.html
 fails == width-special-values-cell-auto.html width-special-values-cell-auto.html
 fails == width-special-values-cell-fixed.html width-special-values-cell-fixed.html
 fails == box-sizing-1.html box-sizing-1.html
 fails == box-sizing-2.html box-sizing-2.html
 fails == box-sizing-3.html box-sizing-3.html
 fails == box-sizing-4.html box-sizing-4.html
-# == box-sizing-minmax-height.html box-sizing-minmax-height.html
+== box-sizing-minmax-height.html box-sizing-minmax-height.html
 == box-sizing-minmax-width.html box-sizing-minmax-width.html
-# == box-sizing-mozbox-minmax-height.html box-sizing-mozbox-minmax-height.html
+== box-sizing-mozbox-minmax-height.html box-sizing-mozbox-minmax-height.html
 fails == abspos-non-replaced-width-offset-margin.html abspos-non-replaced-width-offset-margin.html
 fails == abspos-replaced-width-offset-margin.html abspos-replaced-width-offset-margin.html
 fails HTTP(..) == CSS21-t100301.xhtml CSS21-t100301.xhtml
 == CSS21-t100303.xhtml CSS21-t100303.xhtml
 == CSS21-t100303-simple.xhtml CSS21-t100303-simple.xhtml
 == CSS21-t100801-vertical-align.xhtml CSS21-t100801-vertical-align.xhtml
 == clip-auto.html clip-auto.html
 fails == clip-rect-auto.html clip-rect-auto.html
--- a/layout/reftests/box-shadow/reftest-stylo.list
+++ b/layout/reftests/box-shadow/reftest-stylo.list
@@ -1,15 +1,15 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 == boxshadow-basic.html boxshadow-basic.html
-# == boxshadow-blur.html boxshadow-blur.html
-# == boxshadow-blur.html boxshadow-blur.html
+== boxshadow-blur.html boxshadow-blur.html
+== boxshadow-blur.html boxshadow-blur.html
 fails random == boxshadow-blur-2.html boxshadow-blur-2.html
 fails random == boxshadow-blur-2.html boxshadow-blur-2.html
-# == boxshadow-multiple.html boxshadow-multiple.html
+== boxshadow-multiple.html boxshadow-multiple.html
 == boxshadow-spread.html boxshadow-spread.html
 fails == tableboxshadow-basic.html tableboxshadow-basic.html
 fails == tableboxshadow-trshadow.html tableboxshadow-trshadow.html
 fails == tableboxshadow-tdshadow.html tableboxshadow-tdshadow.html
 == boxshadow-rounding.html boxshadow-rounding.html
 fails == boxshadow-button.html boxshadow-button.html
 fails == boxshadow-fileupload.html boxshadow-fileupload.html
 == boxshadow-inner-basic.html boxshadow-inner-basic.html
@@ -28,19 +28,19 @@ fails == boxshadow-border-radius-int.htm
 == boxshadow-inset-neg-spread.html boxshadow-inset-neg-spread.html
 == boxshadow-inset-neg-spread2.html boxshadow-inset-neg-spread2.html
 fails == boxshadow-rotated.html boxshadow-rotated.html
 == boxshadow-inset-large-border-radius.html boxshadow-inset-large-border-radius.html
 
 # fuzzy due to blur going inside, but as long as it's essentially black instead of a light gray its ok.
 fuzzy(12,9445) fuzzy-if(d2d,13,10926) == boxshadow-inset-large-offset.html boxshadow-inset-large-offset.html
 
-# == overflow-not-scrollable-1.html overflow-not-scrollable-1.html
-# == overflow-not-scrollable-1.html overflow-not-scrollable-1.html
+== overflow-not-scrollable-1.html overflow-not-scrollable-1.html
+== overflow-not-scrollable-1.html overflow-not-scrollable-1.html
 == overflow-not-scrollable-2.html overflow-not-scrollable-2.html
 fails == 611574-1.html 611574-1.html
 fails == 611574-2.html 611574-2.html
-# == fieldset.html fieldset.html
+== fieldset.html fieldset.html
 fuzzy-if(winWidget,5,30) fuzzy-if(skiaContent,16,10) == fieldset-inset.html fieldset-inset.html
 == 1178575.html 1178575.html
 == 1178575-2.html 1178575-2.html
 fails == 1212823-1.html 1212823-1.html
 fails == boxshadow-large-offset.html boxshadow-large-offset.html
--- a/layout/reftests/box-sizing/reftest-stylo.list
+++ b/layout/reftests/box-sizing/reftest-stylo.list
@@ -9,9 +9,9 @@
 == intrinsic-1h.html intrinsic-1h.html
 == intrinsic-1i.html intrinsic-1i.html
 == intrinsic-1j.html intrinsic-1j.html
 == intrinsic-1k.html intrinsic-1k.html
 == intrinsic-1l.html intrinsic-1l.html
 == intrinsic-1m.html intrinsic-1m.html
 == intrinsic-1n.html intrinsic-1n.html
 == intrinsic-1o.html intrinsic-1o.html
-# == computed-size-reporting.html computed-size-reporting.html
+== computed-size-reporting.html computed-size-reporting.html
--- a/layout/reftests/bugs/reftest-stylo.list
+++ b/layout/reftests/bugs/reftest-stylo.list
@@ -1,61 +1,61 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # Please keep this list sorted by bug number (but feel free to use a
 # logical order for the tests for each bug).
 fails == 105-1.html 105-1.html
 fails == 647-1.html 647-1.html
-# == 9458-basic-1.html 9458-basic-1.html
+== 9458-basic-1.html 9458-basic-1.html
 fails == 9458-valign-1.html 9458-valign-1.html
 fails == 9458-valign-2.html 9458-valign-2.html
 == 9458-height-1.html 9458-height-1.html
 == 9458-height-2.html 9458-height-2.html
 == 9458-width-1a.html 9458-width-1a.html
 == 9458-width-1b.html 9458-width-1b.html
 == 9458-width-2a.html 9458-width-2a.html
 == 9458-width-2b.html 9458-width-2b.html
-# == 9458-zorder-1.html 9458-zorder-1.html
+== 9458-zorder-1.html 9458-zorder-1.html
 == 9458-zorder-2.html 9458-zorder-2.html
 == 9458-zorder-3.html 9458-zorder-3.html
 == 9458-zorder-4.html 9458-zorder-4.html
 == 9458-zorder-5.html 9458-zorder-5.html
 fails == 10036-1.html 10036-1.html
 fails == 10209-1.html 10209-1.html
 HTTP(..) == 10209-2.html 10209-2.html
 asserts(2) skip-if(!cocoaWidget) HTTP(..) == 10209-3.html 10209-3.html
-# == 18217-basic-1.html 18217-basic-1.html
+== 18217-basic-1.html 18217-basic-1.html
 == 18217-basic-2a.html 18217-basic-2a.html
 == 18217-basic-2b.html 18217-basic-2b.html
 fails == 18217-valign-1.html 18217-valign-1.html
 == 18217-height-1.html 18217-height-1.html
 == 18217-height-2.html 18217-height-2.html
 == 18217-width-1a.html 18217-width-1a.html
 == 18217-width-1b.html 18217-width-1b.html
 == 18217-width-2a.html 18217-width-2a.html
 == 18217-width-2b.html 18217-width-2b.html
-# == 18217-zorder-1.html 18217-zorder-1.html
+== 18217-zorder-1.html 18217-zorder-1.html
 == 18217-zorder-2.html 18217-zorder-2.html
 == 18217-zorder-3.html 18217-zorder-3.html
 == 18217-zorder-4.html 18217-zorder-4.html
 == 18217-zorder-5.html 18217-zorder-5.html
 fails == 23604-1.html 23604-1.html
 fails == 23604-2.html 23604-2.html
 == 24998-1.html 24998-1.html
-# == 25888-1l.html 25888-1l.html
-# == 25888-1l.html 25888-1l.html
-# == 25888-1r.html 25888-1r.html
-# == 25888-1r.html 25888-1r.html
+== 25888-1l.html 25888-1l.html
+== 25888-1l.html 25888-1l.html
+== 25888-1r.html 25888-1r.html
+== 25888-1r.html 25888-1r.html
 == 25888-2l.html 25888-2l.html
 == 25888-2r.html 25888-2r.html
 == 25888-3l.html 25888-3l.html
 == 25888-3r.html 25888-3r.html
-# == 25888-1l-block.html 25888-1l-block.html
-# == 25888-1l-block.html 25888-1l-block.html
-# == 25888-1r-block.html 25888-1r-block.html
-# == 25888-1r-block.html 25888-1r-block.html
+== 25888-1l-block.html 25888-1l-block.html
+== 25888-1l-block.html 25888-1l-block.html
+== 25888-1r-block.html 25888-1r-block.html
+== 25888-1r-block.html 25888-1r-block.html
 == 25888-2l-block.html 25888-2l-block.html
 == 25888-2r-block.html 25888-2r-block.html
 == 25888-3l-block.html 25888-3l-block.html
 == 25888-3r-block.html 25888-3r-block.html
 fails == 28811-1a.html 28811-1a.html
 fails == 28811-1b.html 28811-1b.html
 fails == 28811-2a.html 28811-2a.html
 fails == 28811-2b.html 28811-2b.html
@@ -69,47 +69,47 @@ fails == 40596-1g.html 40596-1g.html
 fails == 40596-1h.html 40596-1h.html
 fails == 40596-1i.html 40596-1i.html
 fails == 40596-1j.html 40596-1j.html
 == 50630-1a.html 50630-1a.html
 == 50630-1b.html 50630-1b.html
 == 50630-1c.html 50630-1c.html
 == 50630-2.html 50630-2.html
 == 50630-3.html 50630-3.html
-# == 50630-4.html 50630-4.html
-# == 50630-4.html 50630-4.html
+== 50630-4.html 50630-4.html
+== 50630-4.html 50630-4.html
 == 50630-5.html 50630-5.html
 == 67752-1.html 67752-1.html
 == 67752-2.html 67752-2.html
 == 68061-1.xml 68061-1.xml
 == 68061-2.xml 68061-2.xml
 == 76331-1.html 76331-1.html
 fails == 81947-1.html 81947-1.html
 fails == 82711-1.html 82711-1.html
 fails == 82711-2.html 82711-2.html
 fails == 82711-3.html 82711-3.html
-# == 82711-1-ref.html 82711-1-ref.html
-# == 82711-1-ref.html 82711-1-ref.html
+fails == 82711-1-ref.html 82711-1-ref.html # Bug 1341697, Bug 1341637
+fails == 82711-1-ref.html 82711-1-ref.html # Bug 1341697, Bug 1341637
 fails == 82711-2-ref.html 82711-2-ref.html
 fails == 84400-1.html 84400-1.html
 fails == 84400-2.html 84400-2.html
 == 97777-1.html 97777-1.html
 fails == 97777-2.html 97777-2.html
 == 98223-1.html 98223-1.html
 == 98223-2.html 98223-2.html
-# == 99850-1a.html 99850-1a.html # bug 1337695
-# == 99850-1b.html 99850-1b.html # bug 1337695
+skip-if(stylo) == 99850-1a.html 99850-1a.html # bug 1337695
+skip-if(stylo) == 99850-1b.html 99850-1b.html # bug 1337695
 fails == 99850-1c.html 99850-1c.html
-# == 99850-1d.html 99850-1d.html # bug 1337695
+skip-if(stylo) == 99850-1d.html 99850-1d.html # bug 1337695
 == 105030-1.html 105030-1.html
 == 109735-1.html 109735-1.html
 == 116882-1.html 116882-1.html
 == 120834-1a.html 120834-1a.html
 == 120834-2a.html 120834-2a.html
-# == 120834-2b.html 120834-2b.html
+== 120834-2b.html 120834-2b.html
 == 120834-2c.html 120834-2c.html
 == 120834-2d.html 120834-2d.html
 == 120834-2e.html 120834-2e.html
 == 120834-2f.html 120834-2f.html
 == 120834-2g.html 120834-2g.html
 == 120834-2h.html 120834-2h.html
 == 120834-2i.html 120834-2i.html
 == 120834-2j.html 120834-2j.html
@@ -145,19 +145,19 @@ fails == 163504-1b.html 163504-1b.html
 fails == 163504-2a.html 163504-2a.html
 fails == 163504-2b.html 163504-2b.html
 == 167496-1.html 167496-1.html
 == 169749-1.html 169749-1.html
 == 172073-1.html 172073-1.html
 fails == 175190-1.html 175190-1.html
 fails == 179596-1a.html 179596-1a.html
 fails == 179596-1b.html 179596-1b.html
-# == 179596-2.html 179596-2.html
-# == 179596-2.html 179596-2.html
-# == 179596-2.html 179596-2.html
+== 179596-2.html 179596-2.html
+== 179596-2.html 179596-2.html
+== 179596-2.html 179596-2.html
 fails == 180085-1.html 180085-1.html
 fails == 180085-2.html 180085-2.html
 fails == 185388-1.html 185388-1.html
 fails == 186317-1.html 186317-1.html
 fails == 192902-1.html 192902-1.html
 == 192767-01.xul 192767-01.xul
 == 192767-02.xul 192767-02.xul
 == 192767-03.xul 192767-03.xul
@@ -207,17 +207,17 @@ fails == 213834-1.html 213834-1.html
 == 214077-1a.html 214077-1a.html
 == 214077-1b.html 214077-1b.html
 == 218473-1.html 218473-1.html
 fuzzy-if(skiaContent,1,4) == 220165-1.svg 220165-1.svg
 fails == 223809-1.html 223809-1.html
 == 228856-1.html 228856-1.html
 == 228856-2.html 228856-2.html
 == 229591-1.html 229591-1.html
-# == 231823-1.html 231823-1.html
+fails == 231823-1.html 231823-1.html
 == 232990-1a.xhtml 232990-1a.xhtml
 == 232990-1b.xhtml 232990-1b.xhtml
 fails == 233094-1.html 233094-1.html
 fails == 233094-2a.html 233094-2a.html
 fails == 233094-2b.html 233094-2b.html
 fails == 233094-2c.html 233094-2c.html
 == 234686-1.html 234686-1.html
 == 234686-2.html 234686-2.html
@@ -297,27 +297,27 @@ fails == 271747-1b.html 271747-1b.html
 == 272646-2c.xul 272646-2c.xul
 fails == 273681-1.html 273681-1.html
 == 278266-1a.html 278266-1a.html
 == 278266-1b.html 278266-1b.html
 fails == 280708-1a.html 280708-1a.html
 fails == 280708-1b.html 280708-1b.html
 fails == 281241-1.html 281241-1.html
 fails == 281241-2.xhtml 281241-2.xhtml
-# == 283686-1.html 283686-1.html
+== 283686-1.html 283686-1.html
 == 283686-2.html 283686-2.html
-# == 283686-3.html 283686-3.html
+== 283686-3.html 283686-3.html
 fails == 289384-1.xhtml 289384-1.xhtml
-# == 289480.html#top 289480.html#top
+skip-if(stylo) == 289480.html#top 289480.html#top # Bug 1341705
 fails == 290129-1.html 290129-1.html
 fails == 291078-1.html 291078-1.html
 == 291078-2.html 291078-2.html
 == 291262-1.html 291262-1.html
-# == 294306-1.html 294306-1.html
-# == 294306-1.html 294306-1.html
+== 294306-1.html 294306-1.html
+== 294306-1.html 294306-1.html
 fails == 296361-1.html 296361-1.html
 == 296904-1.html 296904-1.html
 fails == 299136-1.html 299136-1.html
 == 299837-1.html 299837-1.html
 == 299837-2.xul 299837-2.xul
 random-if(d2d) == 299837-3.xul 299837-3.xul
 fails == 300691-1a.html 300691-1a.html
 fails == 300691-1b.html 300691-1b.html
@@ -341,18 +341,18 @@ fails == 307102-3.html 307102-3.html
 == 308406-2.html 308406-2.html
 == 309550-1.html 309550-1.html
 == 309914-1.xul 309914-1.xul
 == 311366-unknown-inline-1.html 311366-unknown-inline-1.html
 == 311366-unknown-block-1.html 311366-unknown-block-1.html
 == 311366-unknown-block-3.html 311366-unknown-block-3.html
 == 311366-unknown-block-2.html 311366-unknown-block-2.html
 == 311366-unknown-inline-2.html 311366-unknown-inline-2.html
-# == 311822-1.html 311822-1.html
-# == 311822-1.html 311822-1.html
+fails == 311822-1.html 311822-1.html # bug 1341712, bug 1341714
+fails == 311822-1.html 311822-1.html # bug 1341712, bug 1341714
 fails == 315620-1a.html 315620-1a.html
 == 315620-1b.html 315620-1b.html
 fails == 315620-2a.xhtml 315620-2a.xhtml
 == 315620-2b.xhtml 315620-2b.xhtml
 fails == 315920-1a.html 315920-1a.html
 fails == 315920-1b.html 315920-1b.html
 fails == 315920-1c.html 315920-1c.html
 fails == 315920-1d.html 315920-1d.html
@@ -429,19 +429,19 @@ fails == 323656-3.html 323656-3.html
 == 325292-1.html 325292-1.html
 fails == 325486-1.html 325486-1.html
 == 328111-1.html 328111-1.html
 random == 328829-1.xhtml 328829-1.xhtml
 == 328829-2.xhtml 328829-2.xhtml
 == 329359-1.html 329359-1.html
 fails == 331809-1.html 331809-1.html
 == 332360.html 332360.html
-# == 332360-ltr.html 332360-ltr.html
+== 332360-ltr.html 332360-ltr.html
 == 332360-width.html 332360-width.html
-# == 332360-width-ltr.html 332360-width-ltr.html
+== 332360-width-ltr.html 332360-width-ltr.html
 fails == 332557-1.html 332557-1.html
 == 332975-1.html 332975-1.html
 == 333970-1.html 333970-1.html
 == 334829-1a.xhtml 334829-1a.xhtml
 == 334829-1b.xhtml 334829-1b.xhtml
 fails == 335628-1.html 335628-1.html
 == 335628-2.xul 335628-2.xul
 == 336096-1.xul 336096-1.xul
@@ -465,18 +465,18 @@ fails == 345563-sub.xhtml 345563-sub.xht
 fails == 346774-1a.html 346774-1a.html
 fails == 346774-1b.html 346774-1b.html
 fails == 346774-1c.html 346774-1c.html
 fails == 347348-1.xhtml 347348-1.xhtml
 fails == 347496-1.xhtml 347496-1.xhtml
 == 347912-1.html 347912-1.html
 fails == 348049-1.xhtml 348049-1.xhtml
 fails == 348516-1.html 348516-1.html
-# == 348516-2.html 348516-2.html
-# == 348516-2.html 348516-2.html
+fails == 348516-2.html 348516-2.html # Bug 1321769?
+fails == 348516-2.html 348516-2.html # Bug 1321769?
 fails == 348516-3.html 348516-3.html
 == 348597-1.html 348597-1.html
 == 348809-1a.html 348809-1a.html
 == 348809-1b.html 348809-1b.html
 == 348809-1c.html 348809-1c.html
 == 348809-1d.html 348809-1d.html
 == 348809-1e.html 348809-1e.html
 == 348809-1f.html 348809-1f.html
@@ -526,37 +526,37 @@ fails == 352980-3f.html 352980-3f.html
 == 355548-4.xml 355548-4.xml
 == 355548-5.xml 355548-5.xml
 == 356774-1.html 356774-1.html
 == 356775-1.html 356775-1.html
 fails == 359869-1.html 359869-1.html
 fails == 359903-1.html 359903-1.html
 fails == 359903-2.html 359903-2.html
 == 360065-1.html 360065-1.html
-# == 360746-1.html 360746-1.html
+asserts-if(stylo,1) == 360746-1.html 360746-1.html # Bug 1341721
 == 360757-1a.html 360757-1a.html
 == 360757-1b.html 360757-1b.html
 == 361091-1.html 361091-1.html
 fails == 362594-1a.html 362594-1a.html
 fails == 362594-1b.html 362594-1b.html
 fails == 362594-1c.html 362594-1c.html
-# == 362594-2a.html 362594-2a.html
-# == 362594-2a.html 362594-2a.html
-# == 362594-2b.html 362594-2b.html
-# == 362594-2b.html 362594-2b.html
+fails == 362594-2a.html 362594-2a.html # Bug 1341651
+fails == 362594-2a.html 362594-2a.html # Bug 1341651
+fails == 362594-2b.html 362594-2b.html # Bug 1341651
+fails == 362594-2b.html 362594-2b.html # Bug 1341651
 fails == 362594-2c.html 362594-2c.html
 fails == 362901-1.html 362901-1.html
 == 363247-1.html 363247-1.html
 fails == 363329-1.html 363329-1.html
 fails == 363329-2.html 363329-2.html
 fails == 363370-1.html 363370-1.html
 fails == 363402-1.html 363402-1.html
 == 363637-1.html 363637-1.html
-# == 363706-1.html 363706-1.html
-# == 363706-1.html 363706-1.html
+fails == 363706-1.html 363706-1.html # Bug 1324348
+fails == 363706-1.html 363706-1.html # Bug 1324348
 fails == 363728-1.html 363728-1.html
 == 363728-2.html 363728-2.html
 fails == 363858-1.html 363858-1.html
 fails == 363858-2.html 363858-2.html
 fails == 363858-3.html 363858-3.html
 fails == 363858-4.html 363858-4.html
 fails == 363858-5a.html 363858-5a.html
 fails == 363858-5b.html 363858-5b.html
@@ -603,37 +603,37 @@ fails == 367504-float-1.html 367504-floa
 fails == 368020-1.html 368020-1.html
 fails == 368020-2.html 368020-2.html
 fails == 368020-3.html 368020-3.html
 fails pref(layout.css.box-decoration-break.enabled,true) == 368020-5.html 368020-5.html
 == 368155-1.xhtml 368155-1.xhtml
 fails asserts(4-8) == 368155-negative-margins-1.html 368155-negative-margins-1.html
 # we can't test this because there's antialiasing involved, and our comparison
 # is too exact
-# == 368247-1.html 368247-1.html
+== 368247-1.html 368247-1.html
 == 368247-2.html 368247-2.html
 == 368504-1.html 368504-1.html
 fails == 368504-2.html 368504-2.html
 == 368504-3a.html 368504-3a.html
 == 368504-3b.html 368504-3b.html
 == 368504-4.html 368504-4.html
 == 368504-5.html 368504-5.html
 fails == 368504-6.html 368504-6.html
 fails asserts-if(stylo,2) == 368622-1.html 368622-1.html # bug 1324704
 fails == 368651-1.html 368651-1.html
 == 369361-1.html 369361-1.html
 == 369361-2.html 369361-2.html
 == 369882.xul 369882.xul
 fails == 369975-1.html 369975-1.html
 == 370353-1.html 370353-1.html
 fails == 370422-1.html 370422-1.html
-# == 370525-1.html 370525-1.html
-# == 370525-1.html 370525-1.html
-# == 370525-2.html 370525-2.html
-# == 370525-2.html 370525-2.html
+== 370525-1.html 370525-1.html
+== 370525-1.html 370525-1.html
+== 370525-2.html 370525-2.html
+== 370525-2.html 370525-2.html
 == 370525-rowspan-1a.html 370525-rowspan-1a.html
 == 370525-rowspan-1b.html 370525-rowspan-1b.html
 == 370525-rowspan-1c.html 370525-rowspan-1c.html
 == 370525-rowspan-2a.html 370525-rowspan-2a.html
 == 370525-rowspan-2b.html 370525-rowspan-2b.html
 == 370525-rowspan-3.html 370525-rowspan-3.html
 == 370525-rowspan-4.html 370525-rowspan-4.html
 == 370525-sib.html 370525-sib.html
@@ -699,18 +699,18 @@ fails == 379349-2a.xhtml 379349-2a.xhtml
 fails == 379349-2b.xhtml 379349-2b.xhtml
 fails == 379349-3a.xhtml 379349-3a.xhtml
 fails == 379349-3b.xhtml 379349-3b.xhtml
 fails == 379361-1.html 379361-1.html
 fails == 379361-2.html 379361-2.html
 fails == 379361-3.html 379361-3.html
 == 379461-1.xhtml 379461-1.xhtml
 == 379461-2.xhtml 379461-2.xhtml
-# == 379461-3-container-xhtml.html 379461-3-container-xhtml.html
-# == 379461-3-container-xhtml.html 379461-3-container-xhtml.html
+fails == 379461-3-container-xhtml.html 379461-3-container-xhtml.html # Bug 1341095
+fails == 379461-3-container-xhtml.html 379461-3-container-xhtml.html # Bug 1341095
 == 380004-1.html 380004-1.html
 == 380227-1.html 380227-1.html
 fails == 380825-1.html 380825-1.html
 == 380842-1.html 380842-1.html
 == 381130-1.html 381130-1.html
 fails == 381507-1.html 381507-1.html
 == 381746-1.html 381746-1.html
 fails == 382600-1.html 382600-1.html
@@ -748,34 +748,34 @@ fails test-pref(layout.float-fragments-i
 fails test-pref(layout.float-fragments-inside-column.enabled,true) == 386147-1.html 386147-1.html
 == 386310-1a.html 386310-1a.html
 == 386310-1b.html 386310-1b.html
 == 386310-1c.html 386310-1c.html
 == 386310-1d.html 386310-1d.html
 == 386401-1.html 386401-1.html
 == 386401-2.html 386401-2.html
 == 386401-3.html 386401-3.html
-# == 386470-1a.html 386470-1a.html
+fails == 386470-1a.html 386470-1a.html # Bug 1341725
 fails == 386470-1b.html 386470-1b.html
-# == 386470-1c.html 386470-1c.html
+fails == 386470-1c.html 386470-1c.html  # Bug 1341725
 == 386920-1.html 386920-1.html
 == 387201-1.html 387201-1.html
 == 387201-2.html 387201-2.html
 == 387201-3.html 387201-3.html
 == 387227-1.html 387227-1.html
 == 387227-2.html 387227-2.html
 == 387344-1.html 387344-1.html
 == 387876-1.html 387876-1.html
 == 387876-2.html 387876-2.html
 == 387876-3a.html 387876-3a.html
 == 387876-3b.html 387876-3b.html
 == 388026-1.html 388026-1.html
 fails == 389074-1.html 389074-1.html
-# == 389224-1.html 389224-1.html
-# == 389224-2.html 389224-2.html
+== 389224-1.html 389224-1.html
+fails == 389224-2.html 389224-2.html # Bug 1341728
 fails == 389468-1.html 389468-1.html
 == 389623-1.html 389623-1.html
 == 389636-1.html 389636-1.html
 == 389924-1a.html 389924-1a.html
 == 389924-1b.html 389924-1b.html
 == 389924-1a.html 389924-1a.html
 == 390318-1a.html 390318-1a.html
 == 390318-1b.html 390318-1b.html
@@ -803,17 +803,17 @@ fails == 393490-1.html 393490-1.html
 == 393655-5.html 393655-5.html
 == 393671-1.html 393671-1.html
 == 393671-2.html 393671-2.html
 == 393671-3.html 393671-3.html
 == 393760-1.xml 393760-1.xml
 fuzzy-if(skiaContent,1,500) == 393760-2.xml 393760-2.xml
 == 394111-1.html 394111-1.html
 == 394534-1.html 394534-1.html
-# == 394676-1.xhtml 394676-1.xhtml
+skip-if(stylo) == 394676-1.xhtml 394676-1.xhtml # Bug 1341719
 fails == 395107-1.html 395107-1.html
 fails == 395107-2.html 395107-2.html
 fails == 395107-3.html 395107-3.html
 fails == 395107-4.html 395107-4.html
 fails == 395107-5.html 395107-5.html
 fails == 395130-1.html 395130-1.html
 fails == 395130-2.html 395130-2.html
 == 395331-1.xml 395331-1.xml
@@ -882,17 +882,17 @@ fails == 403519-1.html 403519-1.html
 == 403519-2.html 403519-2.html
 == 403656-1.html 403656-1.html
 == 403656-2.html 403656-2.html
 fails == 403656-3.html 403656-3.html
 == 403656-4.html 403656-4.html
 == 403656-5.html 403656-5.html
 #== 403657-1.html 403657-1.html
 fails == 403733-1.html 403733-1.html
-# == 403962-1.xhtml 403962-1.xhtml
+fails == 403962-1.xhtml 403962-1.xhtml # Bug 1290276
 == 404030-1.html 404030-1.html
 == 404030-1-notref.html 404030-1-notref.html
 == 404030-1-notref2.html 404030-1-notref2.html
 fails == 404123-1.html 404123-1.html
 fails == 404123-2.html 404123-2.html
 fails == 404123-3.html 404123-3.html
 # may fail "randomly" on OS X, doesn't seem to be rendering usefully anyhow - bug 602469
 random-if(cocoaWidget) HTTP(..) == 404149-1.xul 404149-1.xul
@@ -906,17 +906,17 @@ fails == 404553-1.html 404553-1.html
 == 404666-1.html 404666-1.html
 == 404666-2.html 404666-2.html
 == 405186-1.xhtml 405186-1.xhtml
 fails == 405305-1.html 405305-1.html
 == 405380-1.html 405380-1.html
 == 405517-1.xhtml 405517-1.xhtml
 == 405577-1.html 405577-1.html
 == 405584-1.html 405584-1.html
-# == 405952-1.html 405952-1.html
+fails == 405952-1.html 405952-1.html # Bug 1321769?
 == 406484-1.html 406484-1.html
 == 406568-1.html 406568-1.html
 fails == 407016-1-a.html 407016-1-a.html
 fails == 407016-1-b.html 407016-1-b.html
 fails == 407078-1.html 407078-1.html
 fails == 407095-1.html 407095-1.html
 == 407111-1.html 407111-1.html
 == 407227-1.html 407227-1.html
@@ -1040,66 +1040,66 @@ random-if(gtkWidget) == 424074-1-ref2.xu
 == 424236-9.html 424236-9.html
 == 424236-10.html 424236-10.html
 == 424236-11.html 424236-11.html
 == 424434-1.html 424434-1.html
 == 424465-1.html 424465-1.html
 == 424631-1.html 424631-1.html
 == 424710-1.html 424710-1.html
 fails == 424766-1.html 424766-1.html
-# == 425972-1.html 425972-1.html
+== 425972-1.html 425972-1.html
 == 425972-2.html 425972-2.html
-# == 425972-1.html 425972-1.html
+== 425972-1.html 425972-1.html
 fails == 426629-1.html 426629-1.html
 asserts(3-6) == 427017-1.xhtml 427017-1.xhtml
 == 427129-scrollframe.html 427129-scrollframe.html
 == 427129-table.html 427129-table.html
 == 427129-image.html 427129-image.html
 == 427129-table-caption.html 427129-table-caption.html
 == 427370-1.html 427370-1.html
 fails == 427730-1.html 427730-1.html
 == 428278.html 428278.html
 == 428423-1a.html 428423-1a.html
 == 428423-1b.html 428423-1b.html
 fails == 428521-1a.html 428521-1a.html
 fails == 428521-1b.html 428521-1b.html
 fails == 428521-1c.html 428521-1c.html
-# == 428810-1a-ltr.html 428810-1a-ltr.html
-# == 428810-1b-ltr.html 428810-1b-ltr.html
-# == 428810-1c-ltr.html 428810-1c-ltr.html
-# == 428810-1d-ltr.html 428810-1d-ltr.html
+== 428810-1a-ltr.html 428810-1a-ltr.html
+== 428810-1b-ltr.html 428810-1b-ltr.html
+== 428810-1c-ltr.html 428810-1c-ltr.html
+== 428810-1d-ltr.html 428810-1d-ltr.html
 == 428810-1-ltr-ref.html 428810-1-ltr-ref.html
-# == 428810-2a-ltr.html 428810-2a-ltr.html
-# == 428810-2b-ltr.html 428810-2b-ltr.html
-# == 428810-2e-ltr.html 428810-2e-ltr.html
-# == 428810-2f-ltr.html 428810-2f-ltr.html
+== 428810-2a-ltr.html 428810-2a-ltr.html
+== 428810-2b-ltr.html 428810-2b-ltr.html
+== 428810-2e-ltr.html 428810-2e-ltr.html
+== 428810-2f-ltr.html 428810-2f-ltr.html
 == 428810-2-ltr-ref.html 428810-2-ltr-ref.html
-# == 428810-3a-ltr.html 428810-3a-ltr.html
-# == 428810-3b-ltr.html 428810-3b-ltr.html
-# == 428810-3e-ltr.html 428810-3e-ltr.html
-# == 428810-3f-ltr.html 428810-3f-ltr.html
+== 428810-3a-ltr.html 428810-3a-ltr.html
+== 428810-3b-ltr.html 428810-3b-ltr.html
+== 428810-3e-ltr.html 428810-3e-ltr.html
+== 428810-3f-ltr.html 428810-3f-ltr.html
 == 428810-3-ltr-ref.html 428810-3-ltr-ref.html
-# == 428810-1a-rtl.html 428810-1a-rtl.html
-# == 428810-1b-rtl.html 428810-1b-rtl.html
-# == 428810-1c-rtl.html 428810-1c-rtl.html
-# == 428810-1d-rtl.html 428810-1d-rtl.html
-# == 428810-1-rtl-ref.html 428810-1-rtl-ref.html
-# == 428810-1-rtl-ref.html 428810-1-rtl-ref.html
-# == 428810-2a-rtl.html 428810-2a-rtl.html
-# == 428810-2b-rtl.html 428810-2b-rtl.html
-# == 428810-2e-rtl.html 428810-2e-rtl.html
-# == 428810-2f-rtl.html 428810-2f-rtl.html
-# == 428810-2-rtl-ref.html 428810-2-rtl-ref.html
-# == 428810-2-rtl-ref.html 428810-2-rtl-ref.html
-# == 428810-3a-rtl.html 428810-3a-rtl.html
-# == 428810-3b-rtl.html 428810-3b-rtl.html
-# == 428810-3e-rtl.html 428810-3e-rtl.html
-# == 428810-3f-rtl.html 428810-3f-rtl.html
-# == 428810-3-rtl-ref.html 428810-3-rtl-ref.html
-# == 428810-3-rtl-ref.html 428810-3-rtl-ref.html
+== 428810-1a-rtl.html 428810-1a-rtl.html
+== 428810-1b-rtl.html 428810-1b-rtl.html
+== 428810-1c-rtl.html 428810-1c-rtl.html
+== 428810-1d-rtl.html 428810-1d-rtl.html
+== 428810-1-rtl-ref.html 428810-1-rtl-ref.html
+== 428810-1-rtl-ref.html 428810-1-rtl-ref.html
+== 428810-2a-rtl.html 428810-2a-rtl.html
+== 428810-2b-rtl.html 428810-2b-rtl.html
+== 428810-2e-rtl.html 428810-2e-rtl.html
+== 428810-2f-rtl.html 428810-2f-rtl.html
+== 428810-2-rtl-ref.html 428810-2-rtl-ref.html
+== 428810-2-rtl-ref.html 428810-2-rtl-ref.html
+== 428810-3a-rtl.html 428810-3a-rtl.html
+== 428810-3b-rtl.html 428810-3b-rtl.html
+== 428810-3e-rtl.html 428810-3e-rtl.html
+== 428810-3f-rtl.html 428810-3f-rtl.html
+== 428810-3-rtl-ref.html 428810-3-rtl-ref.html
+== 428810-3-rtl-ref.html 428810-3-rtl-ref.html
 == 428810-1a-ltr-insets.html 428810-1a-ltr-insets.html
 == 428810-1b-ltr-insets.html 428810-1b-ltr-insets.html
 == 428810-1c-ltr-insets.html 428810-1c-ltr-insets.html
 == 428810-1d-ltr-insets.html 428810-1d-ltr-insets.html
 == 428810-1-ltr-insets-ref.html 428810-1-ltr-insets-ref.html
 == 428810-2a-ltr-insets.html 428810-2a-ltr-insets.html
 == 428810-2b-ltr-insets.html 428810-2b-ltr-insets.html
 == 428810-2e-ltr-insets.html 428810-2e-ltr-insets.html
@@ -1109,30 +1109,30 @@ fails == 428521-1c.html 428521-1c.html
 == 428810-3b-ltr-insets.html 428810-3b-ltr-insets.html
 == 428810-3e-ltr-insets.html 428810-3e-ltr-insets.html
 == 428810-3f-ltr-insets.html 428810-3f-ltr-insets.html
 == 428810-3-ltr-insets-ref.html 428810-3-ltr-insets-ref.html
 == 428810-1a-rtl-insets.html 428810-1a-rtl-insets.html
 == 428810-1b-rtl-insets.html 428810-1b-rtl-insets.html
 == 428810-1c-rtl-insets.html 428810-1c-rtl-insets.html
 == 428810-1d-rtl-insets.html 428810-1d-rtl-insets.html
-# == 428810-1-rtl-insets-ref.html 428810-1-rtl-insets-ref.html
-# == 428810-1-rtl-insets-ref.html 428810-1-rtl-insets-ref.html
+== 428810-1-rtl-insets-ref.html 428810-1-rtl-insets-ref.html
+== 428810-1-rtl-insets-ref.html 428810-1-rtl-insets-ref.html
 == 428810-2a-rtl-insets.html 428810-2a-rtl-insets.html
 == 428810-2b-rtl-insets.html 428810-2b-rtl-insets.html
 == 428810-2e-rtl-insets.html 428810-2e-rtl-insets.html
 == 428810-2f-rtl-insets.html 428810-2f-rtl-insets.html
-# == 428810-2-rtl-insets-ref.html 428810-2-rtl-insets-ref.html
-# == 428810-2-rtl-insets-ref.html 428810-2-rtl-insets-ref.html
+== 428810-2-rtl-insets-ref.html 428810-2-rtl-insets-ref.html
+== 428810-2-rtl-insets-ref.html 428810-2-rtl-insets-ref.html
 == 428810-3a-rtl-insets.html 428810-3a-rtl-insets.html
 == 428810-3b-rtl-insets.html 428810-3b-rtl-insets.html
 == 428810-3e-rtl-insets.html 428810-3e-rtl-insets.html
 == 428810-3f-rtl-insets.html 428810-3f-rtl-insets.html
-# == 428810-3-rtl-insets-ref.html 428810-3-rtl-insets-ref.html
-# == 428810-3-rtl-insets-ref.html 428810-3-rtl-insets-ref.html
+== 428810-3-rtl-insets-ref.html 428810-3-rtl-insets-ref.html
+== 428810-3-rtl-insets-ref.html 428810-3-rtl-insets-ref.html
 fails == 430412-1.html 430412-1.html
 == 430813-1.html 430813-1.html
 == 430813-2.html 430813-2.html
 == 430813-3.html 430813-3.html
 == 431341-1.html 431341-1.html
 == 431341-2.html 431341-2.html
 fails == 431520-1.html 431520-1.html
 == 431948-1.html 431948-1.html
@@ -1186,17 +1186,17 @@ fails test-pref(dom.use_xbl_scopes_for_r
 fails == 449362-1.html 449362-1.html
 == 449519-1.html 449519-1.html
 == 450670-1.html 450670-1.html
 fails == 451168-1.html 451168-1.html
 == 451876-1.html 451876-1.html
 == 451876-2.html 451876-2.html
 == 452915-1.html 452915-1.html
 == 452964-1.html 452964-1.html
-# == 454361.html 454361.html
+== 454361.html 454361.html
 == 455105-1.html 455105-1.html
 == 455105-2.html 455105-2.html
 fails == 455171-5.html 455171-5.html
 fails == 455280-1.xhtml 455280-1.xhtml
 fails == 455826-1.html 455826-1.html
 fails-if(cocoaWidget) fails-if(Android) == 456147.xul 456147.xul
 == 456219-1a.html 456219-1a.html
 == 456219-1b.html 456219-1b.html
@@ -1272,28 +1272,28 @@ fails == 474417-1.html 474417-1.html
 == 475986-2b.html 475986-2b.html
 == 475986-2c.html 475986-2c.html
 == 475986-2d.html 475986-2d.html
 == 475986-2e.html 475986-2e.html
 == 475986-2f.html 475986-2f.html
 == 475986-3a.html 475986-3a.html
 == 475986-3b.html 475986-3b.html
 == 475986-4.html 475986-4.html
-# == 475986-1-ref.html 475986-1-ref.html
-# == 475986-1-ref.html 475986-1-ref.html
+== 475986-1-ref.html 475986-1-ref.html
+== 475986-1-ref.html 475986-1-ref.html
 == 475986-2-ref.html 475986-2-ref.html
 == 476063-1.html 476063-1.html
 fails == 476063-2.html 476063-2.html
 fails == 476063-3.html 476063-3.html
 == 476063-4.xhtml 476063-4.xhtml
 == 476357-1.html 476357-1.html
-# == 476598-1a.html 476598-1a.html
-# == 476598-1a.html 476598-1a.html
-# == 476598-1b.html 476598-1b.html
-# == 476598-1b.html 476598-1b.html
+fails == 476598-1a.html 476598-1a.html # Bug 1341785
+fails == 476598-1a.html 476598-1a.html # Bug 1341785
+fails == 476598-1b.html 476598-1b.html # Bug 1341785
+fails == 476598-1b.html 476598-1b.html # Bug 1341785
 == 476598-1-ref.html 476598-1-ref.html
 == 476856-1.html 476856-1.html
 random-if(d2d) == 478377-1.xul 478377-1.xul
 == 478614-1.html 478614-1.html
 == 478614-2.html 478614-2.html
 == 478614-3.html 478614-3.html
 == 478614-4.html 478614-4.html
 == 478614-5.html 478614-5.html
@@ -1308,17 +1308,17 @@ fails == 478811-4.html 478811-4.html
 == 480017-1.html 480017-1.html
 == 480880-1a.html 480880-1a.html
 == 480880-1b.html 480880-1b.html
 == 480880-1c.html 480880-1c.html
 == 480880-1d.html 480880-1d.html
 == 480880-1e.html 480880-1e.html
 == 480880-2a.html 480880-2a.html
 == 480880-2b.html 480880-2b.html
-# == 480880-2c.html 480880-2c.html
+== 480880-2c.html 480880-2c.html
 fails-if(Android) == 481024-1a.html 481024-1a.html
 fails-if(Android) == 481024-1b.html 481024-1b.html
 fails-if(Android) == 481024-1c.html 481024-1c.html
 == 481024-1d.html 481024-1d.html
 == 481024-1e.html 481024-1e.html
 fails == 481948-1.html 481948-1.html
 == 481948-2.html 481948-2.html
 fails-if(Android) random-if(winWidget) fails-if(gtkWidget) == 481948-3.html 481948-3.html
@@ -1348,17 +1348,17 @@ fails == 486065-1.html 486065-1.html
 == 487539-1.html 487539-1.html
 == 488390-1.html 488390-1.html
 == 488649-1.html 488649-1.html
 == 488685-1.html 488685-1.html
 == 488692-1.html 488692-1.html
 == 489868-1.svg 489868-1.svg
 == 490173-1.html 490173-1.html
 fails == 490173-2.html 490173-2.html
-# == 490176-1.html 490176-1.html
+== 490176-1.html 490176-1.html
 == 490177-1.svg 490177-1.svg
 fails == 490182-1a.html 490182-1a.html
 fails == 490182-1b.html 490182-1b.html
 pref(browser.display.focus_ring_width,1) == 491180-1.html 491180-1.html
 pref(browser.display.focus_ring_width,1) == 491180-2.html 491180-2.html
 == 491323-1.xul 491323-1.xul
 == 492239-1.xul 492239-1.xul
 == 492661-1.html 492661-1.html
@@ -1372,17 +1372,17 @@ fails == 495354-1b.xhtml 495354-1b.xhtml
 == 495385-1b.html 495385-1b.html
 == 495385-1c.html 495385-1c.html
 == 495385-1d.html 495385-1d.html
 == 495385-1e.html 495385-1e.html
 == 495385-1f.html 495385-1f.html
 == 495385-2a.html 495385-2a.html
 == 495385-2b.html 495385-2b.html
 == 495385-2c.html 495385-2c.html
-# == 495385-2d.html 495385-2d.html
+== 495385-2d.html 495385-2d.html
 == 495385-2e.html 495385-2e.html
 fails pref(dom.use_xbl_scopes_for_remote_xul,true) == 495385-2f.xhtml 495385-2f.xhtml
 == 495385-2g.html 495385-2g.html
 == 495385-2h.html 495385-2h.html
 == 495385-2i.html 495385-2i.html
 == 495385-3.html 495385-3.html
 == 495385-4.html 495385-4.html
 fails == 495385-5.html 495385-5.html
@@ -1470,25 +1470,25 @@ fails random == 536061.html 536061.html
 fails == 538909-1.html 538909-1.html
 == 538935-1.html 538935-1.html
 == 539226-1.html 539226-1.html
 == 539323-1.html 539323-1.html
 == 539323-2.html 539323-2.html
 == 539323-3.html 539323-3.html
 fails == 539880-1.html 539880-1.html
 fails == 539880-1-dynamic.html 539880-1-dynamic.html
-# == 539949-1.html#test2 539949-1.html#test2
+skip-if(stylo) == 539949-1.html#test2 539949-1.html#test2 # load fails???
 fails == 541382-1.html 541382-1.html
 == 541406-1.html 541406-1.html
 fails needs-focus == 542116-1.html 542116-1.html
 fails needs-focus == 542116-2.html 542116-2.html
 needs-focus == 542116-3.html 542116-3.html
 == 542317-1.html 542317-1.html
 == 542620-1.html 542620-1.html
-# == 545049-1.html 545049-1.html
+fails == 545049-1.html 545049-1.html # Bug 1341785
 == 546033-1.html 546033-1.html
 == 546071-1.html 546071-1.html
 == 549184-1.html 549184-1.html
 == 550325-1.html 550325-1.html
 == 550325-2.html 550325-2.html
 == 550325-3.html 550325-3.html
 == 550716-1.html 550716-1.html
 fails == 551463-1.html 551463-1.html
@@ -1549,19 +1549,19 @@ fails == 564054-1.html 564054-1.html
 == 565819-1.html 565819-1.html
 == 565819-2.html 565819-2.html
 fails needs-focus == 568441.html 568441.html
 == 569006-1.html 569006-1.html
 == 571281-1a.html 571281-1a.html
 == 571281-1b.html 571281-1b.html
 == 571281-1c.html 571281-1c.html
 == 571347-1a.html 571347-1a.html
-# == 571347-1b.html 571347-1b.html
-# == 571347-2a.html 571347-2a.html
-# == 571347-2b.html 571347-2b.html
+== 571347-1b.html 571347-1b.html
+== 571347-2a.html 571347-2a.html
+== 571347-2b.html 571347-2b.html
 fails == 571347-2c.html 571347-2c.html
 == 571347-2d.html 571347-2d.html
 fails == 571347-3.html 571347-3.html
 fails == 572598-1.html 572598-1.html
 fails == 574898-1.html 574898-1.html
 # 574907 is a windows-only issue, result on other platforms depends on details of font support
 fails == 574907-1.html 574907-1.html
 fails == 574907-2.html 574907-2.html
@@ -1595,17 +1595,17 @@ fails == 589615-1b.html 589615-1b.html
 fails == 589682-1.html 589682-1.html
 == 593243-1.html 593243-1.html
 fails == 593243-2.html 593243-2.html
 fails == 593544-1.html 593544-1.html
 == 594333-1.html 594333-1.html
 == 594624-1.html 594624-1.html
 fails == 594737-1.html 594737-1.html
 fails == 597721-1.html 597721-1.html
-# == 598726-1.html 598726-1.html
+skip-if(stylo) == 598726-1.html 598726-1.html # Bug 1302946
 == 599113-1.html 599113-1.html
 == 599476.html 599476.html
 == 599882-1a.html 599882-1a.html
 == 599882-1b.html 599882-1b.html
 == 599882-2.html 599882-2.html
 == 600045-1.html 600045-1.html
 fails == 600803-1.html 600803-1.html
 == 600974-1.html 600974-1.html
@@ -1620,25 +1620,25 @@ fails == 604737.html 604737.html
 fails == 605138-1.html 605138-1.html
 == 605157-1.xhtml 605157-1.xhtml
 == 607267-1.html 607267-1.html
 fails == 608636-1.html 608636-1.html
 == 608756-1a.html 608756-1a.html
 == 608756-1b.html 608756-1b.html
 asserts-if(stylo,4) == 608756-2.html 608756-2.html # bug 1324633
 == 609272-1.html 609272-1.html
-# == 613433-1.html 613433-1.html
-# == 613433-1.html 613433-1.html
-# == 613433-1.html 613433-1.html
-# == 613433-2.html 613433-2.html
-# == 613433-2.html 613433-2.html
-# == 613433-2.html 613433-2.html
-# == 613433-3.html 613433-3.html
-# == 613433-3.html 613433-3.html
-# == 613433-3.html 613433-3.html
+fails == 613433-1.html 613433-1.html
+fails == 613433-1.html 613433-1.html
+fails == 613433-1.html 613433-1.html
+fails == 613433-2.html 613433-2.html
+fails == 613433-2.html 613433-2.html
+fails == 613433-2.html 613433-2.html
+fails == 613433-3.html 613433-3.html
+fails == 613433-3.html 613433-3.html
+fails == 613433-3.html 613433-3.html
 == 614272-1.svg 614272-1.svg
 fails HTTP(..) == 615121-1.html 615121-1.html
 fails HTTP(..) == 615121-2.html 615121-2.html
 fails == 617242-1.html 617242-1.html
 fails == 618071.html 618071.html
 fails == 619117-1.html 619117-1.html
 fails HTTP(..) == 619511-1.html 619511-1.html
 fails == 621253-1-externalFilter.html 621253-1-externalFilter.html
@@ -1649,20 +1649,20 @@ random-if(winWidget) fuzzy-if(OSX==1008,
 random-if(winWidget) HTTP(..) == 621918-2.svg 621918-2.svg
 fails == 622585-1.html 622585-1.html
 == 625409-1.html 625409-1.html
 == 627393-1.html 627393-1.html
 # fuzzy-if(skiaContent,1,500) == 630835-1.html 630835-1.html
 == 631352-1.html 631352-1.html
 == 632423-1.html 632423-1.html
 skip-if(Android) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-verybig.html
-# == 632781-normalsize.html 632781-normalsize.html
+== 632781-normalsize.html 632781-normalsize.html
 == 633344-1.html 633344-1.html
 fails == 634232-1.html 634232-1.html
-# == 635302-1.html 635302-1.html
+skip-if(stylo) == 635302-1.html 635302-1.html # Too intermittent.
 == 635373-1.html 635373-1.html
 == 635373-2.html 635373-2.html
 == 635373-3.html 635373-3.html
 fails HTTP(..) == 635639-1.html 635639-1.html
 fails HTTP(..) == 635639-2.html 635639-2.html
 fails random == 637597-1.html 637597-1.html
 fails == 637852-1.html 637852-1.html
 fails == 637852-2.html 637852-2.html
@@ -1808,18 +1808,18 @@ fails == 960277-1.html 960277-1.html
 == 961887-1.html 961887-1.html
 == 961887-2.html 961887-2.html
 == 961887-3.html 961887-3.html
 fails == 966992-1.html 966992-1.html
 fails == 966510-1.html 966510-1.html
 fails == 966510-2.html 966510-2.html
 fuzzy-if(skiaContent,1,123) == 978911-1.svg 978911-1.svg
 == 983084-1.html 983084-1.html
-# == 983084-2.html 983084-2.html
-# == 983084-3.html 983084-3.html
+skip-if(stylo) == 983084-2.html 983084-2.html # Bug 1302946
+skip-if(stylo) == 983084-3.html 983084-3.html # Bug 1302946
 fails == 983691-1.html 983691-1.html
 HTTP(..) == 983985-1.html 983985-1.html
 fails HTTP(..) == 983985-2.html 983985-2.html
 fails == 985303-1a.html 985303-1a.html
 fails == 985303-1b.html 985303-1b.html
 fails == 987680-1.html 987680-1.html
 == 991046-1.html 991046-1.html
 fails == 992447.html 992447.html
@@ -1856,31 +1856,31 @@ fails == 1062792-1.html 1062792-1.html
 fails == 1069716-1.html 1069716-1.html
 == 1078262-1.html 1078262-1.html
 test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1.html
 == 1081185-1.html 1081185-1.html
 == 1097437-1.html 1097437-1.html
 == 1103258-1.html 1103258-1.html
 == 1105137-1.html 1105137-1.html
 fails == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow.html
-# == 1111753-1.html 1111753-1.html
+skip-if(stylo) == 1111753-1.html 1111753-1.html # Bug 1302946
 fails == 1114526-1.html 1114526-1.html
 fuzzy-if(skiaContent,1,800000) == 1119117-1a.html 1119117-1a.html
 fuzzy-if(skiaContent,1,800000) == 1119117-1b.html 1119117-1b.html
 fails == 1120431-1.html 1120431-1.html
 fails == 1120431-2.html 1120431-2.html
 == 1121748-1.html 1121748-1.html
 skip == 1121748-2.html 1121748-2.html
 == 1127107-1a-nowrap.html 1127107-1a-nowrap.html
 == 1127107-1b-pre.html 1127107-1b-pre.html
 == 1127107-2-capitalize.html 1127107-2-capitalize.html
-# == 1127679-1a-inline-flex-relpos.html 1127679-1a-inline-flex-relpos.html
+== 1127679-1a-inline-flex-relpos.html 1127679-1a-inline-flex-relpos.html
 == 1128354-1.html 1128354-1.html
-# == 1130231-1-button-padding-rtl.html 1130231-1-button-padding-rtl.html
-# == 1130231-2-button-padding-rtl.html 1130231-2-button-padding-rtl.html
+fails == 1130231-1-button-padding-rtl.html 1130231-1-button-padding-rtl.html
+fails == 1130231-2-button-padding-rtl.html 1130231-2-button-padding-rtl.html
 # The 1133905-*.html reftests only make sense on platforms where both APZ and
 # <meta viewport> are enabled.
 # (Note: bug 1308702 covers these tests' failures on Android)
 == 1133905-1.html 1133905-1.html
 == 1133905-2.html 1133905-2.html
 skip-if(!Android) == 1133905-3.html 1133905-3.html
 skip-if(!Android) == 1133905-4.html 1133905-4.html
 skip-if(!Android) == 1133905-5.html 1133905-5.html
@@ -1898,43 +1898,43 @@ skip-if(!Android) == 1133905-4-h.html 11
 skip-if(!Android) == 1133905-5-h.html 1133905-5-h.html
 skip-if(!Android) == 1133905-6-h.html 1133905-6-h.html
 skip-if(!Android) fails-if(Android) == 1133905-1-vh.html 1133905-1-vh.html
 skip-if(!Android) fails-if(Android) == 1133905-2-vh.html 1133905-2-vh.html
 skip-if(!Android) fails-if(Android) == 1133905-3-vh.html 1133905-3-vh.html
 skip-if(!Android) == 1133905-4-vh.html 1133905-4-vh.html
 skip-if(!Android) fails-if(Android) == 1133905-5-vh.html 1133905-5-vh.html
 skip-if(!Android) fails-if(Android) == 1133905-6-vh.html 1133905-6-vh.html
-# == 1133905-1-rtl.html 1133905-1-rtl.html
-# == 1133905-2-rtl.html 1133905-2-rtl.html
-# == 1133905-3-rtl.html 1133905-3-rtl.html
-# == 1133905-4-rtl.html 1133905-4-rtl.html
-# == 1133905-5-rtl.html 1133905-5-rtl.html
-# == 1133905-6-rtl.html 1133905-6-rtl.html
-# == 1133905-1-v-rtl.html 1133905-1-v-rtl.html
-# == 1133905-2-v-rtl.html 1133905-2-v-rtl.html
-# == 1133905-3-v-rtl.html 1133905-3-v-rtl.html
-# == 1133905-4-v-rtl.html 1133905-4-v-rtl.html
-# == 1133905-5-v-rtl.html 1133905-5-v-rtl.html
-# == 1133905-6-v-rtl.html 1133905-6-v-rtl.html
-# == 1133905-1-h-rtl.html 1133905-1-h-rtl.html
-# == 1133905-2-h-rtl.html 1133905-2-h-rtl.html
-# == 1133905-3-h-rtl.html 1133905-3-h-rtl.html
-# == 1133905-4-h-rtl.html 1133905-4-h-rtl.html
-# == 1133905-5-h-rtl.html 1133905-5-h-rtl.html
-# == 1133905-6-h-rtl.html 1133905-6-h-rtl.html
-# == 1133905-1-vh-rtl.html 1133905-1-vh-rtl.html
-# == 1133905-2-vh-rtl.html 1133905-2-vh-rtl.html
-# == 1133905-3-vh-rtl.html 1133905-3-vh-rtl.html
-# == 1133905-4-vh-rtl.html 1133905-4-vh-rtl.html
-# == 1133905-5-vh-rtl.html 1133905-5-vh-rtl.html
-# == 1133905-6-vh-rtl.html 1133905-6-vh-rtl.html
+== 1133905-1-rtl.html 1133905-1-rtl.html
+== 1133905-2-rtl.html 1133905-2-rtl.html
+== 1133905-3-rtl.html 1133905-3-rtl.html
+== 1133905-4-rtl.html 1133905-4-rtl.html
+== 1133905-5-rtl.html 1133905-5-rtl.html
+== 1133905-6-rtl.html 1133905-6-rtl.html
+fails == 1133905-1-v-rtl.html 1133905-1-v-rtl.html # Bug 1341095
+fails == 1133905-2-v-rtl.html 1133905-2-v-rtl.html # Bug 1341095
+fails == 1133905-3-v-rtl.html 1133905-3-v-rtl.html # Bug 1341095
+fails == 1133905-4-v-rtl.html 1133905-4-v-rtl.html # Bug 1341095
+fails == 1133905-5-v-rtl.html 1133905-5-v-rtl.html # Bug 1341095
+fails == 1133905-6-v-rtl.html 1133905-6-v-rtl.html # Bug 1341095
+== 1133905-1-h-rtl.html 1133905-1-h-rtl.html
+== 1133905-2-h-rtl.html 1133905-2-h-rtl.html
+== 1133905-3-h-rtl.html 1133905-3-h-rtl.html
+== 1133905-4-h-rtl.html 1133905-4-h-rtl.html
+== 1133905-5-h-rtl.html 1133905-5-h-rtl.html
+== 1133905-6-h-rtl.html 1133905-6-h-rtl.html
+fails == 1133905-1-vh-rtl.html 1133905-1-vh-rtl.html # Bug 1341095
+fails == 1133905-2-vh-rtl.html 1133905-2-vh-rtl.html # Bug 1341095
+fails == 1133905-3-vh-rtl.html 1133905-3-vh-rtl.html # Bug 1341095
+fails == 1133905-4-vh-rtl.html 1133905-4-vh-rtl.html # Bug 1341095
+fails == 1133905-5-vh-rtl.html 1133905-5-vh-rtl.html # Bug 1341095
+fails == 1133905-6-vh-rtl.html 1133905-6-vh-rtl.html # Bug 1341095
 == 1150021-1.xul 1150021-1.xul
 fails == 1151145-1.html 1151145-1.html
-# == 1151306-1.html 1151306-1.html
+== 1151306-1.html 1151306-1.html
 == 1153845-1.html 1153845-1.html
 fails == 1155828-1.html 1155828-1.html
 == 1156129-1.html 1156129-1.html
 pref(dom.use_xbl_scopes_for_remote_xul,true) HTTP(..) == 1157127-1.html 1157127-1.html
 fails == 1169331-1.html 1169331-1.html
 fails == 1174332-1.html 1174332-1.html
 == 1179078-1.html 1179078-1.html
 == 1179288-1.html 1179288-1.html
--- a/layout/reftests/canvas/reftest-stylo.list
+++ b/layout/reftests/canvas/reftest-stylo.list
@@ -1,10 +1,10 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# == default-size.html default-size.html
+== default-size.html default-size.html
 fails == size-1.html size-1.html
 
 == empty-transaction-1.html empty-transaction-1.html
 
 fails == image-rendering-test.html image-rendering-test.html
 == image-shadow.html image-shadow.html
 
 fails == size-change-1.html size-change-1.html
@@ -26,29 +26,29 @@ asserts-if(stylo,1) == text-rtl-left.htm
 asserts-if(stylo,1) == text-ltr-left.html text-ltr-left.html # bug 1324700
 
 fails asserts-if(stylo,1) == text-ltr-alignment-test.html text-ltr-alignment-test.html # bug 1324700
 fails asserts-if(stylo,1) == text-rtl-alignment-test.html text-rtl-alignment-test.html # bug 1324700
 
 asserts-if(stylo,1) == text-horzline-with-bottom.html text-horzline-with-bottom.html # bug 1324700
 fails-if(azureSkia&&OSX>=1008) asserts-if(stylo,1) == text-horzline-with-top.html text-horzline-with-top.html # bug 1324700
 
-# == text-big-stroke.html text-big-stroke.html
-# == text-big-stroke.html text-big-stroke.html
+fails asserts-if(stylo,1) == text-big-stroke.html text-big-stroke.html # Bug 1324700
+fails asserts-if(stylo,1) == text-big-stroke.html text-big-stroke.html # Bug 1324700
 
 fails asserts-if(stylo,1) == text-context-state-test.html text-context-state-test.html # bug 1324700
 fails asserts-if(stylo,1) == text-font-inherit.html text-font-inherit.html # bug 1324700
 fails asserts-if(stylo,1) == text-space-replace-test.html text-space-replace-test.html # bug 1324700
 
 fails asserts-if(stylo,1) == text-no-frame-test.html text-no-frame-test.html # bug 1324700
 fails asserts-if(stylo,1) == text-no-frame-2-test.html text-no-frame-2-test.html # bug 1324700
 fails asserts-if(stylo,1) == text-not-in-doc-test.html text-not-in-doc-test.html # bug 1324700
 
-# == text-bidi-ltr-test.html text-bidi-ltr-test.html
-# == text-bidi-ltr-test.html text-bidi-ltr-test.html
+fails asserts-if(stylo,1) == text-bidi-ltr-test.html text-bidi-ltr-test.html # Bug 1324700
+fails asserts-if(stylo,1) == text-bidi-ltr-test.html text-bidi-ltr-test.html # Bug 1324700
 fails asserts-if(stylo,1) == text-bidi-rtl-test.html text-bidi-rtl-test.html # bug 1324700
 
 fails asserts-if(stylo,4) == text-font-lang.html text-font-lang.html # bug 1324700
 
 fails asserts-if(stylo,1) == text-measure.html text-measure.html # bug 1324700
 fails asserts-if(stylo,1) == text-small-caps-1.html text-small-caps-1.html # bug 1324700
 
 fails asserts-if(stylo,1) == text-subpixel-1.html text-subpixel-1.html # bug 1324700
--- a/layout/reftests/columns/reftest-stylo.list
+++ b/layout/reftests/columns/reftest-stylo.list
@@ -1,10 +1,10 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# == basic-1.html basic-1.html
+== basic-1.html basic-1.html
 == pref-width-1a.html pref-width-1a.html
 == pref-width-1b.html pref-width-1b.html
 == pref-width-1c.html pref-width-1c.html
 fails == min-width-1a.html min-width-1a.html
 == min-width-1b.html min-width-1b.html
 == min-width-1c.html min-width-1c.html
 fails == min-width-2.html min-width-2.html
 fails == column-balancing-overflow-000.html column-balancing-overflow-000.html
@@ -13,25 +13,25 @@ fails == column-balancing-overflow-002.h
 fails == column-balancing-overflow-003.html column-balancing-overflow-003.html
 == column-balancing-overflow-004.html column-balancing-overflow-004.html
 == column-balancing-overflow-005.html column-balancing-overflow-005.html
 fails == column-balancing-000.html column-balancing-000.html
 fails == column-balancing-001.html column-balancing-001.html
 fails == column-balancing-002.html column-balancing-002.html
 fails == column-balancing-003.html column-balancing-003.html
 fails == column-balancing-004.html column-balancing-004.html
-# == column-box-alignment-rtl.html column-box-alignment-rtl.html
+== column-box-alignment-rtl.html column-box-alignment-rtl.html
 fails HTTP(..) == columnfill-balance.html columnfill-balance.html
 fails == columnfill-auto.html columnfill-auto.html
 fails HTTP(..) == columnfill-auto-2.html columnfill-auto-2.html
 fails HTTP(..) == columnfill-auto-3.html columnfill-auto-3.html
 fails == columnrule-basic.html columnrule-basic.html
 fails == columnrule-complex.html columnrule-complex.html
 == columnrule-linestyles.html columnrule-linestyles.html
-# == columnrule-padding.html columnrule-padding.html
+== columnrule-padding.html columnrule-padding.html
 fails == columnfill-overflow.html columnfill-overflow.html
 == margin-collapsing-bug616722-1.html margin-collapsing-bug616722-1.html
 == margin-collapsing-bug616722-2.html margin-collapsing-bug616722-2.html
 fails == column-balancing-nested-000.html column-balancing-nested-000.html
 fails == column-balancing-nested-001.html column-balancing-nested-001.html
 == columnrule-overflow.html columnrule-overflow.html
 == columns-table-caption-000.html columns-table-caption-000.html
 fails == positioning-transforms-bug1112501.html positioning-transforms-bug1112501.html
--- a/layout/reftests/counter-style/reftest-stylo.list
+++ b/layout/reftests/counter-style/reftest-stylo.list
@@ -13,24 +13,24 @@ fails == system-extends.html system-exte
 == system-numeric-invalid.html system-numeric-invalid.html
 == system-additive-invalid.html system-additive-invalid.html
 fails == system-extends-invalid.html system-extends-invalid.html
 fails == descriptor-negative.html descriptor-negative.html
 fails == descriptor-prefix.html descriptor-prefix.html
 fails == descriptor-suffix.html descriptor-suffix.html
 fails == descriptor-range.html descriptor-range.html
 fails == descriptor-pad.html descriptor-pad.html
-# == descriptor-fallback.html descriptor-fallback.html
+fails == descriptor-fallback.html descriptor-fallback.html # Bug 1328319
 fails == descriptor-symbols.html descriptor-symbols.html
 fails == descriptor-negative-invalid.html descriptor-negative-invalid.html
 fails == descriptor-prefix-invalid.html descriptor-prefix-invalid.html
 fails == descriptor-suffix-invalid.html descriptor-suffix-invalid.html
 fails == descriptor-range-invalid.html descriptor-range-invalid.html
 fails == descriptor-pad-invalid.html descriptor-pad-invalid.html
-# == descriptor-fallback.html descriptor-fallback.html
+fails == descriptor-fallback.html descriptor-fallback.html
 fails == descriptor-symbols-invalid.html descriptor-symbols-invalid.html
 fails == name-case-sensitivity.html name-case-sensitivity.html
 fails == dependent-builtin.html dependent-builtin.html
 fails == redefine-builtin.html redefine-builtin.html
 fails == redefine-attr-mapping.html redefine-attr-mapping.html
 fails asserts-if(stylo,2) == disclosure-styles.html disclosure-styles.html # bug 1324704
 fails == symbols-function.html symbols-function.html
 fails == symbols-function-invalid.html symbols-function-invalid.html
--- a/layout/reftests/css-animations/reftest-stylo.list
+++ b/layout/reftests/css-animations/reftest-stylo.list
@@ -1,44 +1,44 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# == screen-animations.html screen-animations.html
-# == screen-animations.html screen-animations.html
-# == print-no-animations.html print-no-animations.html
-# == print-no-animations.html print-no-animations.html
-# == animate-opacity.html animate-opacity.html
+skip-if(stylo) == screen-animations.html screen-animations.html # Too intermittent.
+skip-if(stylo) == screen-animations.html screen-animations.html # Too intermittent.
+== print-no-animations.html print-no-animations.html
+== print-no-animations.html print-no-animations.html
+skip-if(stylo) == animate-opacity.html animate-opacity.html # Too intermittent.
 skip-if(stylo) == animate-preserves3d.html animate-preserves3d.html # bug 1324620
-# == in-visibility-hidden-animation.html in-visibility-hidden-animation.html
-# == in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element.html
-# == partially-out-of-view-animation.html partially-out-of-view-animation.html
-# == animate-display-table-opacity.html animate-display-table-opacity.html
+== in-visibility-hidden-animation.html in-visibility-hidden-animation.html
+fails == in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element.html # Bug 1331047
+== partially-out-of-view-animation.html partially-out-of-view-animation.html
+skip-if(stylo) == animate-display-table-opacity.html animate-display-table-opacity.html # Too intermittent.
 # We need to run 100% opacity test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor
 # test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-opacity-1-animation.html stacking-context-opacity-1-animation.html
 # We need to run transform:none test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor
 # test-pref(layers.offmainthreadcomposition.async-animations,false) == stacking-context-transform-none-animation.html stacking-context-transform-none-animation.html
-# == no-stacking-context-opacity-removing-animation-in-delay.html no-stacking-context-opacity-removing-animation-in-delay.html
-# == no-stacking-context-transform-removing-animation-in-delay.html no-stacking-context-transform-removing-animation-in-delay.html
-# == stacking-context-lose-opacity-1.html stacking-context-lose-opacity-1.html
+== no-stacking-context-opacity-removing-animation-in-delay.html no-stacking-context-opacity-removing-animation-in-delay.html
+== no-stacking-context-transform-removing-animation-in-delay.html no-stacking-context-transform-removing-animation-in-delay.html
+== stacking-context-lose-opacity-1.html stacking-context-lose-opacity-1.html
 == stacking-context-lose-transform-none.html stacking-context-lose-transform-none.html
-# == stacking-context-opacity-win-in-delay.html stacking-context-opacity-win-in-delay.html
+== stacking-context-opacity-win-in-delay.html stacking-context-opacity-win-in-delay.html
 == stacking-context-opacity-win-in-delay-on-main-thread.html stacking-context-opacity-win-in-delay-on-main-thread.html
 == stacking-context-opacity-wins-over-transition.html stacking-context-opacity-wins-over-transition.html
 == stacking-context-transform-win-in-delay.html stacking-context-transform-win-in-delay.html
 == stacking-context-transform-win-in-delay-on-main-thread.html stacking-context-transform-win-in-delay-on-main-thread.html
 == stacking-context-transform-wins-over-transition.html stacking-context-transform-wins-over-transition.html
-# == stacking-context-opacity-1-animation.html stacking-context-opacity-1-animation.html
+== stacking-context-opacity-1-animation.html stacking-context-opacity-1-animation.html
 == stacking-context-opacity-1-with-fill-backwards.html stacking-context-opacity-1-with-fill-backwards.html
 == stacking-context-opacity-1-with-fill-forwards.html stacking-context-opacity-1-with-fill-forwards.html
 == stacking-context-paused-on-opacity-1.html stacking-context-paused-on-opacity-1.html
 == stacking-context-paused-on-transform-none.html stacking-context-paused-on-transform-none.html
-# == stacking-context-transform-none-animation.html stacking-context-transform-none-animation.html
+== stacking-context-transform-none-animation.html stacking-context-transform-none-animation.html
 fails == stacking-context-transform-none-animation-on-svg.html stacking-context-transform-none-animation-on-svg.html
 == stacking-context-transform-none-animation-with-backface-visibility.html stacking-context-transform-none-animation-with-backface-visibility.html
 == stacking-context-transform-none-animation-with-preserve-3d.html stacking-context-transform-none-animation-with-preserve-3d.html
 == stacking-context-transform-none-with-fill-backwards.html stacking-context-transform-none-with-fill-backwards.html
 == stacking-context-transform-none-with-fill-forwards.html stacking-context-transform-none-with-fill-forwards.html
 == stacking-context-opacity-1-in-delay.html stacking-context-opacity-1-in-delay.html
 == stacking-context-opacity-removing-important-in-delay.html stacking-context-opacity-removing-important-in-delay.html
 == stacking-context-transform-none-in-delay.html stacking-context-transform-none-in-delay.html
 == stacking-context-transform-removing-important-in-delay.html stacking-context-transform-removing-important-in-delay.html
 fails == background-position-in-delay.html background-position-in-delay.html
-# == background-position-after-finish.html background-position-after-finish.html
+== background-position-after-finish.html background-position-after-finish.html
 fails == background-position-running.html background-position-running.html
 fails == background-position-important.html background-position-important.html
--- a/layout/reftests/css-break/reftest-stylo.list
+++ b/layout/reftests/css-break/reftest-stylo.list
@@ -1,13 +1,13 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 default-preferences pref(layout.css.box-decoration-break.enabled,true)
 
 fails == box-decoration-break-1.html box-decoration-break-1.html
 fails == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1.html
 fails == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1.html
 fails == box-decoration-break-border-image.html box-decoration-break-border-image.html
-# == box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding.html
+== box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding.html
 == box-decoration-break-block-margin.html box-decoration-break-block-margin.html
 fails == box-decoration-break-first-letter.html box-decoration-break-first-letter.html
 == box-decoration-break-with-bidi.html box-decoration-break-with-bidi.html
 == box-decoration-break-bug-1235152.html box-decoration-break-bug-1235152.html
 fails == box-decoration-break-bug-1249913.html box-decoration-break-bug-1249913.html
--- a/layout/reftests/css-calc/reftest-stylo.list
+++ b/layout/reftests/css-calc/reftest-stylo.list
@@ -1,3 +1,3 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 fails == background-image-gradient-1.html background-image-gradient-1.html
-# == line-height-1.html line-height-1.html
+fails == line-height-1.html line-height-1.html # Bug 1341095
--- a/layout/reftests/css-disabled/output/reftest-stylo.list
+++ b/layout/reftests/css-disabled/output/reftest-stylo.list
@@ -1,2 +1,2 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# == output.html output.html
+== output.html output.html
--- a/layout/reftests/css-display/reftest-stylo.list
+++ b/layout/reftests/css-display/reftest-stylo.list
@@ -1,29 +1,29 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
 # Tests for CSS Display spec features.
 # http://dev.w3.org/csswg/css-display
 
 fails == display-contents-acid.html display-contents-acid.html
 # fuzzy-if(Android,8,604) == display-contents-acid-dyn-1.html display-contents-acid-dyn-1.html
 fails == display-contents-acid-dyn-2.html display-contents-acid-dyn-2.html # bug 1337700
 fails == display-contents-acid-dyn-3.html display-contents-acid-dyn-3.html
-# == display-contents-generated-content.html display-contents-generated-content.html
-# == display-contents-generated-content-2.html display-contents-generated-content-2.html
+skip-if(stylo) == display-contents-generated-content.html display-contents-generated-content.html # Bug 1341083
+skip-if(stylo) == display-contents-generated-content-2.html display-contents-generated-content-2.html # Bug 1341083
 fails == display-contents-style-inheritance-1.html display-contents-style-inheritance-1.html
 fails == display-contents-style-inheritance-1-stylechange.html display-contents-style-inheritance-1-stylechange.html
-# == display-contents-style-inheritance-1-dom-mutations.html display-contents-style-inheritance-1-dom-mutations.html
+skip-if(stylo) == display-contents-style-inheritance-1-dom-mutations.html display-contents-style-inheritance-1-dom-mutations.html # Bug 1341083?
 == display-contents-tables.xhtml display-contents-tables.xhtml
 == display-contents-tables-2.xhtml display-contents-tables-2.xhtml
 == display-contents-tables-3.xhtml display-contents-tables-3.xhtml
 == display-contents-visibility-hidden.html display-contents-visibility-hidden.html
 == display-contents-visibility-hidden-2.html display-contents-visibility-hidden-2.html
-# == display-contents-495385-2d.html display-contents-495385-2d.html
+== display-contents-495385-2d.html display-contents-495385-2d.html
 fails == display-contents-xbl.xhtml display-contents-xbl.xhtml
 # fuzzy-if(Android,7,1186) pref(dom.webcomponents.enabled,true) == display-contents-shadow-dom-1.html display-contents-shadow-dom-1.html
 == display-contents-xbl-2.xul display-contents-xbl-2.xul
 asserts(2) == display-contents-xbl-3.xul display-contents-xbl-3.xul
-# == display-contents-xbl-4.xul display-contents-xbl-4.xul
-# == display-contents-fieldset.html display-contents-fieldset.html
+skip-if(stylo) == display-contents-xbl-4.xul display-contents-xbl-4.xul # Too intermittent.
+skip-if(stylo) == display-contents-fieldset.html display-contents-fieldset.html # Bug 1341083
 asserts(2-10) == display-contents-xbl-5.xul display-contents-xbl-5.xul
-# == display-contents-list-item-child.html display-contents-list-item-child.html # disabled for bug 1340607
+skip-if(stylo) == display-contents-list-item-child.html display-contents-list-item-child.html # disabled for bug 1340607
 == display-contents-writing-mode-1.html display-contents-writing-mode-1.html
 fails == display-contents-writing-mode-2.html display-contents-writing-mode-2.html
--- a/layout/reftests/css-enabled/output/reftest-stylo.list
+++ b/layout/reftests/css-enabled/output/reftest-stylo.list
@@ -1,2 +1,2 @@
 # DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
-# == output.html output.html
+== output.html output.html
--- a/layout/reftests/css-gradients/reftest-stylo.list
+++ b/layout/reftests/css-gradients/reftest-stylo.list
@@ -52,17 +52,17 @@ fails == linear-vertical-1c.html linear-
 fails == linear-vertical-1d.html linear-vertical-1d.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,3,88500) fuzzy-if(azureSkiaGL||skiaContent,3,89700) == linear-vertical-1e.html linear-vertical-1e.html
 fails == linear-vertical-subpixel-1.html linear-vertical-subpixel-1.html
 fails == linear-viewport.html linear-viewport.html
 fails == linear-zero-length-1a.html linear-zero-length-1a.html
 fails == linear-zero-length-1b.html linear-zero-length-1b.html
 fails == linear-zero-length-1c.html linear-zero-length-1c.html
 == nostops.html nostops.html
-# == onestop.html onestop.html
+== onestop.html onestop.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fuzzy-if(cocoaWidget,9,87824) fuzzy-if(azureSkiaGL,6,88024) random-if(d2d) fuzzy-if(skiaContent,4,6000) == radial-1a.html radial-1a.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fuzzy-if(cocoaWidget,9,87824) fuzzy-if(azureSkiaGL,6,88024) random-if(d2d) fuzzy-if(skiaContent,4,6000) == radial-1b.html radial-1b.html
 fails == radial-1c.html radial-1c.html
 fuzzy(3,7860) fuzzy-if(cocoaWidget,5,89041) fuzzy-if(azureSkiaGL,4,90000) == radial-2a.html radial-2a.html
 fuzzy(3,7860) fuzzy-if(cocoaWidget,5,89041) fuzzy-if(azureSkiaGL,4,90000) == radial-2b.html radial-2b.html
 fuzzy(3,7860) fuzzy-if(cocoaWidget,5,89041) fuzzy-if(azureSkiaGL,4,90000) == radial-2c.html radial-2c.html
 fuzzy(3,7860) fuzzy-if(cocoaWidget,5,89041) fuzzy-if(azureSkiaGL,4,90000) == radial-2d.html radial-2d.html
 fails == radial-2e.html radial-2e.