Merge mozilla-central to mozilla-inbound. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Tue, 26 Feb 2019 23:53:15 +0200
changeset 519267 4e181eeea4794a15711bb254f06d2ff216b1bef1
parent 519266 592350649c0fed65fde5d9056c0c550bb4f2af90 (current diff)
parent 519080 8c60d3a2fcc499bac3e232d666ff4491143085e6 (diff)
child 519268 bf486c5f798baff9c7f8fb09882159584917a0ef
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone67.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. CLOSED TREE
devtools/client/aboutdebugging-new/test/browser/resources/bad-extension/manifest.json
ipc/ipdl/test/ipdl/error/asyncMessageListed.ipdl
ipc/ipdl/test/ipdl/ok/AsyncReturn.ipdl
ipc/ipdl/test/ipdl/ok/Delete.ipdl
ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
ipc/ipdl/test/ipdl/ok/EndpointDecl.ipdl
ipc/ipdl/test/ipdl/ok/EndpointUse.ipdl
ipc/ipdl/test/ipdl/ok/Nullable.ipdl
ipc/ipdl/test/ipdl/ok/Struct.ipdl
ipc/ipdl/test/ipdl/ok/SyncSyncManagee.ipdl
ipc/ipdl/test/ipdl/ok/SyncSyncManager.ipdl
ipc/ipdl/test/ipdl/ok/actorparam.ipdl
ipc/ipdl/test/ipdl/ok/actorreturn.ipdl
ipc/ipdl/test/ipdl/ok/array_Basic.ipdl
ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
ipc/ipdl/test/ipdl/ok/array_Union.ipdl
ipc/ipdl/test/ipdl/ok/basicUsing.ipdl
ipc/ipdl/test/ipdl/ok/builtins.ipdl
ipc/ipdl/test/ipdl/ok/bytebuf.ipdl
ipc/ipdl/test/ipdl/ok/empty.ipdl
ipc/ipdl/test/ipdl/ok/emptyStruct.ipdl
ipc/ipdl/test/ipdl/ok/headerProto.ipdl
ipc/ipdl/test/ipdl/ok/intrProtocol.ipdl
ipc/ipdl/test/ipdl/ok/jetpack.ipdl
ipc/ipdl/test/ipdl/ok/manageSelf.ipdl
ipc/ipdl/test/ipdl/ok/manageSelf_Toplevel.ipdl
ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
ipc/ipdl/test/ipdl/ok/maybe_Basic.ipdl
ipc/ipdl/test/ipdl/ok/maybe_OfActors.ipdl
ipc/ipdl/test/ipdl/ok/maybe_OfActorsSub.ipdl
ipc/ipdl/test/ipdl/ok/maybe_Union.ipdl
ipc/ipdl/test/ipdl/ok/media.ipdl
ipc/ipdl/test/ipdl/ok/messageCompress.ipdl
ipc/ipdl/test/ipdl/ok/messageVerify.ipdl
ipc/ipdl/test/ipdl/ok/messageVerifyTopLevel.ipdl
ipc/ipdl/test/ipdl/ok/multiManaged.ipdl
ipc/ipdl/test/ipdl/ok/multiManager1.ipdl
ipc/ipdl/test/ipdl/ok/multiManager2.ipdl
ipc/ipdl/test/ipdl/ok/multipleUsingCxxTypes.ipdl
ipc/ipdl/test/ipdl/ok/mutualRecStructUnion.ipdl
ipc/ipdl/test/ipdl/ok/mutualRecUnion.ipdl
ipc/ipdl/test/ipdl/ok/namespace_Basic.ipdl
ipc/ipdl/test/ipdl/ok/noRedeclCrossMessage.ipdl
ipc/ipdl/test/ipdl/ok/plugin.ipdl
ipc/ipdl/test/ipdl/ok/selfRecUnion.ipdl
ipc/ipdl/test/ipdl/ok/shmem.ipdl
ipc/ipdl/test/ipdl/ok/syncProtocol.ipdl
ipc/ipdl/test/ipdl/ok/threeDirections.ipdl
ipc/ipdl/test/ipdl/ok/union_Basic.ipdl
ipc/ipdl/test/ipdl/ok/union_Namespaced.ipdl
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-006.html.ini
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -945,21 +945,17 @@ pref("app.feedback.baseURL", "https://in
 
 // base URL for web-based marketing pages
 pref("app.productInfo.baseURL", "https://www.mozilla.org/firefox/features/");
 
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
 // Enable the new certificate error pages.
-#ifdef EARLY_BETA_OR_EARLIER
 pref("browser.security.newcerterrorpage.enabled", true);
-#else
-pref("browser.security.newcerterrorpage.enabled", false);
-#endif
 
 pref("browser.security.newcerterrorpage.mitm.enabled", true);
 pref("security.certerrors.recordEventTelemetry", true);
 pref("security.certerrors.permanentOverride", true);
 
 // Whether to start the private browsing mode at application startup
 pref("browser.privatebrowsing.autostart", false);
 
--- a/browser/base/content/test/tabs/browser_allow_process_switches_despite_related_browser.js
+++ b/browser/base/content/test/tabs/browser_allow_process_switches_despite_related_browser.js
@@ -16,16 +16,17 @@ add_task(async function() {
   BrowserViewSource(tab.linkedBrowser);
   let viewSourceTab = await promiseTab;
   registerCleanupFunction(async function() {
     BrowserTestUtils.removeTab(viewSourceTab);
   });
 
   let dummyPage = getChromeDir(getResolvedURI(gTestPath));
   dummyPage.append(DUMMY_FILE);
+  dummyPage.normalize();
   const uriString = Services.io.newFileURI(dummyPage).spec;
 
   let viewSourceBrowser = viewSourceTab.linkedBrowser;
   let promiseLoad =
     BrowserTestUtils.browserLoaded(viewSourceBrowser, false, uriString);
   BrowserTestUtils.loadURI(viewSourceBrowser, uriString);
   let href = await promiseLoad;
   is(href, uriString,
--- a/browser/base/content/test/tabs/browser_contextmenu_openlink_after_tabnavigated.js
+++ b/browser/base/content/test/tabs/browser_contextmenu_openlink_after_tabnavigated.js
@@ -15,29 +15,26 @@ add_task(async function test_contextmenu
   }, gBrowser.selectedBrowser);
   await awaitPopupShown;
   info("Popup Shown");
 
   info("Navigate the tab with the opened context menu");
   BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "about:blank");
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 
-  let awaitNewTabOpen = BrowserTestUtils.waitForNewTab(gBrowser, "http://example.com/");
+  let awaitNewTabOpen = BrowserTestUtils.waitForNewTab(gBrowser, "http://example.com/", true);
 
   info("Click the 'open link in new tab' menu item");
   let openLinkMenuItem = contextMenu.querySelector("#context-openlinkintab");
   openLinkMenuItem.click();
 
   info("Wait for the new tab to be opened");
   const newTab = await awaitNewTabOpen;
 
   // Close the contextMenu popup if it has not been closed yet.
   contextMenu.hidePopup();
 
-  await BrowserTestUtils.browserLoaded(newTab.linkedBrowser);
-  const newTabURL = await ContentTask.spawn(newTab.linkedBrowser, null, async function() {
-    return content.location.href;
-  });
-  is(newTabURL, "http://example.com/", "Got the expected URL loaded in the new tab");
+  is(newTab.linkedBrowser.currentURI.spec, "http://example.com/",
+     "Got the expected URL loaded in the new tab");
 
   BrowserTestUtils.removeTab(newTab);
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -1414,19 +1414,36 @@ BrowserGlue.prototype = {
       if (permission.type == "trackingprotection") {
         exceptions++;
       }
     }
     Services.telemetry.scalarSet("contentblocking.exceptions", exceptions);
 
     let fpEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.fingerprinting.enabled");
     let cmEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.cryptomining.enabled");
+    let categoryPref;
+    switch (Services.prefs.getStringPref("browser.contentblocking.category", null)) {
+    case "standard":
+      categoryPref = 0;
+      break;
+    case "strict":
+      categoryPref = 1;
+      break;
+    case "custom":
+      categoryPref = 2;
+      break;
+    default:
+      // Any other value is unsupported.
+      categoryPref = 3;
+      break;
+    }
 
     Services.telemetry.scalarSet("contentblocking.fingerprinting_blocking_enabled", fpEnabled);
     Services.telemetry.scalarSet("contentblocking.cryptomining_blocking_enabled", cmEnabled);
+    Services.telemetry.scalarSet("contentblocking.category", categoryPref);
   },
 
   _sendMediaTelemetry() {
     let win = Services.appShell.hiddenDOMWindow;
     let v = win.document.createElementNS("http://www.w3.org/1999/xhtml", "video");
     v.reportCanPlayTelemetry();
   },
 
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -1330,18 +1330,19 @@ var PanelView = class extends Associated
         "label" + isMultiline,
         "toolbarbutton[wrap]:not([hidden])",
       ].join(",");
       for (let element of this.node.querySelectorAll(selector)) {
         // Ignore items in hidden containers.
         if (element.closest("[hidden]")) {
           continue;
         }
+
         // Take the label for toolbarbuttons; it only exists on those elements.
-        element = element.labelElement || element;
+        element = element.multilineLabel || element;
 
         let bounds = element.getBoundingClientRect();
         let previous = gMultiLineElementsMap.get(element);
         // We don't need to (re-)apply the workaround for invisible elements or
         // on elements we've seen before and haven't changed in the meantime.
         if (!bounds.width || !bounds.height ||
             (previous && element.textContent == previous.textContent &&
                          bounds.width == previous.bounds.width)) {
--- a/browser/components/urlbar/UrlbarController.jsm
+++ b/browser/components/urlbar/UrlbarController.jsm
@@ -87,19 +87,18 @@ class UrlbarController {
 
   /**
    * Takes a query context and starts the query based on the user input.
    *
    * @param {UrlbarQueryContext} queryContext The query details.
    */
   async startQuery(queryContext) {
     // Cancel any running query.
-    if (this._lastQueryContext) {
-      this.cancelQuery(this._lastQueryContext);
-    }
+    this.cancelQuery();
+
     this._lastQueryContext = queryContext;
 
     queryContext.lastResultCount = 0;
     TelemetryStopwatch.start(TELEMETRY_1ST_RESULT, queryContext);
     TelemetryStopwatch.start(TELEMETRY_6_FIRST_RESULTS, queryContext);
 
     this._notify("onQueryStarted", queryContext);
     await this.manager.startQuery(queryContext, this);
@@ -169,21 +168,24 @@ class UrlbarController {
    *
    * @param {object} listener The listener to add.
    */
   removeQueryListener(listener) {
     this._listeners.delete(listener);
   }
 
   /**
-   * When switching tabs, clear some internal caches to handle cases like
-   * backspace, autofill or repeated searches.
+   * When the containing context changes (for example when switching tabs),
+   * clear any caches that connects consecutive searches in the same context.
+   * For example it can be used to clear information used to improve autofill
+   * or save resourced on repeated searches.
    */
-  tabContextChanged() {
-    // TODO: implementation needed (bug 1496685)
+  viewContextChanged() {
+    this.cancelQuery();
+    this._notify("onViewContextChanged");
   }
 
   /**
    * Receives keyboard events from the input and handles those that should
    * navigate within the view or pick the currently selected item.
    *
    * @param {KeyboardEvent} event
    *   The DOM KeyboardEvent.
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -1102,17 +1102,17 @@ class UrlbarInput {
     }
   }
 
   _on_scrollend(event) {
     this._updateTextOverflow();
   }
 
   _on_TabSelect(event) {
-    this.controller.tabContextChanged();
+    this.controller.viewContextChanged();
   }
 
   _on_keydown(event) {
     this.controller.handleKeyNavigation(event);
     this._toggleActionOverride(event);
   }
 
   _on_keyup(event) {
--- a/browser/components/urlbar/UrlbarView.jsm
+++ b/browser/components/urlbar/UrlbarView.jsm
@@ -268,16 +268,26 @@ class UrlbarView {
       newSelectionIndex = this._queryContext.results.length - 1;
     }
     if (newSelectionIndex >= 0) {
       this.selectedIndex = newSelectionIndex;
     }
   }
 
   /**
+   * Notified when the view context changes, for example when switching tabs.
+   * It can be used to reset internal state tracking.
+   */
+  onViewContextChanged() {
+    // Clear rows, so that when reusing results we don't visually leak them
+    // across different contexts.
+    this._rows.textContent = "";
+  }
+
+  /**
    * Passes DOM events for the view to the _on_<event type> methods.
    * @param {Event} event
    *   DOM event from the <view>.
    */
   handleEvent(event) {
     let methodName = "_on_" + event.type;
     if (methodName in this) {
       this[methodName](event);
--- a/browser/docs/AddressBar.rst
+++ b/browser/docs/AddressBar.rst
@@ -254,19 +254,19 @@ View (e.g. showing/hiding a panel). It i
   UrlbarController {
     async startQuery(queryContext);
     cancelQuery(queryContext);
     // Invoked by the ProvidersManager when results are available.
     receiveResults(queryContext);
     // Used by the View to listen for results.
     addQueryListener(listener);
     removeQueryListener(listener);
-    // Used to indicate the View context changed, as such any cached information
-    // should be reset.
-    tabContextChanged();
+    // Used to indicate the View context changed, so that cached information
+    // about the latest search is no more relevant and can be dropped.
+    viewContextChanged();
   }
 
 
 The View
 =========
 
 The View is the component responsible for presenting search results to the
 user and handling their input.
@@ -342,18 +342,22 @@ Represents the base *View* implementatio
     // Invoked when the query starts.
     onQueryStarted(queryContext);
     // Invoked when new results are available.
     onQueryResults(queryContext);
     // Invoked when the query has been canceled.
     onQueryCancelled(queryContext);
     // Invoked when the query is done.
     onQueryFinished(queryContext);
+    // Invoked when the view context changed, so that cached information about
+    // the latest search is no more relevant and can be dropped.
+    onViewContextChanged();
   }
 
+
 UrlbarResult
 ===========
 
 An `UrlbarResult <https://dxr.mozilla.org/mozilla-central/source/browser/components/urlbar/UrlbarResult.jsm>`_
 instance represents a single search result with a result type, that
 identifies specific kind of results.
 Each kind has its own properties, that the *View* may support, and a few common
 properties, supported by all of the results.
@@ -394,16 +398,17 @@ The following RESULT_TYPEs are supported
     URL: 3,
     // Payload: { icon, url, keyword, postData }
     KEYWORD: 4,
     // Payload: { icon, keyword, title, content }
     OMNIBOX: 5,
     // Payload: { icon, url, device, title }
     REMOTE_TAB: 6,
 
+
 Shared Modules
 ==============
 
 Various modules provide shared utilities to the other components:
 
 `UrlbarPrefs.jsm <https://dxr.mozilla.org/mozilla-central/source/browser/components/urlbar/UrlbarPrefs.jsm>`_
 ----------------
 
--- a/config/external/nspr/pr/moz.build
+++ b/config/external/nspr/pr/moz.build
@@ -105,39 +105,42 @@ else:
 
 LOCAL_INCLUDES += [
     '/config/external/nspr',
     '/nsprpub/pr/include',
     '/nsprpub/pr/include/private',
 ]
 
 SOURCES += [
+    '/nsprpub/pr/src/io/prpolevt.c', # conflicting definition of PRFilePrivate
+    '/nsprpub/pr/src/misc/praton.c', # duplicate definition of index_hex
+    '/nsprpub/pr/src/misc/prcountr.c', # duplicate definition of QName, RName
+ ]
+
+UNIFIED_SOURCES += [
     '/nsprpub/pr/src/io/prfdcach.c',
     '/nsprpub/pr/src/io/priometh.c',
     '/nsprpub/pr/src/io/pripv6.c',
     '/nsprpub/pr/src/io/prlayer.c',
     '/nsprpub/pr/src/io/prlog.c',
     '/nsprpub/pr/src/io/prmapopt.c',
     '/nsprpub/pr/src/io/prmmap.c',
     '/nsprpub/pr/src/io/prmwait.c',
-    '/nsprpub/pr/src/io/prpolevt.c',
     '/nsprpub/pr/src/io/prprf.c',
     '/nsprpub/pr/src/io/prscanf.c',
     '/nsprpub/pr/src/io/prstdio.c',
     '/nsprpub/pr/src/linking/prlink.c',
     '/nsprpub/pr/src/malloc/prmalloc.c',
     '/nsprpub/pr/src/malloc/prmem.c',
     '/nsprpub/pr/src/md/prosdep.c',
     '/nsprpub/pr/src/memory/prseg.c',
     '/nsprpub/pr/src/memory/prshm.c',
     '/nsprpub/pr/src/memory/prshma.c',
     '/nsprpub/pr/src/misc/pralarm.c',
     '/nsprpub/pr/src/misc/pratom.c',
-    '/nsprpub/pr/src/misc/praton.c',
-    '/nsprpub/pr/src/misc/prcountr.c',
     '/nsprpub/pr/src/misc/prdtoa.c',
     '/nsprpub/pr/src/misc/prenv.c',
     '/nsprpub/pr/src/misc/prerr.c',
     '/nsprpub/pr/src/misc/prerror.c',
     '/nsprpub/pr/src/misc/prerrortable.c',
     '/nsprpub/pr/src/misc/prinit.c',
     '/nsprpub/pr/src/misc/prinrval.c',
     '/nsprpub/pr/src/misc/pripc.c',
@@ -153,41 +156,46 @@ SOURCES += [
     '/nsprpub/pr/src/misc/prtrace.c',
     '/nsprpub/pr/src/threads/prcmon.c',
     '/nsprpub/pr/src/threads/prrwlock.c',
     '/nsprpub/pr/src/threads/prtpd.c',
 ]
 
 if CONFIG['OS_TARGET'] != 'WINNT':
     DEFINES['_PR_PTHREADS'] = True
-    SOURCES += [
+    UNIFIED_SOURCES += [
         '/nsprpub/pr/src/md/unix/unix.c',
         '/nsprpub/pr/src/md/unix/unix_errors.c',
         '/nsprpub/pr/src/md/unix/uxproces.c',
         '/nsprpub/pr/src/md/unix/uxrng.c',
         '/nsprpub/pr/src/md/unix/uxshm.c',
         '/nsprpub/pr/src/md/unix/uxwrap.c',
         '/nsprpub/pr/src/pthreads/ptio.c',
         '/nsprpub/pr/src/pthreads/ptmisc.c',
         '/nsprpub/pr/src/pthreads/ptsynch.c',
         '/nsprpub/pr/src/pthreads/ptthread.c',
     ]
 else:
     SOURCES += [
+        # ntinrval.c needs windows.h without WIN32_LEAN_AND_MEAN, so it can't be
+        # unified after any file that pulled in windows.h in lean-and-mean mode.
+        '/nsprpub/pr/src/md/windows/ntinrval.c',
+        # w32poll.c needs a custom value of FD_SETSIZE for winsock.h.
+        '/nsprpub/pr/src/md/windows/w32poll.c',
+    ]
+    UNIFIED_SOURCES += [
         '/nsprpub/pr/src/io/prdir.c',
         '/nsprpub/pr/src/io/prfile.c',
         '/nsprpub/pr/src/io/prio.c',
         '/nsprpub/pr/src/io/prsocket.c',
         '/nsprpub/pr/src/md/windows/ntgc.c',
-        '/nsprpub/pr/src/md/windows/ntinrval.c',
         '/nsprpub/pr/src/md/windows/ntmisc.c',
         '/nsprpub/pr/src/md/windows/ntsec.c',
         '/nsprpub/pr/src/md/windows/ntsem.c',
         '/nsprpub/pr/src/md/windows/w32ipcsem.c',
-        '/nsprpub/pr/src/md/windows/w32poll.c',
         '/nsprpub/pr/src/md/windows/w32rng.c',
         '/nsprpub/pr/src/md/windows/w32shm.c',
         '/nsprpub/pr/src/md/windows/w95cv.c',
         '/nsprpub/pr/src/md/windows/w95dllmain.c',
         '/nsprpub/pr/src/md/windows/w95io.c',
         '/nsprpub/pr/src/md/windows/w95sock.c',
         '/nsprpub/pr/src/md/windows/w95thred.c',
         '/nsprpub/pr/src/md/windows/win32_errors.c',
--- a/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
+++ b/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
@@ -45,17 +45,17 @@ class RuntimePage extends PureComponent 
       otherWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       runtimeDetails: Types.runtimeDetails,
       runtimeId: PropTypes.string.isRequired,
       serviceWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       sharedWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       showProfilerDialog: PropTypes.bool.isRequired,
       tabs: PropTypes.arrayOf(PropTypes.object).isRequired,
       temporaryExtensions: PropTypes.arrayOf(PropTypes.object).isRequired,
-      temporaryInstallError: PropTypes.string,
+      temporaryInstallError: PropTypes.object,
     };
   }
 
   // TODO: avoid the use of this method
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1508688
   componentWillMount() {
     const { dispatch, runtimeId } = this.props;
     dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, runtimeId));
@@ -104,34 +104,46 @@ class RuntimePage extends PureComponent 
     const { runtimeDetails, temporaryInstallError } = this.props;
     const { type } = runtimeDetails.info;
 
     if (!temporaryInstallError ||
         !isSupportedDebugTargetPane(type, DEBUG_TARGET_PANE.TEMPORARY_EXTENSION)) {
       return null;
     }
 
+    let errorMessages = [temporaryInstallError.message];
+
+    // Additional error messages can be found in additionalErrors.
+    if (Array.isArray(temporaryInstallError.additionalErrors)) {
+      errorMessages = errorMessages.concat(temporaryInstallError.additionalErrors);
+    }
+
+    const errors = errorMessages.map((message, index) => {
+      return dom.div(
+        {
+          className: "technical-text",
+          key: "tmp-extension-install-error-" + index,
+        },
+        message
+      );
+    });
+
     return Message(
       {
         level: MESSAGE_LEVEL.ERROR,
       },
       dom.div(
         {},
         Localized(
           {
             id: "about-debugging-tmp-extension-install-error",
           },
           dom.span({}, "There was an error during the temporary add-on installation")
         ),
-        dom.div(
-          {
-            className: "technical-text",
-          },
-          temporaryInstallError
-        )
+        errors
       )
     );
   }
 
   render() {
     const {
       dispatch,
       installedExtensions,
--- a/devtools/client/aboutdebugging-new/src/reducers/ui-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/ui-state.js
@@ -75,17 +75,17 @@ function uiReducer(state = UiState(), ac
     }
 
     case TEMPORARY_EXTENSION_INSTALL_SUCCESS: {
       return Object.assign({}, state, { temporaryInstallError: null });
     }
 
     case TEMPORARY_EXTENSION_INSTALL_FAILURE: {
       const { error } = action;
-      return Object.assign({}, state, { temporaryInstallError: error.message });
+      return Object.assign({}, state, { temporaryInstallError: error });
     }
 
     default:
       return state;
   }
 }
 
 module.exports = {
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -10,17 +10,17 @@ support-files =
   helper-adb.js
   helper-addons.js
   helper-collapsibilities.js
   helper-mocks.js
   helper-real-usb.js
   helper-serviceworker.js
   helper-telemetry.js
   mocks/*
-  resources/bad-extension/*
+  resources/bad-extensions/*
   resources/packaged-extension/*
   resources/service-workers/*
   resources/test-adb-extension/*
   resources/test-temporary-extension/*
   test-tab-favicons.html
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_install_error.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_install_error.js
@@ -6,40 +6,65 @@
 /* import-globals-from helper-addons.js */
 Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this);
 
 /**
  * Test that the installation error messages are displayed when installing temporary
  * extensions.
  */
 
-const BAD_EXTENSION_PATH = "resources/bad-extension/manifest.json";
+const INVALID_JSON_EXTENSION_PATH = "resources/bad-extensions/invalid-json/manifest.json";
+const INVALID_PROP_EXTENSION_PATH =
+  "resources/bad-extensions/invalid-property/manifest.json";
 const EXTENSION_PATH = "resources/test-temporary-extension/manifest.json";
 const EXTENSION_NAME = "test-temporary-extension";
 
-add_task(async function() {
+// Extension with an invalid JSON manifest will not be parsed. We check the expected
+// error message is displayed
+add_task(async function testInvalidJsonExtension() {
   const { document, tab, window } = await openAboutDebugging();
   await selectThisFirefoxPage(document, window.AboutDebugging.store);
 
-  info("Install a bad extension");
-  // Do not use installTemporaryAddon here since the install will fail.
-  prepareMockFilePicker(BAD_EXTENSION_PATH);
-  document.querySelector(".js-temporary-extension-install-button").click();
-
-  info("Wait until the install error message appears");
-  await waitUntil(() => document.querySelector(".js-message"));
-  const installError = document.querySelector(".js-message");
+  const installError = await installBadExtension(INVALID_JSON_EXTENSION_PATH, document);
   ok(installError.textContent.includes("JSON.parse: unexpected keyword"),
     "The expected installation error is displayed: " + installError.textContent);
 
   info("Install a valid extension to make the message disappear");
   await installTemporaryExtension(EXTENSION_PATH, EXTENSION_NAME, document);
 
   info("Wait until the error message disappears");
   await waitUntil(() => !document.querySelector(".js-message"));
 
   info("Wait for the temporary addon to be displayed as a debug target");
   await waitUntil(() => findDebugTargetByText(EXTENSION_NAME, document));
 
   await removeTemporaryExtension(EXTENSION_NAME, document);
 
   await removeTab(tab);
 });
+
+// Extension with a valid JSON manifest but containing an invalid property should display
+// a detailed error message coming from the Addon Manager.
+add_task(async function testInvalidPropertyExtension() {
+  const { document, tab, window } = await openAboutDebugging();
+  await selectThisFirefoxPage(document, window.AboutDebugging.store);
+
+  const installError = await installBadExtension(INVALID_PROP_EXTENSION_PATH, document);
+
+  ok(installError.textContent.includes("Extension is invalid"),
+    "The basic installation error is displayed: " + installError.textContent);
+  ok(installError.textContent.includes(
+    "Reading manifest: Error processing content_scripts.0.matches"),
+    "The detailed installation error is also displayed: " + installError.textContent);
+
+  await removeTab(tab);
+});
+
+async function installBadExtension(path, document) {
+  info("Install a bad extension at path: " + path);
+  // Do not use installTemporaryAddon here since the install will fail.
+  prepareMockFilePicker(path);
+  document.querySelector(".js-temporary-extension-install-button").click();
+
+  info("Wait until the install error message appears");
+  await waitUntil(() => document.querySelector(".js-message"));
+  return document.querySelector(".js-message");
+}
rename from devtools/client/aboutdebugging-new/test/browser/resources/bad-extension/manifest.json
rename to devtools/client/aboutdebugging-new/test/browser/resources/bad-extensions/invalid-json/manifest.json
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/test/browser/resources/bad-extensions/invalid-property/manifest.json
@@ -0,0 +1,26 @@
+{
+  "manifest_version": 2,
+  "name": "test-invalid-extension",
+  "version": "1",
+  "description": "the name says it all",
+  "permissions": [
+    "*://*.foo.com/*",
+    "alarms",
+    "notifications",
+    "tabs"
+  ],
+  "background": {
+    "scripts": ["background.js"]
+  },
+  "content_scripts": [{
+    "matches": "*://*.foo.com/*",
+    "js": ["content.js"]
+  }],
+  "browser_action": {
+    "default_icon": {
+      "32": "home.svg"
+    },
+    "default_title": "foobarbaz (v1)",
+    "browser_style": true
+  }
+}
\ No newline at end of file
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -202,16 +202,22 @@ button {
 
 .addons-install-error .warning,
 .service-worker-multi-process .warning {
   /* The warning icon can be hard to see on red / yellow backgrounds, this turns the icon
   to a black icon. */
   fill: #0c0c0d;
 }
 
+.addons-install-error__additional-errors {
+  font-family: monospace;
+  font-size: 13px;
+  margin-block: 8px;
+}
+
 .addons-options {
   flex: 1;
 }
 
 .service-worker-disabled-label,
 .addons-debugging-label,
 .addons-web-ext-tip {
   display: inline-block;
--- a/devtools/client/aboutdebugging/components/addons/Controls.js
+++ b/devtools/client/aboutdebugging/components/addons/Controls.js
@@ -62,17 +62,17 @@ class AddonsControls extends Component {
 
   installAddon(file) {
     AddonManager.installTemporaryAddon(file)
       .then(() => {
         this.setState({ lastInstallErrorFile: null });
       })
       .catch(e => {
         console.error(e);
-        this.setState({ installError: e.message, lastInstallErrorFile: file });
+        this.setState({ installError: e, lastInstallErrorFile: file });
       });
   }
 
   render() {
     const { debugDisabled } = this.props;
 
     return dom.div({ className: "addons-top" },
       dom.div({ className: "addons-controls" },
--- a/devtools/client/aboutdebugging/components/addons/InstallError.js
+++ b/devtools/client/aboutdebugging/components/addons/InstallError.js
@@ -12,32 +12,41 @@ const dom = require("devtools/client/sha
 const Services = require("Services");
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
 class AddonsInstallError extends Component {
   static get propTypes() {
     return {
-      error: PropTypes.string,
+      error: PropTypes.object,
       retryInstall: PropTypes.func,
     };
   }
 
   render() {
+    const { error } = this.props;
     if (!this.props.error) {
       return null;
     }
-    const text = Strings.formatStringFromName("addonInstallError", [this.props.error], 1);
+    const text = Strings.formatStringFromName("addonInstallError", [error.message], 1);
+
+    const additionalErrors = Array.isArray(error.additionalErrors) ?
+      dom.div(
+        { className: "addons-install-error__additional-errors" },
+        error.additionalErrors.join(" ")
+      ) : null;
+
     return dom.div(
       { className: "addons-install-error" },
       dom.span(
         {},
         dom.div({ className: "warning" }),
         dom.span({}, text),
+        additionalErrors
       ),
       dom.button(
         { className: "addons-install-retry", onClick: this.props.retryInstall },
         Strings.GetStringFromName("retryTemporaryInstall")));
   }
 }
 
 module.exports = AddonsInstallError;
--- a/devtools/client/framework/menu.js
+++ b/devtools/client/framework/menu.js
@@ -92,17 +92,17 @@ Menu.prototype.popup = function(screenX,
   // opening a new one.
   let popup = popupset.querySelector("menupopup[menu-api=\"true\"]");
   if (popup) {
     popup.hidePopup();
   }
 
   popup = doc.createXULElement("menupopup");
   popup.setAttribute("menu-api", "true");
-  popup.setAttribute("consumeoutsideclicks", "true");
+  popup.setAttribute("consumeoutsideclicks", "false");
 
   if (this.id) {
     popup.id = this.id;
   }
   this._createMenuItems(popup);
 
   // Remove the menu from the DOM once it's hidden.
   popup.addEventListener("popuphidden", (e) => {
--- a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css
+++ b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css
@@ -203,16 +203,31 @@
   color: inherit;
   padding-inline-start: 3px;
 }
 
 .theme-dark .network-monitor .tabpanel-summary-value {
   color: var(--theme-selection-color);
 }
 
+.network-monitor .tracking-protection {
+  background-color: var(--toolbarbutton-background);
+  color: inherit;
+  margin-top: 2px;
+  margin-bottom: 2px;
+}
+
+.theme-dark .network-monitor .tracking-protection .tracking-resource {
+  filter: brightness(500%);
+}
+
+.theme-light .network-monitor .tracking-protection .tracking-resource {
+  filter: brightness(0);
+}
+
 .theme-dark .network-monitor .edit-and-resend-button  {
   background-color: var(--toolbarbutton-background);
   color: var(--theme-selection-color);
 }
 
 .summary-edit-and-resend {
   display: flex;
   align-items: center;
--- a/devtools/client/netmonitor/src/assets/styles/RequestList.css
+++ b/devtools/client/netmonitor/src/assets/styles/RequestList.css
@@ -379,17 +379,17 @@
   background-image: url(chrome://devtools/skin/images/globe-small.svg);
 }
 
 .tracking-resource {
   display: inline-block;
   width: 16px;
   height: 16px;
   margin: 0 3px 0 -3px;
-  vertical-align: text-bottom;
+  vertical-align: middle;
   background-image: url(chrome://devtools/content/netmonitor/src/assets/icons/shield.svg);
   background-repeat: no-repeat;
 }
 
 .selected .tracking-resource {
   filter: brightness(500%);
 }
 
--- a/devtools/client/netmonitor/src/components/HeadersPanel.js
+++ b/devtools/client/netmonitor/src/components/HeadersPanel.js
@@ -10,16 +10,17 @@ const dom = require("devtools/client/sha
 const {
   getFormattedIPAndPort,
   getFormattedSize,
 } = require("../utils/format-utils");
 const { L10N } = require("../utils/l10n");
 const {
   getHeadersURL,
   getHTTPStatusCodeURL,
+  getTrackingProtectionURL,
 } = require("../utils/mdn-utils");
 const {
   fetchNetworkUpdatePacket,
   writeHeaderText,
 } = require("../utils/request-utils");
 const {
   HeadersProvider,
   HeaderList,
@@ -353,16 +354,17 @@ class HeadersPanel extends Component {
         remotePort,
         requestHeaders,
         requestHeadersFromUploadStream: uploadHeaders,
         responseHeaders,
         status,
         statusText,
         urlDetails,
         referrerPolicy,
+        isThirdPartyTrackingResource,
       },
     } = this.props;
     const item = { fromCache, fromServiceWorker, status, statusText };
 
     if ((!requestHeaders || !requestHeaders.headers.length) &&
         (!uploadHeaders || !uploadHeaders.headers.length) &&
         (!responseHeaders || !responseHeaders.headers.length)) {
       return div({ className: "empty-notice" },
@@ -411,16 +413,37 @@ class HeadersPanel extends Component {
             title: SUMMARY_STATUS_LEARN_MORE,
           }) : span({
             className: "headers-summary learn-more-link",
           }),
         )
       );
     }
 
+    let trackingProtectionStatus;
+
+    if (isThirdPartyTrackingResource) {
+      const trackingProtectionDocURL = getTrackingProtectionURL();
+
+      trackingProtectionStatus = (
+        div({ className: "tabpanel-summary-container tracking-protection" },
+          div({
+            className: "tracking-resource",
+          }),
+          L10N.getStr("netmonitor.trackingResource.tooltip"),
+          trackingProtectionDocURL ? MDNLink({
+            url: trackingProtectionDocURL,
+            title: SUMMARY_STATUS_LEARN_MORE,
+          }) : span({
+            className: "headers-summary learn-more-link",
+          }),
+        )
+      );
+    }
+
     const summaryVersion = httpVersion ?
       this.renderSummary(SUMMARY_VERSION, httpVersion) : null;
 
     const summaryReferrerPolicy = referrerPolicy ?
       this.renderSummary(SUMMARY_REFERRER_POLICY, referrerPolicy) : null;
 
     const summaryEditAndResendBtn = (
       div({
@@ -432,16 +455,17 @@ class HeadersPanel extends Component {
         }, EDIT_AND_RESEND)
       )
     );
 
     return (
       div({ className: "panel-container" },
         div({ className: "headers-overview" },
           summaryUrl,
+          trackingProtectionStatus,
           summaryMethod,
           summaryAddress,
           summaryStatus,
           summaryVersion,
           summaryEditAndResendBtn,
         ),
         PropertiesView({
           object,
--- a/devtools/client/netmonitor/src/utils/mdn-utils.js
+++ b/devtools/client/netmonitor/src/utils/mdn-utils.js
@@ -209,15 +209,25 @@ function getPerformanceAnalysisURL() {
  *
  * @return {string} The MDN URL for the documentation of Filter box.
  */
 function getFilterBoxURL() {
   return `${MDN_URL}Tools/Network_Monitor/request_list${getGAParams()}` +
     `#Filtering_by_properties`;
 }
 
+/**
+ * Get the MDN URL for Tracking Protection
+ *
+ * @return {string} The MDN URL for the documentation of Tracking Protection.
+ */
+function getTrackingProtectionURL() {
+  return `${MDN_URL}Mozilla/Firefox/Privacy/Tracking_Protection${getGAParams()}`;
+}
+
 module.exports = {
   getHeadersURL,
   getHTTPStatusCodeURL,
   getNetMonitorTimingsURL,
   getPerformanceAnalysisURL,
   getFilterBoxURL,
+  getTrackingProtectionURL,
 };
--- a/devtools/client/themes/changes.css
+++ b/devtools/client/themes/changes.css
@@ -1,33 +1,39 @@
 /* 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/. */
 
  /* CSS Variables specific to the Changes panel that aren't defined by the themes */
  :root {
-   --changes-button-background-color: var(--grey-90-a10);
-   --changes-button-background-color-hover: var(--grey-90-a15);
-   --changes-button-background-color-active: var(--grey-90-a20);
+   --changes-button-copy-all-background-color--hover: var(--grey-90-a10);
+   --changes-button-copy-all-background-color--active: var(--grey-90-a15);
+   --changes-button-copy-rule-background-color: var(--grey-90-a10);
+   --changes-button-copy-rule-background-color--hover: var(--grey-90-a15);
+   --changes-button-copy-rule-background-color--active: var(--grey-90-a20);
    --diff-add-background-color: #f1feec;
    --diff-add-text-color: #54983f;
    --diff-remove-background-color: #fbf2f5;
    --diff-remove-text-color: #bf7173;
    --diff-source-background: var(--theme-toolbar-background);
    --diff-level: 0;
    --diff-level-offset: 10px;
    /*
     Minimum padding so content on the first level (zero) isn't touching the edge. Added
     and removed lines will re-declare this to add extra padding to clear the +/- icons.
    */
    --diff-level-min-offset: 5px;
  }
 
 :root.theme-dark {
-  --changes-button-background-color: #252526;
+  --changes-button-copy-all-background-color--hover: var(--grey-10-a10);
+  --changes-button-copy-all-background-color--active: var(--grey-10-a15);
+  --changes-button-copy-rule-background-color: var(--grey-10-a10);
+  --changes-button-copy-rule-background-color--hover: var(--grey-10-a15);
+  --changes-button-copy-rule-background-color--active: var(--grey-10-a20);
   --diff-add-background-color: rgba(18, 188, 0, 0.15);
   --diff-add-text-color: #12BC00;
   --diff-remove-background-color: rgba(255, 0, 57, 0.15);
   --diff-remove-text-color: #FF0039;
   --diff-source-background: #222225;
 }
 
 :root[dir="rtl"] {
@@ -79,44 +85,66 @@
   padding-bottom: 3px;
   padding-left: calc(var(--diff-level-min-offset) +
                      var(--diff-level-offset) * var(--diff-level));
 }
 
 .changes__copy-all-changes-button {
   -moz-context-properties: fill;
   background: url(chrome://devtools/skin/images/copy.svg) no-repeat;
+  background-position: 4px 3px;
   background-size: 16px;
   border: none;
+  border-radius: 3px;
   color: var(--theme-body-color);
   fill: currentColor;
-  height: 16px;
-  margin: 7px 10px;
-  padding-left: 21px;
+  margin: 2px 5px;
+  padding: 4px 5px 4px 25px;
+}
+
+.changes__copy-all-changes-button:hover {
+  background-color: var(--changes-button-copy-all-background-color--hover);
+}
+
+.changes__copy-all-changes-button:active {
+  background-color: var(--changes-button-copy-all-background-color--active);
 }
 
 /* Hide the Copy Rule button by default. */
 .changes__copy-rule-button {
-  background-color: var(--changes-button-background-color);
-  border-radius: 5px;
+  /**
+   * The rgba() format of the background colors makes the button see-through and it looks
+   * bad when stacked on top of long selectors.
+   *
+   * To solve this and not change the color format which is inherited from the Photon
+   * color guide in `client/themes/variables.css`, we use a blending trick to overlay the
+   * rgba() color value onto a solid color used for the panel background (achieved with
+   * a linear gradient with no transition). This keeps the rgba() color, but prevents the
+   * see-through effect.
+   */
+  background-blend-mode: overlay;
+  background-color: var(--changes-button-copy-rule-background-color);
+  background-image:
+    linear-gradient(var(--theme-sidebar-background), var(--theme-sidebar-background));
+  border-radius: 8px;
   border: none;
   color: var(--theme-body-color);
   display: none;
-  padding: 1px 5px;
+  padding: 1px 7px;
   position: absolute;
   right: 5px;
   top: 2px;
 }
 
 .changes__copy-rule-button:hover {
-  background-color: var(--changes-button-background-color-hover);
+  background-color: var(--changes-button-copy-rule-background-color--hover);
 }
 
 .changes__copy-rule-button:active {
-  background-color: var(--changes-button-background-color-active);
+  background-color: var(--changes-button-copy-rule-background-color--active);
 }
 
 .changes__rule {
   position: relative;
 }
 
 .changes__selector {
   word-wrap: break-word;
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -238,16 +238,19 @@
   --green-70: #058b00;
 
   --yellow-50: #ffe900;
   --yellow-60: #d7b600;
   --yellow-65: #be9b00;
   --yellow-80: #715100;
 
   --grey-10: #f9f9fa;
+  --grey-10-a10: rgba(249, 249, 250, 0.1);
+  --grey-10-a15: rgba(249, 249, 250, 0.15);
+  --grey-10-a20: rgba(249, 249, 250, 0.2);
   --grey-20: #ededf0;
   --grey-25: #e0e0e2;
   --grey-30: #d7d7db;
   --grey-40: #b1b1b3;
   --grey-45: #939395;
   --grey-50: #737373;
   --grey-55: #5c5c5f;
   --grey-60: #4a4a4f;
--- a/devtools/client/webconsole/components/ConsoleOutput.js
+++ b/devtools/client/webconsole/components/ConsoleOutput.js
@@ -68,17 +68,20 @@ class ConsoleOutput extends Component {
 
   constructor(props) {
     super(props);
     this.onContextMenu = this.onContextMenu.bind(this);
     this.maybeScrollToBottom = this.maybeScrollToBottom.bind(this);
   }
 
   componentDidMount() {
-    scrollToBottom(this.outputNode);
+    if (this.props.visibleMessages.length > 0) {
+      scrollToBottom(this.outputNode);
+    }
+
     const {
       serviceContainer,
       onFirstMeaningfulPaint,
       dispatch,
     } = this.props;
     serviceContainer.attachRefToWebConsoleUI("outputScroller", this.outputNode);
 
     // Waiting for the next paint.
@@ -202,17 +205,19 @@ class ConsoleOutput extends Component {
         },
       }, messageNodes
       )
     );
   }
 }
 
 function scrollToBottom(node) {
-  node.scrollTop = node.scrollHeight;
+  if (node.scrollHeight > node.clientHeight) {
+    node.scrollTop = node.scrollHeight;
+  }
 }
 
 function isScrolledToBottom(outputNode, scrollNode) {
   const lastNodeHeight = outputNode.lastChild ?
                        outputNode.lastChild.clientHeight : 0;
   return scrollNode.scrollTop + scrollNode.clientHeight >=
          scrollNode.scrollHeight - lastNodeHeight / 2;
 }
--- a/dom/base/MaybeCrossOriginObject.cpp
+++ b/dom/base/MaybeCrossOriginObject.cpp
@@ -446,14 +446,44 @@ bool MaybeCrossOriginObject<Base>::enume
   JS::Rooted<JSObject*> self(cx, proxy);
   if (!MaybeWrapObject(cx, &self)) {
     return false;
   }
 
   return js::GetPropertyKeys(cx, self, 0, &props);
 }
 
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::hasInstance(JSContext* cx,
+                                               JS::Handle<JSObject*> proxy,
+                                               JS::MutableHandle<JS::Value> v,
+                                               bool* bp) const {
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    // In the cross-origin case we never have @@hasInstance, and we're never
+    // callable, so just go ahead and report an error.  If we enter the realm of
+    // "proxy" to do that, our caller won't be able to do anything with the
+    // exception, so instead let's wrap "proxy" into our realm.  We definitely
+    // do NOT want to call JS::InstanceofOperator here after entering "proxy's"
+    // realm, because that would do the wrong thing with @@hasInstance on the
+    // object by seeing any such definitions when we should not.
+    JS::Rooted<JS::Value> val(cx, JS::ObjectValue(*proxy));
+    if (!MaybeWrapValue(cx, &val)) {
+      return false;
+    }
+    return js::ReportIsNotFunction(cx, val);
+  }
+
+  // Safe to enter the realm of "proxy" and do the normal thing of looking up
+  // @@hasInstance, etc.
+  JSAutoRealm ar(cx, proxy);
+  JS::Rooted<JS::Value> val(cx, v);
+  if (!MaybeWrapValue(cx, &val)) {
+    return false;
+  }
+  return JS::InstanceofOperator(cx, proxy, val, bp);
+}
+
 // Force instantiations of the out-of-line template methods we need.
 template class MaybeCrossOriginObject<js::Wrapper>;
 template class MaybeCrossOriginObject<DOMProxyHandler>;
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/MaybeCrossOriginObject.h
+++ b/dom/base/MaybeCrossOriginObject.h
@@ -314,16 +314,24 @@ class MaybeCrossOriginObject : public Ba
 
   /**
    * Spidermonkey-internal hook for enumerating objects.
    */
   bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
                  JS::AutoIdVector& props) const final;
 
   /**
+   * Spidermonkey-internal hook used for instanceof.  We need to override this
+   * because otherwise we can end up doing instanceof work in the wrong
+   * compartment.
+   */
+  bool hasInstance(JSContext* cx, JS::Handle<JSObject*> proxy,
+                   JS::MutableHandle<JS::Value> v, bool* bp) const final;
+
+  /**
    * Spidermonkey-internal hook used by Object.prototype.toString.  Subclasses
    * need to implement this, because we don't know what className they want.
    * Except in the cross-origin case, when we could maybe handle it...
    */
   const char* className(JSContext* cx,
                         JS::Handle<JSObject*> proxy) const override = 0;
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1528675.html
@@ -0,0 +1,28 @@
+<script>
+function start() {
+  o14=window.document;
+  o432=document.createElement('audio');
+  o433=document.createElement('track');
+  o432.appendChild(o433);
+  o493=o432.textTracks;
+    o14.write('<html></html>');
+  o757=document.createElement('iframe');
+  o757.addEventListener('load', fun0, false);
+    document.documentElement.appendChild(o757);
+  o432.controls^=1;
+}
+function fun0(e) {
+  o1062=e.target;
+  o1063=o1062.contentWindow;
+  o1064=o1063.document;
+  document.documentElement.appendChild(o432);
+  setTimeout(fun1,240);
+}
+function fun1() {
+  o433.parentNode.removeChild(o433);
+  document.replaceChild(o1064.documentElement,document.documentElement);
+  SpecialPowers.forceGC();
+  SpecialPowers.forceCC();
+}
+</script>
+<body onload="start()"></body>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -241,11 +241,12 @@ load 1458016.html
 load 1459688.html
 load 1460794.html
 load 1462548.html
 load 1505811.html
 load 1505875.html
 load 1508845.html
 load 1516289.html
 load 1516560.html
+load 1528675.html
 load structured_clone_container_throws.html
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -9909,17 +9909,17 @@ class CGStaticMethodJitinfo(CGGeneric):
     """
     def __init__(self, method):
         CGGeneric.__init__(
             self,
             "\n"
             "static const JSJitInfo %s_methodinfo = {\n"
             "  { (JSJitGetterOp)%s },\n"
             "  { prototypes::id::_ID_Count }, { 0 }, JSJitInfo::StaticMethod,\n"
-            "  JSJitInfo::AliasEverything, JSVAL_TYPE_MISSING, false, false,\n"
+            "  JSJitInfo::AliasEverything, JSVAL_TYPE_OBJECT, false, false,\n"
             "  false, false, 0\n"
             "};\n" %
             (IDLToCIdentifier(method.identifier.name),
              CppKeywords.checkMethodName(
                  IDLToCIdentifier(method.identifier.name))))
 
 
 def getEnumValueName(value):
--- a/dom/tests/mochitest/bugs/mochitest.ini
+++ b/dom/tests/mochitest/bugs/mochitest.ini
@@ -143,10 +143,11 @@ skip-if = toolkit == 'android' || os == 
 skip-if = toolkit == 'android' #Windows can't change size on Android
 [test_toJSON.html]
 [test_window_bar.html]
 skip-if = toolkit == 'android'
 [test_bug1022869.html]
 [test_bug1112040.html]
 [test_bug1160342_marquee.html]
 [test_bug1171215.html]
+[test_bug1530292.html]
 [test_no_find_showDialog.html]
 skip-if = toolkit == 'android' # Bug 1358633 - window.find doesn't work for Android
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug1530292.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1530292
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1530292</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1530292 **/
+  SimpleTest.waitForExplicitFinish();
+  addLoadEvent(() => {
+    // This is really a crashtest, but we need some cross-origin (and hence
+    // cross-compartment) windows to test it, so can't use the crashtest
+    // harness.
+    try {
+      ({} instanceof frames[0]);
+      ok(false, "Should have thrown for same-process window");
+    } catch (e) {
+      is(e.message, "frames[0] is not a function");
+    }
+    try {
+      ({} instanceof frames[1]);
+      ok(false, "Should have thrown for maybe other-process window");
+    } catch (e) {
+      is(e.message, "frames[1] is not a function");
+    }
+    SimpleTest.finish();
+  });
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1530292">Mozilla Bug 1530292</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <!-- Cross-origin but same-site; must be same-process -->
+  <iframe src="//test1.mochi.test:8888/tests/dom/tests/mochitest/bugs/file_empty.html"></iframe>
+  <!-- Completely cross-origin; might be cross-process -->
+  <iframe src="//example.org/tests/dom/tests/mochitest/bugs/file_empty.html"></iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -513,17 +513,17 @@ constexpr int eCornerCount = 4;
 static inline Corner operator++(Corner& aCorner) {
   MOZ_ASSERT(aCorner >= eCornerTopLeft && aCorner <= eCornerBottomLeft,
              "Out of range corner!");
   aCorner = Corner(aCorner + 1);
   return aCorner;
 }
 
 // Indices into "half corner" arrays (nsStyleCorners e.g.)
-enum HalfCorner {
+enum HalfCorner : uint8_t {
   // This order is important!
   eCornerTopLeftX = 0,
   eCornerTopLeftY = 1,
   eCornerTopRightX = 2,
   eCornerTopRightY = 3,
   eCornerBottomRightX = 4,
   eCornerBottomRightY = 5,
   eCornerBottomLeftX = 6,
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -2340,28 +2340,24 @@ impl Device {
     fn create_vao_with_vbos(
         &mut self,
         descriptor: &VertexDescriptor,
         main_vbo_id: VBOId,
         instance_vbo_id: VBOId,
         ibo_id: IBOId,
         owns_vertices_and_indices: bool,
     ) -> VAO {
-        debug_assert!(self.inside_frame);
-
         let instance_stride = descriptor.instance_stride() as usize;
         let vao_id = self.gl.gen_vertex_arrays(1)[0];
 
-        self.gl.bind_vertex_array(vao_id);
+        self.bind_vao_impl(vao_id);
 
         descriptor.bind(self.gl(), main_vbo_id, instance_vbo_id);
         ibo_id.bind(self.gl()); // force it to be a part of VAO
 
-        self.gl.bind_vertex_array(0);
-
         VAO {
             id: vao_id,
             ibo_id,
             main_vbo_id,
             instance_vbo_id,
             instance_stride,
             owns_vertices_and_indices,
         }
@@ -2369,32 +2365,30 @@ impl Device {
 
     pub fn create_custom_vao(
         &mut self,
         streams: &[Stream],
     ) -> CustomVAO {
         debug_assert!(self.inside_frame);
 
         let vao_id = self.gl.gen_vertex_arrays(1)[0];
-        self.gl.bind_vertex_array(vao_id);
+        self.bind_vao_impl(vao_id);
 
         let mut attrib_index = 0;
         for stream in streams {
             VertexDescriptor::bind_attributes(
                 stream.attributes,
                 attrib_index,
                 0,
                 self.gl(),
                 stream.vbo,
             );
             attrib_index += stream.attributes.len();
         }
 
-        self.gl.bind_vertex_array(0);
-
         CustomVAO {
             id: vao_id,
         }
     }
 
     pub fn delete_custom_vao(&mut self, mut vao: CustomVAO) {
         self.gl.delete_vertex_arrays(&[vao.id]);
         vao.id = 0;
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -4241,16 +4241,20 @@ impl Renderer {
         self.debug_flags = flags;
     }
 
     pub fn save_cpu_profile(&self, filename: &str) {
         write_profile(filename);
     }
 
     fn draw_frame_debug_items(&mut self, items: &[DebugItem]) {
+        if items.is_empty() {
+            return;
+        }
+
         let debug_renderer = match self.debug.get_mut(&mut self.device) {
             Some(render) => render,
             None => return,
         };
 
         for item in items {
             match item {
                 DebugItem::Rect { rect, color } => {
--- a/ipc/ipdl/ipdl/direct_call.py
+++ b/ipc/ipdl/ipdl/direct_call.py
@@ -133,16 +133,308 @@ DIRECT_CALL_OVERRIDES = {
     ("PVRGPU", "child"): ("VRGPUChild", "VRGPUChild.h"),
     ("PVRGPU", "parent"): ("VRGPUParent", "VRGPUParent.h"),
     ("PVRLayer", "child"): ("VRLayerChild", "VRLayerChild.h"),
     ("PVRManager", "child"): ("VRManagerChild", "VRManagerChild.h"),
     ("PVRManager", "parent"): ("VRManagerParent", "VRManagerParent.h"),
 
     ("PWebSocket", "child"): ("WebSocketChannelChild", "mozilla/net/WebSocketChannelChild.h"),
     ("PWebSocket", "parent"): ("WebSocketChannelParent", "mozilla/net/WebSocketChannelParent.h"),
+
+    # _ipdltest
+    ("PTestActorPunning", "child"): (
+        "TestActorPunningChild", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunning", "parent"): (
+        "TestActorPunningParent", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningPunned", "child"): (
+        "TestActorPunningPunnedChild", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningPunned", "parent"): (
+        "TestActorPunningPunnedParent", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningSub", "child"): (
+        "TestActorPunningSubChild", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningSub", "parent"): (
+        "TestActorPunningSubParent", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+
+    ("PTestAsyncReturns", "child"): (
+        "TestAsyncReturnsChild", "mozilla/_ipdltest/TestAsyncReturns.h"
+    ),
+    ("PTestAsyncReturns", "parent"): (
+        "TestAsyncReturnsParent", "mozilla/_ipdltest/TestAsyncReturns.h"
+    ),
+
+    ("PTestBadActor", "parent"): ("TestBadActorParent", "mozilla/_ipdltest/TestBadActor.h"),
+    ("PTestBadActor", "child"): ("TestBadActorChild", "mozilla/_ipdltest/TestBadActor.h"),
+    ("PTestBadActorSub", "child"): ("TestBadActorSubChild", "mozilla/_ipdltest/TestBadActor.h"),
+    ("PTestBadActorSub", "parent"): ("TestBadActorSubParent", "mozilla/_ipdltest/TestBadActor.h"),
+
+    ("PTestCancel", "child"): ("TestCancelChild", "mozilla/_ipdltest/TestCancel.h"),
+    ("PTestCancel", "parent"): ("TestCancelParent", "mozilla/_ipdltest/TestCancel.h"),
+
+    ("PTestCrashCleanup", "child"): (
+        "TestCrashCleanupChild", "mozilla/_ipdltest/TestCrashCleanup.h"
+    ),
+    ("PTestCrashCleanup", "parent"): (
+        "TestCrashCleanupParent", "mozilla/_ipdltest/TestCrashCleanup.h"
+    ),
+
+    ("PTestDataStructures", "child"): (
+        "TestDataStructuresChild", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+    ("PTestDataStructures", "parent"): (
+        "TestDataStructuresParent", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+    ("PTestDataStructuresSub", "child"): (
+        "TestDataStructuresSub", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+    ("PTestDataStructuresSub", "parent"): (
+        "TestDataStructuresSub", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+
+    ("PTestDemon", "child"): ("TestDemonChild", "mozilla/_ipdltest/TestDemon.h"),
+    ("PTestDemon", "parent"): ("TestDemonParent", "mozilla/_ipdltest/TestDemon.h"),
+
+    ("PTestDesc", "child"): ("TestDescChild", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDesc", "parent"): ("TestDescParent", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSub", "child"): ("TestDescSubChild", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSub", "parent"): ("TestDescSubParent", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSubsub", "child"): ("TestDescSubsubChild", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSubsub", "parent"): ("TestDescSubsubParent", "mozilla/_ipdltest/TestDesc.h"),
+
+    ("PTestEndpointBridgeMain", "child"): (
+        "TestEndpointBridgeMainChild", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeMain", "parent"): (
+        "TestEndpointBridgeMainParent", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeMainSub", "child"): (
+        "TestEndpointBridgeMainSubChild", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeMainSub", "parent"): (
+        "TestEndpointBridgeMainSubParent", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeSub", "child"): (
+        "TestEndpointBridgeSubChild", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeSub", "parent"): (
+        "TestEndpointBridgeSubParent", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+
+    ("PTestEndpointOpens", "child"): (
+        "TestEndpointOpensChild", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+    ("PTestEndpointOpens", "parent"): (
+        "TestEndpointOpensParent", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+    ("PTestEndpointOpensOpened", "child"): (
+        "TestEndpointOpensOpenedChild", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+    ("PTestEndpointOpensOpened", "parent"): (
+        "TestEndpointOpensOpenedParent", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+
+    ("PTestFailedCtor", "child"): ("TestFailedCtorChild", "mozilla/_ipdltest/TestFailedCtor.h"),
+    ("PTestFailedCtor", "parent"): ("TestFailedCtorParent", "mozilla/_ipdltest/TestFailedCtor.h"),
+    ("PTestFailedCtorSub", "child"): (
+        "TestFailedCtorSubChild", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+    ("PTestFailedCtorSub", "parent"): (
+        "TestFailedCtorSubParent", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+    ("PTestFailedCtorSubsub", "child"): (
+        "TestFailedCtorSubsub", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+    ("PTestFailedCtorSubsub", "parent"): (
+        "TestFailedCtorSubsub", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+
+    ("PTestHandle", "child"): ("TestHandleChild", "mozilla/_ipdltest/TestJSON.h"),
+    ("PTestHandle", "parent"): ("TestHandleParent", "mozilla/_ipdltest/TestJSON.h"),
+    ("PTestJSON", "child"): ("TestJSONChild", "mozilla/_ipdltest/TestJSON.h"),
+    ("PTestJSON", "parent"): ("TestJSONParent", "mozilla/_ipdltest/TestJSON.h"),
+
+    ("PTestHangs", "child"): ("TestHangsChild", "mozilla/_ipdltest/TestHangs.h"),
+    ("PTestHangs", "parent"): ("TestHangsParent", "mozilla/_ipdltest/TestHangs.h"),
+
+    ("PTestHighestPrio", "child"): ("TestHighestPrioChild", "mozilla/_ipdltest/TestHighestPrio.h"),
+    ("PTestHighestPrio", "parent"): (
+        "TestHighestPrioParent", "mozilla/_ipdltest/TestHighestPrio.h"
+    ),
+
+    ("PTestInterruptErrorCleanup", "child"): (
+        "TestInterruptErrorCleanupChild", "mozilla/_ipdltest/TestInterruptErrorCleanup.h"
+    ),
+    ("PTestInterruptErrorCleanup", "parent"): (
+        "TestInterruptErrorCleanupParent", "mozilla/_ipdltest/TestInterruptErrorCleanup.h"
+    ),
+
+    ("PTestInterruptRaces", "child"): (
+        "TestInterruptRacesChild", "mozilla/_ipdltest/TestInterruptRaces.h"
+    ),
+    ("PTestInterruptRaces", "parent"): (
+        "TestInterruptRacesParent", "mozilla/_ipdltest/TestInterruptRaces.h"
+    ),
+
+    ("PTestInterruptShutdownRace", "child"): (
+        "TestInterruptShutdownRaceChild", "mozilla/_ipdltest/TestInterruptShutdownRace.h"
+    ),
+    ("PTestInterruptShutdownRace", "parent"): (
+        "TestInterruptShutdownRaceParent", "mozilla/_ipdltest/TestInterruptShutdownRace.h"
+    ),
+
+    ("PTestLatency", "child"): ("TestLatencyChild", "mozilla/_ipdltest/TestLatency.h"),
+    ("PTestLatency", "parent"): ("TestLatencyParent", "mozilla/_ipdltest/TestLatency.h"),
+
+    ("PTestLayoutThread", "child"): (
+        "TestOffMainThreadPaintingChild", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+    ("PTestLayoutThread", "parent"): (
+        "TestOffMainThreadPaintingParent", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+    ("PTestPaintThread", "child"): (
+        "TestPaintThreadChild", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+    ("PTestPaintThread", "parent"): (
+        "TestPaintThreadParent", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+
+    ("PTestManyChildAllocs", "child"): (
+        "TestManyChildAllocsChild", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+    ("PTestManyChildAllocs", "parent"): (
+        "TestManyChildAllocsParent", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+    ("PTestManyChildAllocsSub", "child"): (
+        "TestManyChildAllocsSubChild", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+    ("PTestManyChildAllocsSub", "parent"): (
+        "TestManyChildAllocsSubParent", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+
+    ("PTestMultiMgrs", "child"): ("TestMultiMgrsChild", "mozilla/_ipdltest/TestMultiMgrs.h"),
+    ("PTestMultiMgrs", "parent"): ("TestMultiMgrsParent", "mozilla/_ipdltest/TestMultiMgrs.h"),
+    ("PTestMultiMgrsBottom", "child"): (
+        "TestMultiMgrsBottomChild", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsBottom", "parent"): (
+        "TestMultiMgrsBottomParent", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsLeft", "child"): (
+        "TestMultiMgrsLeftChild", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsLeft", "parent"): (
+        "TestMultiMgrsLeftParent", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsRight", "child"): (
+        "TestMultiMgrsRightChild", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsRight", "parent"): (
+        "TestMultiMgrsRightParent", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+
+    ("PTestNestedLoops", "child"): ("TestNestedLoopsChild", "mozilla/_ipdltest/TestNestedLoops.h"),
+    ("PTestNestedLoops", "parent"): (
+        "TestNestedLoopsParent", "mozilla/_ipdltest/TestNestedLoops.h"
+    ),
+
+    ("PTestRaceDeadlock", "child"): (
+        "TestRaceDeadlockChild", "mozilla/_ipdltest/TestRaceDeadlock.h"
+    ),
+    ("PTestRaceDeadlock", "parent"): (
+        "TestRaceDeadlockParent", "mozilla/_ipdltest/TestRaceDeadlock.h"
+    ),
+
+    ("PTestRaceDeferral", "child"): (
+        "TestRaceDeferralChild", "mozilla/_ipdltest/TestRaceDeferral.h"
+    ),
+    ("PTestRaceDeferral", "parent"): (
+        "TestRaceDeferralParent", "mozilla/_ipdltest/TestRaceDeferral.h"
+    ),
+
+    ("PTestRacyInterruptReplies", "child"): (
+        "TestRacyInterruptRepliesChild", "mozilla/_ipdltest/TestRacyInterruptReplies.h"
+    ),
+    ("PTestRacyInterruptReplies", "parent"): (
+        "TestRacyInterruptRepliesParent", "mozilla/_ipdltest/TestRacyInterruptReplies.h"
+    ),
+
+    ("PTestRacyReentry", "child"): ("TestRacyReentryChild", "mozilla/_ipdltest/TestRacyReentry.h"),
+    ("PTestRacyReentry", "parent"): (
+        "TestRacyReentryParent", "mozilla/_ipdltest/TestRacyReentry.h"
+    ),
+
+    ("PTestRacyUndefer", "child"): ("TestRacyUndeferChild", "mozilla/_ipdltest/TestRacyUndefer.h"),
+    ("PTestRacyUndefer", "parent"): (
+        "TestRacyUndeferParent", "mozilla/_ipdltest/TestRacyUndefer.h"
+    ),
+
+    ("PTestRPC", "child"): ("TestRPCChild", "mozilla/_ipdltest/TestRPC.h"),
+    ("PTestRPC", "parent"): ("TestRPCParent", "mozilla/_ipdltest/TestRPC.h"),
+
+    ("PTestSanity", "child"): ("TestSanityChild", "mozilla/_ipdltest/TestSanity.h"),
+    ("PTestSanity", "parent"): ("TestSanityParent", "mozilla/_ipdltest/TestSanity.h"),
+
+    ("PTestSelfManage", "child"): (
+        "TestSelfManageChild", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+    ("PTestSelfManage", "parent"): (
+        "TestSelfManageParent", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+    ("PTestSelfManageRoot", "child"): (
+        "TestSelfManageRootChild", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+    ("PTestSelfManageRoot", "parent"): (
+        "TestSelfManageRootParent", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+
+    ("PTestShmem", "child"): ("TestShmemChild", "mozilla/_ipdltest/TestShmem.h"),
+    ("PTestShmem", "parent"): ("TestShmemParent", "mozilla/_ipdltest/TestShmem.h"),
+
+    ("PTestShutdown", "child"): ("TestShutdownChild", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdown", "parent"): ("TestShutdownParent", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdownSub", "child"): ("TestShutdownSubChild", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdownSub", "parent"): ("TestShutdownSubParent", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdownSubsub", "child"): (
+        "TestShutdownSubsubChild", "mozilla/_ipdltest/TestShutdown.h"
+    ),
+    ("PTestShutdownSubsub", "parent"): (
+        "TestShutdownSubsubParent", "mozilla/_ipdltest/TestShutdown.h"
+    ),
+
+    ("PTestStackHooks", "child"): ("TestStackHooksChild", "mozilla/_ipdltest/TestStackHooks.h"),
+    ("PTestStackHooks", "parent"): ("TestStackHooksParent", "mozilla/_ipdltest/TestStackHooks.h"),
+
+    ("PTestSyncError", "child"): ("TestSyncErrorChild", "mozilla/_ipdltest/TestSyncError.h"),
+    ("PTestSyncError", "parent"): ("TestSyncErrorParent", "mozilla/_ipdltest/TestSyncError.h"),
+
+    ("PTestSyncHang", "child"): ("TestSyncHangChild", "mozilla/_ipdltest/TestSyncHang.h"),
+    ("PTestSyncHang", "parent"): ("TestSyncHangParent", "mozilla/_ipdltest/TestSyncHang.h"),
+
+    ("PTestSyncWakeup", "child"): ("TestSyncWakeupChild", "mozilla/_ipdltest/TestSyncWakeup.h"),
+    ("PTestSyncWakeup", "parent"): ("TestSyncWakeupParent", "mozilla/_ipdltest/TestSyncWakeup.h"),
+
+    ("PTestUniquePtrIPC", "child"): (
+        "TestUniquePtrIPCChild", "mozilla/_ipdltest/TestUniquePtrIPC.h"
+    ),
+    ("PTestUniquePtrIPC", "parent"): (
+        "TestUniquePtrIPCParent", "mozilla/_ipdltest/TestUniquePtrIPC.h"
+    ),
+
+    ("PTestUrgency", "child"): ("TestUrgencyChild", "mozilla/_ipdltest/TestUrgency.h"),
+    ("PTestUrgency", "parent"): ("TestUrgencyParent", "mozilla/_ipdltest/TestUrgency.h"),
+
+    ("PTestUrgentHangs", "child"): ("TestUrgentHangsChild", "mozilla/_ipdltest/TestUrgentHangs.h"),
+    ("PTestUrgentHangs", "parent"): (
+        "TestUrgentHangsParent", "mozilla/_ipdltest/TestUrgentHangs.h"
+    ),
 }
 
 # Our long term goal is to burn this list down, so new entries should be added
 # extremely sparingly and only with a very good reason! You must have an IPC
 # peer's r+ to add something new!
 
 # set() of (Protocol, side)
 VIRTUAL_CALL_CLASSES = set([
@@ -319,9 +611,20 @@ VIRTUAL_CALL_CLASSES = set([
     ("PGMPVideoDecoder", "parent"),
     ("PGMPVideoEncoder", "parent"),
     ("PWebRenderBridge", "parent"),
 
     # Not actually subclassed
     ("PLoginReputation", "child"),
     ("PPluginSurface", "child"),
     ("PTestShellCommand", "child"),
+
+    # _ipdltest
+    # Not actually subclassed
+    ("PTestIndirectProtocolParamFirst", "child"),
+    ("PTestIndirectProtocolParamFirst", "parent"),
+    ("PTestIndirectProtocolParamManage", "child"),
+    ("PTestIndirectProtocolParamManage", "parent"),
+    ("PTestIndirectProtocolParamSecond", "child"),
+    ("PTestIndirectProtocolParamSecond", "parent"),
+    ("PTestPriority", "child"),
+    ("PTestPriority", "parent"),
 ])
--- a/ipc/ipdl/test/cxx/PTestShmem.ipdl
+++ b/ipc/ipdl/test/cxx/PTestShmem.ipdl
@@ -1,17 +1,17 @@
 namespace mozilla {
 namespace _ipdltest {
 
 protocol PTestShmem {
 child:
-    async Give(Shmem mem, Shmem unsafe, size_t expectedSize);
+    async Give(Shmem mem, Shmem unsafe, uint32_t expectedSize);
 
 parent:
-    async Take(Shmem mem, Shmem unsafe, size_t expectedSize);
+    async Take(Shmem mem, Shmem unsafe, uint32_t expectedSize);
     async __delete__();
 
 /*
 state GIVING:
     send Give goto TAKING;
 
 state TAKING:
     recv Take goto TAKING;
--- a/ipc/ipdl/test/cxx/TestActorPunning.h
+++ b/ipc/ipdl/test/cxx/TestActorPunning.h
@@ -9,33 +9,33 @@
 #include "mozilla/_ipdltest/PTestActorPunningChild.h"
 #include "mozilla/_ipdltest/PTestActorPunningPunnedChild.h"
 #include "mozilla/_ipdltest/PTestActorPunningSubChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestActorPunningParent : public PTestActorPunningParent {
+  friend class PTestActorPunningParent;
+
  public:
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  PTestActorPunningPunnedParent* AllocPTestActorPunningPunnedParent() override;
-  bool DeallocPTestActorPunningPunnedParent(
-      PTestActorPunningPunnedParent* a) override;
+  PTestActorPunningPunnedParent* AllocPTestActorPunningPunnedParent();
+  bool DeallocPTestActorPunningPunnedParent(PTestActorPunningPunnedParent* a);
 
-  PTestActorPunningSubParent* AllocPTestActorPunningSubParent() override;
-  bool DeallocPTestActorPunningSubParent(
-      PTestActorPunningSubParent* a) override;
+  PTestActorPunningSubParent* AllocPTestActorPunningSubParent();
+  bool DeallocPTestActorPunningSubParent(PTestActorPunningSubParent* a);
 
-  virtual mozilla::ipc::IPCResult RecvPun(PTestActorPunningSubParent* a,
-                                          const Bad& bad) override;
+  mozilla::ipc::IPCResult RecvPun(PTestActorPunningSubParent* a,
+                                  const Bad& bad);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown == why) fail("should have died from error!");
     passed("ok");
     QuitParent();
   }
 
   virtual void HandleFatalError(const char* aErrorMsg) const override;
@@ -55,29 +55,30 @@ class TestActorPunningSubParent : public
   TestActorPunningSubParent() {}
   virtual ~TestActorPunningSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestActorPunningChild : public PTestActorPunningChild {
+  friend class PTestActorPunningChild;
+
  public:
   TestActorPunningChild() {}
   virtual ~TestActorPunningChild() {}
 
  protected:
-  PTestActorPunningPunnedChild* AllocPTestActorPunningPunnedChild() override;
-  bool DeallocPTestActorPunningPunnedChild(
-      PTestActorPunningPunnedChild* a) override;
+  PTestActorPunningPunnedChild* AllocPTestActorPunningPunnedChild();
+  bool DeallocPTestActorPunningPunnedChild(PTestActorPunningPunnedChild* a);
 
-  PTestActorPunningSubChild* AllocPTestActorPunningSubChild() override;
-  bool DeallocPTestActorPunningSubChild(PTestActorPunningSubChild* a) override;
+  PTestActorPunningSubChild* AllocPTestActorPunningSubChild();
+  bool DeallocPTestActorPunningSubChild(PTestActorPunningSubChild* a);
 
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have been killed off!");
   }
 };
 
 class TestActorPunningPunnedChild : public PTestActorPunningPunnedChild {
  public:
@@ -85,15 +86,15 @@ class TestActorPunningPunnedChild : publ
   virtual ~TestActorPunningPunnedChild() {}
 };
 
 class TestActorPunningSubChild : public PTestActorPunningSubChild {
  public:
   TestActorPunningSubChild() {}
   virtual ~TestActorPunningSubChild() {}
 
-  virtual mozilla::ipc::IPCResult RecvBad() override;
+  mozilla::ipc::IPCResult RecvBad();
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
 
 #endif  // ifndef mozilla__ipdltest_TestActorPunning_h
--- a/ipc/ipdl/test/cxx/TestAsyncReturns.h
+++ b/ipc/ipdl/test/cxx/TestAsyncReturns.h
@@ -5,43 +5,47 @@
 
 #include "mozilla/_ipdltest/PTestAsyncReturnsParent.h"
 #include "mozilla/_ipdltest/PTestAsyncReturnsChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestAsyncReturnsParent : public PTestAsyncReturnsParent {
+  friend class PTestAsyncReturnsParent;
+
  public:
   TestAsyncReturnsParent();
   virtual ~TestAsyncReturnsParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  mozilla::ipc::IPCResult RecvPong(PongResolver&& aResolve) override;
+  mozilla::ipc::IPCResult RecvPong(PongResolver&& aResolve);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestAsyncReturnsChild : public PTestAsyncReturnsChild {
+  friend class PTestAsyncReturnsChild;
+
  public:
   TestAsyncReturnsChild();
   virtual ~TestAsyncReturnsChild();
 
  protected:
-  mozilla::ipc::IPCResult RecvPing(PingResolver&& aResolve) override;
-  mozilla::ipc::IPCResult RecvNoReturn(NoReturnResolver&& aResolve) override;
+  mozilla::ipc::IPCResult RecvPing(PingResolver&& aResolve);
+  mozilla::ipc::IPCResult RecvNoReturn(NoReturnResolver&& aResolve);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestBadActor.h
+++ b/ipc/ipdl/test/cxx/TestBadActor.h
@@ -8,16 +8,18 @@
 
 #include "mozilla/_ipdltest/PTestBadActorSubParent.h"
 #include "mozilla/_ipdltest/PTestBadActorSubChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestBadActorParent : public PTestBadActorParent {
+  friend class PTestBadActorParent;
+
  public:
   TestBadActorParent() {}
   virtual ~TestBadActorParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
@@ -26,36 +28,39 @@ class TestBadActorParent : public PTestB
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction");
     passed("ok");
     QuitParent();
   }
 
   virtual void HandleFatalError(const char* aErrorMsg) const override;
 
-  virtual PTestBadActorSubParent* AllocPTestBadActorSubParent() override;
+  PTestBadActorSubParent* AllocPTestBadActorSubParent();
 
-  virtual bool DeallocPTestBadActorSubParent(
-      PTestBadActorSubParent* actor) override {
+  bool DeallocPTestBadActorSubParent(PTestBadActorSubParent* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestBadActorSubParent : public PTestBadActorSubParent {
+  friend class PTestBadActorSubParent;
+
  public:
   TestBadActorSubParent() {}
   virtual ~TestBadActorSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
-  virtual mozilla::ipc::IPCResult RecvPing() override;
+  mozilla::ipc::IPCResult RecvPing();
 };
 
 class TestBadActorChild : public PTestBadActorChild {
+  friend class PTestBadActorChild;
+
  public:
   TestBadActorChild() {}
   virtual ~TestBadActorChild() {}
 
  protected:
   virtual PTestBadActorSubChild* AllocPTestBadActorSubChild();
 
   virtual bool DeallocPTestBadActorSubChild(PTestBadActorSubChild* actor) {
--- a/ipc/ipdl/test/cxx/TestCancel.h
+++ b/ipc/ipdl/test/cxx/TestCancel.h
@@ -14,41 +14,41 @@ class TestCancelParent : public PTestCan
   TestCancelParent();
   virtual ~TestCancelParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  virtual mozilla::ipc::IPCResult RecvDone1() override;
-  virtual mozilla::ipc::IPCResult RecvTest2_1() override;
-  virtual mozilla::ipc::IPCResult RecvStart3() override;
-  virtual mozilla::ipc::IPCResult RecvTest3_2() override;
-  virtual mozilla::ipc::IPCResult RecvDone() override;
+  mozilla::ipc::IPCResult RecvDone1();
+  mozilla::ipc::IPCResult RecvTest2_1();
+  mozilla::ipc::IPCResult RecvStart3();
+  mozilla::ipc::IPCResult RecvTest3_2();
+  mozilla::ipc::IPCResult RecvDone();
 
-  virtual mozilla::ipc::IPCResult RecvCheckParent(uint32_t *reply) override;
+  mozilla::ipc::IPCResult RecvCheckParent(uint32_t *reply);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     passed("ok");
     QuitParent();
   }
 };
 
 class TestCancelChild : public PTestCancelChild {
  public:
   TestCancelChild();
   virtual ~TestCancelChild();
 
-  virtual mozilla::ipc::IPCResult RecvTest1_1() override;
-  virtual mozilla::ipc::IPCResult RecvStart2() override;
-  virtual mozilla::ipc::IPCResult RecvTest2_2() override;
-  virtual mozilla::ipc::IPCResult RecvTest3_1() override;
+  mozilla::ipc::IPCResult RecvTest1_1();
+  mozilla::ipc::IPCResult RecvStart2();
+  mozilla::ipc::IPCResult RecvTest2_2();
+  mozilla::ipc::IPCResult RecvTest3_1();
 
-  virtual mozilla::ipc::IPCResult RecvCheckChild(uint32_t *reply) override;
+  mozilla::ipc::IPCResult RecvCheckChild(uint32_t *reply);
 
   virtual void ActorDestroy(ActorDestroyReason why) override { QuitChild(); }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
 
 #endif  // ifndef mozilla__ipdltest_TestCancel_h
--- a/ipc/ipdl/test/cxx/TestCrashCleanup.h
+++ b/ipc/ipdl/test/cxx/TestCrashCleanup.h
@@ -24,22 +24,24 @@ class TestCrashCleanupParent : public PT
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     mCleanedUp = true;
   }
 
   bool mCleanedUp;
 };
 
 class TestCrashCleanupChild : public PTestCrashCleanupChild {
+  friend class PTestCrashCleanupChild;
+
  public:
   TestCrashCleanupChild();
   virtual ~TestCrashCleanupChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerDIEDIEDIE() override;
+  mozilla::ipc::IPCResult AnswerDIEDIEDIE();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have 'crashed'!");
   }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestDataStructures.h
+++ b/ipc/ipdl/test/cxx/TestDataStructures.h
@@ -25,143 +25,131 @@ class TestDataStructuresSub : public PTe
   }
   uint32_t mI;
 };
 
 //-----------------------------------------------------------------------------
 // Main actors
 
 class TestDataStructuresParent : public PTestDataStructuresParent {
+  friend class PTestDataStructuresParent;
+
  public:
   TestDataStructuresParent();
   virtual ~TestDataStructuresParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual PTestDataStructuresSubParent* AllocPTestDataStructuresSubParent(
-      const int& i) override {
+  PTestDataStructuresSubParent* AllocPTestDataStructuresSubParent(
+      const int& i) {
     PTestDataStructuresSubParent* actor = new TestDataStructuresSub(i);
     mKids.AppendElement(actor);
     return actor;
   }
 
-  virtual bool DeallocPTestDataStructuresSubParent(
-      PTestDataStructuresSubParent* actor) override;
+  bool DeallocPTestDataStructuresSubParent(PTestDataStructuresSubParent* actor);
 
-  virtual mozilla::ipc::IPCResult RecvTest1(InfallibleTArray<int>&& i1,
-                                            InfallibleTArray<int>* o1) override;
+  mozilla::ipc::IPCResult RecvTest1(InfallibleTArray<int>&& i1,
+                                    InfallibleTArray<int>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest2(
+  mozilla::ipc::IPCResult RecvTest2(
       InfallibleTArray<PTestDataStructuresSubParent*>&& i1,
-      InfallibleTArray<PTestDataStructuresSubParent*>* o1) override;
+      InfallibleTArray<PTestDataStructuresSubParent*>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest3(const IntDouble& i1,
-                                            const IntDouble& i2, IntDouble* o1,
-                                            IntDouble* o2) override;
+  mozilla::ipc::IPCResult RecvTest3(const IntDouble& i1, const IntDouble& i2,
+                                    IntDouble* o1, IntDouble* o2);
 
-  virtual mozilla::ipc::IPCResult RecvTest4(
-      InfallibleTArray<IntDouble>&& i1,
-      InfallibleTArray<IntDouble>* o1) override;
+  mozilla::ipc::IPCResult RecvTest4(InfallibleTArray<IntDouble>&& i1,
+                                    InfallibleTArray<IntDouble>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest5(const IntDoubleArrays& i1,
-                                            const IntDoubleArrays& i2,
-                                            const IntDoubleArrays& i3,
-                                            IntDoubleArrays* o1,
-                                            IntDoubleArrays* o2,
-                                            IntDoubleArrays* o3) override;
+  mozilla::ipc::IPCResult RecvTest5(const IntDoubleArrays& i1,
+                                    const IntDoubleArrays& i2,
+                                    const IntDoubleArrays& i3,
+                                    IntDoubleArrays* o1, IntDoubleArrays* o2,
+                                    IntDoubleArrays* o3);
 
-  virtual mozilla::ipc::IPCResult RecvTest6(
-      InfallibleTArray<IntDoubleArrays>&& i1,
-      InfallibleTArray<IntDoubleArrays>* o1) override;
+  mozilla::ipc::IPCResult RecvTest6(InfallibleTArray<IntDoubleArrays>&& i1,
+                                    InfallibleTArray<IntDoubleArrays>* o1);
+
+  mozilla::ipc::IPCResult RecvTest7_0(const ActorWrapper& i1, ActorWrapper* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest7_0(const ActorWrapper& i1,
-                                              ActorWrapper* o1) override;
-
-  virtual mozilla::ipc::IPCResult RecvTest7(const Actors& i1, const Actors& i2,
-                                            const Actors& i3, Actors* o1,
-                                            Actors* o2, Actors* o3) override;
+  mozilla::ipc::IPCResult RecvTest7(const Actors& i1, const Actors& i2,
+                                    const Actors& i3, Actors* o1, Actors* o2,
+                                    Actors* o3);
 
-  virtual mozilla::ipc::IPCResult RecvTest8(
-      InfallibleTArray<Actors>&& i1, InfallibleTArray<Actors>* o1) override;
+  mozilla::ipc::IPCResult RecvTest8(InfallibleTArray<Actors>&& i1,
+                                    InfallibleTArray<Actors>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest9(const Unions& i1, const Unions& i2,
-                                            const Unions& i3, const Unions& i4,
-                                            Unions* o1, Unions* o2, Unions* o3,
-                                            Unions* o4) override;
+  mozilla::ipc::IPCResult RecvTest9(const Unions& i1, const Unions& i2,
+                                    const Unions& i3, const Unions& i4,
+                                    Unions* o1, Unions* o2, Unions* o3,
+                                    Unions* o4);
 
-  virtual mozilla::ipc::IPCResult RecvTest10(
-      InfallibleTArray<Unions>&& i1, InfallibleTArray<Unions>* o1) override;
+  mozilla::ipc::IPCResult RecvTest10(InfallibleTArray<Unions>&& i1,
+                                     InfallibleTArray<Unions>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest11(const SIntDouble& i,
-                                             SIntDouble* o) override;
+  mozilla::ipc::IPCResult RecvTest11(const SIntDouble& i, SIntDouble* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest12(const SIntDoubleArrays& i,
-                                             SIntDoubleArrays* o) override;
+  mozilla::ipc::IPCResult RecvTest12(const SIntDoubleArrays& i,
+                                     SIntDoubleArrays* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest13(const SActors& i,
-                                             SActors* o) override;
+  mozilla::ipc::IPCResult RecvTest13(const SActors& i, SActors* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest14(const Structs& i,
-                                             Structs* o) override;
+  mozilla::ipc::IPCResult RecvTest14(const Structs& i, Structs* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest15(
+  mozilla::ipc::IPCResult RecvTest15(
       const WithStructs& i1, const WithStructs& i2, const WithStructs& i3,
       const WithStructs& i4, const WithStructs& i5, WithStructs* o1,
-      WithStructs* o2, WithStructs* o3, WithStructs* o4,
-      WithStructs* o5) override;
+      WithStructs* o2, WithStructs* o3, WithStructs* o4, WithStructs* o5);
 
-  virtual mozilla::ipc::IPCResult RecvTest16(const WithUnions& i,
-                                             WithUnions* o) override;
+  mozilla::ipc::IPCResult RecvTest16(const WithUnions& i, WithUnions* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest17(
-      InfallibleTArray<Op>&& sa) override;
+  mozilla::ipc::IPCResult RecvTest17(InfallibleTArray<Op>&& sa);
 
-  virtual mozilla::ipc::IPCResult RecvTest18(
-      InfallibleTArray<nsIntRegion>&& ra) override;
+  mozilla::ipc::IPCResult RecvTest18(InfallibleTArray<nsIntRegion>&& ra);
 
-  virtual mozilla::ipc::IPCResult RecvDummy(const ShmemUnion& su,
-                                            ShmemUnion* rsu) override {
+  mozilla::ipc::IPCResult RecvDummy(const ShmemUnion& su, ShmemUnion* rsu) {
     *rsu = su;
     return IPC_OK();
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
  private:
   InfallibleTArray<PTestDataStructuresSubParent*> mKids;
 };
 
 class TestDataStructuresChild : public PTestDataStructuresChild {
+  friend class PTestDataStructuresChild;
+
  public:
   TestDataStructuresChild();
   virtual ~TestDataStructuresChild();
 
  protected:
-  virtual PTestDataStructuresSubChild* AllocPTestDataStructuresSubChild(
-      const int& i) override {
+  PTestDataStructuresSubChild* AllocPTestDataStructuresSubChild(const int& i) {
     PTestDataStructuresSubChild* actor = new TestDataStructuresSub(i);
     mKids.AppendElement(actor);
     return actor;
   }
 
-  virtual bool DeallocPTestDataStructuresSubChild(
-      PTestDataStructuresSubChild* actor) override {
+  bool DeallocPTestDataStructuresSubChild(PTestDataStructuresSubChild* actor) {
     delete actor;
     return true;
   }
 
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
  private:
   void Test1();
--- a/ipc/ipdl/test/cxx/TestDemon.h
+++ b/ipc/ipdl/test/cxx/TestDemon.h
@@ -24,22 +24,22 @@ class TestDemonParent : public PTestDemo
 #ifdef DEBUG
   bool ShouldContinueFromReplyTimeout() override;
   bool ArtificialTimeout() override;
 
   bool NeedArtificialSleep() override { return true; }
   void ArtificialSleep() override;
 #endif
 
-  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvHiPrioSyncMessage() override;
+  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvHiPrioSyncMessage();
 
-  mozilla::ipc::IPCResult RecvSyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvUrgentAsyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvUrgentSyncMessage(const int& n) override;
+  mozilla::ipc::IPCResult RecvSyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvUrgentAsyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvUrgentSyncMessage(const int& n);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     mDone = true;
     printf("Parent ActorDestroy\n");
     passed("ok");
     QuitParent();
   }
 
@@ -57,25 +57,25 @@ class TestDemonParent : public PTestDemo
   bool DoAction(int flags = 0);
 };
 
 class TestDemonChild : public PTestDemonChild {
  public:
   TestDemonChild();
   virtual ~TestDemonChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
 #ifdef DEBUG
   bool NeedArtificialSleep() override { return true; }
   void ArtificialSleep() override;
 #endif
 
-  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvHiPrioSyncMessage() override;
+  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvHiPrioSyncMessage();
 
   virtual void ActorDestroy(ActorDestroyReason why) override { _exit(0); }
 
   virtual void IntentionalCrash() override { _exit(0); }
 
  private:
   int mIncoming[3];
   int mOutgoing[3];
--- a/ipc/ipdl/test/cxx/TestDesc.h
+++ b/ipc/ipdl/test/cxx/TestDesc.h
@@ -14,82 +14,86 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Top-level
 //
 class TestDescParent : public PTestDescParent {
+  friend class PTestDescParent;
+
  public:
   TestDescParent() {}
   virtual ~TestDescParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
-  virtual mozilla::ipc::IPCResult RecvOk(PTestDescSubsubParent* a) override;
+  mozilla::ipc::IPCResult RecvOk(PTestDescSubsubParent* a);
 
  protected:
-  virtual PTestDescSubParent* AllocPTestDescSubParent(
-      PTestDescSubsubParent*) override;
-  virtual bool DeallocPTestDescSubParent(PTestDescSubParent* actor) override;
+  PTestDescSubParent* AllocPTestDescSubParent(PTestDescSubsubParent*);
+  bool DeallocPTestDescSubParent(PTestDescSubParent* actor);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestDescChild : public PTestDescChild {
+  friend class PTestDescChild;
+
  public:
   TestDescChild() {}
   virtual ~TestDescChild() {}
 
  protected:
-  virtual PTestDescSubChild* AllocPTestDescSubChild(
-      PTestDescSubsubChild*) override;
+  PTestDescSubChild* AllocPTestDescSubChild(PTestDescSubsubChild*);
 
-  virtual bool DeallocPTestDescSubChild(PTestDescSubChild* actor) override;
+  bool DeallocPTestDescSubChild(PTestDescSubChild* actor);
 
-  virtual mozilla::ipc::IPCResult RecvTest(PTestDescSubsubChild* a) override;
+  mozilla::ipc::IPCResult RecvTest(PTestDescSubsubChild* a);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 //-----------------------------------------------------------------------------
 // First descendent
 //
 class TestDescSubParent : public PTestDescSubParent {
+  friend class PTestDescSubParent;
+
  public:
   TestDescSubParent() {}
   virtual ~TestDescSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
-  virtual PTestDescSubsubParent* AllocPTestDescSubsubParent() override;
-  virtual bool DeallocPTestDescSubsubParent(
-      PTestDescSubsubParent* actor) override;
+  PTestDescSubsubParent* AllocPTestDescSubsubParent();
+  bool DeallocPTestDescSubsubParent(PTestDescSubsubParent* actor);
 };
 
 class TestDescSubChild : public PTestDescSubChild {
+  friend class PTestDescSubChild;
+
  public:
   TestDescSubChild() {}
   virtual ~TestDescSubChild() {}
 
  protected:
-  virtual PTestDescSubsubChild* AllocPTestDescSubsubChild() override;
-  virtual bool DeallocPTestDescSubsubChild(
-      PTestDescSubsubChild* actor) override;
+  PTestDescSubsubChild* AllocPTestDescSubsubChild();
+  bool DeallocPTestDescSubsubChild(PTestDescSubsubChild* actor);
 };
 
 //-----------------------------------------------------------------------------
 // Grand-descendent
 //
 class TestDescSubsubParent : public PTestDescSubsubParent {
  public:
   TestDescSubsubParent() {}
--- a/ipc/ipdl/test/cxx/TestEndpointBridgeMain.h
+++ b/ipc/ipdl/test/cxx/TestEndpointBridgeMain.h
@@ -17,103 +17,114 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // "Main" process
 //
 class TestEndpointBridgeMainParent : public PTestEndpointBridgeMainParent {
+  friend class PTestEndpointBridgeMainParent;
+
  public:
   TestEndpointBridgeMainParent() {}
   virtual ~TestEndpointBridgeMainParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
   mozilla::ipc::IPCResult RecvBridged(
-      mozilla::ipc::Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint)
-      override;
+      mozilla::ipc::Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 class TestEndpointBridgeMainSubParent
     : public PTestEndpointBridgeMainSubParent {
+  friend class PTestEndpointBridgeMainSubParent;
+
  public:
   explicit TestEndpointBridgeMainSubParent() {}
   virtual ~TestEndpointBridgeMainSubParent() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHello() override;
-  virtual mozilla::ipc::IPCResult RecvHelloSync() override;
-  virtual mozilla::ipc::IPCResult AnswerHelloRpc() override;
+  mozilla::ipc::IPCResult RecvHello();
+  mozilla::ipc::IPCResult RecvHelloSync();
+  mozilla::ipc::IPCResult AnswerHelloRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
 // "Sub" process --- child of "main"
 //
 class TestEndpointBridgeSubParent;
 
 class TestEndpointBridgeMainChild : public PTestEndpointBridgeMainChild {
+  friend class PTestEndpointBridgeMainChild;
+
  public:
   TestEndpointBridgeMainChild();
   virtual ~TestEndpointBridgeMainChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   IPDLUnitTestSubprocess* mSubprocess;
 };
 
 class TestEndpointBridgeSubParent : public PTestEndpointBridgeSubParent {
+  friend class PTestEndpointBridgeSubParent;
+
  public:
   TestEndpointBridgeSubParent() {}
   virtual ~TestEndpointBridgeSubParent() {}
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvBridgeEm() override;
+  mozilla::ipc::IPCResult RecvBridgeEm();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
 // "Subsub" process --- child of "sub"
 //
 class TestEndpointBridgeSubChild : public PTestEndpointBridgeSubChild {
+  friend class PTestEndpointBridgeSubChild;
+
  public:
   TestEndpointBridgeSubChild();
   virtual ~TestEndpointBridgeSubChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPing() override;
+  mozilla::ipc::IPCResult RecvPing();
 
   mozilla::ipc::IPCResult RecvBridged(
-      Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint) override;
+      Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 class TestEndpointBridgeMainSubChild : public PTestEndpointBridgeMainSubChild {
+  friend class PTestEndpointBridgeMainSubChild;
+
  public:
   explicit TestEndpointBridgeMainSubChild() : mGotHi(false) {}
   virtual ~TestEndpointBridgeMainSubChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHi() override;
-  virtual mozilla::ipc::IPCResult AnswerHiRpc() override;
+  mozilla::ipc::IPCResult RecvHi();
+  mozilla::ipc::IPCResult AnswerHiRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool mGotHi;
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestEndpointOpens.h
+++ b/ipc/ipdl/test/cxx/TestEndpointOpens.h
@@ -14,79 +14,86 @@
 
 namespace mozilla {
 
 // parent process
 
 namespace _ipdltest {
 
 class TestEndpointOpensParent : public PTestEndpointOpensParent {
+  friend class PTestEndpointOpensParent;
+
  public:
   TestEndpointOpensParent() {}
   virtual ~TestEndpointOpensParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartSubprotocol(
-      mozilla::ipc::Endpoint<PTestEndpointOpensOpenedParent>&& endpoint)
-      override;
+  mozilla::ipc::IPCResult RecvStartSubprotocol(
+      mozilla::ipc::Endpoint<PTestEndpointOpensOpenedParent>&& endpoint);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest
 
 namespace _ipdltest2 {
 
 class TestEndpointOpensOpenedParent : public PTestEndpointOpensOpenedParent {
+  friend class PTestEndpointOpensOpenedParent;
+
  public:
   explicit TestEndpointOpensOpenedParent() {}
   virtual ~TestEndpointOpensOpenedParent() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHello() override;
-  virtual mozilla::ipc::IPCResult RecvHelloSync() override;
-  virtual mozilla::ipc::IPCResult AnswerHelloRpc() override;
+  mozilla::ipc::IPCResult RecvHello();
+  mozilla::ipc::IPCResult RecvHelloSync();
+  mozilla::ipc::IPCResult AnswerHelloRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest2
 
 // child process
 
 namespace _ipdltest {
 
 class TestEndpointOpensChild : public PTestEndpointOpensChild {
+  friend class PTestEndpointOpensChild;
+
  public:
   TestEndpointOpensChild();
   virtual ~TestEndpointOpensChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest
 
 namespace _ipdltest2 {
 
 class TestEndpointOpensOpenedChild : public PTestEndpointOpensOpenedChild {
+  friend class PTestEndpointOpensOpenedChild;
+
  public:
   explicit TestEndpointOpensOpenedChild() : mGotHi(false) {}
   virtual ~TestEndpointOpensOpenedChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHi() override;
-  virtual mozilla::ipc::IPCResult AnswerHiRpc() override;
+  mozilla::ipc::IPCResult RecvHi();
+  mozilla::ipc::IPCResult AnswerHiRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool mGotHi;
 };
 
 }  // namespace _ipdltest2
 
--- a/ipc/ipdl/test/cxx/TestFailedCtor.h
+++ b/ipc/ipdl/test/cxx/TestFailedCtor.h
@@ -14,97 +14,99 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Top-level
 //
 class TestFailedCtorParent : public PTestFailedCtorParent {
+  friend class PTestFailedCtorParent;
+
  public:
   TestFailedCtorParent() {}
   virtual ~TestFailedCtorParent() {}
 
   static bool RunTestInProcesses() { return true; }
 
   // FIXME/bug 703322 Disabled because child calls exit() to end
   //                  test, not clear how to handle failed ctor in
   //                  threaded mode.
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  virtual PTestFailedCtorSubParent* AllocPTestFailedCtorSubParent() override;
-  virtual bool DeallocPTestFailedCtorSubParent(
-      PTestFailedCtorSubParent* actor) override;
+  PTestFailedCtorSubParent* AllocPTestFailedCtorSubParent();
+  bool DeallocPTestFailedCtorSubParent(PTestFailedCtorSubParent* actor);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestFailedCtorChild : public PTestFailedCtorChild {
+  friend class PTestFailedCtorChild;
+
  public:
   TestFailedCtorChild() {}
   virtual ~TestFailedCtorChild() {}
 
  protected:
-  virtual PTestFailedCtorSubChild* AllocPTestFailedCtorSubChild() override;
+  PTestFailedCtorSubChild* AllocPTestFailedCtorSubChild();
 
-  virtual mozilla::ipc::IPCResult AnswerPTestFailedCtorSubConstructor(
+  mozilla::ipc::IPCResult AnswerPTestFailedCtorSubConstructor(
       PTestFailedCtorSubChild* actor) override;
 
-  virtual bool DeallocPTestFailedCtorSubChild(
-      PTestFailedCtorSubChild* actor) override;
+  bool DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* actor);
 
   virtual void ProcessingError(Result aCode, const char* aReason) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have _exit()ed");
   }
 };
 
 //-----------------------------------------------------------------------------
 // First descendent
 //
 class TestFailedCtorSubsub;
 
 class TestFailedCtorSubParent : public PTestFailedCtorSubParent {
+  friend class PTestFailedCtorSubParent;
+
  public:
   TestFailedCtorSubParent() : mOne(nullptr), mTwo(nullptr), mThree(nullptr) {}
   virtual ~TestFailedCtorSubParent();
 
  protected:
-  virtual PTestFailedCtorSubsubParent* AllocPTestFailedCtorSubsubParent()
-      override;
+  PTestFailedCtorSubsubParent* AllocPTestFailedCtorSubsubParent();
 
-  virtual bool DeallocPTestFailedCtorSubsubParent(
-      PTestFailedCtorSubsubParent* actor) override;
-  virtual mozilla::ipc::IPCResult RecvSync() override { return IPC_OK(); }
+  bool DeallocPTestFailedCtorSubsubParent(PTestFailedCtorSubsubParent* actor);
+  mozilla::ipc::IPCResult RecvSync() { return IPC_OK(); }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   TestFailedCtorSubsub* mOne;
   TestFailedCtorSubsub* mTwo;
   TestFailedCtorSubsub* mThree;
 };
 
 class TestFailedCtorSubChild : public PTestFailedCtorSubChild {
+  friend class PTestFailedCtorSubChild;
+
  public:
   TestFailedCtorSubChild() {}
   virtual ~TestFailedCtorSubChild() {}
 
  protected:
-  virtual PTestFailedCtorSubsubChild* AllocPTestFailedCtorSubsubChild()
-      override;
-  virtual bool DeallocPTestFailedCtorSubsubChild(
-      PTestFailedCtorSubsubChild* actor) override;
+  PTestFailedCtorSubsubChild* AllocPTestFailedCtorSubsubChild();
+  bool DeallocPTestFailedCtorSubsubChild(PTestFailedCtorSubsubChild* actor);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
 // Grand-descendent
 //
 class TestFailedCtorSubsub : public PTestFailedCtorSubsubParent,
--- a/ipc/ipdl/test/cxx/TestHangs.h
+++ b/ipc/ipdl/test/cxx/TestHangs.h
@@ -5,64 +5,68 @@
 
 #include "mozilla/_ipdltest/PTestHangsParent.h"
 #include "mozilla/_ipdltest/PTestHangsChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestHangsParent : public PTestHangsParent {
+  friend class PTestHangsParent;
+
  public:
   TestHangsParent();
   virtual ~TestHangsParent();
 
   static bool RunTestInProcesses() { return true; }
 
   // FIXME/bug 703320 Disabled because parent kills child proc, not
   //                  clear how that should work in threads.
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
   virtual bool ShouldContinueFromReplyTimeout() override;
 
-  virtual mozilla::ipc::IPCResult RecvNonce() override { return IPC_OK(); }
+  mozilla::ipc::IPCResult RecvNonce() { return IPC_OK(); }
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   void CleanUp();
 
   bool mDetectedHang;
   int32_t mNumAnswerStackFrame;
 };
 
 class TestHangsChild : public PTestHangsChild {
+  friend class PTestHangsChild;
+
  public:
   TestHangsChild();
   virtual ~TestHangsChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override {
+  mozilla::ipc::IPCResult RecvStart() {
     if (!SendNonce()) fail("sending Nonce");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override {
+  mozilla::ipc::IPCResult AnswerStackFrame() {
     if (CallStackFrame()) fail("should have failed");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerHang() override;
+  mozilla::ipc::IPCResult AnswerHang();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestHighestPrio.h
+++ b/ipc/ipdl/test/cxx/TestHighestPrio.h
@@ -14,20 +14,20 @@ class TestHighestPrioParent : public PTe
   TestHighestPrioParent();
   virtual ~TestHighestPrioParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  mozilla::ipc::IPCResult RecvMsg1() override;
-  mozilla::ipc::IPCResult RecvMsg2() override;
-  mozilla::ipc::IPCResult RecvMsg3() override;
-  mozilla::ipc::IPCResult RecvMsg4() override;
+  mozilla::ipc::IPCResult RecvMsg1();
+  mozilla::ipc::IPCResult RecvMsg2();
+  mozilla::ipc::IPCResult RecvMsg3();
+  mozilla::ipc::IPCResult RecvMsg4();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     if (msg_num_ != 4) fail("missed IPC call");
     passed("ok");
     QuitParent();
   }
 
@@ -35,18 +35,18 @@ class TestHighestPrioParent : public PTe
   int msg_num_;
 };
 
 class TestHighestPrioChild : public PTestHighestPrioChild {
  public:
   TestHighestPrioChild();
   virtual ~TestHighestPrioChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
-  mozilla::ipc::IPCResult RecvStartInner() override;
+  mozilla::ipc::IPCResult RecvStart();
+  mozilla::ipc::IPCResult RecvStartInner();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestInterruptErrorCleanup.h
+++ b/ipc/ipdl/test/cxx/TestInterruptErrorCleanup.h
@@ -27,22 +27,24 @@ class TestInterruptErrorCleanupParent
   }
 
   virtual void ProcessingError(Result aCode, const char* aReason) override;
 
   bool mGotProcessingError;
 };
 
 class TestInterruptErrorCleanupChild : public PTestInterruptErrorCleanupChild {
+  friend class PTestInterruptErrorCleanupChild;
+
  public:
   TestInterruptErrorCleanupChild();
   virtual ~TestInterruptErrorCleanupChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerError() override;
+  mozilla::ipc::IPCResult AnswerError();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have 'crashed'!");
   }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestInterruptRaces.h
+++ b/ipc/ipdl/test/cxx/TestInterruptRaces.h
@@ -9,41 +9,42 @@
 namespace mozilla {
 namespace _ipdltest {
 
 mozilla::ipc::RacyInterruptPolicy MediateRace(
     const mozilla::ipc::MessageChannel::MessageInfo& parent,
     const mozilla::ipc::MessageChannel::MessageInfo& child);
 
 class TestInterruptRacesParent : public PTestInterruptRacesParent {
+  friend class PTestInterruptRacesParent;
+
  public:
   TestInterruptRacesParent()
       : mHasReply(false), mChildHasReply(false), mAnsweredParent(false) {}
   virtual ~TestInterruptRacesParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
+  mozilla::ipc::IPCResult RecvStartRace();
 
-  virtual mozilla::ipc::IPCResult AnswerRace(bool* hasRace) override;
+  mozilla::ipc::IPCResult AnswerRace(bool* hasRace);
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame3() override;
+  mozilla::ipc::IPCResult AnswerStackFrame3();
 
-  virtual mozilla::ipc::IPCResult AnswerParent() override;
+  mozilla::ipc::IPCResult AnswerParent();
 
-  virtual mozilla::ipc::IPCResult RecvGetAnsweredParent(
-      bool* answeredParent) override;
+  mozilla::ipc::IPCResult RecvGetAnsweredParent(bool* answeredParent);
 
-  virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
+  mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override {
     return MediateRace(parent, child);
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     if (!(mHasReply && mChildHasReply)) fail("both sides should have replies!");
     passed("ok");
@@ -57,34 +58,36 @@ class TestInterruptRacesParent : public 
   void Test3();
 
   bool mHasReply;
   bool mChildHasReply;
   bool mAnsweredParent;
 };
 
 class TestInterruptRacesChild : public PTestInterruptRacesChild {
+  friend class PTestInterruptRacesChild;
+
  public:
   TestInterruptRacesChild() : mHasReply(false) {}
   virtual ~TestInterruptRacesChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerRace(bool* hasRace) override;
+  mozilla::ipc::IPCResult AnswerRace(bool* hasRace);
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame3() override;
+  mozilla::ipc::IPCResult AnswerStackFrame3();
 
-  virtual mozilla::ipc::IPCResult RecvWakeup() override;
+  mozilla::ipc::IPCResult RecvWakeup();
 
-  virtual mozilla::ipc::IPCResult RecvWakeup3() override;
+  mozilla::ipc::IPCResult RecvWakeup3();
 
-  virtual mozilla::ipc::IPCResult AnswerChild() override;
+  mozilla::ipc::IPCResult AnswerChild();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override {
     return MediateRace(parent, child);
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
--- a/ipc/ipdl/test/cxx/TestInterruptShutdownRace.h
+++ b/ipc/ipdl/test/cxx/TestInterruptShutdownRace.h
@@ -16,37 +16,39 @@ class TestInterruptShutdownRaceParent
   virtual ~TestInterruptShutdownRaceParent();
 
   static bool RunTestInProcesses() { return true; }
   // FIXME/bug 703323 Could work if modified
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  virtual mozilla::ipc::IPCResult RecvStartDeath() override;
+  mozilla::ipc::IPCResult RecvStartDeath();
 
-  virtual mozilla::ipc::IPCResult RecvOrphan() override;
+  mozilla::ipc::IPCResult RecvOrphan();
 
  protected:
   void StartShuttingDown();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
   }
 };
 
 class TestInterruptShutdownRaceChild : public PTestInterruptShutdownRaceChild {
+  friend class PTestInterruptShutdownRaceChild;
+
  public:
   TestInterruptShutdownRaceChild();
   virtual ~TestInterruptShutdownRaceChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerExit() override;
+  mozilla::ipc::IPCResult AnswerExit();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have 'crashed'!");
   }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestJSON.h
+++ b/ipc/ipdl/test/cxx/TestJSON.h
@@ -17,34 +17,35 @@ class TestHandleParent : public PTestHan
   TestHandleParent() {}
   virtual ~TestHandleParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestJSONParent : public PTestJSONParent {
+  friend class PTestJSONParent;
+
  public:
   TestJSONParent() {}
   virtual ~TestJSONParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvTest(const JSONVariant& i,
-                                           JSONVariant* o) override;
+  mozilla::ipc::IPCResult RecvTest(const JSONVariant& i, JSONVariant* o);
 
-  virtual PTestHandleParent* AllocPTestHandleParent() override {
+  PTestHandleParent* AllocPTestHandleParent() {
     return mKid = new TestHandleParent();
   }
 
-  virtual bool DeallocPTestHandleParent(PTestHandleParent* actor) override {
+  bool DeallocPTestHandleParent(PTestHandleParent* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
@@ -55,28 +56,30 @@ class TestJSONParent : public PTestJSONP
 
 class TestHandleChild : public PTestHandleChild {
  public:
   TestHandleChild() {}
   virtual ~TestHandleChild() {}
 };
 
 class TestJSONChild : public PTestJSONChild {
+  friend class PTestJSONChild;
+
  public:
   TestJSONChild() {}
   virtual ~TestJSONChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual PTestHandleChild* AllocPTestHandleChild() override {
+  PTestHandleChild* AllocPTestHandleChild() {
     return mKid = new TestHandleChild();
   }
 
-  virtual bool DeallocPTestHandleChild(PTestHandleChild* actor) override {
+  bool DeallocPTestHandleChild(PTestHandleChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestLatency.h
+++ b/ipc/ipdl/test/cxx/TestLatency.h
@@ -10,32 +10,34 @@
 
 #define NR_TRIALS 10000
 #define NR_SPAMS 25000
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestLatencyParent : public PTestLatencyParent {
+  friend class PTestLatencyParent;
+
  private:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
  public:
   TestLatencyParent();
   virtual ~TestLatencyParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPong() override;
-  virtual mozilla::ipc::IPCResult RecvPong5() override;
+  mozilla::ipc::IPCResult RecvPong();
+  mozilla::ipc::IPCResult RecvPong5();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
 
     passed(
         "\n"
         "  average #ping-pong/sec:        %g\n"
         "  average #ping5-pong5/sec:      %g\n"
@@ -68,30 +70,31 @@ class TestLatencyParent : public PTestLa
 
   int mPPTrialsToGo;
   int mPP5TrialsToGo;
   uint32_t mNumChildProcessedCompressedSpams;
   uint32_t mWhichPong5;
 };
 
 class TestLatencyChild : public PTestLatencyChild {
+  friend class PTestLatencyChild;
+
  public:
   TestLatencyChild();
   virtual ~TestLatencyChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPing() override;
-  virtual mozilla::ipc::IPCResult RecvPing5() override;
-  virtual mozilla::ipc::IPCResult AnswerRpc() override;
-  virtual mozilla::ipc::IPCResult RecvSpam() override;
-  virtual mozilla::ipc::IPCResult AnswerSynchro() override;
-  virtual mozilla::ipc::IPCResult RecvCompressedSpam(
-      const uint32_t& seqno) override;
-  virtual mozilla::ipc::IPCResult AnswerSynchro2(
-      uint32_t* lastSeqno, uint32_t* numMessagesDispatched) override;
+  mozilla::ipc::IPCResult RecvPing();
+  mozilla::ipc::IPCResult RecvPing5();
+  mozilla::ipc::IPCResult AnswerRpc();
+  mozilla::ipc::IPCResult RecvSpam();
+  mozilla::ipc::IPCResult AnswerSynchro();
+  mozilla::ipc::IPCResult RecvCompressedSpam(const uint32_t& seqno);
+  mozilla::ipc::IPCResult AnswerSynchro2(uint32_t* lastSeqno,
+                                         uint32_t* numMessagesDispatched);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
   uint32_t mLastSeqno;
   uint32_t mNumProcessedCompressedSpams;
--- a/ipc/ipdl/test/cxx/TestManyChildAllocs.h
+++ b/ipc/ipdl/test/cxx/TestManyChildAllocs.h
@@ -10,67 +10,69 @@
 #include "mozilla/_ipdltest/PTestManyChildAllocsSubChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 // top-level protocol
 
 class TestManyChildAllocsParent : public PTestManyChildAllocsParent {
+  friend class PTestManyChildAllocsParent;
+
  public:
   TestManyChildAllocsParent();
   virtual ~TestManyChildAllocsParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvDone() override;
-  virtual bool DeallocPTestManyChildAllocsSubParent(
-      PTestManyChildAllocsSubParent* __a) override;
-  virtual PTestManyChildAllocsSubParent* AllocPTestManyChildAllocsSubParent()
-      override;
+  mozilla::ipc::IPCResult RecvDone();
+  bool DeallocPTestManyChildAllocsSubParent(PTestManyChildAllocsSubParent* __a);
+  PTestManyChildAllocsSubParent* AllocPTestManyChildAllocsSubParent();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestManyChildAllocsChild : public PTestManyChildAllocsChild {
+  friend class PTestManyChildAllocsChild;
+
  public:
   TestManyChildAllocsChild();
   virtual ~TestManyChildAllocsChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvGo() override;
-  virtual bool DeallocPTestManyChildAllocsSubChild(
-      PTestManyChildAllocsSubChild* __a) override;
-  virtual PTestManyChildAllocsSubChild* AllocPTestManyChildAllocsSubChild()
-      override;
+  mozilla::ipc::IPCResult RecvGo();
+  bool DeallocPTestManyChildAllocsSubChild(PTestManyChildAllocsSubChild* __a);
+  PTestManyChildAllocsSubChild* AllocPTestManyChildAllocsSubChild();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 // do-nothing sub-protocol actors
 
 class TestManyChildAllocsSubParent : public PTestManyChildAllocsSubParent {
+  friend class PTestManyChildAllocsSubParent;
+
  public:
   TestManyChildAllocsSubParent() {}
   virtual ~TestManyChildAllocsSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
-  virtual mozilla::ipc::IPCResult RecvHello() override { return IPC_OK(); }
+  mozilla::ipc::IPCResult RecvHello() { return IPC_OK(); }
 };
 
 class TestManyChildAllocsSubChild : public PTestManyChildAllocsSubChild {
  public:
   TestManyChildAllocsSubChild() {}
   virtual ~TestManyChildAllocsSubChild() {}
 };
 
--- a/ipc/ipdl/test/cxx/TestMultiMgrs.h
+++ b/ipc/ipdl/test/cxx/TestMultiMgrs.h
@@ -24,92 +24,92 @@ class TestMultiMgrsBottomParent : public
   TestMultiMgrsBottomParent() {}
   virtual ~TestMultiMgrsBottomParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestMultiMgrsLeftParent : public PTestMultiMgrsLeftParent {
+  friend class PTestMultiMgrsLeftParent;
+
  public:
   TestMultiMgrsLeftParent() {}
   virtual ~TestMultiMgrsLeftParent() {}
 
   bool HasChild(TestMultiMgrsBottomParent* c) {
     return ManagedPTestMultiMgrsBottomParent().Contains(c);
   }
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 
-  virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent()
-      override {
+  PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() {
     return new TestMultiMgrsBottomParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomParent(
-      PTestMultiMgrsBottomParent* actor) override {
+  bool DeallocPTestMultiMgrsBottomParent(PTestMultiMgrsBottomParent* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsRightParent : public PTestMultiMgrsRightParent {
+  friend class PTestMultiMgrsRightParent;
+
  public:
   TestMultiMgrsRightParent() {}
   virtual ~TestMultiMgrsRightParent() {}
 
   bool HasChild(TestMultiMgrsBottomParent* c) {
     return ManagedPTestMultiMgrsBottomParent().Contains(c);
   }
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 
-  virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent()
-      override {
+  PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() {
     return new TestMultiMgrsBottomParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomParent(
-      PTestMultiMgrsBottomParent* actor) override {
+  bool DeallocPTestMultiMgrsBottomParent(PTestMultiMgrsBottomParent* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsParent : public PTestMultiMgrsParent {
+  friend class PTestMultiMgrsParent;
+
  public:
   TestMultiMgrsParent() {}
   virtual ~TestMultiMgrsParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvOK() override;
+  mozilla::ipc::IPCResult RecvOK();
 
-  virtual PTestMultiMgrsLeftParent* AllocPTestMultiMgrsLeftParent() override {
+  PTestMultiMgrsLeftParent* AllocPTestMultiMgrsLeftParent() {
     return new TestMultiMgrsLeftParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsLeftParent(
-      PTestMultiMgrsLeftParent* actor) override {
+  bool DeallocPTestMultiMgrsLeftParent(PTestMultiMgrsLeftParent* actor) {
     delete actor;
     return true;
   }
 
-  virtual PTestMultiMgrsRightParent* AllocPTestMultiMgrsRightParent() override {
+  PTestMultiMgrsRightParent* AllocPTestMultiMgrsRightParent() {
     return new TestMultiMgrsRightParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsRightParent(
-      PTestMultiMgrsRightParent* actor) override {
+  bool DeallocPTestMultiMgrsRightParent(PTestMultiMgrsRightParent* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
@@ -122,92 +122,94 @@ class TestMultiMgrsParent : public PTest
 
 class TestMultiMgrsBottomChild : public PTestMultiMgrsBottomChild {
  public:
   TestMultiMgrsBottomChild() {}
   virtual ~TestMultiMgrsBottomChild() {}
 };
 
 class TestMultiMgrsLeftChild : public PTestMultiMgrsLeftChild {
+  friend class PTestMultiMgrsLeftChild;
+
  public:
   TestMultiMgrsLeftChild() {}
   virtual ~TestMultiMgrsLeftChild() {}
 
   bool HasChild(PTestMultiMgrsBottomChild* c) {
     return ManagedPTestMultiMgrsBottomChild().Contains(c);
   }
 
  protected:
   virtual mozilla::ipc::IPCResult RecvPTestMultiMgrsBottomConstructor(
       PTestMultiMgrsBottomChild* actor) override;
 
-  virtual PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() override {
+  PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() {
     return new TestMultiMgrsBottomChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomChild(
-      PTestMultiMgrsBottomChild* actor) override {
+  bool DeallocPTestMultiMgrsBottomChild(PTestMultiMgrsBottomChild* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsRightChild : public PTestMultiMgrsRightChild {
+  friend class PTestMultiMgrsRightChild;
+
  public:
   TestMultiMgrsRightChild() {}
   virtual ~TestMultiMgrsRightChild() {}
 
   bool HasChild(PTestMultiMgrsBottomChild* c) {
     return ManagedPTestMultiMgrsBottomChild().Contains(c);
   }
 
  protected:
   virtual mozilla::ipc::IPCResult RecvPTestMultiMgrsBottomConstructor(
       PTestMultiMgrsBottomChild* actor) override;
 
-  virtual PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() override {
+  PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() {
     return new TestMultiMgrsBottomChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomChild(
-      PTestMultiMgrsBottomChild* actor) override {
+  bool DeallocPTestMultiMgrsBottomChild(PTestMultiMgrsBottomChild* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsChild : public PTestMultiMgrsChild {
+  friend class PTestMultiMgrsChild;
+
  public:
   TestMultiMgrsChild() {}
   virtual ~TestMultiMgrsChild() {}
 
   void Main();
 
   PTestMultiMgrsBottomChild* mBottomL;
   PTestMultiMgrsBottomChild* mBottomR;
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvCheck() override;
+  mozilla::ipc::IPCResult RecvCheck();
 
-  virtual PTestMultiMgrsLeftChild* AllocPTestMultiMgrsLeftChild() override {
+  PTestMultiMgrsLeftChild* AllocPTestMultiMgrsLeftChild() {
     return new TestMultiMgrsLeftChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsLeftChild(
-      PTestMultiMgrsLeftChild* actor) override {
+  bool DeallocPTestMultiMgrsLeftChild(PTestMultiMgrsLeftChild* actor) {
     delete actor;
     return true;
   }
 
-  virtual PTestMultiMgrsRightChild* AllocPTestMultiMgrsRightChild() override {
+  PTestMultiMgrsRightChild* AllocPTestMultiMgrsRightChild() {
     return new TestMultiMgrsRightChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsRightChild(
-      PTestMultiMgrsRightChild* actor) override {
+  bool DeallocPTestMultiMgrsRightChild(PTestMultiMgrsRightChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitChild();
--- a/ipc/ipdl/test/cxx/TestNestedLoops.h
+++ b/ipc/ipdl/test/cxx/TestNestedLoops.h
@@ -5,48 +5,52 @@
 
 #include "mozilla/_ipdltest/PTestNestedLoopsParent.h"
 #include "mozilla/_ipdltest/PTestNestedLoopsChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestNestedLoopsParent : public PTestNestedLoopsParent {
+  friend class PTestNestedLoopsParent;
+
  public:
   TestNestedLoopsParent();
   virtual ~TestNestedLoopsParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvNonce() override;
+  mozilla::ipc::IPCResult RecvNonce();
 
   void BreakNestedLoop();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   bool mBreakNestedLoop;
 };
 
 class TestNestedLoopsChild : public PTestNestedLoopsChild {
+  friend class PTestNestedLoopsChild;
+
  public:
   TestNestedLoopsChild();
   virtual ~TestNestedLoopsChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerR() override;
+  mozilla::ipc::IPCResult AnswerR();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestOffMainThreadPainting.h
+++ b/ipc/ipdl/test/cxx/TestOffMainThreadPainting.h
@@ -21,20 +21,20 @@ class TestOffMainThreadPaintingParent fi
   static bool RunTestInThreads() { return false; }
   static bool RunTestInProcesses() { return true; }
 
   void Main();
 
   MOZ_IMPLICIT TestOffMainThreadPaintingParent();
   ~TestOffMainThreadPaintingParent() override;
 
-  ipc::IPCResult RecvFinishedLayout(const uint64_t& aTxnId) override;
-  ipc::IPCResult RecvAsyncMessage(const uint64_t& aTxnId) override;
-  ipc::IPCResult RecvSyncMessage(const uint64_t& aTxnId) override;
-  ipc::IPCResult RecvEndTest() override;
+  ipc::IPCResult RecvFinishedLayout(const uint64_t& aTxnId);
+  ipc::IPCResult RecvAsyncMessage(const uint64_t& aTxnId);
+  ipc::IPCResult RecvSyncMessage(const uint64_t& aTxnId);
+  ipc::IPCResult RecvEndTest();
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void NotifyFinishedPaint(const uint64_t& aTxnId);
 
  private:
   RefPtr<TestPaintThreadParent> mPaintActor;
   Maybe<uint64_t> mCompletedTxn;
   Maybe<uint64_t> mPaintedTxn;
@@ -44,17 +44,17 @@ class TestOffMainThreadPaintingParent fi
 
 // Analagous to LayerTransactionChild.
 class TestOffMainThreadPaintingChild final : public PTestLayoutThreadChild {
  public:
   TestOffMainThreadPaintingChild();
   ~TestOffMainThreadPaintingChild() override;
 
   ipc::IPCResult RecvStartTest(
-      ipc::Endpoint<PTestPaintThreadChild>&& aEndpoint) override;
+      ipc::Endpoint<PTestPaintThreadChild>&& aEndpoint);
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void ProcessingError(Result aCode, const char* aReason) override;
 
  private:
   void IssueTransaction();
 
  private:
   UniquePtr<base::Thread> mPaintThread;
@@ -68,17 +68,17 @@ class TestOffMainThreadPaintingChild fin
 
 class TestPaintThreadParent final : public PTestPaintThreadParent {
  public:
   explicit TestPaintThreadParent(TestOffMainThreadPaintingParent* aMainBridge);
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestPaintThreadParent);
 
   bool Bind(ipc::Endpoint<PTestPaintThreadParent>&& aEndpoint);
-  ipc::IPCResult RecvFinishedPaint(const uint64_t& aTxnId) override;
+  ipc::IPCResult RecvFinishedPaint(const uint64_t& aTxnId);
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeallocPTestPaintThreadParent() override;
 
  private:
   ~TestPaintThreadParent() override;
 
  private:
   TestOffMainThreadPaintingParent* mMainBridge;
--- a/ipc/ipdl/test/cxx/TestRPC.h
+++ b/ipc/ipdl/test/cxx/TestRPC.h
@@ -14,20 +14,20 @@ class TestRPCParent : public PTestRPCPar
   TestRPCParent();
   virtual ~TestRPCParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  mozilla::ipc::IPCResult RecvTest1_Start(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest1_InnerEvent(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest2_Start() override;
-  mozilla::ipc::IPCResult RecvTest2_OutOfOrder() override;
+  mozilla::ipc::IPCResult RecvTest1_Start(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest1_InnerEvent(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest2_Start();
+  mozilla::ipc::IPCResult RecvTest2_OutOfOrder();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     if (!reentered_) fail("never processed raced RPC call!");
     if (!resolved_first_cpow_) fail("never resolved first CPOW!");
     passed("ok");
     QuitParent();
   }
@@ -37,21 +37,21 @@ class TestRPCParent : public PTestRPCPar
   bool resolved_first_cpow_;
 };
 
 class TestRPCChild : public PTestRPCChild {
  public:
   TestRPCChild();
   virtual ~TestRPCChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
-  mozilla::ipc::IPCResult RecvTest1_InnerQuery(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest1_NoReenter(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest2_FirstUrgent() override;
-  mozilla::ipc::IPCResult RecvTest2_SecondUrgent() override;
+  mozilla::ipc::IPCResult RecvStart();
+  mozilla::ipc::IPCResult RecvTest1_InnerQuery(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest1_NoReenter(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest2_FirstUrgent();
+  mozilla::ipc::IPCResult RecvTest2_SecondUrgent();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestRaceDeadlock.h
+++ b/ipc/ipdl/test/cxx/TestRaceDeadlock.h
@@ -5,54 +5,58 @@
 
 #include "mozilla/_ipdltest/PTestRaceDeadlockParent.h"
 #include "mozilla/_ipdltest/PTestRaceDeadlockChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRaceDeadlockParent : public PTestRaceDeadlockParent {
+  friend class PTestRaceDeadlockParent;
+
  public:
   TestRaceDeadlockParent();
   virtual ~TestRaceDeadlockParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
   virtual bool ShouldContinueFromReplyTimeout() override;
 
   void Test1();
 
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
-  virtual mozilla::ipc::IPCResult AnswerLose() override;
+  mozilla::ipc::IPCResult RecvStartRace();
+  mozilla::ipc::IPCResult AnswerLose();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestRaceDeadlockChild : public PTestRaceDeadlockChild {
+  friend class PTestRaceDeadlockChild;
+
  public:
   TestRaceDeadlockChild();
   virtual ~TestRaceDeadlockChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
+  mozilla::ipc::IPCResult RecvStartRace();
 
-  virtual mozilla::ipc::IPCResult AnswerWin() override;
+  mozilla::ipc::IPCResult AnswerWin();
 
-  virtual mozilla::ipc::IPCResult AnswerRpc() override;
+  mozilla::ipc::IPCResult AnswerRpc();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestRaceDeferral.h
+++ b/ipc/ipdl/test/cxx/TestRaceDeferral.h
@@ -5,53 +5,57 @@
 
 #include "mozilla/_ipdltest/PTestRaceDeferralParent.h"
 #include "mozilla/_ipdltest/PTestRaceDeferralChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRaceDeferralParent : public PTestRaceDeferralParent {
+  friend class PTestRaceDeferralParent;
+
  public:
   TestRaceDeferralParent();
   virtual ~TestRaceDeferralParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
   void Test1();
 
-  virtual mozilla::ipc::IPCResult AnswerLose() override;
+  mozilla::ipc::IPCResult AnswerLose();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   bool mProcessedLose;
 };
 
 class TestRaceDeferralChild : public PTestRaceDeferralChild {
+  friend class PTestRaceDeferralChild;
+
  public:
   TestRaceDeferralChild();
   virtual ~TestRaceDeferralChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
+  mozilla::ipc::IPCResult RecvStartRace();
 
-  virtual mozilla::ipc::IPCResult AnswerWin() override;
+  mozilla::ipc::IPCResult AnswerWin();
 
-  virtual mozilla::ipc::IPCResult AnswerRpc() override;
+  mozilla::ipc::IPCResult AnswerRpc();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestRacyInterruptReplies.h
+++ b/ipc/ipdl/test/cxx/TestRacyInterruptReplies.h
@@ -5,51 +5,55 @@
 
 #include "mozilla/_ipdltest/PTestRacyInterruptRepliesParent.h"
 #include "mozilla/_ipdltest/PTestRacyInterruptRepliesChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRacyInterruptRepliesParent : public PTestRacyInterruptRepliesParent {
+  friend class PTestRacyInterruptRepliesParent;
+
  public:
   TestRacyInterruptRepliesParent();
   virtual ~TestRacyInterruptRepliesParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvA_() override;
+  mozilla::ipc::IPCResult RecvA_();
 
-  virtual mozilla::ipc::IPCResult Answer_R(int* replyNum) override;
+  mozilla::ipc::IPCResult Answer_R(int* replyNum);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
  private:
   int mReplyNum;
 };
 
 class TestRacyInterruptRepliesChild : public PTestRacyInterruptRepliesChild {
+  friend class PTestRacyInterruptRepliesChild;
+
  public:
   TestRacyInterruptRepliesChild();
   virtual ~TestRacyInterruptRepliesChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerR_(int* replyNum) override;
+  mozilla::ipc::IPCResult AnswerR_(int* replyNum);
 
-  virtual mozilla::ipc::IPCResult RecvChildTest() override;
+  mozilla::ipc::IPCResult RecvChildTest();
 
-  virtual mozilla::ipc::IPCResult Recv_A() override;
+  mozilla::ipc::IPCResult Recv_A();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
  private:
   int mReplyNum;
--- a/ipc/ipdl/test/cxx/TestRacyReentry.h
+++ b/ipc/ipdl/test/cxx/TestRacyReentry.h
@@ -5,48 +5,52 @@
 
 #include "mozilla/_ipdltest/PTestRacyReentryParent.h"
 #include "mozilla/_ipdltest/PTestRacyReentryChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRacyReentryParent : public PTestRacyReentryParent {
+  friend class PTestRacyReentryParent;
+
  public:
   TestRacyReentryParent();
   virtual ~TestRacyReentryParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerE() override;
+  mozilla::ipc::IPCResult AnswerE();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   bool mRecvdE;
 };
 
 class TestRacyReentryChild : public PTestRacyReentryChild {
+  friend class PTestRacyReentryChild;
+
  public:
   TestRacyReentryChild();
   virtual ~TestRacyReentryChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult RecvN() override;
+  mozilla::ipc::IPCResult RecvN();
 
-  virtual mozilla::ipc::IPCResult AnswerH() override;
+  mozilla::ipc::IPCResult AnswerH();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestRacyUndefer.h
+++ b/ipc/ipdl/test/cxx/TestRacyUndefer.h
@@ -5,51 +5,55 @@
 
 #include "mozilla/_ipdltest/PTestRacyUndeferParent.h"
 #include "mozilla/_ipdltest/PTestRacyUndeferChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRacyUndeferParent : public PTestRacyUndeferParent {
+  friend class PTestRacyUndeferParent;
+
  public:
   TestRacyUndeferParent();
   virtual ~TestRacyUndeferParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerSpam() override;
+  mozilla::ipc::IPCResult AnswerSpam();
 
-  virtual mozilla::ipc::IPCResult AnswerRaceWinTwice() override;
+  mozilla::ipc::IPCResult AnswerRaceWinTwice();
 
-  virtual mozilla::ipc::IPCResult RecvDone() override;
+  mozilla::ipc::IPCResult RecvDone();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestRacyUndeferChild : public PTestRacyUndeferChild {
+  friend class PTestRacyUndeferChild;
+
  public:
   TestRacyUndeferChild();
   virtual ~TestRacyUndeferChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult RecvAwakenSpam() override;
-  virtual mozilla::ipc::IPCResult RecvAwakenRaceWinTwice() override;
+  mozilla::ipc::IPCResult RecvAwakenSpam();
+  mozilla::ipc::IPCResult RecvAwakenRaceWinTwice();
 
-  virtual mozilla::ipc::IPCResult AnswerRace() override;
+  mozilla::ipc::IPCResult AnswerRace();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestSanity.h
+++ b/ipc/ipdl/test/cxx/TestSanity.h
@@ -5,46 +5,48 @@
 
 #include "mozilla/_ipdltest/PTestSanityParent.h"
 #include "mozilla/_ipdltest/PTestSanityChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestSanityParent : public PTestSanityParent {
+  friend class PTestSanityParent;
+
  public:
   TestSanityParent();
   virtual ~TestSanityParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPong(const int& one,
-                                           const float& zeroPtTwoFive,
-                                           const uint8_t& dummy) override;
+  mozilla::ipc::IPCResult RecvPong(const int& one, const float& zeroPtTwoFive,
+                                   const uint8_t& dummy);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSanityChild : public PTestSanityChild {
+  friend class PTestSanityChild;
+
  public:
   TestSanityChild();
   virtual ~TestSanityChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPing(const int& zero,
-                                           const float& zeroPtFive,
-                                           const int8_t& dummy) override;
+  mozilla::ipc::IPCResult RecvPing(const int& zero, const float& zeroPtFive,
+                                   const int8_t& dummy);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestSelfManageRoot.h
+++ b/ipc/ipdl/test/cxx/TestSelfManageRoot.h
@@ -10,98 +10,102 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Parent side
 
 class TestSelfManageParent : public PTestSelfManageParent {
+  friend class PTestSelfManageParent;
+
  public:
   TestSelfManageParent() { MOZ_COUNT_CTOR(TestSelfManageParent); }
   virtual ~TestSelfManageParent() { MOZ_COUNT_DTOR(TestSelfManageParent); }
 
   ActorDestroyReason mWhy;
 
  protected:
-  virtual PTestSelfManageParent* AllocPTestSelfManageParent() override {
+  PTestSelfManageParent* AllocPTestSelfManageParent() {
     return new TestSelfManageParent();
   }
 
-  virtual bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) override {
-    return true;
-  }
+  bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) { return true; }
 
   virtual void ActorDestroy(ActorDestroyReason why) override { mWhy = why; }
 };
 
 class TestSelfManageRootParent : public PTestSelfManageRootParent {
+  friend class PTestSelfManageRootParent;
+
  public:
   TestSelfManageRootParent() { MOZ_COUNT_CTOR(TestSelfManageRootParent); }
   virtual ~TestSelfManageRootParent() {
     MOZ_COUNT_DTOR(TestSelfManageRootParent);
   }
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual PTestSelfManageParent* AllocPTestSelfManageParent() override {
+  PTestSelfManageParent* AllocPTestSelfManageParent() {
     return new TestSelfManageParent();
   }
 
-  virtual bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) override {
-    return true;
-  }
+  bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) { return true; }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 //-----------------------------------------------------------------------------
 // Child side
 
 class TestSelfManageChild : public PTestSelfManageChild {
+  friend class PTestSelfManageChild;
+
  public:
   TestSelfManageChild() { MOZ_COUNT_CTOR(TestSelfManageChild); }
   virtual ~TestSelfManageChild() { MOZ_COUNT_DTOR(TestSelfManageChild); }
 
  protected:
-  virtual PTestSelfManageChild* AllocPTestSelfManageChild() override {
+  PTestSelfManageChild* AllocPTestSelfManageChild() {
     return new TestSelfManageChild();
   }
 
-  virtual bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) override {
+  bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) {
     delete a;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestSelfManageRootChild : public PTestSelfManageRootChild {
+  friend class PTestSelfManageRootChild;
+
  public:
   TestSelfManageRootChild() { MOZ_COUNT_CTOR(TestSelfManageRootChild); }
   virtual ~TestSelfManageRootChild() {
     MOZ_COUNT_DTOR(TestSelfManageRootChild);
   }
 
   void Main();
 
  protected:
-  virtual PTestSelfManageChild* AllocPTestSelfManageChild() override {
+  PTestSelfManageChild* AllocPTestSelfManageChild() {
     return new TestSelfManageChild();
   }
 
-  virtual bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) override {
+  bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) {
     delete a;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestShmem.h
+++ b/ipc/ipdl/test/cxx/TestShmem.h
@@ -5,44 +5,48 @@
 
 #include "mozilla/_ipdltest/PTestShmemParent.h"
 #include "mozilla/_ipdltest/PTestShmemChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestShmemParent : public PTestShmemParent {
+  friend class PTestShmemParent;
+
  public:
   TestShmemParent() {}
   virtual ~TestShmemParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvTake(Shmem&& mem, Shmem&& unsafe,
-                                           const size_t& expectedSize) override;
+  mozilla::ipc::IPCResult RecvTake(Shmem&& mem, Shmem&& unsafe,
+                                   const size_t& expectedSize);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestShmemChild : public PTestShmemChild {
+  friend class PTestShmemChild;
+
  public:
   TestShmemChild() {}
   virtual ~TestShmemChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvGive(Shmem&& mem, Shmem&& unsafe,
-                                           const size_t& expectedSize) override;
+  mozilla::ipc::IPCResult RecvGive(Shmem&& mem, Shmem&& unsafe,
+                                   const size_t& expectedSize);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestShutdown.h
+++ b/ipc/ipdl/test/cxx/TestShutdown.h
@@ -28,72 +28,73 @@ class TestShutdownSubsubParent : public 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectParentDeleted;
 };
 
 class TestShutdownSubParent : public PTestShutdownSubParent {
+  friend class PTestShutdownSubParent;
+
  public:
   explicit TestShutdownSubParent(bool expectCrash)
       : mExpectCrash(expectCrash), mDeletedCount(0) {}
 
   virtual ~TestShutdownSubParent() {
     if (2 != mDeletedCount) fail("managees outliving manager!");
   }
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override {
+  mozilla::ipc::IPCResult AnswerStackFrame() {
     if (!CallStackFrame()) {
       return IPC_FAIL_NO_REASON(this);
     }
     return IPC_OK();
   }
 
-  virtual PTestShutdownSubsubParent* AllocPTestShutdownSubsubParent(
-      const bool& expectParentDelete) override {
+  PTestShutdownSubsubParent* AllocPTestShutdownSubsubParent(
+      const bool& expectParentDelete) {
     return new TestShutdownSubsubParent(expectParentDelete);
   }
 
-  virtual bool DeallocPTestShutdownSubsubParent(
-      PTestShutdownSubsubParent* actor) override {
+  bool DeallocPTestShutdownSubsubParent(PTestShutdownSubsubParent* actor) {
     delete actor;
     ++mDeletedCount;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectCrash;
   int mDeletedCount;
 };
 
 class TestShutdownParent : public PTestShutdownParent {
+  friend class PTestShutdownParent;
+
  public:
   TestShutdownParent() {}
   virtual ~TestShutdownParent() {}
 
   static bool RunTestInProcesses() { return true; }
   // FIXME/bug 703323 Could work if modified
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvSync() override { return IPC_OK(); }
+  mozilla::ipc::IPCResult RecvSync() { return IPC_OK(); }
 
-  virtual PTestShutdownSubParent* AllocPTestShutdownSubParent(
-      const bool& expectCrash) override {
+  PTestShutdownSubParent* AllocPTestShutdownSubParent(const bool& expectCrash) {
     return new TestShutdownSubParent(expectCrash);
   }
 
-  virtual bool DeallocPTestShutdownSubParent(
-      PTestShutdownSubParent* actor) override {
+  bool DeallocPTestShutdownSubParent(PTestShutdownSubParent* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
@@ -108,56 +109,57 @@ class TestShutdownSubsubChild : public P
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectParentDeleted;
 };
 
 class TestShutdownSubChild : public PTestShutdownSubChild {
+  friend class PTestShutdownSubChild;
+
  public:
   explicit TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash) {}
 
   virtual ~TestShutdownSubChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual PTestShutdownSubsubChild* AllocPTestShutdownSubsubChild(
-      const bool& expectParentDelete) override {
+  PTestShutdownSubsubChild* AllocPTestShutdownSubsubChild(
+      const bool& expectParentDelete) {
     return new TestShutdownSubsubChild(expectParentDelete);
   }
 
-  virtual bool DeallocPTestShutdownSubsubChild(
-      PTestShutdownSubsubChild* actor) override {
+  bool DeallocPTestShutdownSubsubChild(PTestShutdownSubsubChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectCrash;
 };
 
 class TestShutdownChild : public PTestShutdownChild {
+  friend class PTestShutdownChild;
+
  public:
   TestShutdownChild() {}
   virtual ~TestShutdownChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual PTestShutdownSubChild* AllocPTestShutdownSubChild(
-      const bool& expectCrash) override {
+  PTestShutdownSubChild* AllocPTestShutdownSubChild(const bool& expectCrash) {
     return new TestShutdownSubChild(expectCrash);
   }
 
-  virtual bool DeallocPTestShutdownSubChild(
-      PTestShutdownSubChild* actor) override {
+  bool DeallocPTestShutdownSubChild(PTestShutdownSubChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestStackHooks.h
+++ b/ipc/ipdl/test/cxx/TestStackHooks.h
@@ -5,42 +5,44 @@
 
 #include "mozilla/_ipdltest/PTestStackHooksParent.h"
 #include "mozilla/_ipdltest/PTestStackHooksChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestStackHooksParent : public PTestStackHooksParent {
+  friend class PTestStackHooksParent;
+
  public:
   TestStackHooksParent();
   virtual ~TestStackHooksParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvAsync() override {
+  mozilla::ipc::IPCResult RecvAsync() {
     if (!mOnStack) fail("not on C++ stack?!");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult RecvSync() override {
+  mozilla::ipc::IPCResult RecvSync() {
     if (!mOnStack) fail("not on C++ stack?!");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerRpc() override {
+  mozilla::ipc::IPCResult AnswerRpc() {
     if (!mOnStack) fail("not on C++ stack?!");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   virtual void EnteredCxxStack() override { mOnStack = true; }
@@ -50,26 +52,28 @@ class TestStackHooksParent : public PTes
   virtual void ExitedCall() override { --mIncallDepth; }
 
  private:
   bool mOnStack;
   int mIncallDepth;
 };
 
 class TestStackHooksChild : public PTestStackHooksChild {
+  friend class PTestStackHooksChild;
+
  public:
   TestStackHooksChild();
   virtual ~TestStackHooksChild();
 
   void RunTests();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
 
     if (mEntered != mExited) fail("unbalanced enter/exit notifications");
 
     if (mOnStack)
       fail("computing mOnStack went awry; should have failed above assertion");
--- a/ipc/ipdl/test/cxx/TestSyncError.h
+++ b/ipc/ipdl/test/cxx/TestSyncError.h
@@ -5,46 +5,50 @@
 
 #include "mozilla/_ipdltest/PTestSyncErrorParent.h"
 #include "mozilla/_ipdltest/PTestSyncErrorChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestSyncErrorParent : public PTestSyncErrorParent {
+  friend class PTestSyncErrorParent;
+
  public:
   TestSyncErrorParent();
   virtual ~TestSyncErrorParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvError() override;
+  mozilla::ipc::IPCResult RecvError();
 
   virtual void ProcessingError(Result aCode, const char* aReason) override {
     // Ignore errors
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSyncErrorChild : public PTestSyncErrorChild {
+  friend class PTestSyncErrorChild;
+
  public:
   TestSyncErrorChild();
   virtual ~TestSyncErrorChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ProcessingError(Result aCode, const char* aReason) override {
     // Ignore errors
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
--- a/ipc/ipdl/test/cxx/TestSyncHang.h
+++ b/ipc/ipdl/test/cxx/TestSyncHang.h
@@ -24,22 +24,24 @@ class TestSyncHangParent : public PTestS
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSyncHangChild : public PTestSyncHangChild {
+  friend class PTestSyncHangChild;
+
  public:
   TestSyncHangChild();
   virtual ~TestSyncHangChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvUnusedMessage() override;
+  mozilla::ipc::IPCResult RecvUnusedMessage();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestSyncWakeup.h
+++ b/ipc/ipdl/test/cxx/TestSyncWakeup.h
@@ -5,52 +5,56 @@
 
 #include "mozilla/_ipdltest/PTestSyncWakeupParent.h"
 #include "mozilla/_ipdltest/PTestSyncWakeupChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestSyncWakeupParent : public PTestSyncWakeupParent {
+  friend class PTestSyncWakeupParent;
+
  public:
   TestSyncWakeupParent();
   virtual ~TestSyncWakeupParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult RecvSync1() override;
+  mozilla::ipc::IPCResult RecvSync1();
 
-  virtual mozilla::ipc::IPCResult RecvSync2() override;
+  mozilla::ipc::IPCResult RecvSync2();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSyncWakeupChild : public PTestSyncWakeupChild {
+  friend class PTestSyncWakeupChild;
+
  public:
   TestSyncWakeupChild();
   virtual ~TestSyncWakeupChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult RecvNote1() override;
+  mozilla::ipc::IPCResult RecvNote1();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult RecvNote2() override;
+  mozilla::ipc::IPCResult RecvNote2();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
  private:
   bool mDone;
--- a/ipc/ipdl/test/cxx/TestUniquePtrIPC.h
+++ b/ipc/ipdl/test/cxx/TestUniquePtrIPC.h
@@ -38,20 +38,19 @@ class TestUniquePtrIPCParent : public PT
 class TestUniquePtrIPCChild : public PTestUniquePtrIPCChild {
  public:
   TestUniquePtrIPCChild() { MOZ_COUNT_CTOR(TestUniquePtrIPCChild); }
   virtual ~TestUniquePtrIPCChild() { MOZ_COUNT_DTOR(TestUniquePtrIPCChild); }
 
   mozilla::ipc::IPCResult RecvTestMessage(UniquePtr<int>&& aA1,
                                           UniquePtr<DummyStruct>&& aA2,
                                           const DummyStruct& aA3,
-                                          UniquePtr<int>&& aA4) override;
+                                          UniquePtr<int>&& aA4);
 
-  mozilla::ipc::IPCResult RecvTestSendReference(
-      UniquePtr<DummyStruct>&& aA) override;
+  mozilla::ipc::IPCResult RecvTestSendReference(UniquePtr<DummyStruct>&& aA);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) {
       fail("Abnormal shutdown of child");
     }
     QuitChild();
   }
 };
--- a/ipc/ipdl/test/cxx/TestUrgency.h
+++ b/ipc/ipdl/test/cxx/TestUrgency.h
@@ -14,41 +14,41 @@ class TestUrgencyParent : public PTestUr
   TestUrgencyParent();
   virtual ~TestUrgencyParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  mozilla::ipc::IPCResult RecvTest1(uint32_t *value) override;
-  mozilla::ipc::IPCResult RecvTest2() override;
-  mozilla::ipc::IPCResult RecvTest3(uint32_t *value) override;
+  mozilla::ipc::IPCResult RecvTest1(uint32_t *value);
+  mozilla::ipc::IPCResult RecvTest2();
+  mozilla::ipc::IPCResult RecvTest3(uint32_t *value);
   mozilla::ipc::IPCResult RecvTest4_Begin();
   mozilla::ipc::IPCResult RecvTest4_NestedSync();
-  mozilla::ipc::IPCResult RecvFinalTest_Begin() override;
+  mozilla::ipc::IPCResult RecvFinalTest_Begin();
 
   bool ShouldContinueFromReplyTimeout() override { return false; }
   virtual void ActorDestroy(ActorDestroyReason why) override {
     passed("ok");
     QuitParent();
   }
 
  private:
   bool inreply_;
 };
 
 class TestUrgencyChild : public PTestUrgencyChild {
  public:
   TestUrgencyChild();
   virtual ~TestUrgencyChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
-  mozilla::ipc::IPCResult RecvReply1(uint32_t *reply) override;
-  mozilla::ipc::IPCResult RecvReply2(uint32_t *reply) override;
+  mozilla::ipc::IPCResult RecvStart();
+  mozilla::ipc::IPCResult RecvReply1(uint32_t *reply);
+  mozilla::ipc::IPCResult RecvReply2(uint32_t *reply);
 
   virtual void ActorDestroy(ActorDestroyReason why) override { QuitChild(); }
 
  private:
   uint32_t test_;
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestUrgentHangs.h
+++ b/ipc/ipdl/test/cxx/TestUrgentHangs.h
@@ -16,19 +16,19 @@ class TestUrgentHangsParent : public PTe
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
   void SecondStage();
   void ThirdStage();
 
-  mozilla::ipc::IPCResult RecvTest1_2() override;
-  mozilla::ipc::IPCResult RecvTestInner() override;
-  mozilla::ipc::IPCResult RecvTestInnerUrgent() override;
+  mozilla::ipc::IPCResult RecvTest1_2();
+  mozilla::ipc::IPCResult RecvTestInner();
+  mozilla::ipc::IPCResult RecvTestInnerUrgent();
 
   bool ShouldContinueFromReplyTimeout() override { return false; }
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (mInnerCount != 1) {
       fail("wrong mInnerCount");
     }
     if (mInnerUrgentCount != 2) {
       fail("wrong mInnerUrgentCount");
@@ -41,24 +41,24 @@ class TestUrgentHangsParent : public PTe
   size_t mInnerCount, mInnerUrgentCount;
 };
 
 class TestUrgentHangsChild : public PTestUrgentHangsChild {
  public:
   TestUrgentHangsChild();
   virtual ~TestUrgentHangsChild();
 
-  mozilla::ipc::IPCResult RecvTest1_1() override;
-  mozilla::ipc::IPCResult RecvTest1_3() override;
-  mozilla::ipc::IPCResult RecvTest2() override;
-  mozilla::ipc::IPCResult RecvTest3() override;
-  mozilla::ipc::IPCResult RecvTest4() override;
-  mozilla::ipc::IPCResult RecvTest4_1() override;
-  mozilla::ipc::IPCResult RecvTest5() override;
-  mozilla::ipc::IPCResult RecvTest5_1() override;
+  mozilla::ipc::IPCResult RecvTest1_1();
+  mozilla::ipc::IPCResult RecvTest1_3();
+  mozilla::ipc::IPCResult RecvTest2();
+  mozilla::ipc::IPCResult RecvTest3();
+  mozilla::ipc::IPCResult RecvTest4();
+  mozilla::ipc::IPCResult RecvTest4_1();
+  mozilla::ipc::IPCResult RecvTest5();
+  mozilla::ipc::IPCResult RecvTest5_1();
 
   virtual void ActorDestroy(ActorDestroyReason why) override { QuitChild(); }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
 
 #endif  // ifndef mozilla__ipdltest_TestUrgentHangs_h
--- a/ipc/ipdl/test/cxx/moz.build
+++ b/ipc/ipdl/test/cxx/moz.build
@@ -6,16 +6,55 @@
 
 DIRS += ['app']
 
 EXPORTS.mozilla._ipdltest += [
     'IPDLUnitTestProcessChild.h',
     'IPDLUnitTests.h',
     'IPDLUnitTestTypes.h',
     'IPDLUnitTestUtils.h',
+    'TestActorPunning.h',
+    'TestAsyncReturns.h',
+    'TestBadActor.h',
+    'TestCancel.h',
+    'TestCrashCleanup.h',
+    'TestDataStructures.h',
+    'TestDemon.h',
+    'TestDesc.h',
+    'TestEndpointBridgeMain.h',
+    'TestEndpointOpens.h',
+    'TestFailedCtor.h',
+    'TestHangs.h',
+    'TestHighestPrio.h',
+    'TestInterruptErrorCleanup.h',
+    'TestInterruptRaces.h',
+    'TestInterruptShutdownRace.h',
+    'TestJSON.h',
+    'TestLatency.h',
+    'TestManyChildAllocs.h',
+    'TestMultiMgrs.h',
+    'TestNestedLoops.h',
+    'TestOffMainThreadPainting.h',
+    'TestRaceDeadlock.h',
+    'TestRaceDeferral.h',
+    'TestRacyInterruptReplies.h',
+    'TestRacyReentry.h',
+    'TestRacyUndefer.h',
+    'TestRPC.h',
+    'TestSanity.h',
+    'TestSelfManageRoot.h',
+    'TestShmem.h',
+    'TestShutdown.h',
+    'TestStackHooks.h',
+    'TestSyncError.h',
+    'TestSyncHang.h',
+    'TestSyncWakeup.h',
+    'TestUniquePtrIPC.h',
+    'TestUrgency.h',
+    'TestUrgentHangs.h',
 ]
 
 SOURCES += [
     'TestActorPunning.cpp',
     'TestAsyncReturns.cpp',
     'TestBadActor.cpp',
     'TestCancel.cpp',
     'TestCrashCleanup.cpp',
--- a/ipc/ipdl/test/ipdl/error/Nullable.ipdl
+++ b/ipc/ipdl/test/ipdl/error/Nullable.ipdl
@@ -1,6 +1,6 @@
 //error: `nullable' qualifier for type `int' makes no sense
 
-protocol Nullable {
+protocol PNullable {
 child:
     async Msg(nullable int i);
 };
rename from ipc/ipdl/test/ipdl/error/asyncMessageListed.ipdl
rename to ipc/ipdl/test/ipdl/error/PasyncMessageListed.ipdl
--- a/ipc/ipdl/test/ipdl/error/asyncMessageListed.ipdl
+++ b/ipc/ipdl/test/ipdl/error/PasyncMessageListed.ipdl
@@ -1,6 +1,6 @@
-//error: IPC message asyncMessageListed::Msg is async, can be delisted
+//error: IPC message PasyncMessageListed::Msg is async, can be delisted
 
-protocol asyncMessageListed {
+protocol PasyncMessageListed {
 parent:
     async Msg();
 };
rename from ipc/ipdl/test/ipdl/ok/AsyncReturn.ipdl
rename to ipc/ipdl/test/ipdl/ok/PAsyncReturn.ipdl
--- a/ipc/ipdl/test/ipdl/ok/AsyncReturn.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PAsyncReturn.ipdl
@@ -1,8 +1,8 @@
 // Async messages are not allowed to return values.
 
 //error: asynchronous message `Msg' declares return values
 
-protocol AsyncReturn {
+protocol PAsyncReturn {
 child:
     async Msg() returns(int32_t aNumber);
 };
rename from ipc/ipdl/test/ipdl/ok/Delete.ipdl
rename to ipc/ipdl/test/ipdl/ok/PDelete.ipdl
--- a/ipc/ipdl/test/ipdl/ok/Delete.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PDelete.ipdl
@@ -1,8 +1,8 @@
-include protocol DeleteSub;
+include protocol PDeleteSub;
 
-sync protocol Delete {
-    manages DeleteSub;
+sync protocol PDelete {
+    manages PDeleteSub;
 
 child:
-    async DeleteSub();
+    async PDeleteSub();
 };
rename from ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
rename to ipc/ipdl/test/ipdl/ok/PDeleteSub.ipdl
--- a/ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PDeleteSub.ipdl
@@ -1,10 +1,10 @@
-include protocol Delete;
+include protocol PDelete;
 
-sync protocol DeleteSub {
-    manager Delete;
+sync protocol PDeleteSub {
+    manager PDelete;
 
 parent:
     sync __delete__(int x) returns (double d);
 
 };
 
rename from ipc/ipdl/test/ipdl/ok/EndpointDecl.ipdl
rename to ipc/ipdl/test/ipdl/ok/PEndpointDecl.ipdl
--- a/ipc/ipdl/test/ipdl/ok/EndpointDecl.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PEndpointDecl.ipdl
@@ -1,18 +1,18 @@
 
 // Basic test that Endpoint types are declared for protocols, within
 // that protocol.
 
 struct Whatever {
-  Endpoint<EndpointDeclParent> par;
-  Endpoint<EndpointDeclChild> chi;
+  Endpoint<PEndpointDeclParent> par;
+  Endpoint<PEndpointDeclChild> chi;
 };
 
 namespace mozilla {
 
-protocol EndpointDecl {
+protocol PEndpointDecl {
   child:
-    async Message(Endpoint<EndpointDeclParent> aEndpointParent,
-                  Endpoint<EndpointDeclChild> aEndpointChild);
+    async Message(Endpoint<PEndpointDeclParent> aEndpointParent,
+                  Endpoint<PEndpointDeclChild> aEndpointChild);
 };
 
 }
rename from ipc/ipdl/test/ipdl/ok/EndpointUse.ipdl
rename to ipc/ipdl/test/ipdl/ok/PEndpointUse.ipdl
--- a/ipc/ipdl/test/ipdl/ok/EndpointUse.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PEndpointUse.ipdl
@@ -1,9 +1,9 @@
-include protocol EndpointDecl;
+include protocol PEndpointDecl;
 
 // Basic test that Endpoint types are declared for included protocols.
 
-protocol EndpointUse {
+protocol PEndpointUse {
   child:
-    async Message(Endpoint<EndpointDeclParent> aEndpointParent,
-                  Endpoint<EndpointDeclChild> aEndpointChild);
+    async Message(Endpoint<PEndpointDeclParent> aEndpointParent,
+                  Endpoint<PEndpointDeclChild> aEndpointChild);
 };
rename from ipc/ipdl/test/ipdl/ok/Nullable.ipdl
rename to ipc/ipdl/test/ipdl/ok/PNullable.ipdl
--- a/ipc/ipdl/test/ipdl/ok/Nullable.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PNullable.ipdl
@@ -1,11 +1,11 @@
 union Union {
-    nullable Nullable;
-    nullable Nullable[];
+    nullable PNullable;
+    nullable PNullable[];
 };
 
-protocol Nullable {
+protocol PNullable {
 child:
-    async Msg(nullable Nullable n);
-    async Msg2(nullable Nullable[] N);
+    async Msg(nullable PNullable n);
+    async Msg2(nullable PNullable[] N);
     async Msg3(Union u);
 };
rename from ipc/ipdl/test/ipdl/ok/Struct.ipdl
rename to ipc/ipdl/test/ipdl/ok/PStruct.ipdl
--- a/ipc/ipdl/test/ipdl/ok/Struct.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PStruct.ipdl
@@ -1,10 +1,10 @@
 struct S {
     int i;
     double d;
 };
 
-sync protocol Struct {
+sync protocol PStruct {
 parent:
     sync test(S s) returns (S ss);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/SyncSyncManagee.ipdl
rename to ipc/ipdl/test/ipdl/ok/PSyncSyncManagee.ipdl
--- a/ipc/ipdl/test/ipdl/ok/SyncSyncManagee.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PSyncSyncManagee.ipdl
@@ -1,7 +1,7 @@
-include protocol SyncSyncManager;
+include protocol PSyncSyncManager;
 
-sync protocol SyncSyncManagee {
-    manager SyncSyncManager;
+sync protocol PSyncSyncManagee {
+    manager PSyncSyncManager;
 child:
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/SyncSyncManager.ipdl
rename to ipc/ipdl/test/ipdl/ok/PSyncSyncManager.ipdl
--- a/ipc/ipdl/test/ipdl/ok/SyncSyncManager.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PSyncSyncManager.ipdl
@@ -1,11 +1,11 @@
-include protocol SyncSyncManagee;
+include protocol PSyncSyncManagee;
 
 /* The main reason for this test is that it would have caught a bug
  * in the Rust IPDL parser that was treating "sync" like "async" in the
  * nested case.
  */
-nested(upto not) sync protocol SyncSyncManager {
-    manages SyncSyncManagee;
+nested(upto not) sync protocol PSyncSyncManager {
+    manages PSyncSyncManagee;
 parent:
-    async SyncSyncManagee();
+    async PSyncSyncManagee();
 };
rename from ipc/ipdl/test/ipdl/ok/actorparam.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pactorparam.ipdl
--- a/ipc/ipdl/test/ipdl/ok/actorparam.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pactorparam.ipdl
@@ -1,5 +1,5 @@
-protocol actorparam {
+protocol Pactorparam {
 
-child: async Msg(actorparam p);
+child: async Msg(Pactorparam p);
 
 };
rename from ipc/ipdl/test/ipdl/ok/actorreturn.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pactorreturn.ipdl
--- a/ipc/ipdl/test/ipdl/ok/actorreturn.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pactorreturn.ipdl
@@ -1,6 +1,6 @@
-sync protocol actorreturn {
+sync protocol Pactorreturn {
 
 parent:
-    sync Msg(actorreturn p) returns (actorreturn r);
+    sync Msg(Pactorreturn p) returns (Pactorreturn r);
 
 };
rename from ipc/ipdl/test/ipdl/ok/array_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_Basic.ipdl
@@ -1,4 +1,4 @@
-protocol array_Basic {
+protocol Parray_Basic {
 child:
     async Msg(int[] array);
 };
rename from ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_OfActors.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_OfActors.ipdl
@@ -1,10 +1,10 @@
-include protocol array_OfActorsSub;
+include protocol Parray_OfActorsSub;
 
-protocol array_OfActors {
-    manages array_OfActorsSub;
+protocol Parray_OfActors {
+    manages Parray_OfActorsSub;
 
 child:
-    async Msg(array_OfActorsSub[] p);
+    async Msg(Parray_OfActorsSub[] p);
 
-    async array_OfActorsSub();
+    async Parray_OfActorsSub();
 };
rename from ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_OfActorsSub.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_OfActorsSub.ipdl
@@ -1,7 +1,7 @@
-include protocol array_OfActors;
+include protocol Parray_OfActors;
 
-protocol array_OfActorsSub {
-    manager array_OfActors;
+protocol Parray_OfActorsSub {
+    manager Parray_OfActors;
 
 child: async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/array_Union.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_Union.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_Union.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_Union.ipdl
@@ -1,10 +1,10 @@
 union Union {
     int[];
     int;
     double;
 };
 
-sync protocol array_Union {
+sync protocol Parray_Union {
 parent:
     sync Msg(Union u, Union[] au) returns (Union r);
 };
rename from ipc/ipdl/test/ipdl/ok/basicUsing.ipdl
rename to ipc/ipdl/test/ipdl/ok/PbasicUsing.ipdl
--- a/ipc/ipdl/test/ipdl/ok/basicUsing.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PbasicUsing.ipdl
@@ -11,12 +11,12 @@ union SomeUnion
   SomeType;
   SomeClass;
   SomeStruct;
   SomeRefcountedType;
   SomeRefcountedClass;
   SomeRefcountedStruct;
 };
 
-protocol basicUsing {
+protocol PbasicUsing {
 child:
     async Msg(SomeUnion foo);
 };
rename from ipc/ipdl/test/ipdl/ok/builtins.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pbuiltins.ipdl
--- a/ipc/ipdl/test/ipdl/ok/builtins.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pbuiltins.ipdl
@@ -1,9 +1,9 @@
-protocol builtins {
+protocol Pbuiltins {
 
     // sanity-check that "essential" builtins are being declared
 
 child: async Msg(bool b,
            char c,
            int i,
            long l,
 
rename from ipc/ipdl/test/ipdl/ok/bytebuf.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pbytebuf.ipdl
--- a/ipc/ipdl/test/ipdl/ok/bytebuf.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pbytebuf.ipdl
@@ -1,13 +1,13 @@
 union Foo {
     int;
     ByteBuf;
 };
 
-intr protocol bytebuf {
+intr protocol Pbytebuf {
 parent:
     async Msg(ByteBuf s, Foo f);
     sync SyncMsg(ByteBuf s, Foo f)
         returns (ByteBuf t, Foo g);
     intr InterruptMsg(ByteBuf s, Foo f)
         returns (ByteBuf t, Foo g);
 };
rename from ipc/ipdl/test/ipdl/ok/empty.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pempty.ipdl
--- a/ipc/ipdl/test/ipdl/ok/empty.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pempty.ipdl
@@ -1,3 +1,3 @@
-protocol empty {
+protocol Pempty {
 child: async Msg();
 };
rename from ipc/ipdl/test/ipdl/ok/emptyStruct.ipdl
rename to ipc/ipdl/test/ipdl/ok/PemptyStruct.ipdl
--- a/ipc/ipdl/test/ipdl/ok/emptyStruct.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PemptyStruct.ipdl
@@ -1,3 +1,3 @@
 struct empty { };
 
-protocol emptyStruct { child:  async __delete__(); };
+protocol PemptyStruct { child:  async __delete__(); };
rename from ipc/ipdl/test/ipdl/ok/headerProto.ipdl
rename to ipc/ipdl/test/ipdl/ok/PheaderProto.ipdl
--- a/ipc/ipdl/test/ipdl/ok/headerProto.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PheaderProto.ipdl
@@ -1,10 +1,10 @@
 include header;
 
 namespace c {
 
-protocol headerProto {
+protocol PheaderProto {
 child:
     async __delete__(foo a, baz b, Inner1 c, Inner2 d, X x);
 };
 
 }
rename from ipc/ipdl/test/ipdl/ok/intrProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PintrProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/intrProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PintrProtocol.ipdl
@@ -1,9 +1,9 @@
-intr protocol intrProtocol {
+intr protocol PintrProtocol {
 
     // sanity check of Interrupt protocols
 child:
     async AsyncMsg();
 
 parent:
     sync SyncMsg(int i) returns (int r);
 
rename from ipc/ipdl/test/ipdl/ok/jetpack.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pjetpack.ipdl
--- a/ipc/ipdl/test/ipdl/ok/jetpack.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pjetpack.ipdl
@@ -1,5 +1,5 @@
-sync protocol jetpack {
+sync protocol Pjetpack {
 child:
     async __delete__();
 
 };
rename from ipc/ipdl/test/ipdl/ok/manageSelf.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanageSelf.ipdl
--- a/ipc/ipdl/test/ipdl/ok/manageSelf.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanageSelf.ipdl
@@ -1,10 +1,10 @@
-include protocol manageSelf_Toplevel;
+include protocol PmanageSelf_Toplevel;
 
-protocol manageSelf {
-    manager manageSelf_Toplevel or manageSelf;
-    manages manageSelf;
+protocol PmanageSelf {
+    manager PmanageSelf_Toplevel or PmanageSelf;
+    manages PmanageSelf;
 
 child:
-    async manageSelf();
+    async PmanageSelf();
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/manageSelf_Toplevel.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanageSelf_Toplevel.ipdl
--- a/ipc/ipdl/test/ipdl/ok/manageSelf_Toplevel.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanageSelf_Toplevel.ipdl
@@ -1,9 +1,9 @@
-include protocol manageSelf;
+include protocol PmanageSelf;
 
-protocol manageSelf_Toplevel {
-    manages manageSelf;
+protocol PmanageSelf_Toplevel {
+    manages PmanageSelf;
 
 child:
-    async manageSelf();
+    async PmanageSelf();
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanagedProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanagedProtocol.ipdl
@@ -1,8 +1,8 @@
-include protocol managerProtocol;
+include protocol PmanagerProtocol;
 
-protocol managedProtocol {
-    manager managerProtocol;
+protocol PmanagedProtocol {
+    manager PmanagerProtocol;
 
 child:
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanagerProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanagerProtocol.ipdl
@@ -1,11 +1,11 @@
-include protocol managedProtocol;
+include protocol PmanagedProtocol;
 
 // sanity check of managed/manager protocols
 
-protocol managerProtocol {
-    manages managedProtocol;
+protocol PmanagerProtocol {
+    manages PmanagedProtocol;
 
 parent:
-    async managedProtocol(int i);
+    async PmanagedProtocol(int i);
 
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_Basic.ipdl
@@ -1,4 +1,4 @@
-protocol maybe_Basic {
+protocol Pmaybe_Basic {
 child:
     async Msg(int? maybe);
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_OfActors.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_OfActors.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_OfActors.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_OfActors.ipdl
@@ -1,10 +1,10 @@
-include protocol maybe_OfActorsSub;
+include protocol Pmaybe_OfActorsSub;
 
-protocol maybe_OfActors {
-    manages maybe_OfActorsSub;
+protocol Pmaybe_OfActors {
+    manages Pmaybe_OfActorsSub;
 
 child:
-    async Msg(maybe_OfActorsSub? p);
+    async Msg(Pmaybe_OfActorsSub? p);
 
-    async maybe_OfActorsSub();
+    async Pmaybe_OfActorsSub();
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_OfActorsSub.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_OfActorsSub.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_OfActorsSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_OfActorsSub.ipdl
@@ -1,7 +1,7 @@
-include protocol maybe_OfActors;
+include protocol Pmaybe_OfActors;
 
-protocol maybe_OfActorsSub {
-    manager maybe_OfActors;
+protocol Pmaybe_OfActorsSub {
+    manager Pmaybe_OfActors;
 
 child: async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_Union.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_Union.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_Union.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_Union.ipdl
@@ -1,10 +1,10 @@
 union MaybeUnion {
     int[];
     int;
     double;
 };
 
-sync protocol maybe_Union {
+sync protocol Pmaybe_Union {
 parent:
     async Msg(MaybeUnion u, MaybeUnion? au) returns (MaybeUnion r);
 };
rename from ipc/ipdl/test/ipdl/ok/media.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmedia.ipdl
--- a/ipc/ipdl/test/ipdl/ok/media.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmedia.ipdl
@@ -1,5 +1,5 @@
-sync protocol media {
+sync protocol Pmedia {
 child:
     async __delete__();
 
 };
rename from ipc/ipdl/test/ipdl/ok/messageCompress.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmessageCompress.ipdl
--- a/ipc/ipdl/test/ipdl/ok/messageCompress.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmessageCompress.ipdl
@@ -1,4 +1,4 @@
-intr protocol messageCompress {
+intr protocol PmessageCompress {
 child:
     async foo() compress;
 };
rename from ipc/ipdl/test/ipdl/ok/messageVerify.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmessageVerify.ipdl
--- a/ipc/ipdl/test/ipdl/ok/messageVerify.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmessageVerify.ipdl
@@ -1,12 +1,12 @@
-include protocol messageVerifyTopLevel;
+include protocol PmessageVerifyTopLevel;
 
-intr protocol messageVerify {
-  manager messageVerifyTopLevel;
+intr protocol PmessageVerify {
+  manager PmessageVerifyTopLevel;
 
 parent:
     sync __delete__(uint32_t x) returns (double rv1) verify;
     async msg1() verify;
     async msg2(uint32_t aParam1) verify;
     sync msg3()
       returns (uint32_t rv1) verify;
     sync msg4(uint32_t aParam1)
rename from ipc/ipdl/test/ipdl/ok/messageVerifyTopLevel.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmessageVerifyTopLevel.ipdl
--- a/ipc/ipdl/test/ipdl/ok/messageVerifyTopLevel.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmessageVerifyTopLevel.ipdl
@@ -1,7 +1,7 @@
-include protocol messageVerify;
+include protocol PmessageVerify;
 
-intr protocol messageVerifyTopLevel{
-  manages messageVerify;
+intr protocol PmessageVerifyTopLevel{
+  manages PmessageVerify;
   parent:
-    sync messageVerify(uint32_t aParam1) returns (double rv1) verify;
+    sync PmessageVerify(uint32_t aParam1) returns (double rv1) verify;
 };
rename from ipc/ipdl/test/ipdl/ok/multiManaged.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultiManaged.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multiManaged.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultiManaged.ipdl
@@ -1,9 +1,9 @@
-include protocol multiManager1;
-include protocol multiManager2;
+include protocol PmultiManager1;
+include protocol PmultiManager2;
 
-protocol multiManaged {
-    manager multiManager1 or multiManager2;
+protocol PmultiManaged {
+    manager PmultiManager1 or PmultiManager2;
 
 child:
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/multiManager1.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultiManager1.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multiManager1.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultiManager1.ipdl
@@ -1,8 +1,8 @@
-include protocol multiManaged;
+include protocol PmultiManaged;
 
-protocol multiManager1 {
-    manages multiManaged;
+protocol PmultiManager1 {
+    manages PmultiManaged;
 
 child:
-    async multiManaged();
+    async PmultiManaged();
 };
rename from ipc/ipdl/test/ipdl/ok/multiManager2.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultiManager2.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multiManager2.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultiManager2.ipdl
@@ -1,8 +1,8 @@
-include protocol multiManaged;
+include protocol PmultiManaged;
 
-protocol multiManager2 {
-    manages multiManaged;
+protocol PmultiManager2 {
+    manages PmultiManaged;
 
 child:
-    async multiManaged();
+    async PmultiManaged();
 };
rename from ipc/ipdl/test/ipdl/ok/multipleUsingCxxTypes.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultipleUsingCxxTypes.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multipleUsingCxxTypes.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultipleUsingCxxTypes.ipdl
@@ -1,7 +1,7 @@
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
-protocol multipleUsingCxxTypes {
+protocol PmultipleUsingCxxTypes {
 child:
     async Msg(void_t foo);
 };
rename from ipc/ipdl/test/ipdl/ok/mutualRecStructUnion.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmutualRecStructUnion.ipdl
--- a/ipc/ipdl/test/ipdl/ok/mutualRecStructUnion.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmutualRecStructUnion.ipdl
@@ -9,13 +9,13 @@ union Y {
     Z;
 };
 
 struct Z {
     X x;
     Y y;
 };
 
-protocol mutualRecStructUnion {
+protocol PmutualRecStructUnion {
 child:
     async Test(X x, Y y, Z z);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/mutualRecUnion.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmutualRecUnion.ipdl
--- a/ipc/ipdl/test/ipdl/ok/mutualRecUnion.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmutualRecUnion.ipdl
@@ -9,13 +9,13 @@ union Y {
     Z;
 };
 
 union Z {
     double;
     X;
 };
 
-protocol mutualRecUnion {
+protocol PmutualRecUnion {
 child:
     async Test(X x, Y y, Z z);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/namespace_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pnamespace_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/namespace_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pnamespace_Basic.ipdl
@@ -1,12 +1,12 @@
 namespace basic {
 
 // sanity check of namespaced protocols
 
-protocol namespace_Basic {
+protocol Pnamespace_Basic {
 
 child:
     async Msg();
 
 };
 
 } // namespace basic
rename from ipc/ipdl/test/ipdl/ok/noRedeclCrossMessage.ipdl
rename to ipc/ipdl/test/ipdl/ok/PnoRedeclCrossMessage.ipdl
--- a/ipc/ipdl/test/ipdl/ok/noRedeclCrossMessage.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PnoRedeclCrossMessage.ipdl
@@ -1,9 +1,9 @@
-protocol noRedeclCrossMessage {
+protocol PnoRedeclCrossMessage {
 
     // each message has its own scope for param/return names
 
 child:
     async Msg1(int f);
     async Msg2(int f);
 
 };
rename from ipc/ipdl/test/ipdl/ok/plugin.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pplugin.ipdl
--- a/ipc/ipdl/test/ipdl/ok/plugin.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pplugin.ipdl
@@ -1,5 +1,5 @@
-intr protocol plugin {
+intr protocol Pplugin {
 child:
     async __delete__();
 
 };
rename from ipc/ipdl/test/ipdl/ok/selfRecUnion.ipdl
rename to ipc/ipdl/test/ipdl/ok/PselfRecUnion.ipdl
--- a/ipc/ipdl/test/ipdl/ok/selfRecUnion.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PselfRecUnion.ipdl
@@ -1,11 +1,11 @@
 union R {
     int;
     double;
     R;
 };
 
-protocol selfRecUnion {
+protocol PselfRecUnion {
 child:
     async Test(R r);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/shmem.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pshmem.ipdl
--- a/ipc/ipdl/test/ipdl/ok/shmem.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pshmem.ipdl
@@ -1,13 +1,13 @@
 union Foo {
     int;
     Shmem;
 };
 
-intr protocol shmem {
+intr protocol Pshmem {
 parent:
     async Msg(Shmem s, Foo f);
     sync SyncMsg(Shmem s, Foo f)
         returns (Shmem t, Foo g);
     intr InterruptMsg(Shmem s, Foo f)
         returns (Shmem t, Foo g);
 };
rename from ipc/ipdl/test/ipdl/ok/syncProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PsyncProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/syncProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PsyncProtocol.ipdl
@@ -1,9 +1,9 @@
-sync protocol syncProtocol {
+sync protocol PsyncProtocol {
 
     // sanity check of sync protocols
 
 child:
     async AsyncMsg();
 
 parent:
     sync SyncMsg() returns (int i);
rename from ipc/ipdl/test/ipdl/ok/threeDirections.ipdl
rename to ipc/ipdl/test/ipdl/ok/PthreeDirections.ipdl
--- a/ipc/ipdl/test/ipdl/ok/threeDirections.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PthreeDirections.ipdl
@@ -1,9 +1,9 @@
-protocol threeDirections {
+protocol PthreeDirections {
 
     // sanity check that the three direction specifiers are being accepted
 child:
     async ChildMsg();
 
 parent:
     async ParentMsg();
 
rename from ipc/ipdl/test/ipdl/ok/union_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Punion_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/union_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Punion_Basic.ipdl
@@ -1,11 +1,11 @@
 union Basic {
     int;
     double;
 };
 
-sync protocol union_Basic {
+sync protocol Punion_Basic {
 
 parent:
     sync Msg(Basic p) returns (Basic r);
 
 };
rename from ipc/ipdl/test/ipdl/ok/union_Namespaced.ipdl
rename to ipc/ipdl/test/ipdl/ok/Punion_Namespaced.ipdl
--- a/ipc/ipdl/test/ipdl/ok/union_Namespaced.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Punion_Namespaced.ipdl
@@ -5,14 +5,14 @@ union Socks {
     double;
 };
 
 } // namespace kitties
 
 
 namespace puppies {
 
-protocol union_Namespaced {
+protocol Punion_Namespaced {
 child:
     async Msg(Socks s);
 };
 
 } // namespace puppies
--- a/ipc/ipdl/test/ipdl/sync-messages.ini
+++ b/ipc/ipdl/test/ipdl/sync-messages.ini
@@ -1,24 +1,24 @@
-[actorreturn::Msg]
-[array_Union::Msg]
-[union_Basic::Msg]
-[Struct::test]
-[intrProtocol::SyncMsg]
-[intrProtocol::InterruptMsg]
-[shmem::SyncMsg]
-[shmem::InterruptMsg]
-[bytebuf::SyncMsg]
-[bytebuf::InterruptMsg]
-[syncProtocol::SyncMsg]
-[messageVerify::__delete__]
-[messageVerify::msg3]
-[messageVerify::msg4]
-[messageVerifyTopLevel::messageVerify]
-[DeleteSub::__delete__]
-[intrMessageCompress::foo]
-[intrMessageCompress::bar]
-[syncMessageCompress::foo]
-[syncParentToChild::Msg]
-[tooWeakIntrSync::Msg]
-[tooWeakSyncAsync::Msg]
-[undeclReturnType::Msg]
-[asyncMessageListed::Msg]
+[Pactorreturn::Msg]
+[Parray_Union::Msg]
+[Punion_Basic::Msg]
+[PStruct::test]
+[PintrProtocol::SyncMsg]
+[PintrProtocol::InterruptMsg]
+[Pshmem::SyncMsg]
+[Pshmem::InterruptMsg]
+[Pbytebuf::SyncMsg]
+[Pbytebuf::InterruptMsg]
+[PsyncProtocol::SyncMsg]
+[PmessageVerify::__delete__]
+[PmessageVerify::msg3]
+[PmessageVerify::msg4]
+[PmessageVerifyTopLevel::PmessageVerify]
+[PDeleteSub::__delete__]
+[PintrMessageCompress::foo]
+[PintrMessageCompress::bar]
+[PsyncMessageCompress::foo]
+[PsyncParentToChild::Msg]
+[PtooWeakIntrSync::Msg]
+[PtooWeakSyncAsync::Msg]
+[PundeclReturnType::Msg]
+[PasyncMessageListed::Msg]
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -59,20 +59,18 @@ enum JSValueType : uint8_t {
   JSVAL_TYPE_NULL = 0x04,
   JSVAL_TYPE_MAGIC = 0x05,
   JSVAL_TYPE_STRING = 0x06,
   JSVAL_TYPE_SYMBOL = 0x07,
   JSVAL_TYPE_PRIVATE_GCTHING = 0x08,
   JSVAL_TYPE_BIGINT = 0x09,
   JSVAL_TYPE_OBJECT = 0x0c,
 
-  // These never appear in a jsval; they are only provided as an out-of-band
-  // value.
-  JSVAL_TYPE_UNKNOWN = 0x20,
-  JSVAL_TYPE_MISSING = 0x21
+  // This type never appears in a Value; it's only an out-of-band value.
+  JSVAL_TYPE_UNKNOWN = 0x20
 };
 
 namespace JS {
 enum class ValueType : uint8_t {
   Double = JSVAL_TYPE_DOUBLE,
   Int32 = JSVAL_TYPE_INT32,
   Boolean = JSVAL_TYPE_BOOLEAN,
   Undefined = JSVAL_TYPE_UNDEFINED,
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6182,37 +6182,25 @@ GeneralParser<ParseHandler, Unit>::break
   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Break));
   uint32_t begin = pos().begin;
 
   RootedPropertyName label(cx_);
   if (!matchLabel(yieldHandling, &label)) {
     return null();
   }
 
-  // Labeled 'break' statements target the nearest labeled statements (could
-  // be any kind) with the same label. Unlabeled 'break' statements target
-  // the innermost loop or switch statement.
-  if (label) {
-    auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
-      return stmt->label() == label;
-    };
-
-    if (!pc_->template findInnermostStatement<ParseContext::LabelStatement>(
-            hasSameLabel)) {
-      error(JSMSG_LABEL_NOT_FOUND);
-      return null();
-    }
-  } else {
-    auto isBreakTarget = [](ParseContext::Statement* stmt) {
-      return StatementKindIsUnlabeledBreakTarget(stmt->kind());
-    };
-
-    if (!pc_->findInnermostStatement(isBreakTarget)) {
-      errorAt(begin, JSMSG_TOUGH_BREAK);
-      return null();
+  auto validity = pc_->checkBreakStatement(label);
+  if (validity.isErr()) {
+    switch (validity.unwrapErr()) {
+      case ParseContext::BreakStatementError::ToughBreak:
+        errorAt(begin, JSMSG_TOUGH_BREAK);
+        return null();
+      case ParseContext::BreakStatementError::LabelNotFound:
+        error(JSMSG_LABEL_NOT_FOUND);
+        return null();
     }
   }
 
   if (!matchOrInsertSemicolon()) {
     return null();
   }
 
   return handler_.newBreakStatement(label, TokenPos(begin, pos().end));
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -264,18 +264,21 @@ class MOZ_STACK_CLASS ParserSharedBase :
 
   // Root atoms and objects allocated for the parsed tree.
   AutoKeepAtoms keepAtoms_;
 
  private:
   // This is needed to cast a parser to JS::AutoGCRooter.
   friend void js::frontend::TraceParser(JSTracer* trc,
                                         JS::AutoGCRooter* parser);
+
+#if defined(JS_BUILD_BINAST)
   friend void js::frontend::TraceBinParser(JSTracer* trc,
                                            JS::AutoGCRooter* parser);
+#endif  // JS_BUILD_BINAST
 
  private:
   // Create a new traceable node and store it into the trace list.
   template <typename BoxT, typename ArgT>
   BoxT* newTraceListNode(ArgT* arg);
 
  public:
   // Create a new JSObject and store it into the trace list.
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..46f28b933007d2f697f1fa862632d0c0b19204cd
GIT binary patch
literal 209
zc$`I!y$ZrW5QM`aK_rhM!BWJ|#t7j!F)8lS1&cG;goXUESwUZ3JY#Xw?aar{TvUEF
zqLezxvP9pphJlgar%!Z9<{5~gHWlH-vKt?^Gu1f3&L!9my+hO2MBuJ*IC`_N)B>yJ
zRf9mWrwm($AG5z91KBQr_CQ#9BKp^rrqC*v#xDwmuw|js)LZc;a1x<d1?ynZ_WT7M
C$Vc%2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0a42bbe83fbcc1616e78c74537e7ca8a01e0edeb
GIT binary patch
literal 197
zc${<c^z#a4igpij^!0TNip@+(%`3?)skDB^W8_#|oLW?pni8B`lvz;Xo|B)Hm=m0w
zUy!N+l*vrb%LOWRttco;1@iLqOb~)0iACwDC7xiT(lS$v416+6Qi~FE{7Q3Ei!zfD
zdUzm4^SxcLFaGVexzWKPL7sl@!3bBdF)<}ZhXlF0B81d97=VC@i;0DSjR6ck*aHB%
C`$dre
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/binast/invalid/wtf-8-interface-name.dir
@@ -0,0 +1,1 @@
+// |jit-test| error:SyntaxError
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..141cce1ca9ca26983413081d98b729f44fb3c41a
GIT binary patch
literal 238
zc${61Jqp4=5QW1Mf=IBjw~!!~Vryf>5F(l)8*GBen2a*8`C+n(9!BsKmfpxaC=n6-
z%J+CbvmjhZk@%6jTDj4NGAuOd%cLthL$|JxHD+^66)<KY<T(C{GG(f?ugV=LnU)py
zXH;ZV9D=4|PspPsX=G60F-NA<J6DW#O=V$!!h<z1!A{|40QB2({<V@58An0r%ip=4
kWu1Tpbe^}z_IbZ1apZYFd)yMjFpW2&Z3x>GmeJr$Ul{CAF#rGn
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/binast/invalid/wtf-8-scope-name.dir
@@ -0,0 +1,1 @@
+// |jit-test| error:SyntaxError
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ba221702d16b1d0f2ae670fe4e55774f99d78068
GIT binary patch
literal 215
zc${<c^z#a4igpij^!0TNip@+(%`3?)skHvbW8_#|oLW?pni8B`lvz;Xo|B)Hm=m0w
zUy!N+l*vrb%LOWRttco;1@iLqOb~)0iACwDC7xiT(lS$v)DWtIOA<>`L23+qGD}j6
z5_9}Yb5n~llMyO-Al5|(hXi^0xd$U$B*et`cEP^*x7+4MhXlF0A|%wf7=VC@jfsVU
Jg8>Xw8~|LiOp*Wq
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/binast/invalid/wtf-8-variable-name.dir
@@ -0,0 +1,1 @@
+// |jit-test| error:SyntaxError
--- a/js/src/jsapi-tests/binast/invalid/lib/filter_utils.py
+++ b/js/src/jsapi-tests/binast/invalid/lib/filter_utils.py
@@ -76,16 +76,31 @@ def assert_interface(obj, expected_name)
            The name of the interface
     """
     assert_tagged_tuple(obj)
     actual_name = obj['@INTERFACE']
     if actual_name != expected_name:
         raise Exception('expected {}, got {}'.format(expected_name, actual_name))
 
 
+def set_interface_name(obj, name):
+    """
+    Set the tagged tuple's interface name
+
+    :param obj (dict)
+           The tagged tuple
+    :param name (string)
+           The name of the interface
+    """
+    assert_tagged_tuple(obj)
+    obj['@INTERFACE'] = name
+    if type(name) is not str and type(name) is not unicode:
+        raise Exception('passed value is not string: {}'.format(name))
+
+
 def get_field(obj, name):
     """
     Returns the field of the tagged tuple.
 
     :param obj (dict)
            The tagged tuple
     :param name (string)
            The name of the field to get
@@ -141,16 +156,39 @@ def remove_field(obj, name):
     for field in fields:
         if field['@FIELD_NAME'] == name:
             del fields[i]
             return
         i += 1
     raise Exception('No such field: {}'.format(name))
 
 
+def append_field(obj, name, value):
+    """
+    Append a field to the tagged tuple
+
+    :param obj (dict)
+           the tagged tuple
+    :param name (string)
+           the name of the field to add
+    :param value (dict)
+           the value of the field to add
+    """
+    assert_tagged_tuple(obj)
+    fields = obj['@FIELDS']
+    if type(name) is not str and type(name) is not unicode:
+        raise Exception('passed name is not string: {}'.format(name))
+    if type(value) is not dict:
+        raise Exception('passed value is not dict: {}'.format(value))
+    fields.append({
+        '@FIELD_NAME': name,
+        '@FIELD_VALUE': value,
+    })
+
+
 def get_element(obj, i):
     """
     Returns the element of the list.
 
     :param obj (dict)
            The list
     :param i (int)
            The indef of the element to get
@@ -251,26 +289,26 @@ def set_string(obj, value):
     Set string value
 
     :param obj (dict)
            the string object
     :param value (int)
            the value to set
     """
     assert_string(obj)
-    if type(value) is not str:
+    if type(value) is not str and type(value) is not unicode:
         raise Exception('passed value is not string: {}'.format(value))
     obj['@VALUE'] = value
 
 
 def set_identifier_name(obj, value):
     """
     Set identifier name value
 
     :param obj (dict)
            the identifier name object
     :param value (int)
            the value to set
     """
     assert_identifier_name(obj)
-    if type(value) is not str:
+    if type(value) is not str and type(value) is not unicode:
         raise Exception('passed value is not string: {}'.format(value))
     obj['@VALUE'] = value
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-field-name.js
@@ -0,0 +1,1 @@
+a = 10;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-field-name.py
@@ -0,0 +1,18 @@
+def filter_ast(ast):
+    # Put WTF-8 string into field name.
+    # In multipart format, field name is not encoded into the file,
+    # so this has no effect.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+    global_stmts = utils.get_field(ast, 'statements')
+
+    expr_stmt = utils.get_element(global_stmts, 0)
+    utils.assert_interface(expr_stmt, 'ExpressionStatement')
+
+    field = utils.get_field(expr_stmt, 'expression')
+
+    utils.append_field(expr_stmt, u'\uD83E_\uDD9D', field)
+    utils.remove_field(expr_stmt, 'expression')
+
+    return ast
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-interface-name.js
@@ -0,0 +1,1 @@
+a = 1;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-interface-name.py
@@ -0,0 +1,13 @@
+def filter_ast(ast):
+    # Put WTF-8 string into interface name.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+    global_stmts = utils.get_field(ast, 'statements')
+
+    expr_stmt = utils.get_element(global_stmts, 0)
+    utils.assert_interface(expr_stmt, 'ExpressionStatement')
+
+    utils.set_interface_name(expr_stmt, u'\uD83E_\uDD9D')
+
+    return ast
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-scope-name.js
@@ -0,0 +1,1 @@
+var a = 10;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-scope-name.py
@@ -0,0 +1,18 @@
+def filter_ast(ast):
+    # Put WTF-8 string into scope name.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+
+    scope = utils.get_field(ast, 'scope')
+    utils.assert_interface(scope, 'AssertedScriptGlobalScope')
+
+    names = utils.get_field(scope, 'declaredNames')
+
+    decl_name = utils.get_element(names, 0)
+    utils.assert_interface(decl_name, 'AssertedDeclaredName')
+
+    name = utils.get_field(decl_name, 'name')
+    utils.set_identifier_name(name, u'\uD83E_\uDD9D')
+
+    return ast
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-variable-name.js
@@ -0,0 +1,1 @@
+a = 10;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-variable-name.py
@@ -0,0 +1,20 @@
+def filter_ast(ast):
+    # Put WTF-8 string into identifier name.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+    global_stmts = utils.get_field(ast, 'statements')
+
+    expr_stmt = utils.get_element(global_stmts, 0)
+    utils.assert_interface(expr_stmt, 'ExpressionStatement')
+
+    assign_expr = utils.get_field(expr_stmt, 'expression')
+    utils.assert_interface(assign_expr, 'AssignmentExpression')
+
+    binding = utils.get_field(assign_expr, 'binding')
+    utils.assert_interface(binding, 'AssignmentTargetIdentifier')
+
+    name = utils.get_field(binding, 'name')
+    utils.set_identifier_name(name, u'\uD83E_\uDD9D')
+
+    return ast
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -954,17 +954,17 @@ bool ErrorReport::populateUncaughtExcept
   // XXXbz this assumes the stack we have right now is still
   // related to our exception object.  It would be better if we
   // could accept a passed-in stack of some sort instead.
   NonBuiltinFrameIter iter(cx, cx->realm()->principals());
   if (!iter.done()) {
     ownedReport.filename = iter.filename();
     uint32_t column;
     ownedReport.sourceId =
-      iter.script() ? iter.script()->scriptSource()->id() : 0;
+      iter.hasScript() ? iter.script()->scriptSource()->id() : 0;
     ownedReport.lineno = iter.computeLine(&column);
     ownedReport.column = FixupColumnForDisplay(column);
     ownedReport.isMuted = iter.mutedErrors();
   }
 
   if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr,
                               JSMSG_UNCAUGHT_EXCEPTION, nullptr,
                               ArgumentsAreUTF8, &ownedReport, ap)) {
--- a/js/src/vm/JSFunction-inl.h
+++ b/js/src/vm/JSFunction-inl.h
@@ -39,16 +39,19 @@ inline bool CanReuseFunctionForClone(JSC
     }
     lazy->setHasBeenCloned();
   } else {
     JSScript* script = fun->nonLazyScript();
     if (script->hasBeenCloned()) {
       return false;
     }
     script->setHasBeenCloned();
+    if (LazyScript* lazy = script->maybeLazyScript()) {
+      lazy->setHasBeenCloned();
+    }
   }
   return true;
 }
 
 inline JSFunction* CloneFunctionObjectIfNotSingleton(
     JSContext* cx, HandleFunction fun, HandleObject parent,
     HandleObject proto = nullptr, NewObjectKind newKind = GenericObject) {
   /*
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -3464,77 +3464,91 @@ void GetObjectSlotNameFunctor::operator(
 
 /*
  * Routines to print out values during debugging.  These are FRIEND_API to help
  * the debugger find them and to support temporarily hacking js::Dump* calls
  * into other code.
  */
 
 static void dumpValue(const Value& v, js::GenericPrinter& out) {
-  if (v.isNull()) {
-    out.put("null");
-  } else if (v.isUndefined()) {
-    out.put("undefined");
-  } else if (v.isInt32()) {
-    out.printf("%d", v.toInt32());
-  } else if (v.isDouble()) {
-    out.printf("%g", v.toDouble());
-  } else if (v.isString()) {
-    v.toString()->dumpNoNewline(out);
-  } else if (v.isSymbol()) {
-    v.toSymbol()->dump(out);
-  } else if (v.isBigInt()) {
-    v.toBigInt()->dump(out);
-  } else if (v.isObject() && v.toObject().is<JSFunction>()) {
-    JSFunction* fun = &v.toObject().as<JSFunction>();
-    if (fun->displayAtom()) {
-      out.put("<function ");
-      EscapedStringPrinter(out, fun->displayAtom(), 0);
-    } else {
-      out.put("<unnamed function");
-    }
-    if (fun->hasScript()) {
-      JSScript* script = fun->nonLazyScript();
-      out.printf(" (%s:%u)", script->filename() ? script->filename() : "",
-                 script->lineno());
-    }
-    out.printf(" at %p>", (void*)fun);
-  } else if (v.isObject()) {
-    JSObject* obj = &v.toObject();
-    const Class* clasp = obj->getClass();
-    out.printf("<%s%s at %p>", clasp->name,
-               (clasp == &PlainObject::class_) ? "" : " object", (void*)obj);
-  } else if (v.isBoolean()) {
-    if (v.toBoolean()) {
-      out.put("true");
-    } else {
-      out.put("false");
-    }
-  } else if (v.isMagic()) {
-    out.put("<invalid");
-    switch (v.whyMagic()) {
-      case JS_ELEMENTS_HOLE:
-        out.put(" elements hole");
-        break;
-      case JS_NO_ITER_VALUE:
-        out.put(" no iter value");
-        break;
-      case JS_GENERATOR_CLOSING:
-        out.put(" generator closing");
-        break;
-      case JS_OPTIMIZED_OUT:
-        out.put(" optimized out");
-        break;
-      default:
-        out.put(" ?!");
-        break;
-    }
-    out.putChar('>');
-  } else {
-    out.put("unexpected value");
+  switch (v.type()) {
+    case ValueType::Null:
+      out.put("null");
+      break;
+    case ValueType::Undefined:
+      out.put("undefined");
+      break;
+    case ValueType::Int32:
+      out.printf("%d", v.toInt32());
+      break;
+    case ValueType::Double:
+      out.printf("%g", v.toDouble());
+      break;
+    case ValueType::String:
+      v.toString()->dumpNoNewline(out);
+      break;
+    case ValueType::Symbol:
+      v.toSymbol()->dump(out);
+      break;
+    case ValueType::BigInt:
+      v.toBigInt()->dump(out);
+      break;
+    case ValueType::Object:
+      if (v.toObject().is<JSFunction>()) {
+        JSFunction* fun = &v.toObject().as<JSFunction>();
+        if (fun->displayAtom()) {
+          out.put("<function ");
+          EscapedStringPrinter(out, fun->displayAtom(), 0);
+        } else {
+          out.put("<unnamed function");
+        }
+        if (fun->hasScript()) {
+          JSScript* script = fun->nonLazyScript();
+          out.printf(" (%s:%u)", script->filename() ? script->filename() : "",
+                     script->lineno());
+        }
+        out.printf(" at %p>", (void*)fun);
+      } else {
+        JSObject* obj = &v.toObject();
+        const Class* clasp = obj->getClass();
+        out.printf("<%s%s at %p>", clasp->name,
+                   (clasp == &PlainObject::class_) ? "" : " object", (void*)obj);
+      }
+      break;
+    case ValueType::Boolean:
+      if (v.toBoolean()) {
+        out.put("true");
+      } else {
+        out.put("false");
+      }
+      break;
+    case ValueType::Magic:
+      out.put("<magic");
+      switch (v.whyMagic()) {
+        case JS_ELEMENTS_HOLE:
+          out.put(" elements hole");
+          break;
+        case JS_NO_ITER_VALUE:
+          out.put(" no iter value");
+          break;
+        case JS_GENERATOR_CLOSING:
+          out.put(" generator closing");
+          break;
+        case JS_OPTIMIZED_OUT:
+          out.put(" optimized out");
+          break;
+        default:
+          out.put(" ?!");
+          break;
+      }
+      out.putChar('>');
+      break;
+    case ValueType::PrivateGCThing:
+      out.printf("<PrivateGCThing %p>", v.toGCThing());
+      break;
   }
 }
 
 namespace js {
 
 // We don't want jsfriendapi.h to depend on GenericPrinter,
 // so these functions are declared directly in the cpp.
 
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -277,17 +277,17 @@ static XDRResult XDRRelazificationInfo(X
     uint32_t sourceEnd = script->sourceEnd();
     uint32_t toStringStart = script->toStringStart();
     uint32_t toStringEnd = script->toStringEnd();
     uint32_t lineno = script->lineno();
     uint32_t column = script->column();
     uint32_t numFieldInitializers;
 
     if (mode == XDR_ENCODE) {
-      packedFields = lazy->packedFields();
+      packedFields = lazy->packedFieldsForXDR();
       MOZ_ASSERT(sourceStart == lazy->sourceStart());
       MOZ_ASSERT(sourceEnd == lazy->sourceEnd());
       MOZ_ASSERT(toStringStart == lazy->toStringStart());
       MOZ_ASSERT(toStringEnd == lazy->toStringEnd());
       MOZ_ASSERT(lineno == lazy->lineno());
       MOZ_ASSERT(column == lazy->column());
       // We can assert we have no inner functions because we don't
       // relazify scripts with inner functions.  See
@@ -313,21 +313,16 @@ static XDRResult XDRRelazificationInfo(X
         return xdr->fail(JS::TranscodeResult_Throw);
       }
 
       lazy->setToStringEnd(toStringEnd);
       if (numFieldInitializers != UINT32_MAX) {
         lazy->setFieldInitializers(
             FieldInitializers((size_t)numFieldInitializers));
       }
-
-      // As opposed to XDRLazyScript, we need to restore the runtime bits
-      // of the script, as we are trying to match the fact this function
-      // has already been parsed and that it would need to be re-lazified.
-      lazy->initRuntimeFields(packedFields);
     }
   }
 
   // Code binding names.
   MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy));
 
   // No need to do anything with inner functions, since we asserted we don't
   // have any.
@@ -1005,17 +1000,17 @@ XDRResult js::XDRLazyScript(XDRState<mod
       MOZ_ASSERT(fun == lazy->functionNonDelazifying());
 
       sourceStart = lazy->sourceStart();
       sourceEnd = lazy->sourceEnd();
       toStringStart = lazy->toStringStart();
       toStringEnd = lazy->toStringEnd();
       lineno = lazy->lineno();
       column = lazy->column();
-      packedFields = lazy->packedFields();
+      packedFields = lazy->packedFieldsForXDR();
       if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
         numFieldInitializers =
             (uint32_t)lazy->getFieldInitializers().numFieldInitializers;
       } else {
         numFieldInitializers = UINT32_MAX;
       }
     }
 
@@ -4820,33 +4815,46 @@ ScriptSourceObject& LazyScript::sourceOb
 
 ScriptSource* LazyScript::maybeForwardedScriptSource() const {
   JSObject* source = MaybeForwarded(&sourceObject());
   return UncheckedUnwrapWithoutExpose(source)
       ->as<ScriptSourceObject>()
       .source();
 }
 
+uint64_t LazyScript::packedFieldsForXDR() const {
+  union {
+    PackedView p;
+    uint64_t packedFields;
+  };
+
+  packedFields = packedFields_;
+
+  // Reset runtime flags
+  p.hasBeenCloned = false;
+
+  return packedFields;
+}
+
 /* static */ LazyScript* LazyScript::CreateRaw(
     JSContext* cx, HandleFunction fun, HandleScriptSourceObject sourceObject,
     uint64_t packedFields, uint32_t sourceStart, uint32_t sourceEnd,
     uint32_t toStringStart, uint32_t lineno, uint32_t column) {
   cx->check(fun);
 
   MOZ_ASSERT(sourceObject);
   union {
     PackedView p;
     uint64_t packed;
   };
 
   packed = packedFields;
 
   // Reset runtime flags to obtain a fresh LazyScript.
   p.hasBeenCloned = false;
-  p.treatAsRunOnce = false;
 
   size_t bytes = (p.numClosedOverBindings * sizeof(JSAtom*)) +
                  (p.numInnerFunctions * sizeof(GCPtrFunction));
 
   UniquePtr<uint8_t, JS::FreePolicy> table;
   if (bytes) {
     table.reset(cx->pod_malloc<uint8_t>(bytes));
     if (!table) {
@@ -4884,16 +4892,17 @@ ScriptSource* LazyScript::maybeForwarded
   p.numClosedOverBindings = closedOverBindings.length();
   p.numInnerFunctions = innerFunctions.length();
   p.isGenerator = false;
   p.strict = false;
   p.bindingsAccessedDynamically = false;
   p.hasDebuggerStatement = false;
   p.hasDirectEval = false;
   p.isLikelyConstructorWrapper = false;
+  p.treatAsRunOnce = false;
   p.isDerivedClassConstructor = false;
   p.needsHomeObject = false;
   p.isBinAST = false;
   p.parseGoal = uint32_t(parseGoal);
 
   LazyScript* res =
       LazyScript::CreateRaw(cx, fun, sourceObject, packedFields, sourceStart,
                             sourceEnd, toStringStart, lineno, column);
@@ -4962,27 +4971,16 @@ ScriptSource* LazyScript::maybeForwarded
   MOZ_ASSERT(!res->hasScript());
   if (script) {
     res->initScript(script);
   }
 
   return res;
 }
 
-void LazyScript::initRuntimeFields(uint64_t packedFields) {
-  union {
-    PackedView p;
-    uint64_t packed;
-  };
-
-  packed = packedFields;
-  p_.hasBeenCloned = p.hasBeenCloned;
-  p_.treatAsRunOnce = p.treatAsRunOnce;
-}
-
 void JSScript::updateJitCodeRaw(JSRuntime* rt) {
   MOZ_ASSERT(rt);
   if (hasBaselineScript() && baseline->hasPendingIonBuilder()) {
     MOZ_ASSERT(!isIonCompilingOffThread());
     jitCodeRaw_ = rt->jitRuntime()->lazyLinkStub().value;
     jitCodeSkipArgCheck_ = jitCodeRaw_;
   } else if (hasIonScript()) {
     jitCodeRaw_ = ion->method()->raw();
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2968,22 +2968,24 @@ class LazyScript : public gc::TenuredCel
     // MSVC. If you add another boolean here, make sure to initialize it in
     // LazyScript::Create().
     uint32_t isGenerator : 1;
     uint32_t strict : 1;
     uint32_t bindingsAccessedDynamically : 1;
     uint32_t hasDebuggerStatement : 1;
     uint32_t hasDirectEval : 1;
     uint32_t isLikelyConstructorWrapper : 1;
-    uint32_t hasBeenCloned : 1;
     uint32_t treatAsRunOnce : 1;
     uint32_t isDerivedClassConstructor : 1;
     uint32_t needsHomeObject : 1;
     uint32_t hasRest : 1;
     uint32_t parseGoal : 1;
+
+    // Runtime flags
+    uint32_t hasBeenCloned : 1;
   };
 
   union {
     PackedView p_;
     uint64_t packedFields_;
   };
 
   FieldInitializers fieldInitializers_;
@@ -3039,18 +3041,16 @@ class LazyScript : public gc::TenuredCel
   static LazyScript* CreateForXDR(JSContext* cx, HandleFunction fun,
                                   HandleScript script,
                                   HandleScope enclosingScope,
                                   HandleScriptSourceObject sourceObject,
                                   uint64_t packedData, uint32_t begin,
                                   uint32_t end, uint32_t toStringStart,
                                   uint32_t lineno, uint32_t column);
 
-  void initRuntimeFields(uint64_t packedFields);
-
   static inline JSFunction* functionDelazifying(JSContext* cx,
                                                 Handle<LazyScript*>);
   JSFunction* functionNonDelazifying() const { return function_; }
 
   JS::Compartment* compartment() const;
   JS::Compartment* maybeCompartment() const { return compartment(); }
   Realm* realm() const;
 
@@ -3213,17 +3213,17 @@ class LazyScript : public gc::TenuredCel
   void finalize(js::FreeOp* fop);
 
   static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
 
   size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
     return mallocSizeOf(table_);
   }
 
-  uint64_t packedFields() const { return packedFields_; }
+  uint64_t packedFieldsForXDR() const;
 };
 
 /* If this fails, add/remove padding within LazyScript. */
 static_assert(sizeof(LazyScript) % js::gc::CellAlignBytes == 0,
               "Size of LazyScript must be an integral multiple of "
               "js::gc::CellAlignBytes");
 
 struct ScriptAndCounts {
--- a/layout/base/ShapeUtils.cpp
+++ b/layout/base/ShapeUtils.cpp
@@ -135,17 +135,17 @@ nsSize ShapeUtils::ComputeEllipseRadii(c
   }
 
   return nsRect(x, y, width, height);
 }
 
 /* static */ bool ShapeUtils::ComputeInsetRadii(
     const StyleBasicShape& aBasicShape, const nsRect& aInsetRect,
     const nsRect& aRefBox, nscoord aRadii[8]) {
-  const nsStyleCorners& radius = aBasicShape.GetRadius();
+  const auto& radius = aBasicShape.GetRadius();
   return nsIFrame::ComputeBorderRadii(radius, aInsetRect.Size(), aRefBox.Size(),
                                       Sides(), aRadii);
 }
 
 /* static */ nsTArray<nsPoint> ShapeUtils::ComputePolygonVertices(
     const StyleBasicShape& aBasicShape, const nsRect& aRefBox) {
   MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Polygon,
              "The basic shape must be polygon()!");
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6857,30 +6857,25 @@ static ImgDrawResult DrawImageInternal(
 
   if (aOrientation == StyleImageOrientation::FromImage) {
     img = ImageOps::Orient(img, img->GetOrientation());
   }
 
   return img.forget();
 }
 
-static bool NonZeroStyleCoord(const nsStyleCoord& aCoord) {
-  if (aCoord.IsCoordPercentCalcUnit()) {
-    // Since negative results are clamped to 0, check > 0.
-    return aCoord.ComputeCoordPercentCalc(nscoord_MAX) > 0 ||
-           aCoord.ComputeCoordPercentCalc(0) > 0;
-  }
-
-  return true;
+static bool NonZeroCorner(const LengthPercentage& aLength) {
+  // Since negative results are clamped to 0, check > 0.
+  return aLength.Resolve(nscoord_MAX) > 0 || aLength.Resolve(0) > 0;
 }
 
 /* static */ bool nsLayoutUtils::HasNonZeroCorner(
-    const nsStyleCorners& aCorners) {
+    const BorderRadius& aCorners) {
   NS_FOR_CSS_HALF_CORNERS(corner) {
-    if (NonZeroStyleCoord(aCorners.Get(corner))) return true;
+    if (NonZeroCorner(aCorners.Get(corner))) return true;
   }
   return false;
 }
 
 // aCorner is a "full corner" value, i.e. eCornerTopLeft etc.
 static bool IsCornerAdjacentToSide(uint8_t aCorner, Side aSide) {
   static_assert((int)eSideTop == eCornerTopLeft, "Check for Full Corner");
   static_assert((int)eSideRight == eCornerTopRight, "Check for Full Corner");
@@ -6895,17 +6890,17 @@ static bool IsCornerAdjacentToSide(uint8
                 "Check for Full Corner");
   static_assert((int)eSideLeft == ((eCornerTopLeft - 1) & 3),
                 "Check for Full Corner");
 
   return aSide == aCorner || aSide == ((aCorner - 1) & 3);
 }
 
 /* static */ bool nsLayoutUtils::HasNonZeroCornerOnSide(
-    const nsStyleCorners& aCorners, Side aSide) {
+    const BorderRadius& aCorners, Side aSide) {
   static_assert(eCornerTopLeftX / 2 == eCornerTopLeft,
                 "Check for Non Zero on side");
   static_assert(eCornerTopLeftY / 2 == eCornerTopLeft,
                 "Check for Non Zero on side");
   static_assert(eCornerTopRightX / 2 == eCornerTopRight,
                 "Check for Non Zero on side");
   static_assert(eCornerTopRightY / 2 == eCornerTopRight,
                 "Check for Non Zero on side");
@@ -6916,17 +6911,17 @@ static bool IsCornerAdjacentToSide(uint8
   static_assert(eCornerBottomLeftX / 2 == eCornerBottomLeft,
                 "Check for Non Zero on side");
   static_assert(eCornerBottomLeftY / 2 == eCornerBottomLeft,
                 "Check for Non Zero on side");
 
   NS_FOR_CSS_HALF_CORNERS(corner) {
     // corner is a "half corner" value, so dividing by two gives us a
     // "full corner" value.
-    if (NonZeroStyleCoord(aCorners.Get(corner)) &&
+    if (NonZeroCorner(aCorners.Get(corner)) &&
         IsCornerAdjacentToSide(corner / 2, aSide))
       return true;
   }
   return false;
 }
 
 /* static */ nsTransparencyMode nsLayoutUtils::GetFrameTransparency(
     nsIFrame* aBackgroundFrame, nsIFrame* aCSSRootFrame) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -50,17 +50,16 @@ class nsDisplayItem;
 class nsFontMetrics;
 class nsFontFaceList;
 class nsIImageLoadingContent;
 class nsBlockFrame;
 class nsContainerFrame;
 class nsView;
 class nsIFrame;
 class nsStyleCoord;
-class nsStyleCorners;
 class nsPIDOMWindowOuter;
 class imgIRequest;
 struct nsStyleFont;
 struct nsOverflowAreas;
 
 namespace mozilla {
 class ComputedStyle;
 enum class PseudoStyleType : uint8_t;
@@ -1932,32 +1931,32 @@ class nsLayoutUtils {
    * @param aOrientation The desired orientation.
    */
   static already_AddRefed<imgIContainer> OrientImage(
       imgIContainer* aContainer,
       const mozilla::StyleImageOrientation& aOrientation);
 
   /**
    * Determine if any corner radius is of nonzero size
-   *   @param aCorners the |nsStyleCorners| object to check
+   *   @param aCorners the |BorderRadius| object to check
    *   @return true unless all the coordinates are 0%, 0 or null.
    *
    * A corner radius with one dimension zero and one nonzero is
    * treated as a nonzero-radius corner, even though it will end up
    * being rendered like a zero-radius corner.  This is because such
    * corners are not expected to appear outside of test cases, and it's
    * simpler to implement the test this way.
    */
-  static bool HasNonZeroCorner(const nsStyleCorners& aCorners);
+  static bool HasNonZeroCorner(const mozilla::BorderRadius& aCorners);
 
   /**
    * Determine if there is any corner radius on corners adjacent to the
    * given side.
    */
-  static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners,
+  static bool HasNonZeroCornerOnSide(const mozilla::BorderRadius& aCorners,
                                      mozilla::Side aSide);
 
   /**
    * Determine if a widget is likely to require transparency or translucency.
    *   @param aBackgroundFrame The frame that the background is set on. For
    *                           <window>s, this will be the canvas frame.
    *   @param aCSSRootFrame    The frame that holds CSS properties affecting
    *                           the widget's transparency. For menupopups,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1639,35 +1639,25 @@ nsRect nsIFrame::GetContentRectRelativeT
   r.Deflate(bp);
   return r;
 }
 
 nsRect nsIFrame::GetContentRect() const {
   return GetContentRectRelativeToSelf() + GetPosition();
 }
 
-bool nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
+bool nsIFrame::ComputeBorderRadii(const BorderRadius& aBorderRadius,
                                   const nsSize& aFrameSize,
                                   const nsSize& aBorderArea, Sides aSkipSides,
                                   nscoord aRadii[8]) {
   // Percentages are relative to whichever side they're on.
   NS_FOR_CSS_HALF_CORNERS(i) {
-    const nsStyleCoord c = aBorderRadius.Get(i);
+    const LengthPercentage& c = aBorderRadius.Get(i);
     nscoord axis = HalfCornerIsX(i) ? aFrameSize.width : aFrameSize.height;
-
-    if (c.IsCoordPercentCalcUnit()) {
-      aRadii[i] = c.ComputeCoordPercentCalc(axis);
-      if (aRadii[i] < 0) {
-        // clamp calc()
-        aRadii[i] = 0;
-      }
-    } else {
-      MOZ_ASSERT_UNREACHABLE("ComputeBorderRadii: bad unit");
-      aRadii[i] = 0;
-    }
+    aRadii[i] = std::max(0, c.Resolve(axis));
   }
 
   if (aSkipSides.Top()) {
     aRadii[eCornerTopLeftX] = 0;
     aRadii[eCornerTopLeftY] = 0;
     aRadii[eCornerTopRightX] = 0;
     aRadii[eCornerTopRightY] = 0;
   }
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1358,17 +1358,17 @@ class nsIFrame : public nsQueryFrame {
    * aBorderArea is used for the adjustment of radii that might be too
    * large.
    * FIXME: In the long run, we can probably get away with only one of
    * these, especially if we change the way we handle outline-radius (by
    * removing it and inflating the border radius)
    *
    * Return whether any radii are nonzero.
    */
-  static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
+  static bool ComputeBorderRadii(const mozilla::BorderRadius&,
                                  const nsSize& aFrameSize,
                                  const nsSize& aBorderArea, Sides aSkipSides,
                                  nscoord aRadii[8]);
 
   /*
    * Given a set of border radii for one box (e.g., border box), convert
    * it to the equivalent set of radii for another box (e.g., in to
    * padding box, out to outline box) by reducing radii or increasing
--- a/layout/reftests/xul/accesskey.xul
+++ b/layout/reftests/xul/accesskey.xul
@@ -20,24 +20,24 @@ function changeKeys()
 
   document.documentElement.className='';
 }
 
 ]]>
 </script>
 
 <hbox align="start">
-  <label control="b1">Label1</label><textbox id="b1" accesskey="L" size="2"/>
-  <label control="b2">Label2</label><textbox id="b2" accesskey="l" size="2"/>
-  <label control="b3">Label3</label><textbox id="b3" accesskey="b" size="2"/>
-  <label control="b4">Label4</label><textbox id="b4" accesskey="x" size="2"/>
-  <label control="b5" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="b5" accesskey="l" size="2"/>
+  <label control="b1" accesskey="L">Label1</label><textbox id="b1" size="2"/>
+  <label control="b2" accesskey="l">Label2</label><textbox id="b2" size="2"/>
+  <label control="b3" accesskey="b">Label3</label><textbox id="b3" size="2"/>
+  <label control="b4" accesskey="x">Label4</label><textbox id="b4" size="2"/>
+  <label control="b5" accesskey="l" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="b5" size="2"/>
 </hbox>
 
 <hbox id="d" align="start">
-  <label control="d1">Label1</label><textbox id="d1" accesskey="z" size="2"/>
+  <label control="d1" accesskey="z">Label1</label><textbox id="d1" size="2"/>
   <label control="d2">Label2</label><textbox id="d2" size="2"/>
-  <label control="d3">Label3</label><textbox id="d3" accesskey="t" size="2"/>
-  <label control="d4">Label4</label><textbox id="d4" accesskey="b" size="2"/>
-  <label control="d5" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="d5" accesskey="l" size="2"/>
+  <label control="d3" accesskey="t">Label3</label><textbox id="d3" size="2"/>
+  <label control="d4" accesskey="b">Label4</label><textbox id="d4" size="2"/>
+  <label control="d5" accesskey="l" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="d5" size="2"/>
 </hbox>
 
 </window>
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -508,16 +508,18 @@ RawServoDeclarationBlockStrong Servo_Par
     RawGeckoURLExtraData* data, mozilla::ParsingMode parsing_mode,
     nsCompatibility quirks_mode, mozilla::css::Loader* loader);
 
 bool Servo_ParseEasing(const nsAString* easing, RawGeckoURLExtraData* data,
                        nsTimingFunctionBorrowedMut output);
 
 void Servo_SerializeEasing(nsTimingFunctionBorrowed easing, nsAString* output);
 
+void Servo_SerializeBorderRadius(const mozilla::StyleBorderRadius*, nsAString*);
+
 void Servo_GetComputedKeyframeValues(
     RawGeckoKeyframeListBorrowed keyframes, RawGeckoElementBorrowed element,
     ComputedStyleBorrowed style, RawServoStyleSetBorrowed set,
     RawGeckoComputedKeyframeValuesListBorrowedMut result);
 
 RawServoAnimationValueStrong Servo_ComputedValues_ExtractAnimationValue(
     ComputedStyleBorrowed computed_values, nsCSSPropertyID property);
 
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -439,16 +439,17 @@ cbindgen-types = [
     { gecko = "StyleNonNegativeLength", servo = "values::computed::NonNegativeLength" },
     { gecko = "StyleNonNegativeNumber", servo = "values::computed::NonNegativeNumber" },
     { gecko = "StylePercentage", servo = "values::computed::Percentage" },
     { gecko = "StylePerspective", servo = "values::computed::Perspective" },
     { gecko = "StyleGenericPerspective", servo = "values::generics::box_::Perspective" },
     { gecko = "StyleZIndex", servo = "values::computed::ZIndex" },
     { gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
     { gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
+    { gecko = "StyleGenericBorderRadius", servo = "values::generics::border::BorderRadius" },
 ]
 
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::RustCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
@@ -497,16 +498,17 @@ structs-types = [
     "mozilla::CORSMode",
     "mozilla::FontStretch",
     "mozilla::FontSlantStyle",
     "mozilla::FontWeight",
     "mozilla::MallocSizeOf",
     "mozilla::OriginFlags",
     "mozilla::StyleMotion",
     "mozilla::UniquePtr",
+    "mozilla::StyleBorderRadius",
     "mozilla::StyleDisplayMode",
     "mozilla::StylePrefersColorScheme",
     "mozilla::StyleIntersectionObserverRootMargin",
     "mozilla::StyleComputedFontStretchRange",
     "mozilla::StyleComputedFontStyleDescriptor",
     "mozilla::StyleComputedFontWeightRange",
     "mozilla::StyleFontDisplay",
     "mozilla::StyleUnicodeRange",
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1897,34 +1897,34 @@ already_AddRefed<CSSValue> nsComputedDOM
   return GetEllipseRadii(StyleOutline()->mOutlineRadius, eCornerTopLeft);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetOutlineRadiusTopRight() {
   return GetEllipseRadii(StyleOutline()->mOutlineRadius, eCornerTopRight);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::GetEllipseRadii(
-    const nsStyleCorners& aRadius, Corner aFullCorner) {
-  nsStyleCoord radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
-  nsStyleCoord radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
+    const BorderRadius& aRadius, Corner aFullCorner) {
+  const auto& radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
+  const auto& radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
 
   // for compatibility, return a single value if X and Y are equal
   if (radiusX == radiusY) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-    SetValueToCoord(val, radiusX, true);
+    SetValueToLengthPercentage(val, radiusX, true);
     return val.forget();
   }
 
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
   RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
   RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
 
-  SetValueToCoord(valX, radiusX, true);
-  SetValueToCoord(valY, radiusY, true);
+  SetValueToLengthPercentage(valX, radiusX, true);
+  SetValueToLengthPercentage(valY, radiusY, true);
 
   valueList->AppendCSSValue(valX.forget());
   valueList->AppendCSSValue(valY.forget());
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::GetCSSShadowArray(
@@ -3268,32 +3268,19 @@ void nsComputedDOMStyle::BoxValuesToStri
       if (value2 != value4) {
         aString.Append(' ');
         aString.Append(value4);
       }
     }
   }
 }
 
-void nsComputedDOMStyle::BasicShapeRadiiToString(
-    nsAString& aCssText, const nsStyleCorners& aCorners) {
-  nsTArray<nsStyleCoord> horizontal, vertical;
-  nsAutoString horizontalString, verticalString;
-  NS_FOR_CSS_FULL_CORNERS(corner) {
-    horizontal.AppendElement(aCorners.Get(FullToHalfCorner(corner, false)));
-    vertical.AppendElement(aCorners.Get(FullToHalfCorner(corner, true)));
-  }
-  BoxValuesToString(horizontalString, horizontal, true);
-  BoxValuesToString(verticalString, vertical, true);
-  aCssText.Append(horizontalString);
-  if (horizontalString == verticalString) {
-    return;
-  }
-  aCssText.AppendLiteral(" / ");
-  aCssText.Append(verticalString);
+void nsComputedDOMStyle::BasicShapeRadiiToString(nsAString& aCssText,
+                                                 const BorderRadius& aCorners) {
+  Servo_SerializeBorderRadius(&aCorners, &aCssText);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::CreatePrimitiveValueForBasicShape(
     const UniquePtr<StyleBasicShape>& aStyleBasicShape) {
   MOZ_ASSERT(aStyleBasicShape, "Expect a valid basic shape pointer!");
 
   StyleBasicShapeType type = aStyleBasicShape->GetShapeType();
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -36,17 +36,16 @@ struct ComputedGridTrackInfo;
 struct ComputedStyleMap;
 struct nsCSSKTableEntry;
 class nsIFrame;
 class nsIPresShell;
 class nsDOMCSSValueList;
 struct nsMargin;
 class nsROCSSPrimitiveValue;
 class nsStyleCoord;
-class nsStyleCorners;
 struct nsStyleFilter;
 class nsStyleGradient;
 struct nsStyleImage;
 class nsStyleSides;
 
 class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
                                  public nsStubMutationObserver {
  private:
@@ -165,21 +164,20 @@ class nsComputedDOMStyle final : public 
 #undef STYLE_STRUCT
 
   /**
    * A method to get a percentage base for a percentage value.  Returns true
    * if a percentage base value was determined, false otherwise.
    */
   typedef bool (nsComputedDOMStyle::*PercentageBaseGetter)(nscoord&);
 
-  already_AddRefed<CSSValue> GetEllipseRadii(const nsStyleCorners& aRadius,
+  already_AddRefed<CSSValue> GetEllipseRadii(const mozilla::BorderRadius&,
                                              mozilla::Corner aFullCorner);
 
-  already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side aSide);
-
+  already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side);
   already_AddRefed<CSSValue> GetAbsoluteOffset(mozilla::Side);
   nscoord GetUsedAbsoluteOffset(mozilla::Side);
   already_AddRefed<CSSValue> GetNonStaticPositionOffset(
       mozilla::Side aSide, bool aResolveAuto, PercentageBaseGetter aWidthGetter,
       PercentageBaseGetter aHeightGetter);
 
   already_AddRefed<CSSValue> GetStaticOffset(mozilla::Side aSide);
 
@@ -291,16 +289,17 @@ class nsComputedDOMStyle final : public 
   already_AddRefed<CSSValue> DoGetBorderBottomWidth();
   already_AddRefed<CSSValue> DoGetBorderLeftWidth();
   already_AddRefed<CSSValue> DoGetBorderRightWidth();
   already_AddRefed<CSSValue> DoGetBorderBottomLeftRadius();
   already_AddRefed<CSSValue> DoGetBorderBottomRightRadius();
   already_AddRefed<CSSValue> DoGetBorderTopLeftRadius();
   already_AddRefed<CSSValue> DoGetBorderTopRightRadius();
 
+
   /* Border Image */
   already_AddRefed<CSSValue> DoGetBorderImageWidth();
 
   /* Box Shadow */
   already_AddRefed<CSSValue> DoGetBoxShadow();
 
   /* Margin Properties */
   already_AddRefed<CSSValue> DoGetMarginTopWidth();
@@ -310,16 +309,17 @@ class nsComputedDOMStyle final : public 
 
   /* Outline Properties */
   already_AddRefed<CSSValue> DoGetOutlineWidth();
   already_AddRefed<CSSValue> DoGetOutlineRadiusBottomLeft();
   already_AddRefed<CSSValue> DoGetOutlineRadiusBottomRight();
   already_AddRefed<CSSValue> DoGetOutlineRadiusTopLeft();
   already_AddRefed<CSSValue> DoGetOutlineRadiusTopRight();
 
+
   /* Text Properties */
   already_AddRefed<CSSValue> DoGetInitialLetter();
   already_AddRefed<CSSValue> DoGetLineHeight();
   already_AddRefed<CSSValue> DoGetTextDecoration();
   already_AddRefed<CSSValue> DoGetTextDecorationColor();
   already_AddRefed<CSSValue> DoGetTextDecorationLine();
   already_AddRefed<CSSValue> DoGetTextDecorationStyle();
   already_AddRefed<CSSValue> DoGetTextEmphasisPosition();
@@ -491,17 +491,17 @@ class nsComputedDOMStyle final : public 
 
   // Helper function for computing basic shape styles.
   already_AddRefed<CSSValue> CreatePrimitiveValueForBasicShape(
       const mozilla::UniquePtr<mozilla::StyleBasicShape>& aStyleBasicShape);
   void BoxValuesToString(nsAString& aString,
                          const nsTArray<nsStyleCoord>& aBoxValues,
                          bool aClampNegativeCalc);
   void BasicShapeRadiiToString(nsAString& aCssText,
-                               const nsStyleCorners& aCorners);
+                               const mozilla::BorderRadius&);
 
   // Find out if we can safely skip flushing for aDocument (i.e. pending
   // restyles does not affect mContent).
   bool NeedsToFlush(Document*) const;
 
   static ComputedStyleMap* GetComputedStyleMap();
 
   // We don't really have a good immutable representation of "presentation".
--- a/layout/style/nsStyleCoord.cpp
+++ b/layout/style/nsStyleCoord.cpp
@@ -198,52 +198,16 @@ bool nsStyleSides::operator==(const nsSt
   }
   return true;
 }
 
 void nsStyleSides::Reset() {
   NS_FOR_CSS_SIDES(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
 }
 
-nsStyleCorners::nsStyleCorners() {
-  NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
-  mozilla::PodArrayZero(mValues);
-}
-
-nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther) {
-  NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
-  *this = aOther;
-}
-
-nsStyleCorners::~nsStyleCorners() { Reset(); }
-
-nsStyleCorners& nsStyleCorners::operator=(const nsStyleCorners& aCopy) {
-  if (this != &aCopy) {
-    NS_FOR_CSS_HALF_CORNERS(i) {
-      nsStyleCoord::SetValue(mUnits[i], mValues[i], aCopy.mUnits[i],
-                             aCopy.mValues[i]);
-    }
-  }
-  return *this;
-}
-
-bool nsStyleCorners::operator==(const nsStyleCorners& aOther) const {
-  NS_FOR_CSS_HALF_CORNERS(i) {
-    if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
-        nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
-      return false;
-    }
-  }
-  return true;
-}
-
-void nsStyleCorners::Reset() {
-  NS_FOR_CSS_HALF_CORNERS(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
-}
-
 // Validation of SideIsVertical.
 #define CASE(side, result) \
   static_assert(SideIsVertical(side) == result, "SideIsVertical is wrong")
 CASE(eSideTop, false);
 CASE(eSideRight, true);
 CASE(eSideBottom, false);
 CASE(eSideLeft, true);
 #undef CASE
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -39,16 +39,17 @@ enum LogicalCorner {
   eLogicalCornerBEndIStart = 3
 };
 
 using LengthPercentage = StyleLengthPercentage;
 using LengthPercentageOrAuto = StyleLengthPercentageOrAuto;
 using NonNegativeLengthPercentage = StyleNonNegativeLengthPercentage;
 using NonNegativeLengthPercentageOrAuto =
     StyleNonNegativeLengthPercentageOrAuto;
+using BorderRadius = StyleBorderRadius;
 
 nscoord StyleCSSPixelLength::ToAppUnits() const {
   // We want to resolve the length part of the calc() expression rounding 0.5
   // away from zero, instead of the default behavior of NSToCoordRoundWithClamp
   // which is floor(x + 0.5).
   //
   // This is what the rust code in the app_units crate does, and not doing this
   // would regress bug 1323735, for example.
@@ -246,16 +247,24 @@ bool StyleRect<T>::All(Predicate aPredic
 }
 
 template <typename T>
 template <typename Predicate>
 bool StyleRect<T>::Any(Predicate aPredicate) const {
   return aPredicate(_0) || aPredicate(_1) || aPredicate(_2) || aPredicate(_3);
 }
 
+template <>
+inline const LengthPercentage& BorderRadius::Get(HalfCorner aCorner) const {
+  static_assert(sizeof(BorderRadius) == sizeof(LengthPercentage) * 8, "");
+  static_assert(alignof(BorderRadius) == alignof(LengthPercentage), "");
+  auto* self = reinterpret_cast<const LengthPercentage*>(this);
+  return self[aCorner];
+}
+
 }  // namespace mozilla
 
 enum nsStyleUnit : uint8_t {
   eStyleUnit_Null = 0,           // (no value) value is not specified
   eStyleUnit_Normal = 1,         // (no value)
   eStyleUnit_Auto = 2,           // (no value)
   eStyleUnit_None = 3,           // (no value)
   eStyleUnit_Percent = 10,       // (float) 1.0 == 100%
@@ -584,55 +593,16 @@ class nsStyleSides {
     return true;
   }
 
  protected:
   nsStyleUnit mUnits[4];
   nsStyleUnion mValues[4];
 };
 
-/**
- * Class that represents a set of top-left/top-right/bottom-right/bottom-left
- * nsStyleCoord pairs.  This is used to hold the dimensions of the
- * corners of a box (for, e.g., border-radius and outline-radius).
- */
-/** <div rustbindgen private accessor="unsafe"></div> */
-class nsStyleCorners {
- public:
-  nsStyleCorners();
-  nsStyleCorners(const nsStyleCorners&);
-  ~nsStyleCorners();
-
-  // use compiler's version
-  nsStyleCorners& operator=(const nsStyleCorners& aCopy);
-  bool operator==(const nsStyleCorners& aOther) const;
-  bool operator!=(const nsStyleCorners& aOther) const;
-
-  // aHalfCorner is always one of enum HalfCorner in gfx/2d/Types.h.
-  inline nsStyleUnit GetUnit(uint8_t aHalfCorner) const;
-
-  inline nsStyleCoord Get(uint8_t aHalfCorner) const;
-
-  // Sets each corner to null and releases any refcounted objects.  Only use
-  // this if the object is initialized (i.e. don't use it in nsStyleCorners
-  // constructors).
-  void Reset();
-
-  inline void Set(uint8_t aHalfCorner, const nsStyleCoord& aCoord);
-
- protected:
-  // Stored as:
-  // top-left.x, top-left.y,
-  // top-right.x, top-right.y,
-  // bottom-right.x, bottom-right.y,
-  // bottom-left.x, bottom-left.y
-  nsStyleUnit mUnits[8];
-  nsStyleUnion mValues[8];
-};
-
 // -------------------------
 // nsStyleCoord inlines
 //
 inline nsStyleCoord::nsStyleCoord(nscoord aValue, CoordConstructorType)
     : mUnit(eStyleUnit_Coord) {
   mValue.mInt = aValue;
 }
 
@@ -825,29 +795,9 @@ inline void nsStyleSides::SetTop(const n
 
 inline void nsStyleSides::SetRight(const nsStyleCoord& aCoord) {
   Set(mozilla::eSideRight, aCoord);
 }
 
 inline void nsStyleSides::SetBottom(const nsStyleCoord& aCoord) {
   Set(mozilla::eSideBottom, aCoord);
 }
-
-// -------------------------
-// nsStyleCorners inlines
-//
-inline bool nsStyleCorners::operator!=(const nsStyleCorners& aOther) const {
-  return !((*this) == aOther);
-}
-
-inline nsStyleUnit nsStyleCorners::GetUnit(uint8_t aCorner) const {
-  return (nsStyleUnit)mUnits[aCorner];
-}
-
-inline nsStyleCoord nsStyleCorners::Get(uint8_t aCorner) const {
-  return nsStyleCoord(mValues[aCorner], nsStyleUnit(mUnits[aCorner]));
-}
-
-inline void nsStyleCorners::Set(uint8_t aCorner, const nsStyleCoord& aCoord) {
-  nsStyleCoord::SetValue(mUnits[aCorner], mValues[aCorner], aCoord);
-}
-
 #endif /* nsStyleCoord_h___ */
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -237,38 +237,40 @@ nsChangeHint nsStylePadding::CalcDiffere
   return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
 }
 
 static nscoord TwipsPerPixel(const Document& aDocument) {
   auto* pc = aDocument.GetPresContext();
   return pc ? pc->AppUnitsPerDevPixel() : mozilla::AppUnitsPerCSSPixel();
 }
 
+static inline BorderRadius ZeroBorderRadius() {
+  auto zero = LengthPercentage::Zero();
+  return {{{zero, zero}}, {{zero, zero}}, {{zero, zero}}, {{zero, zero}}};
+}
+
 nsStyleBorder::nsStyleBorder(const Document& aDocument)
-    : mBorderImageOutset(
+    : mBorderRadius(ZeroBorderRadius()),
+      mBorderImageOutset(
           StyleRectWithAllSides(StyleNonNegativeLengthOrNumber::Number(0.))),
       mBorderImageSlice(
           {StyleRectWithAllSides(StyleNumberOrPercentage::Percentage({1.})),
            false}),
       mBorderImageRepeatH(StyleBorderImageRepeat::Stretch),
       mBorderImageRepeatV(StyleBorderImageRepeat::Stretch),
       mFloatEdge(StyleFloatEdge::ContentBox),
       mBoxDecorationBreak(StyleBoxDecorationBreak::Slice),
       mBorderTopColor(StyleComplexColor::CurrentColor()),
       mBorderRightColor(StyleComplexColor::CurrentColor()),
       mBorderBottomColor(StyleComplexColor::CurrentColor()),
       mBorderLeftColor(StyleComplexColor::CurrentColor()),
       mComputedBorder(0, 0, 0, 0),
       mTwipsPerPixel(TwipsPerPixel(aDocument)) {
   MOZ_COUNT_CTOR(nsStyleBorder);
 
-  NS_FOR_CSS_HALF_CORNERS(corner) {
-    mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
-  }
-
   nscoord medium = kMediumBorderWidth;
   NS_FOR_CSS_SIDES(side) {
     mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
     mBorder.Side(side) = medium;
     mBorderStyle[side] = StyleBorderStyle::None;
   }
 }
 
@@ -395,26 +397,24 @@ nsChangeHint nsStyleBorder::CalcDifferen
       mBorderImageWidth != aNewData.mBorderImageWidth) {
     return nsChangeHint_NeutralChange;
   }
 
   return nsChangeHint(0);
 }
 
 nsStyleOutline::nsStyleOutline(const Document& aDocument)
-    : mOutlineWidth(kMediumBorderWidth),
+    : mOutlineRadius(ZeroBorderRadius()),
+      mOutlineWidth(kMediumBorderWidth),
       mOutlineOffset(0),
       mOutlineColor(StyleComplexColor::CurrentColor()),
       mOutlineStyle(StyleOutlineStyle::BorderStyle(StyleBorderStyle::None)),
       mActualOutlineWidth(0),
       mTwipsPerPixel(TwipsPerPixel(aDocument)) {
   MOZ_COUNT_CTOR(nsStyleOutline);
-  // spacing values not inherited
-  nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
-  NS_FOR_CSS_HALF_CORNERS(corner) { mOutlineRadius.Set(corner, zero); }
 }
 
 nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
     : mOutlineRadius(aSrc.mOutlineRadius),
       mOutlineWidth(aSrc.mOutlineWidth),
       mOutlineOffset(aSrc.mOutlineOffset),
       mOutlineColor(aSrc.mOutlineColor),
       mOutlineStyle(aSrc.mOutlineStyle),
@@ -777,16 +777,22 @@ nsChangeHint nsStyleSVG::CalcDifference(
   }
 
   return hint;
 }
 
 // --------------------
 // StyleBasicShape
 
+StyleBasicShape::StyleBasicShape(StyleBasicShapeType aType)
+    : mType(aType),
+      mFillRule(StyleFillRule::Nonzero),
+      mPosition(Position::FromPercentage(0.5f)),
+      mRadius(ZeroBorderRadius()) {}
+
 nsCSSKeyword StyleBasicShape::GetShapeTypeName() const {
   switch (mType) {
     case StyleBasicShapeType::Polygon:
       return eCSSKeyword_polygon;
     case StyleBasicShapeType::Circle:
       return eCSSKeyword_circle;
     case StyleBasicShapeType::Ellipse:
       return eCSSKeyword_ellipse;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -938,17 +938,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   imgIRequest* GetBorderImageRequest() const {
     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
       return mBorderImageSource.GetImageData();
     }
     return nullptr;
   }
 
  public:
-  nsStyleCorners mBorderRadius;  // coord, percent
+  mozilla::StyleBorderRadius mBorderRadius;  // coord, percent
   nsStyleImage mBorderImageSource;
   nsStyleSides mBorderImageWidth;  // length, factor, percent, auto
   mozilla::StyleNonNegativeLengthOrNumberRect mBorderImageOutset;
   mozilla::StyleBorderImageSlice mBorderImageSlice;  // factor, percent
   mozilla::StyleBorderImageRepeat mBorderImageRepeatH;
   mozilla::StyleBorderImageRepeat mBorderImageRepeatV;
   mozilla::StyleFloatEdge mFloatEdge;
   mozilla::StyleBoxDecorationBreak mBoxDecorationBreak;
@@ -1042,17 +1042,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   explicit nsStyleOutline(const mozilla::dom::Document&);
   nsStyleOutline(const nsStyleOutline& aOutline);
   ~nsStyleOutline() { MOZ_COUNT_DTOR(nsStyleOutline); }
   void TriggerImageLoads(mozilla::dom::Document&, const nsStyleOutline*) {}
   const static bool kHasTriggerImageLoads = false;
 
   nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
 
-  nsStyleCorners mOutlineRadius;  // coord, percent, calc
+  mozilla::StyleBorderRadius mOutlineRadius;
 
   // This is the specified value of outline-width, but with length values
   // computed to absolute.  mActualOutlineWidth stores the outline-width
   // value used by layout.  (We must store mOutlineWidth for the same
   // style struct resolution reasons that we do nsStyleBorder::mBorder;
   // see that field's comment.)
   nscoord mOutlineWidth;
   nscoord mOutlineOffset;
@@ -1286,19 +1286,19 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   // mSpecifiedJustifyItems, except when the latter is AUTO -- in that case,
   // mJustifyItems is set to NORMAL, or to the parent ComputedStyle's
   // mJustifyItems if it has the legacy flag.
   //
   // This last part happens in ComputedStyle::ApplyStyleFixups.
   uint8_t mSpecifiedJustifyItems;
   uint8_t mJustifyItems;
   uint8_t mJustifySelf;
-  mozilla::StyleFlexDirection mFlexDirection;  
-  uint8_t mFlexWrap;       // NS_STYLE_FLEX_WRAP_*
-  uint8_t mObjectFit;      // NS_STYLE_OBJECT_FIT_*
+  mozilla::StyleFlexDirection mFlexDirection;
+  uint8_t mFlexWrap;   // NS_STYLE_FLEX_WRAP_*
+  uint8_t mObjectFit;  // NS_STYLE_OBJECT_FIT_*
   int32_t mOrder;
   float mFlexGrow;
   float mFlexShrink;
   mozilla::StyleZIndex mZIndex;
   mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateColumns;
   mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateRows;
 
   // nullptr for 'none'
@@ -1630,46 +1630,42 @@ struct StyleAnimation {
   dom::PlaybackDirection mDirection;
   dom::FillMode mFillMode;
   StyleAnimationPlayState mPlayState;
   float mIterationCount;  // mozilla::PositiveInfinity<float>() means infinite
 };
 
 class StyleBasicShape final {
  public:
-  explicit StyleBasicShape(StyleBasicShapeType type)
-      : mType(type),
-        mFillRule(StyleFillRule::Nonzero),
-        mPosition(Position::FromPercentage(0.5f)) {}
+  explicit StyleBasicShape(StyleBasicShapeType);
 
   StyleBasicShapeType GetShapeType() const { return mType; }
   nsCSSKeyword GetShapeTypeName() const;
 
   StyleFillRule GetFillRule() const { return mFillRule; }
 
   const mozilla::Position& GetPosition() const {
     MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
                    mType == StyleBasicShapeType::Ellipse,
                "expected circle or ellipse");
     return mPosition;
   }
 
   bool HasRadius() const {
     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
-    nsStyleCoord zero;
-    zero.SetCoordValue(0);
     NS_FOR_CSS_HALF_CORNERS(corner) {
-      if (mRadius.Get(corner) != zero) {
+      auto& radius = mRadius.Get(corner);
+      if (radius.HasPercent() || radius.LengthInCSSPixels() != 0.0f) {
         return true;
       }
     }
     return false;
   }
 
-  const nsStyleCorners& GetRadius() const {
+  const mozilla::StyleBorderRadius& GetRadius() const {
     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
     return mRadius;
   }
 
   // mCoordinates has coordinates for polygon or radii for
   // ellipse and circle.
   const nsTArray<nsStyleCoord>& Coordinates() const { return mCoordinates; }
 
@@ -1688,17 +1684,17 @@ class StyleBasicShape final {
 
   // mCoordinates has coordinates for polygon or radii for
   // ellipse and circle.
   // (top, right, bottom, left) for inset
   nsTArray<nsStyleCoord> mCoordinates;
   // position of center for ellipse or circle
   mozilla::Position mPosition;
   // corner radii for inset (0 if not set)
-  nsStyleCorners mRadius;
+  mozilla::StyleBorderRadius mRadius;
 };
 
 struct StyleSVGPath final {
   const nsTArray<StylePathCommand>& Path() const { return mPath; }
 
   StyleFillRule FillRule() const { return mFillRule; }
 
   bool operator==(const StyleSVGPath& aOther) const {
--- a/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
@@ -337,22 +337,22 @@ public final class IntentHelper implemen
         if ("intent".equals(scheme) || "android-app".equals(scheme)) {
             return IntentUtils.getSafeIntent(uri);
         }
 
         // Compute our most likely intent, then check to see if there are any
         // custom handlers that would apply.
         // Start with the original URI. If we end up modifying it, we'll
         // overwrite it.
-        final String extension = MimeTypeMap.getFileExtensionFromUrl(targetURI);
         final Intent intent = getIntentForActionString(action);
         intent.setData(uri);
 
         if ("file".equals(scheme)) {
             // Only set explicit mimeTypes on file://.
+            final String extension = MimeTypeMap.getFileExtensionFromUrl(targetURI);
             final String mimeType2 = GeckoAppShell.getMimeTypeFromExtension(extension);
             intent.setType(mimeType2);
             return intent;
         }
 
         // Have a special handling for SMS based schemes, as the query parameters
         // are not extracted from the URI automatically.
         if (!"sms".equals(scheme) && !"smsto".equals(scheme) && !"mms".equals(scheme) && !"mmsto".equals(scheme)) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
@@ -50,16 +50,18 @@ public class PanZoomController extends J
      * Specifies auto scrolling which jumps content to the desired scroll position.
      */
     public static final int SCROLL_BEHAVIOR_AUTO = 1;
 
     private SynthesizedEventState mPointerState;
 
     private ArrayList<Pair<Integer, MotionEvent>> mQueuedEvents;
 
+    private boolean mSynthesizedEvent = false;
+
     @WrapForJNI(calledFrom = "ui")
     private native boolean handleMotionEvent(
             int action, int actionIndex, long time, int metaState,  float screenX, float screenY,
             int pointerId[], float x[], float y[], float orientation[], float pressure[],
             float toolMajor[], float toolMinor[]);
 
     @WrapForJNI(calledFrom = "ui")
     private native boolean handleScrollEvent(
@@ -112,17 +114,20 @@ public class PanZoomController extends J
             toolMinor[i] = coords.toolMinor;
         }
 
         final float screenX = event.getRawX() - event.getX();
         final float screenY = event.getRawY() - event.getY();
 
         // Take this opportunity to update screen origin of session. This gets
         // dispatched to the gecko thread, so we also pass the new screen x/y directly to apz.
-        mSession.onScreenOriginChanged((int)screenX, (int)screenY);
+        // If this is a synthesized touch, the screen offset is bogus so ignore it.
+        if (!mSynthesizedEvent) {
+            mSession.onScreenOriginChanged((int)screenX, (int)screenY);
+        }
 
         return handleMotionEvent(action, event.getActionIndex(), event.getEventTime(),
                 event.getMetaState(), screenX, screenY, pointerId, x, y, orientation, pressure,
                 toolMajor, toolMinor);
     }
 
     private boolean handleScrollEvent(MotionEvent event) {
         if (!mAttached) {
@@ -515,17 +520,20 @@ public class PanZoomController extends J
             /*metaState*/ 0,
             /*buttonState*/ (isButtonDown ? MotionEvent.BUTTON_PRIMARY : 0),
             /*xPrecision*/ 0,
             /*yPrecision*/ 0,
             /*deviceId*/ 0,
             /*edgeFlags*/ 0,
             /*source*/ source,
             /*flags*/ 0);
+
+        mSynthesizedEvent = true;
         onTouchEvent(event);
+        mSynthesizedEvent = false;
 
         // Forget about removed pointers
         if (eventType == MotionEvent.ACTION_POINTER_UP ||
             eventType == MotionEvent.ACTION_UP ||
             eventType == MotionEvent.ACTION_CANCEL ||
             eventType == MotionEvent.ACTION_HOVER_MOVE)
         {
             mPointerState.pointers.remove(pointerIndex);
--- a/mobile/android/modules/HelperApps.jsm
+++ b/mobile/android/modules/HelperApps.jsm
@@ -15,99 +15,112 @@ ChromeUtils.defineModuleGetter(this, "Ev
                                "resource://gre/modules/Messaging.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() {
   let ContentAreaUtils = {};
   Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", ContentAreaUtils);
   return ContentAreaUtils;
 });
 
+const NON_FILE_URI_IGNORED_MIME_TYPES = new Set([
+  "text/html",
+  "application/xhtml+xml",
+]);
+
 var EXPORTED_SYMBOLS = ["App", "HelperApps"];
 
-function App(data) {
-  this.name = data.name;
-  this.isDefault = data.isDefault;
-  this.packageName = data.packageName;
-  this.activityName = data.activityName;
-  this.iconUri = "-moz-icon://" + data.packageName;
-}
+class App {
+  constructor(data) {
+    this.name = data.name;
+    this.isDefault = data.isDefault;
+    this.packageName = data.packageName;
+    this.activityName = data.activityName;
+    this.iconUri = "-moz-icon://" + data.packageName;
+  }
 
-App.prototype = {
   // callback will be null if a result is not requested
-  launch: function(uri, callback) {
+  launch(uri, callback) {
     HelperApps._launchApp(this, uri, callback);
     return false;
-  },
-};
+  }
+}
 
 var HelperApps =  {
   get defaultBrowsers() {
     delete this.defaultBrowsers;
-    this.defaultBrowsers = this._getHandlers("http://www.example.com", {
+    this.defaultBrowsers = this._collectDefaultBrowsers();
+    return this.defaultBrowsers;
+  },
+
+  _collectDefaultBrowsers() {
+    let httpHandlers = this._getHandlers("http://www.example.com", {
       filterBrowsers: false,
       filterHtml: false,
     });
-    return this.defaultBrowsers;
+    let httpsHandlers = this._getHandlers("https://www.example.com", {
+      filterBrowsers: false,
+      filterHtml: false,
+    });
+    return {...httpHandlers, ...httpsHandlers};
   },
 
-  // Finds handlers that have registered for text/html pages or urls ending in html. Some apps, like
-  // the Samsung Video player will only appear for these urls, while some Browsers (like Link Bubble)
-  // won't register here because of the text/html mime type.
+  // Finds handlers that have registered for urls ending in html. Some apps, like
+  // the Samsung Video player, will only appear for these urls.
   get defaultHtmlHandlers() {
     delete this.defaultHtmlHandlers;
     return this.defaultHtmlHandlers = this._getHandlers("http://www.example.com/index.html", {
       filterBrowsers: false,
       filterHtml: false,
     });
   },
 
-  _getHandlers: function(url, options) {
+  _getHandlers(url, options) {
     let values = {};
 
     let handlers = this.getAppsForUri(Services.io.newURI(url), options);
-    handlers.forEach(function(app) {
+    handlers.forEach(app => {
       values[app.name] = app;
-    }, this);
+    });
 
     return values;
   },
 
   get protoSvc() {
     delete this.protoSvc;
     return this.protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
   },
 
   get urlHandlerService() {
     delete this.urlHandlerService;
     return this.urlHandlerService = Cc["@mozilla.org/uriloader/external-url-handler-service;1"].getService(Ci.nsIExternalURLHandlerService);
   },
 
-  prompt: function showPicker(apps, promptOptions, callback) {
+  prompt(apps, promptOptions, callback) {
     let p = new Prompt(promptOptions).addIconGrid({ items: apps });
     p.show(callback);
   },
 
-  getAppsForProtocol: function getAppsForProtocol(scheme) {
+  getAppsForProtocol(scheme) {
     let protoHandlers = this.protoSvc.getProtocolHandlerInfoFromOS(scheme, {}).possibleApplicationHandlers;
 
     let results = {};
     for (let i = 0; i < protoHandlers.length; i++) {
       try {
         let protoApp = protoHandlers.queryElementAt(i, Ci.nsIHandlerApp);
         results[protoApp.name] = new App({
           name: protoApp.name,
           description: protoApp.detailedDescription,
         });
       } catch (e) {}
     }
 
     return results;
   },
 
-  getAppsForUri: function getAppsForUri(uri, flags = { }, callback) {
+  getAppsForUri(uri, flags = { }, callback) {
     // Return early for well-known internal schemes
     if (!uri || uri.schemeIs("about") || uri.schemeIs("chrome")) {
       if (callback) {
         callback([]);
       }
       return [];
     }
 
@@ -119,92 +132,104 @@ var HelperApps =  {
     let parseData = (apps) => {
       if (!apps) {
         return [];
       }
 
       apps = this._parseApps(apps);
 
       if (flags.filterBrowsers) {
-        apps = apps.filter((app) => {
-          return app.name && !this.defaultBrowsers[app.name];
-        });
+        apps = apps.filter(app =>
+          app.name && !this.defaultBrowsers[app.name]);
       }
 
       // Some apps will register for html files (the Samsung Video player) but should be shown
       // for non-HTML files (like videos). This filters them only if the page has an htm of html
       // file extension.
       if (flags.filterHtml) {
         // Matches from the first '.' to the end of the string, '?', or '#'
         let ext = /\.([^\?#]*)/.exec(uri.pathQueryRef);
         if (ext && (ext[1] === "html" || ext[1] === "htm")) {
-          apps = apps.filter(function(app) {
-            return app.name && !this.defaultHtmlHandlers[app.name];
-          }, this);
+          apps = apps.filter(app =>
+            app.name && !this.defaultHtmlHandlers[app.name]);
         }
       }
 
       return apps;
     };
 
     if (!callback) {
       let data = null;
       // Use dispatch to enable synchronous callback for Gecko thread event.
       EventDispatcher.instance.dispatch(msg.type, msg, {
-        onSuccess: (result) => { data = result; },
+        onSuccess: result => { data = result; },
         onError: () => { throw new Error("Intent:GetHandler callback failed"); },
       });
       if (data === null) {
         throw new Error("Intent:GetHandler did not return data");
       }
       return parseData(data);
     }
-      EventDispatcher.instance.sendRequestForResult(msg).then(function(data) {
+      EventDispatcher.instance.sendRequestForResult(msg).then(data => {
         callback(parseData(data));
       });
   },
 
-  launchUri: function launchUri(uri) {
+  launchUri(uri) {
     let msg = this._getMessage("Intent:Open", uri);
     EventDispatcher.instance.sendRequest(msg);
   },
 
-  _parseApps: function _parseApps(appInfo) {
+  _parseApps(appInfo) {
     // appInfo -> {apps: [app1Label, app1Default, app1PackageName, app1ActivityName, app2Label, app2Defaut, ...]}
     // see GeckoAppShell.java getHandlersForIntent function for details
     const numAttr = 4; // 4 elements per ResolveInfo: label, default, package name, activity name.
 
     let apps = [];
     for (let i = 0; i < appInfo.length; i += numAttr) {
       apps.push(new App({"name": appInfo[i],
                  "isDefault": appInfo[i + 1],
                  "packageName": appInfo[i + 2],
                  "activityName": appInfo[i + 3]}));
     }
 
     return apps;
   },
 
-  _getMessage: function(type, uri, options = {}) {
+  _getMessage(type, uri, options = {}) {
     let mimeType = options.mimeType;
     if (uri && mimeType == undefined) {
       mimeType = ContentAreaUtils.getMIMETypeForURI(uri) || "";
+      if (uri.scheme != "file" && NON_FILE_URI_IGNORED_MIME_TYPES.has(mimeType)) {
+        // We're guessing the MIME type based on the extension, which especially
+        // with non-local HTML documents will yield inconsistent results, as those
+        // commonly use URLs without any sort of extension, too.
+        // At the same time, apps offering to handle certain URLs in lieu of a
+        // browser often don't expect a MIME type to be used, and correspondingly
+        // register their intent filters without a MIME type.
+        // This means that when we *do* guess a non-empty MIME type because this
+        // time the URL *did* end on .(x)htm(l), Android won't offer any apps whose
+        // intent filter doesn't explicitly include that MIME type.
+        // Therefore, if the MIME type looks like something from that category,
+        // don't bother including it in the Intent for non-local files.
+        mimeType = "";
+      }
     }
 
     return {
       type: type,
       mime: mimeType,
       action: options.action || "", // empty action string defaults to android.intent.action.VIEW
       url: uri ? uri.displaySpec : "",
       packageName: options.packageName || "",
       className: options.className || "",
     };
   },
 
-  _launchApp: function launchApp(app, uri, callback) {
+  _launchApp(app, uri, callback) {
     if (callback) {
         let msg = this._getMessage("Intent:OpenForResult", uri, {
             packageName: app.packageName,
             className: app.activityName,
         });
 
         EventDispatcher.instance.sendRequestForResult(msg).then(callback);
     } else {
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -3239,17 +3239,17 @@ bool nsCookieService::CanSetCookie(nsIUR
 
   // Collect telemetry on how often secure cookies are set from non-secure
   // origins, and vice-versa.
   //
   // 0 = nonsecure and "http:"
   // 1 = nonsecure and "https:"
   // 2 = secure and "http:"
   // 3 = secure and "https:"
-  bool isHTTPS;
+  bool isHTTPS = true;
   nsresult rv = aHostURI->SchemeIs("https", &isHTTPS);
   if (NS_SUCCEEDED(rv)) {
     Telemetry::Accumulate(Telemetry::COOKIE_SCHEME_SECURITY,
                           ((aCookieAttributes.isSecure) ? 0x02 : 0x00) |
                               ((isHTTPS) ? 0x01 : 0x00));
 
     // Collect telemetry on how often are first- and third-party cookies set
     // from HTTPS origins:
@@ -3340,25 +3340,20 @@ bool nsCookieService::CanSetCookie(nsIUR
 
   // if the new cookie is httponly, make sure we're not coming from script
   if (!aFromHttp && aCookieAttributes.isHttpOnly) {
     COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader,
                       "cookie is httponly; coming from script");
     return newCookie;
   }
 
-  bool isSecure = true;
-  if (aHostURI) {
-    aHostURI->SchemeIs("https", &isSecure);
-  }
-
   // If the new cookie is non-https and wants to set secure flag,
   // browser have to ignore this new cookie.
   // (draft-ietf-httpbis-cookie-alone section 3.1)
-  if (aCookieAttributes.isSecure && !isSecure) {
+  if (aCookieAttributes.isSecure && !isHTTPS) {
     COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader,
                       "non-https cookie can't set secure flag");
     return newCookie;
   }
 
   // If the new cookie is same-site but in a cross site context,
   // browser must ignore the cookie.
   if ((aCookieAttributes.sameSite != nsICookie2::SAMESITE_UNSET) &&
--- a/services/common/kinto-offline-client.js
+++ b/services/common/kinto-offline-client.js
@@ -28,17 +28,17 @@
 //
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1394556#c3 for
 // more details.
 const global = this;
 
 var EXPORTED_SYMBOLS = ["Kinto"];
 
 /*
- * Version 12.2.4 - 8fb687a
+ * Version 12.3.0 - f7a9e81
  */
 
 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Kinto = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
 /*
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -560,17 +560,17 @@ class IDB extends _base.default {
     super();
     this.cid = cid;
     this.dbName = options.dbName || "KintoDB";
     this._options = options;
     this._db = null;
   }
 
   _handleError(method, err) {
-    const error = new Error(method + "() " + err.message);
+    const error = new Error(`IndexedDB ${method}() ${err.message}`);
     error.stack = err.stack;
     throw error;
   }
   /**
    * Ensures a connection to the IndexedDB database has been opened.
    *
    * @override
    * @return {Promise}
@@ -609,17 +609,17 @@ class IDB extends _base.default {
       }
     });
 
     if (dataToMigrate) {
       const {
         records,
         timestamp
       } = dataToMigrate;
-      await this.loadDump(records);
+      await this.importBulk(records);
       await this.saveLastModified(timestamp);
       console.log(`${this.cid}: data was migrated successfully.`); // Delete the old database.
 
       await deleteDatabase(this.cid);
       console.warn(`${this.cid}: old database was deleted.`);
     }
 
     return this;
@@ -881,23 +881,36 @@ class IDB extends _base.default {
       return entry ? entry.value : null;
     } catch (e) {
       this._handleError("getLastModified", e);
     }
   }
   /**
    * Load a dump of records exported from a server.
    *
+   * @deprecated Use {@link importBulk} instead.
    * @abstract
    * @param  {Array} records The records to load.
    * @return {Promise}
    */
 
 
   async loadDump(records) {
+    return this.importBulk(records);
+  }
+  /**
+   * Load records in bulk that were exported from a server.
+   *
+   * @abstract
+   * @param  {Array} records The records to load.
+   * @return {Promise}
+   */
+
+
+  async importBulk(records) {
     try {
       await this.execute(transaction => {
         // Since the put operations are asynchronous, we chain
         // them together. The last one will be waited for the
         // `transaction.oncomplete` callback. (see #execute())
         let i = 0;
         putNext();
 
@@ -915,17 +928,17 @@ class IDB extends _base.default {
       const lastModified = Math.max(...records.map(record => record.last_modified));
 
       if (lastModified > previousLastModified) {
         await this.saveLastModified(lastModified);
       }
 
       return records;
     } catch (e) {
-      this._handleError("loadDump", e);
+      this._handleError("importBulk", e);
     }
   }
 
 }
 /**
  * IDB transaction proxy.
  *
  * @param  {IDB} adapter        The call IDB adapter
@@ -1112,18 +1125,31 @@ class BaseAdapter {
    * @return {Promise}
    */
 
 
   getLastModified() {
     throw new Error("Not Implemented.");
   }
   /**
+   * Load records in bulk that were exported from a server.
+   *
+   * @abstract
+   * @param  {Array} records The records to load.
+   * @return {Promise}
+   */
+
+
+  importBulk(records) {
+    throw new Error("Not Implemented.");
+  }
+  /**
    * Load a dump of records exported from a server.
    *
+   * @deprecated Use {@link importBulk} instead.
    * @abstract
    * @param  {Array} records The records to load.
    * @return {Promise}
    */
 
 
   loadDump(records) {
     throw new Error("Not Implemented.");
@@ -1135,17 +1161,17 @@ exports.default = BaseAdapter;
 
 },{}],6:[function(require,module,exports){
 "use strict";
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.recordsEqual = recordsEqual;
-exports.CollectionTransaction = exports.default = exports.SyncResultObject = void 0;
+exports.CollectionTransaction = exports.default = exports.ServerWasFlushedError = exports.SyncResultObject = void 0;
 
 var _base = _interopRequireDefault(require("./adapters/base"));
 
 var _IDB = _interopRequireDefault(require("./adapters/IDB"));
 
 var _utils = require("./utils");
 
 var _uuid = require("uuid");
@@ -1258,16 +1284,32 @@ class SyncResultObject {
     this.ok = this.errors.length + this.conflicts.length === 0;
     return this;
   }
 
 }
 
 exports.SyncResultObject = SyncResultObject;
 
+class ServerWasFlushedError extends Error {
+  constructor(clientTimestamp, serverTimestamp, message) {
+    super(message);
+
+    if (Error.captureStackTrace) {
+      Error.captureStackTrace(this, ServerWasFlushedError);
+    }
+
+    this.clientTimestamp = clientTimestamp;
+    this.serverTimestamp = serverTimestamp;
+  }
+
+}
+
+exports.ServerWasFlushedError = ServerWasFlushedError;
+
 function createUUIDSchema() {
   return {
     generate() {
       return (0, _uuid.v4)();
     },
 
     validate(id) {
       return typeof id == "string" && _utils.RE_RECORD_ID.test(id);
@@ -2257,17 +2299,18 @@ class Collection {
     // This is relevant for the Kinto demo server
     // (and thus for many new comers).
 
     const localSynced = options.lastModified;
     const serverChanged = unquoted > options.lastModified;
     const emptyCollection = data.length === 0;
 
     if (!options.exclude && localSynced && serverChanged && emptyCollection) {
-      throw Error("Server has been flushed.");
+      const e = new ServerWasFlushedError(localSynced, unquoted, "Server has been flushed. Client Side Timestamp: " + localSynced + " Server Side Timestamp: " + unquoted);
+      throw e;
     }
 
     syncResultObject.lastModified = unquoted; // Decode incoming changes.
 
     const decodedChanges = await Promise.all(data.map(change => {
       return this._decodeRecord("remote", change);
     })); // Hook receives decoded records.
 
@@ -2573,22 +2616,37 @@ class Collection {
     return result;
   }
   /**
    * Load a list of records already synced with the remote server.
    *
    * The local records which are unsynced or whose timestamp is either missing
    * or superior to those being loaded will be ignored.
    *
+   * @deprecated Use {@link importBulk} instead.
    * @param  {Array} records The previously exported list of records to load.
    * @return {Promise} with the effectively imported records.
    */
 
 
   async loadDump(records) {
+    return this.importBulk(records);
+  }
+  /**
+   * Load a list of records already synced with the remote server.
+   *
+   * The local records which are unsynced or whose timestamp is either missing
+   * or superior to those being loaded will be ignored.
+   *
+   * @param  {Array} records The previously exported list of records to load.
+   * @return {Promise} with the effectively imported records.
+   */
+
+
+  async importBulk(records) {
     if (!Array.isArray(records)) {
       throw new Error("Records is not an array.");
     }
 
     for (const record of records) {
       if (!record.hasOwnProperty("id") || !this.idSchema.validate(record.id)) {
         throw new Error("Record has invalid ID: " + JSON.stringify(record));
       }
@@ -2614,17 +2672,17 @@ class Collection {
       const localRecord = existingById[record.id];
       const shouldKeep = // No local record with this id.
       localRecord === undefined || // Or local record is synced
       localRecord._status === "synced" && // And was synced from server
       localRecord.last_modified !== undefined && // And is older than imported one.
       record.last_modified > localRecord.last_modified;
       return shouldKeep;
     });
-    return await this.db.loadDump(newRecords.map(markSynced));
+    return await this.db.importBulk(newRecords.map(markSynced));
   }
 
 }
 /**
  * A Collection-oriented wrapper for an adapter's transaction.
  *
  * This defines the high-level functions available on a collection.
  * The collection itself offers functions of the same name. These will
--- a/services/common/kinto-storage-adapter.js
+++ b/services/common/kinto-storage-adapter.js
@@ -326,27 +326,31 @@ class FirefoxAdapter extends Kinto.adapt
       return records;
     }).then(results => {
       // The resulting list of records is filtered and sorted.
       // XXX: with some efforts, this could be implemented using SQL.
       return reduceRecords(params.filters, params.order, results);
     });
   }
 
+  async loadDump(records) {
+    return this.importBulk(records);
+  }
+
   /**
    * Load a list of records into the local database.
    *
    * Note: The adapter is not in charge of filtering the already imported
    * records. This is done in `Collection#loadDump()`, as a common behaviour
    * between every adapters.
    *
    * @param  {Array} records.
    * @return {Array} imported records.
    */
-  async loadDump(records) {
+  async importBulk(records) {
     const connection = this._connection;
     const collection_name = this.collection;
     await connection.executeTransaction(async function doImport() {
       for (let record of records) {
         const params = {
           collection_name,
           record_id: record.id,
           record: JSON.stringify(record),
--- a/services/common/tests/unit/test_kinto.js
+++ b/services/common/tests/unit/test_kinto.js
@@ -208,24 +208,24 @@ add_task(async function test_kinto_list(
     }
   } finally {
     await sqliteHandle.close();
   }
 });
 
 add_task(clear_collection);
 
-add_task(async function test_loadDump_ignores_already_imported_records() {
+add_task(async function test_importBulk_ignores_already_imported_records() {
   let sqliteHandle;
   try {
     sqliteHandle = await do_get_kinto_sqliteHandle();
     const collection = do_get_kinto_collection(sqliteHandle);
     const record = {id: "41b71c13-17e9-4ee3-9268-6a41abf9730f", title: "foo", last_modified: 1457896541};
-    await collection.loadDump([record]);
-    let impactedRecords = await collection.loadDump([record]);
+    await collection.importBulk([record]);
+    let impactedRecords = await collection.importBulk([record]);
     Assert.equal(impactedRecords.length, 0);
   } finally {
     await sqliteHandle.close();
   }
 });
 
 add_task(clear_collection);
 
--- a/services/settings/RemoteSettingsClient.jsm
+++ b/services/settings/RemoteSettingsClient.jsm
@@ -380,17 +380,17 @@ class RemoteSettingsClient extends Event
           await this.emit("sync", { data: filteredSyncResult });
         } catch (e) {
           reportStatus = UptakeTelemetry.STATUS.APPLY_ERROR;
           throw e;
         }
       }
     } catch (e) {
       // IndexedDB errors. See https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/error
-      if (/(AbortError|ConstraintError|QuotaExceededError|VersionError)/.test(e.message)) {
+      if (/(IndexedDB|AbortError|ConstraintError|QuotaExceededError|VersionError)/.test(e.message)) {
         reportStatus = UptakeTelemetry.STATUS.CUSTOM_1_ERROR;
       }
       // No specific error was tracked, mark it as unknown.
       if (reportStatus === null) {
         reportStatus = UptakeTelemetry.STATUS.UNKNOWN_ERROR;
       }
       throw e;
     } finally {
--- a/services/settings/test/unit/test_remote_settings.js
+++ b/services/settings/test/unit/test_remote_settings.js
@@ -380,16 +380,33 @@ add_task(async function test_telemetry_r
 
   client.openCollection = backup;
   const endHistogram = getUptakeTelemetrySnapshot(client.identifier);
   const expectedIncrements = {[UptakeTelemetry.STATUS.UNKNOWN_ERROR]: 1};
   checkUptakeTelemetry(startHistogram, endHistogram, expectedIncrements);
 });
 add_task(clear_state);
 
+add_task(async function test_telemetry_reports_indexeddb_as_custom_1() {
+  const backup = client.openCollection;
+  const msg = "IndexedDB getLastModified() The operation failed for reasons unrelated to the database itself";
+  client.openCollection = () => { throw new Error(msg); };
+  const startHistogram = getUptakeTelemetrySnapshot(client.identifier);
+
+  try {
+    await client.maybeSync(2000);
+  } catch (e) { }
+
+  client.openCollection = backup;
+  const endHistogram = getUptakeTelemetrySnapshot(client.identifier);
+  const expectedIncrements = {[UptakeTelemetry.STATUS.CUSTOM_1_ERROR]: 1};
+  checkUptakeTelemetry(startHistogram, endHistogram, expectedIncrements);
+});
+add_task(clear_state);
+
 add_task(async function test_bucketname_changes_when_bucket_pref_changes() {
   equal(client.bucketName, "main");
 
   Services.prefs.setCharPref("services.settings.default_bucket", "main-preview");
 
   equal(client.bucketName, "main-preview");
 });
 add_task(clear_state);
--- a/servo/components/style/cbindgen.toml
+++ b/servo/components/style/cbindgen.toml
@@ -8,16 +8,17 @@ autogen_warning = """/* DO NOT MODIFY TH
  *   2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h`
  */
 #include "nsCoord.h"
 #include "Units.h"
 #include "mozilla/gfx/Types.h"
 class nsAtom;
 namespace mozilla {
   class WritingMode;
+  enum HalfCorner : uint8_t;
   enum LogicalSide : uint8_t;
   namespace css {
     struct URLValue;
   }
 
   // Work-around weird cbindgen renaming.
   typedef css::URLValue StyleURLValue;
   typedef nsAtom StylensAtom;
@@ -83,16 +84,18 @@ include = [
   "Rect",
   "IntersectionObserverRootMargin",
   "Size",
   "MaxSize",
   "FlexBasis",
   "Position",
   "BackgroundSize",
   "BorderImageSlice",
+  "BorderSpacing",
+  "BorderRadius",
   "NonNegativeLengthOrNumberRect",
   "Perspective",
   "ZIndex",
   "TransformOrigin",
 ]
 item_types = ["enums", "structs", "typedefs"]
 
 [export.body]
@@ -180,8 +183,12 @@ item_types = ["enums", "structs", "typed
   // Defined in WritingModes.h
   inline const T& Get(mozilla::Side) const;
   inline const T& Get(mozilla::WritingMode, mozilla::LogicalSide) const;
   inline const T& GetIStart(mozilla::WritingMode) const;
   inline const T& GetBStart(mozilla::WritingMode) const;
   inline const T& GetIEnd(mozilla::WritingMode) const;
   inline const T& GetBEnd(mozilla::WritingMode) const;
 """
+
+"GenericBorderRadius" = """
+  inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
+"""
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -570,38 +570,34 @@ impl nsStyleImage {
         })
     }
 }
 
 pub mod basic_shape {
     //! Conversions from and to CSS shape representations.
 
     use crate::gecko::values::GeckoStyleCoordConvertible;
-    use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCorners};
+    use crate::gecko_bindings::structs::nsStyleCoord;
     use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType};
     use crate::gecko_bindings::structs::{
         StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
     };
-    use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
     use crate::gecko_bindings::sugar::refptr::RefPtr;
     use crate::values::computed::basic_shape::{
         BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
     };
-    use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
     use crate::values::computed::length::LengthPercentage;
     use crate::values::computed::motion::OffsetPath;
     use crate::values::computed::url::ComputedUrl;
     use crate::values::generics::basic_shape::{
         BasicShape as GenericBasicShape, InsetRect, Polygon,
     };
     use crate::values::generics::basic_shape::{Circle, Ellipse, Path, PolygonCoord};
     use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
-    use crate::values::generics::border::BorderRadius as GenericBorderRadius;
     use crate::values::generics::rect::Rect;
-    use crate::values::generics::NonNegative;
     use crate::values::specified::SVGPathData;
     use std::borrow::Borrow;
 
     impl StyleShapeSource {
         /// Convert StyleShapeSource to ShapeSource except URL and Image
         /// types.
         fn into_shape_source<ReferenceBox, ImageOrUrl>(
             &self,
@@ -701,17 +697,17 @@ pub mod basic_shape {
     impl<'a> From<&'a StyleBasicShape> for BasicShape {
         fn from(other: &'a StyleBasicShape) -> Self {
             match other.mType {
                 StyleBasicShapeType::Inset => {
                     let t = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[0]);
                     let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
                     let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
                     let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
-                    let round: BorderRadius = (&other.mRadius).into();
+                    let round = other.mRadius;
                     let round = if round.all_zero() { None } else { Some(round) };
                     let rect = Rect::new(
                         t.expect("inset() offset should be a length, percentage, or calc value"),
                         r.expect("inset() offset should be a length, percentage, or calc value"),
                         b.expect("inset() offset should be a length, percentage, or calc value"),
                         l.expect("inset() offset should be a length, percentage, or calc value"),
                     );
                     GenericBasicShape::Inset(InsetRect { rect, round })
@@ -747,75 +743,16 @@ pub mod basic_shape {
                         fill: other.mFillRule,
                         coordinates: coords,
                     })
                 },
             }
         }
     }
 
-    impl<'a> From<&'a nsStyleCorners> for BorderRadius {
-        fn from(other: &'a nsStyleCorners) -> Self {
-            let get_corner = |index| {
-                BorderCornerRadius::new(
-                    NonNegative(
-                        LengthPercentage::from_gecko_style_coord(&other.data_at(index)).expect(
-                            "<border-radius> should be a length, percentage, or calc value",
-                        ),
-                    ),
-                    NonNegative(
-                        LengthPercentage::from_gecko_style_coord(&other.data_at(index + 1)).expect(
-                            "<border-radius> should be a length, percentage, or calc value",
-                        ),
-                    ),
-                )
-            };
-
-            GenericBorderRadius {
-                top_left: get_corner(0),
-                top_right: get_corner(2),
-                bottom_right: get_corner(4),
-                bottom_left: get_corner(6),
-            }
-        }
-    }
-
-    // Can't be a From impl since we need to set an existing
-    // nsStyleCorners, not create a new one
-    impl BorderRadius {
-        /// Set this `BorderRadius` into a given `nsStyleCoord`.
-        pub fn set_corners(&self, other: &mut nsStyleCorners) {
-            let mut set_corner = |field: &BorderCornerRadius, index| {
-                field
-                    .0
-                    .width()
-                    .to_gecko_style_coord(&mut other.data_at_mut(index));
-                field
-                    .0
-                    .height()
-                    .to_gecko_style_coord(&mut other.data_at_mut(index + 1));
-            };
-            set_corner(&self.top_left, 0);
-            set_corner(&self.top_right, 2);
-            set_corner(&self.bottom_right, 4);
-            set_corner(&self.bottom_left, 6);
-        }
-    }
-
-    /// We use None for a nonexistant radius, but Gecko uses (0 0 0 0 / 0 0 0 0)
-    pub fn set_corners_from_radius(radius: Option<BorderRadius>, other: &mut nsStyleCorners) {
-        if let Some(radius) = radius {
-            radius.set_corners(other);
-        } else {
-            for i in 0..8 {
-                other.data_at_mut(i).set_value(CoordDataValue::Coord(0));
-            }
-        }
-    }
-
     impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
         fn from(other: &'a nsStyleCoord) -> Self {
             let other = other.borrow();
             ShapeRadius::from_gecko_style_coord(other)
                 .expect("<shape-radius> should be a length, percentage, calc, or keyword value")
         }
     }
 
--- a/servo/components/style/gecko_bindings/sugar/ns_style_coord.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_style_coord.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! Rust helpers for Gecko's `nsStyleCoord`.
 
 use crate::gecko_bindings::bindings;
 use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue};
-use crate::gecko_bindings::structs::{nsStyleCorners, nsStyleSides};
+use crate::gecko_bindings::structs::nsStyleSides;
 use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
 use std::mem;
 
 impl nsStyleCoord {
     #[inline]
     /// Get a `null` nsStyleCoord.
     pub fn null() -> Self {
         // Can't construct directly because it has private fields
@@ -118,74 +118,16 @@ unsafe impl<'a> CoordData for SidesDataM
 unsafe impl<'a> CoordDataMut for SidesDataMut<'a> {
     unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
         let unit = &mut self.sides.get_mUnits_mut()[self.index] as *mut _;
         let value = &mut self.sides.get_mValues_mut()[self.index] as *mut _;
         (&mut *unit, &mut *value)
     }
 }
 
-impl nsStyleCorners {
-    /// Get a `nsStyleCoord` like object representing the given index's value
-    /// and unit.
-    #[inline]
-    pub fn data_at(&self, index: usize) -> CornersData {
-        CornersData {
-            corners: self,
-            index: index,
-        }
-    }
-
-    /// Get a `nsStyleCoord` like object representing the mutable given index's
-    /// value and unit.
-    #[inline]
-    pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut {
-        CornersDataMut {
-            corners: self,
-            index: index,
-        }
-    }
-}
-
-/// A `nsStyleCoord`-like struct on top of `nsStyleCorners`.
-pub struct CornersData<'a> {
-    corners: &'a nsStyleCorners,
-    index: usize,
-}
-
-/// A `nsStyleCoord`-like struct on top of a mutable `nsStyleCorners` reference.
-pub struct CornersDataMut<'a> {
-    corners: &'a mut nsStyleCorners,
-    index: usize,
-}
-
-unsafe impl<'a> CoordData for CornersData<'a> {
-    fn unit(&self) -> nsStyleUnit {
-        unsafe { self.corners.get_mUnits()[self.index] }
-    }
-    fn union(&self) -> nsStyleUnion {
-        unsafe { self.corners.get_mValues()[self.index] }
-    }
-}
-unsafe impl<'a> CoordData for CornersDataMut<'a> {
-    fn unit(&self) -> nsStyleUnit {
-        unsafe { self.corners.get_mUnits()[self.index] }
-    }
-    fn union(&self) -> nsStyleUnion {
-        unsafe { self.corners.get_mValues()[self.index] }
-    }
-}
-unsafe impl<'a> CoordDataMut for CornersDataMut<'a> {
-    unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
-        let unit = &mut self.corners.get_mUnits_mut()[self.index] as *mut _;
-        let value = &mut self.corners.get_mValues_mut()[self.index] as *mut _;
-        (&mut *unit, &mut *value)
-    }
-}
-
 /// Enum representing the tagged union that is CoordData.
 ///
 /// In release mode this should never actually exist in the code, and will be
 /// optimized out by threading matches and inlining.
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum CoordDataValue {
     /// eStyleUnit_Null
     Null,
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -47,17 +47,17 @@ use crate::gecko::values::round_border_t
 use crate::logical_geometry::WritingMode;
 use crate::media_queries::Device;
 use crate::properties::computed_value_flags::*;
 use crate::properties::longhands;
 use crate::rule_tree::StrongRuleNode;
 use crate::selector_parser::PseudoElement;
 use servo_arc::{Arc, RawOffsetArc};
 use std::marker::PhantomData;
-use std::mem::{forget, uninitialized, transmute, zeroed};
+use std::mem::{forget, uninitialized, zeroed};
 use std::{cmp, ops, ptr};
 use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
 use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
 use crate::values::computed::BorderStyle;
 use crate::values::computed::font::FontSize;
 use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
 use crate::values::generics::column::ColumnCount;
 use crate::values::generics::transform::TransformStyle;
@@ -812,44 +812,33 @@ def set_gecko_property(ffi_name, expr):
     }
 
     #[allow(non_snake_case)]
     pub fn reset_${ident}(&mut self, other: &Self) {
         self.copy_${ident}_from(other)
     }
 </%def>
 
-<%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index)">
+<%def name="impl_corner_style_coord(ident, gecko_ffi_name, corner)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
-        v.0.width().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}));
-        v.0.height().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
+        self.gecko.${gecko_ffi_name}.${corner} = v;
     }
     #[allow(non_snake_case)]
     pub fn copy_${ident}_from(&mut self, other: &Self) {
-        self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})
-                  .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index}));
-        self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
-                  .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
+        self.gecko.${gecko_ffi_name}.${corner} =
+            other.gecko.${gecko_ffi_name}.${corner};
     }
     #[allow(non_snake_case)]
     pub fn reset_${ident}(&mut self, other: &Self) {
         self.copy_${ident}_from(other)
     }
-
     #[allow(non_snake_case)]
     pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-        use crate::values::computed::border::BorderCornerRadius;
-        let width = GeckoStyleCoordConvertible::from_gecko_style_coord(
-                        &self.gecko.${gecko_ffi_name}.data_at(${x_index}))
-                        .expect("Failed to clone ${ident}");
-        let height = GeckoStyleCoordConvertible::from_gecko_style_coord(
-                        &self.gecko.${gecko_ffi_name}.data_at(${y_index}))
-                        .expect("Failed to clone ${ident}");
-        BorderCornerRadius::new(width, height)
+        self.gecko.${gecko_ffi_name}.${corner}
     }
 </%def>
 
 <%def name="impl_css_url(ident, gecko_ffi_name)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         match v {
             UrlOrNone::Url(ref url) => {
@@ -1382,55 +1371,40 @@ impl ${style_struct.gecko_struct_name} {
 
 <%!
 class Side(object):
     def __init__(self, name, index):
         self.name = name
         self.ident = name.lower()
         self.index = index
 
-class Corner(object):
-    def __init__(self, vert, horiz, index):
-        self.x_name = "HalfCorner::eCorner" + vert + horiz + "X"
-        self.y_name = "HalfCorner::eCorner" + vert + horiz + "Y"
-        self.ident = (vert + "_" + horiz).lower()
-        self.x_index = 2 * index
-        self.y_index = 2 * index + 1
-
 class GridLine(object):
     def __init__(self, name):
         self.ident = "grid-" + name.lower()
         self.name = self.ident.replace('-', '_')
         self.gecko = "m" + to_camel_case(self.ident)
 
 SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
-CORNERS = [Corner("Top", "Left", 0), Corner("Top", "Right", 1),
-           Corner("Bottom", "Right", 2), Corner("Bottom", "Left", 3)]
+CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
 GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
 %>
 
 #[allow(dead_code)]
 fn static_assert() {
-    unsafe {
-        % for corner in CORNERS:
-        transmute::<_, [u32; ${corner.x_index}]>([1; structs::${corner.x_name} as usize]);
-        transmute::<_, [u32; ${corner.y_index}]>([1; structs::${corner.y_name} as usize]);
-        % endfor
-    }
     // Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate.
     % for side in SIDES:
     { const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; }
     % endfor
 }
 
 
 <% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
                                      for x in SIDES
                                      for y in ["color", "style", "width"]] +
-                                    ["border-{0}-radius".format(x.ident.replace("_", "-"))
+                                    ["border-{0}-radius".format(x.replace("_", "-"))
                                      for x in CORNERS]) %>
 
 <%self:impl_trait style_struct_name="Border"
                   skip_longhands="${skip_border_longhands} border-image-source
                                   border-image-repeat border-image-width">
     % for side in SIDES:
     pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
         self.gecko.mBorderStyle[${side.index}] = v;
@@ -1489,20 +1463,19 @@ fn static_assert() {
                                 round_to_pixels=True) %>
 
     pub fn border_${side.ident}_has_nonzero_width(&self) -> bool {
         self.gecko.mComputedBorder.${side.ident} != 0
     }
     % endfor
 
     % for corner in CORNERS:
-    <% impl_corner_style_coord("border_%s_radius" % corner.ident,
+    <% impl_corner_style_coord("border_%s_radius" % corner,
                                "mBorderRadius",
-                               corner.x_index,
-                               corner.y_index) %>
+                               corner) %>
     % endfor
 
     pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) {
         unsafe {
             // Prevent leaking of the last elements we did set
             Gecko_SetNullImageValue(&mut self.gecko.mBorderImageSource);
         }
 
@@ -2022,17 +1995,17 @@ fn static_assert() {
         };
 
         Either::First(TemplateAreasArc(Arc::new(TemplateAreas{ areas, strings, width })))
     }
 
 </%self:impl_trait>
 
 <% skip_outline_longhands = " ".join("outline-style outline-width".split() +
-                                     ["-moz-outline-radius-{0}".format(x.ident.replace("_", ""))
+                                     ["-moz-outline-radius-{0}".format(x.replace("_", ""))
                                       for x in CORNERS]) %>
 <%self:impl_trait style_struct_name="Outline"
                   skip_longhands="${skip_outline_longhands}">
 
     pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) {
         self.gecko.mOutlineStyle = v;
         // NB: This is needed to correctly handling the initial value of
         // outline-width when outline-style changes, see the
@@ -2054,20 +2027,19 @@ fn static_assert() {
         self.gecko.mOutlineStyle.clone()
     }
 
     <% impl_non_negative_length("outline_width", "mActualOutlineWidth",
                                 inherit_from="mOutlineWidth",
                                 round_to_pixels=True) %>
 
     % for corner in CORNERS:
-    <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""),
+    <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.replace("_", ""),
                                "mOutlineRadius",
-                               corner.x_index,
-                               corner.y_index) %>
+                               corner) %>
     % endfor
 
     pub fn outline_has_nonzero_width(&self) -> bool {
         self.gecko.mActualOutlineWidth != 0
     }
 </%self:impl_trait>
 
 <%
@@ -4588,17 +4560,16 @@ fn set_style_svg_path(
     gecko_path.mFillRule = fill;
 }
 
 <%def name="impl_shape_source(ident, gecko_ffi_name)">
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         use crate::gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource};
         use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
         use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
-        use crate::gecko::conversions::basic_shape::set_corners_from_radius;
         use crate::gecko::values::GeckoStyleCoordConvertible;
         use crate::values::generics::basic_shape::{BasicShape, ShapeSource};
 
         let ref mut ${ident} = self.gecko.${gecko_ffi_name};
 
         // clean up existing struct
         unsafe { Gecko_DestroyShapeSource(${ident}) };
         ${ident}.mType = StyleShapeSourceType::None;
@@ -4653,18 +4624,20 @@ fn set_style_svg_path(
                         shape.mCoordinates[0].leaky_set_null();
                         inset.rect.0.to_gecko_style_coord(&mut shape.mCoordinates[0]);
                         shape.mCoordinates[1].leaky_set_null();
                         inset.rect.1.to_gecko_style_coord(&mut shape.mCoordinates[1]);
                         shape.mCoordinates[2].leaky_set_null();
                         inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]);
                         shape.mCoordinates[3].leaky_set_null();
                         inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
-
-                        set_corners_from_radius(inset.round, &mut shape.mRadius);
+                        shape.mRadius = match inset.round {
+                            Some(radius) => radius,
+                            None => crate::values::computed::BorderRadius::zero(),
+                        };
                     }
                     BasicShape::Circle(circ) => {
                         let shape = init_shape(${ident}, StyleBasicShapeType::Circle);
                         unsafe { shape.mCoordinates.set_len(1) };
                         shape.mCoordinates[0].leaky_set_null();
                         circ.radius.to_gecko_style_coord(&mut shape.mCoordinates[0]);
 
                         shape.mPosition = circ.position.into();
--- a/servo/components/style/values/computed/border.rs
+++ b/servo/components/style/values/computed/border.rs
@@ -82,16 +82,26 @@ impl BorderCornerRadius {
         GenericBorderCornerRadius(Size2D::new(
             NonNegativeLengthPercentage::zero(),
             NonNegativeLengthPercentage::zero(),
         ))
     }
 }
 
 impl BorderRadius {
+    /// Returns a `0` border radius.
+    pub fn zero() -> Self {
+        Self {
+            top_left: BorderCornerRadius::zero(),
+            top_right: BorderCornerRadius::zero(),
+            bottom_right: BorderCornerRadius::zero(),
+            bottom_left: BorderCornerRadius::zero(),
+        }
+    }
+
     /// Returns whether all the values are `0px`.
     pub fn all_zero(&self) -> bool {
         fn all(corner: &BorderCornerRadius) -> bool {
             fn is_zero(l: &NonNegativeLengthPercentage) -> bool {
                 *l == NonNegativeLengthPercentage::zero()
             }
             is_zero(corner.0.width()) && is_zero(corner.0.height())
         }
--- a/servo/components/style/values/generics/border.rs
+++ b/servo/components/style/values/generics/border.rs
@@ -48,17 +48,20 @@ pub use self::GenericBorderImageSlice as
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
 )]
-pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
+#[repr(C)]
+pub struct GenericBorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
+
+pub use self::GenericBorderCornerRadius as BorderCornerRadius;
 
 impl<L> BorderCornerRadius<L> {
     /// Trivially create a `BorderCornerRadius`.
     pub fn new(w: L, h: L) -> Self {
         BorderCornerRadius(Size2D::new(w, h))
     }
 }
 
@@ -72,16 +75,17 @@ impl<L> BorderCornerRadius<L> {
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
 )]
+#[repr(transparent)]
 pub struct BorderSpacing<L>(#[css(field_bound)] pub Size2D<L>);
 
 impl<L> BorderSpacing<L> {
     /// Trivially create a `BorderCornerRadius`.
     pub fn new(w: L, h: L) -> Self {
         BorderSpacing(Size2D::new(w, h))
     }
 }
@@ -96,27 +100,30 @@ impl<L> BorderSpacing<L> {
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
 )]
-pub struct BorderRadius<LengthPercentage> {
+#[repr(C)]
+pub struct GenericBorderRadius<LengthPercentage> {
     /// The top left radius.
-    pub top_left: BorderCornerRadius<LengthPercentage>,
+    pub top_left: GenericBorderCornerRadius<LengthPercentage>,
     /// The top right radius.
-    pub top_right: BorderCornerRadius<LengthPercentage>,
+    pub top_right: GenericBorderCornerRadius<LengthPercentage>,
     /// The bottom right radius.
-    pub bottom_right: BorderCornerRadius<LengthPercentage>,
+    pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
     /// The bottom left radius.
-    pub bottom_left: BorderCornerRadius<LengthPercentage>,
+    pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
 }
 
+pub use self::GenericBorderRadius as BorderRadius;
+
 impl<L> BorderRadius<L> {
     /// Returns a new `BorderRadius<L>`.
     #[inline]
     pub fn new(
         tl: BorderCornerRadius<L>,
         tr: BorderCornerRadius<L>,
         br: BorderCornerRadius<L>,
         bl: BorderCornerRadius<L>,
--- a/servo/components/style/values/generics/size.rs
+++ b/servo/components/style/values/generics/size.rs
@@ -20,16 +20,17 @@ use style_traits::{CssWriter, ParseError
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToAnimatedValue,
     ToComputedValue,
 )]
 #[allow(missing_docs)]
+#[repr(C)]
 pub struct Size2D<L> {
     pub width: L,
     pub height: L,
 }
 
 impl<L> Size2D<L> {
     #[inline]
     /// Create a new `Size2D` for an area of given width and height.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3698,16 +3698,25 @@ pub unsafe extern "C" fn Servo_Serialize
     output: *mut nsAString,
 ) {
     easing
         .mTiming
         .to_css(&mut CssWriter::new(&mut *output))
         .unwrap();
 }
 
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_SerializeBorderRadius(
+    radius: *const computed::BorderRadius,
+    output: *mut nsAString,
+) {
+    (*radius).to_css(&mut CssWriter::new(&mut *output)).unwrap();
+}
+
 #[no_mangle]
 pub extern "C" fn Servo_GetProperties_Overriding_Animation(
     element: RawGeckoElementBorrowed,
     list: RawGeckoCSSPropertyIDListBorrowed,
     set: nsCSSPropertyIDSetBorrowedMut,
 ) {
     let element = GeckoElement(element);
     let element_data = match element.borrow_data() {
--- a/taskcluster/ci/test/raptor.yml
+++ b/taskcluster/ci/test/raptor.yml
@@ -448,17 +448,17 @@ raptor-speedometer-geckoview-power:
 raptor-speedometer-fennec:
     description: "Raptor Speedometer on Fennec"
     try-name: raptor-speedometer-fennec
     treeherder-symbol: Rap(sp)
     target: target.apk
     run-on-projects:
         by-test-platform:
             android-hw.*: ['try', 'trunk', 'mozilla-beta']
-    tier: 3
+    tier: 2
     max-run-time: 900
     mozharness:
         extra-options:
             - --test=raptor-speedometer-fennec
             - --app=fennec
             - --binary=org.mozilla.fennec_aurora
 
 raptor-speedometer-chrome:
--- a/testing/mozbase/mozlog/mozlog/formatters/html/html.py
+++ b/testing/mozbase/mozlog/mozlog/formatters/html/html.py
@@ -71,18 +71,18 @@ class HTMLFormatter(base.BaseFormatter):
             self.env["Gecko version"] = version_info.get("application_version")
             self.env["Gecko build"] = version_info.get("application_buildid")
 
             if version_info.get("application_changeset"):
                 self.env["Gecko revision"] = version_info.get("application_changeset")
                 if version_info.get("application_repository"):
                     self.env["Gecko revision"] = html.a(
                         version_info.get("application_changeset"),
-                        href="/".join([version_info.get("application_repository"),
-                                       version_info.get("application_changeset")]),
+                        href="/rev/".join([version_info.get("application_repository"),
+                                           version_info.get("application_changeset")]),
                         target="_blank")
 
             if version_info.get("gaia_changeset"):
                 self.env["Gaia revision"] = html.a(
                     version_info.get("gaia_changeset")[:12],
                     href="https://github.com/mozilla-b2g/gaia/commit/%s" % version_info.get(
                         "gaia_changeset"),
                     target="_blank")
--- a/testing/raptor/test/test_manifest.py
+++ b/testing/raptor/test/test_manifest.py
@@ -121,27 +121,24 @@ def test_get_raptor_test_list_chrome(cre
     args = create_args(app="chrome",
                        test="raptor-speedometer")
 
     test_list = get_raptor_test_list(args, mozinfo.os)
     assert len(test_list) == 1
     assert test_list[0]['name'] == 'raptor-speedometer-chrome'
 
 
-# Commented test_get_raptor_test_list_geckoview
-# in order to disable raptor-unity-webgl-geckoview - Bug 1524495
-"""
- def test_get_raptor_test_list_geckoview(create_args):
-    args = create_args(app="geckoview",
-                         test="raptor-unity-webgl")
-
-    test_list = get_raptor_test_list(args, mozinfo.os)
-    assert len(test_list) == 1
-    assert test_list[0]['name'] == 'raptor-unity-webgl-geckoview'
-"""
+def test_get_raptor_test_list_geckoview(create_args):
+    return
+#   args = create_args(app="geckoview",
+#                      test="raptor-unity-webgl")
+#
+#   test_list = get_raptor_test_list(args, mozinfo.os)
+#   assert len(test_list) == 1
+#   assert test_list[0]['name'] == 'raptor-unity-webgl-geckoview'
 
 
 def test_get_raptor_test_list_gecko_profiling(create_args):
     args = create_args(test="raptor-tp6-google-firefox",
                        gecko_profile=True)
 
     test_list = get_raptor_test_list(args, mozinfo.os)
     assert len(test_list) == 1
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-006.html.ini
+++ /dev/null
@@ -1,22 +0,0 @@
-[shape-outside-inset-006.html]
-  [inset(10px round 10.1200px 20.34px 30.56px 40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round 10.123px 20.00px 30.10px 40.5678px) - computed]
-    expected: FAIL
-
-  [inset(10px round +10.1200px +20.340px +30.56px +40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round 10.1200px 20.34px 30.56px 40.780px / 10.1200px 20.34px 30.56px 40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round 10.123px 20.00px 30.10px 40.5678px / 10.123px 20.00px 30.10px 40.5678px) - computed]
-    expected: FAIL
-
-  [inset(10px round +10.1200px +20.340px +30.56px +40.780px / +10.1200px +20.340px +30.56px +40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round +10.123px +20.00px +30.10px +40.5678px / 10.123px +20.00px +30.10px +40.5678px) - computed]
-    expected: FAIL
-
--- a/testing/webdriver/src/command.rs
+++ b/testing/webdriver/src/command.rs
@@ -444,16 +444,19 @@ pub enum NewSessionParameters {
 
 impl<'de> Deserialize<'de> for NewSessionParameters {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where
         D: Deserializer<'de>,
     {
         let value = serde_json::Value::deserialize(deserializer)?;
         if let Some(caps) = value.get("capabilities") {
+            if !caps.is_object() {
+                return Err(de::Error::custom("capabilities must be objects"));
+            }
             let caps = SpecNewSessionParameters::deserialize(caps).map_err(de::Error::custom)?;
             return Ok(NewSessionParameters::Spec(caps));
         }
 
         warn!("You are using deprecated legacy session negotiation patterns (desiredCapabilities/requiredCapabilities), see https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities#Legacy");
         let legacy = LegacyNewSessionParameters::deserialize(value).map_err(de::Error::custom)?;
         Ok(NewSessionParameters::Legacy(legacy))
     }
--- a/toolkit/components/extensions/ExtensionStorageSync.jsm
+++ b/toolkit/components/extensions/ExtensionStorageSync.jsm
@@ -1052,17 +1052,17 @@ class ExtensionStorageSync {
       }
       // No conflicts, or conflict was just someone else adding keys.
       return result;
     } catch (e) {
       if (KeyRingEncryptionRemoteTransformer.isOutdatedKB(e) ||
           e instanceof ServerKeyringDeleted ||
           // This is another way that ServerKeyringDeleted can
           // manifest; see bug 1350088 for more details.
-          e.message == "Server has been flushed.") {
+          e.message.includes("Server has been flushed.")) {
         // Check if our token is still valid, or if we got locked out
         // between starting the sync and talking to Kinto.
         const isSessionValid = await this._fxaService.sessionStatus();
         if (isSessionValid) {
           log.error("Couldn't decipher old keyring; deleting the default bucket and resetting sync status");
           await this._deleteBucket();
           await this.cryptoCollection.resetSyncStatus();
 
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -501,16 +501,29 @@ contentblocking:
     expires: never
     kind: boolean
     notification_emails:
       - aedelstein@mozilla.com
       - seceng-telemetry@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - main
+  category:
+    bug_numbers:
+      - 1529425
+    description: >
+      This scalar reports the value of the content blocking category pref (0 = "standard", 1 = "strict", 2 = "custom", 3 = some other value, this is not supported).
+    expires: never
+    kind: uint
+    notification_emails:
+      - aedelstein@mozilla.com
+      - seceng-telemetry@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - main
 
 sandbox:
   no_job:
     bug_numbers:
       - 1392570
     description: >
       Indicates that we can't use a job object for sandboxed child processes.
       Keyed by whether we are in a remote session or not from ::GetSystemMetrics(SM_REMOTESESSION).
--- a/toolkit/components/utils/JsonSchemaValidator.jsm
+++ b/toolkit/components/utils/JsonSchemaValidator.jsm
@@ -151,16 +151,32 @@ function validateAndParseParamRecursive(
           if (!valid) {
             return [false, null];
           }
           parsedObj[item] = parsedValue;
         }
       }
       return [true, parsedObj];
     }
+
+    case "JSON":
+      if (typeof(param) == "object") {
+        return [true, param];
+      }
+      try {
+        let json = JSON.parse(param);
+        if (typeof(json) != "object") {
+          log.error("JSON was not an object");
+          return [false, null];
+        }
+        return [true, json];
+      } catch (e) {
+        log.error("JSON string couldn't be parsed");
+        return [false, null];
+      }
   }
 
   return [false, null];
 }
 
 function validateAndParseSimpleParam(param, type) {
   let valid = false;
   let parsedParam = param;
--- a/toolkit/components/utils/test/browser/browser_JsonSchemaValidator.js
+++ b/toolkit/components/utils/test/browser/browser_JsonSchemaValidator.js
@@ -442,8 +442,49 @@ add_task(async function test_patternProp
       "[": {" type": "string" },
     },
   };
 
   Assert.throws(() => {
     [valid, parsed] = JsonSchemaValidator.validateAndParseParameters({}, schema);
   }, /Invalid property pattern/, "Checking that invalid property patterns throw");
 });
+
+add_task(async function test_JSON_type() {
+  let schema = {
+    type: "JSON",
+  };
+
+  let valid, parsed;
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters({
+    "a": "b",
+  }, schema);
+
+  ok(valid, "Object is valid");
+  ok(typeof(parsed) == "object", "parsed in an object");
+  is(parsed.a, "b", "parsedProperty is correct");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "{\"a\": \"b\"}"
+  , schema);
+
+  ok(valid, "Object is valid");
+  ok(typeof(parsed) == "object", "parsed in an object");
+  is(parsed.a, "b", "parsedProperty is correct");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "{This{is{not{JSON}}}}"
+  , schema);
+
+  ok(!valid, "Object is not valid since JSON was incorrect");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "0"
+  , schema);
+
+  ok(!valid, "Object is not valid since input wasn't an object");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "true"
+  , schema);
+
+  ok(!valid, "Object is not valid since input wasn't an object");
+});
--- a/toolkit/content/tests/chrome/test_labelcontrol.xul
+++ b/toolkit/content/tests/chrome/test_labelcontrol.xul
@@ -5,39 +5,48 @@
   XUL Widget Test for label control="value"
   -->
 <window title="tabindex" width="500" height="600"
         onload="runTests()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>  
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>  
 
-<label id="lab" control="ctl"/>
-<textbox id="ctl" value="Test"/>
-<checkbox id="chk" value="Checkbox"/>
+<label id="textbox-label" control="textbox" />
+<textbox id="textbox" value="Test"/>
+<label id="checkbox-label" control="checkbox" />
+<checkbox id="checkbox" value="Checkbox"/>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script>
 <![CDATA[
 
 SimpleTest.waitForExplicitFinish();
  
 function runTests()
 {
-  is($("lab").control, "ctl", "control");
-  is($("lab").labeledControlElement, $("ctl"), "labeledControlElement");
-  is($("ctl").labelElement, $("lab"), "labelElement");
-  is($("chk").labelElement.className, "checkbox-label", "labelElement");
+  let textbox = $("textbox");
+  let textboxLabel = $("textbox-label");
+  is(textboxLabel.control, "textbox", "textbox control");
+  is(textboxLabel.labeledControlElement, textbox, "textbox labeledControlElement");
+
+  let checkbox = $("checkbox");
+  let checkboxLabel = $("checkbox-label");
+  is(checkboxLabel.control, "checkbox", "checkbox control");
+  is(checkboxLabel.labeledControlElement, checkbox, "checkbox labeledControlElement");
+  is(checkbox.accessKey, "", "checkbox accessKey not set");
+  checkboxLabel.accessKey = "C";
+  is(checkbox.accessKey, "C", "checkbox accessKey set");
 
   SimpleTest.finish();
 }
 
 ]]>
 
 </script>
 
--- a/toolkit/content/widgets/general.xml
+++ b/toolkit/content/widgets/general.xml
@@ -31,30 +31,29 @@
                                   onget="return this.getAttribute('crop');"/>
       <property name="image"      onset="this.setAttribute('image',val); return val;"
                                   onget="return this.getAttribute('image');"/>
       <property name="command"    onset="this.setAttribute('command',val); return val;"
                                   onget="return this.getAttribute('command');"/>
       <property name="accessKey">
         <getter>
           <![CDATA[
-            return this.labelElement ? this.labelElement.accessKey : this.getAttribute("accesskey");
+            return this.getAttribute("accesskey");
           ]]>
         </getter>
         <setter>
           <![CDATA[
             // Always store on the control
             this.setAttribute("accesskey", val);
             // If there is a label, change the accesskey on the labelElement
             // if it's also set there
-            if (this.labelElement) {
-              this.labelElement.accessKey = val;
+            let labelElement = document.getElementsByAttribute("control", this.id)[0];
+            if (labelElement) {
+              labelElement.setAttribute("accesskey", val);
             }
             return val;
           ]]>
         </setter>
       </property>
-
-      <field name="labelElement"/>
     </implementation>
   </binding>
 
 </bindings>
--- a/toolkit/content/widgets/text.xml
+++ b/toolkit/content/widgets/text.xml
@@ -19,31 +19,16 @@
           this.formatAccessKey(true);
         ]]>
       </constructor>
 
       <method name="formatAccessKey">
         <parameter name="firstTime"/>
         <body>
           <![CDATA[
-            var control = this.labeledControlElement;
-            if (!control) {
-              var bindingParent = document.getBindingParent(this);
-              if ("accessKey" in bindingParent) {
-                control = bindingParent; // For controls that make the <label> an anon child
-              }
-            }
-            if (control) {
-              control.labelElement = this;
-              var controlAccessKey = control.getAttribute("accesskey");
-              if (controlAccessKey) {
-                this.setAttribute("accesskey", controlAccessKey);
-              }
-            }
-
             var accessKey = this.accessKey;
             // No need to remove existing formatting the first time.
             if (firstTime && !accessKey)
               return;
 
             if (this.mInsertSeparator === undefined) {
               try {
                 var prefs = Cc["@mozilla.org/preferences-service;1"].
@@ -83,17 +68,17 @@
 
             var oldHiddenSpan =
               this.getElementsByAttribute("class", "hiddenColon").item(0);
             if (oldHiddenSpan) {
               this.mergeElement(oldHiddenSpan);
             }
 
             var labelText = this.textContent;
-            if (!accessKey || !labelText || !control) {
+            if (!accessKey || !labelText) {
               return;
             }
             var accessKeyIndex = -1;
             if (!this.mAlwaysAppendAccessKey) {
               accessKeyIndex = labelText.indexOf(accessKey);
               if (accessKeyIndex < 0) { // Try again in upper case
                 accessKeyIndex =
                   labelText.toUpperCase().indexOf(accessKey.toUpperCase());
@@ -190,48 +175,39 @@
         !/Mac/.test(navigator.platform)
       </field>
       <field name="mInsertSeparator"/>
       <field name="mAlwaysAppendAccessKey">false</field>
 
       <property name="accessKey">
         <getter>
           <![CDATA[
-            var accessKey = this.getAttribute("accesskey");
-            return accessKey ? accessKey[0] : null;
+            return this.getAttribute("accesskey");
           ]]>
         </getter>
         <setter>
           <![CDATA[
-            // If this label already has an accesskey attribute store it here as well
-            if (this.hasAttribute("accesskey")) {
-              this.setAttribute("accesskey", val);
-            }
+            this.setAttribute("accesskey", val);
             var control = this.labeledControlElement;
             if (control) {
               control.setAttribute("accesskey", val);
             }
             this.formatAccessKey(false);
             return val;
           ]]>
         </setter>
       </property>
 
       <property name="labeledControlElement" readonly="true"
                 onget="var control = this.control; return control ? document.getElementById(control) : null;" />
 
       <property name="control" onget="return this.getAttribute('control');">
         <setter>
           <![CDATA[
-            var control = this.labeledControlElement;
-            if (control) {
-              control.labelElement = null; // No longer pointed to be this label
-            }
             this.setAttribute("control", val);
-            this.formatAccessKey(false);
             return val;
           ]]>
         </setter>
       </property>
     </implementation>
 
     <handlers>
       <handler event="click"><![CDATA[
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -47,19 +47,17 @@
         ]]></getter>
       </property>
 
       <property name="value"      onset="this.inputField.value = val; return val;"
                                   onget="return this.inputField.value;"/>
       <property name="defaultValue" onset="this.inputField.defaultValue = val; return val;"
                                   onget="return this.inputField.defaultValue;"/>
       <property name="label"      onset="this.setAttribute('label', val); return val;"
-                                  onget="return this.getAttribute('label') ||
-                                                (this.labelElement ? this.labelElement.value :
-                                                 this.placeholder);"/>
+                                  onget="return this.getAttribute('label') || this.placeholder;" />
       <property name="placeholder" onset="this.inputField.placeholder = val; return val;"
                                   onget="return this.inputField.placeholder;"/>
       <property name="emptyText"  onset="this.placeholder = val; return val;"
                                   onget="return this.placeholder;"/>
       <property name="type"       onset="if (val) this.setAttribute('type', val);
                                          else this.removeAttribute('type'); return val;"
                                   onget="return this.getAttribute('type');"/>
       <property name="maxLength"  onset="this.inputField.maxLength = val; return val;"
--- a/toolkit/content/widgets/toolbarbutton.xml
+++ b/toolkit/content/widgets/toolbarbutton.xml
@@ -6,16 +6,20 @@
 
 <bindings id="toolbarbuttonBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="toolbarbutton" display="xul:button"
            extends="chrome://global/content/bindings/button.xml#button-base">
+    <implementation>
+      <property name="multilineLabel"
+        onget="return document.getAnonymousElementByAttribute(this, 'class', 'toolbarbutton-multiline-text');" />
+    </implementation>
     <content>
       <children includes="observes|template|menupopup|panel|tooltip"/>
       <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal"/>
       <xul:label class="toolbarbutton-text" crop="right" flex="1"
                  xbl:inherits="value=label,accesskey,crop,dragover-top,wrap"/>
       <xul:label class="toolbarbutton-multiline-text" flex="1"
                  xbl:inherits="xbl:text=label,accesskey,wrap"/>
       <children includes="box"/>
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -390,17 +390,21 @@ async function loadManifestFromWebManife
   let manifest = await extension.loadManifest();
 
   // Read the list of available locales, and pre-load messages for
   // all locales.
   let locales = (extension.errors.length == 0) ?
                 await extension.initAllLocales() : null;
 
   if (extension.errors.length > 0) {
-    throw new Error("Extension is invalid");
+    let error = new Error("Extension is invalid");
+    // Add detailed errors on the error object so that the front end can display them
+    // if needed (eg in about:debugging).
+    error.additionalErrors = extension.errors;
+    throw error;
   }
 
   let bss = (manifest.browser_specific_settings && manifest.browser_specific_settings.gecko)
       || (manifest.applications && manifest.applications.gecko) || {};
   if (manifest.browser_specific_settings && manifest.applications) {
     logger.warn("Ignoring applications property in manifest");
   }
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js
@@ -46,16 +46,53 @@ add_task(async function test_implicit_id
   // file url of the installed xpi file.
   equal(addon.sourceURI && addon.sourceURI.spec,
         Services.io.newFileURI(xpifile).spec,
         "SourceURI of the add-on has the expected value");
 
   await addon.uninstall();
 });
 
+// Test that extension install error attach the detailed error messages to the
+// Error object.
+add_task(async function test_invalid_extension_install_errors() {
+  const manifest = {
+    name: "invalid",
+    applications: {
+      gecko: {
+        id: "invalid@tests.mozilla.org",
+      },
+    },
+    description: "extension with an invalid 'matches' value",
+    manifest_version: 2,
+    content_scripts: [{
+      "matches": "*://*.foo.com/*",
+      "js": ["content.js"],
+    }],
+    version: "1.0",
+  };
+
+  const addonDir = await promiseWriteWebManifestForExtension(manifest, gTmpD,
+                                                "the-addon-sub-dir");
+
+  await Assert.rejects(
+    AddonManager.installTemporaryAddon(addonDir),
+    err => {
+      return err.additionalErrors.length == 1 &&
+             err.additionalErrors[0] ==
+              `Reading manifest: Error processing content_scripts.0.matches: ` +
+              `Expected array instead of "*://*.foo.com/*"`;
+    },
+    "Exception has the proper additionalErrors details"
+  );
+
+  Services.obs.notifyObservers(addonDir, "flush-cache-entry");
+  addonDir.remove(true);
+});
+
 // We should be able to temporarily install an unsigned web extension
 // that does not have an ID in its manifest.
 add_task(async function test_unsigned_no_id_temp_install() {
   AddonTestUtils.useRealCertChecks = true;
   const manifest = {
     name: "no ID",
     description: "extension without an ID",
     manifest_version: 2,
--- a/toolkit/mozapps/update/common/updatedefines.h
+++ b/toolkit/mozapps/update/common/updatedefines.h
@@ -2,30 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef UPDATEDEFINES_H
 #define UPDATEDEFINES_H
 
 #include "readstrings.h"
 
-#ifndef MAXPATHLEN
-#  ifdef PATH_MAX
-#    define MAXPATHLEN PATH_MAX
-#  elif defined(MAX_PATH)
-#    define MAXPATHLEN MAX_PATH
-#  elif defined(_MAX_PATH)
-#    define MAXPATHLEN _MAX_PATH
-#  elif defined(CCHMAXPATH)
-#    define MAXPATHLEN CCHMAXPATH
-#  else
-#    define MAXPATHLEN 1024
-#  endif
-#endif
-
 #if defined(XP_WIN)
 #  include <windows.h>
 #  include <shlwapi.h>
 #  include <direct.h>
 #  include <io.h>
 #  include <stdio.h>
 #  include <stdarg.h>
 
@@ -140,9 +126,23 @@ static inline int mywcsprintf(WCHAR* des
 #  define NS_tdirent dirent
 #  define NS_topendir opendir
 #  define NS_tclosedir closedir
 #  define NS_treaddir readdir
 #endif
 
 #define BACKUP_EXT NS_T(".moz-backup")
 
+#ifndef MAXPATHLEN
+#  ifdef PATH_MAX
+#    define MAXPATHLEN PATH_MAX
+#  elif defined(MAX_PATH)
+#    define MAXPATHLEN MAX_PATH
+#  elif defined(_MAX_PATH)
+#    define MAXPATHLEN _MAX_PATH
+#  elif defined(CCHMAXPATH)
+#    define MAXPATHLEN CCHMAXPATH
+#  else
+#    define MAXPATHLEN 1024
+#  endif
 #endif
+
+#endif
--- a/tools/tryselect/preset.py
+++ b/tools/tryselect/preset.py
@@ -73,28 +73,29 @@ def migrate_old_presets():
     config.read(old_preset_path)
 
     unknown = defaultdict(list)
     for section in config.sections():
         for name, value in config.items(section):
             kwargs = {}
             if section == 'fuzzy':  # try fuzzy
                 kwargs['query'] = [value]
+                kwargs['selector'] = 'fuzzy'
 
             elif section == 'try':  # try syntax
-                section = 'syntax'
                 parser = SyntaxParser()
                 kwargs = vars(parser.parse_args(AutoTry.split_try_string(value)))
                 kwargs = {k: v for k, v in kwargs.items() if v != parser.get_default(k)}
+                kwargs['selector'] = 'syntax'
 
             else:
                 unknown[section].append("{} = {}".format(name, value))
                 continue
 
-            presets.save(name, selector=section, **kwargs)
+            presets.save(name, **kwargs)
 
     os.remove(old_preset_path)
 
     if unknown:
         for section, values in unknown.items():
             print("""
 warning: unknown section '{}', the following presets were not migrated:
   {}