Merge inbound to mozilla-central r=merge a=merge
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Tue, 09 Jan 2018 11:52:55 +0200
changeset 452623 7c9de87c6eb02d7448297bff489f27cb20c33d24
parent 452589 4248602674ff589f368a4b868fa4743a033640e4 (current diff)
parent 452622 eef0978b42ad4765f71c8c9abe9e5b4a7356da68 (diff)
child 452624 6f5fac320fcb6625603fa8a744ffa8523f8b3d71
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
7c9de87c6eb0 / 59.0a1 / 20180109100117 / files
nightly linux64
7c9de87c6eb0 / 59.0a1 / 20180109100117 / files
nightly mac
7c9de87c6eb0 / 59.0a1 / 20180109100117 / files
nightly win32
7c9de87c6eb0 / 59.0a1 / 20180109100117 / files
nightly win64
7c9de87c6eb0 / 59.0a1 / 20180109100117 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central r=merge a=merge
docshell/base/nsDocShell.cpp
dom/notification/DesktopNotification.cpp
dom/notification/DesktopNotification.h
dom/tests/mochitest/notification/desktop-notification/create_notification.html
dom/tests/mochitest/notification/desktop-notification/moz.build
dom/tests/mochitest/notification/desktop-notification/notification_common.js
dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html
dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html
dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html
dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html
dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul
dom/webidl/DesktopNotification.webidl
editor/reftests/xul/emptytextbox-5.xul
gfx/webrender_bindings/WebRenderTypes.h
modules/libpref/init/all.js
testing/web-platform/meta/service-workers/service-worker/fetch-response-taint.https.html.ini
testing/web-platform/meta/service-workers/service-worker/worker-interception.https.html.ini
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/Scalars.yaml
--- a/accessible/windows/msaa/CompatibilityUIA.cpp
+++ b/accessible/windows/msaa/CompatibilityUIA.cpp
@@ -2,20 +2,23 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Compatibility.h"
 
 #include "mozilla/Telemetry.h"
+#include "mozilla/WindowsVersion.h"
 
+#include "nsDataHashtable.h"
 #include "nsPrintfCString.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
+#include "nsTHashtable.h"
 #include "nsUnicharUtils.h"
 #include "nsWinUtils.h"
 
 #include "NtUndoc.h"
 
 #if defined(UIA_LOGGING)
 
 #define LOG_ERROR(FuncName) \
@@ -26,42 +29,112 @@
   }
 
 #else
 
 #define LOG_ERROR(FuncName)
 
 #endif // defined(UIA_LOGGING)
 
-static bool
-GetLocalObjectHandle(DWORD aSrcPid, HANDLE aSrcHandle, nsAutoHandle& aProcess,
-                     nsAutoHandle& aLocal)
+struct ByteArrayDeleter
 {
-  aLocal.reset();
+  void operator()(void* aBuf)
+  {
+    delete[] reinterpret_cast<char*>(aBuf);
+  }
+};
+
+typedef UniquePtr<OBJECT_DIRECTORY_INFORMATION, ByteArrayDeleter> ObjDirInfoPtr;
 
-  if (!aProcess) {
-    HANDLE rawProcess = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, aSrcPid);
-    if (!rawProcess) {
-      LOG_ERROR(OpenProcess);
-      return false;
-    }
-
-    aProcess.own(rawProcess);
+// ComparatorFnT returns true to continue searching, or else false to indicate
+// search completion.
+template <typename ComparatorFnT>
+static bool
+FindNamedObject(ComparatorFnT aComparator)
+{
+  // We want to enumerate every named kernel object in our session. We do this
+  // by opening a directory object using a path constructed using the session
+  // id under which our process resides.
+  DWORD sessionId;
+  if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &sessionId)) {
+    return false;
   }
 
-  HANDLE rawDuped;
-  if (!::DuplicateHandle(aProcess.get(), aSrcHandle, ::GetCurrentProcess(),
-                         &rawDuped, GENERIC_READ, FALSE, 0)) {
-    LOG_ERROR(DuplicateHandle);
+  nsAutoString path;
+  path.AppendPrintf("\\Sessions\\%u\\BaseNamedObjects", sessionId);
+
+  UNICODE_STRING baseNamedObjectsName;
+  ::RtlInitUnicodeString(&baseNamedObjectsName, path.get());
+
+  OBJECT_ATTRIBUTES attributes;
+  InitializeObjectAttributes(&attributes, &baseNamedObjectsName, 0,
+                             nullptr, nullptr);
+
+  HANDLE rawBaseNamedObjects;
+  NTSTATUS ntStatus = ::NtOpenDirectoryObject(&rawBaseNamedObjects,
+                                              DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
+                                              &attributes);
+  if (!NT_SUCCESS(ntStatus)) {
     return false;
   }
 
-  aLocal.own(rawDuped);
+  nsAutoHandle baseNamedObjects(rawBaseNamedObjects);
+
+  ULONG context = 0, returnedLen;
+
+  ULONG objDirInfoBufLen = 1024 * sizeof(OBJECT_DIRECTORY_INFORMATION);
+  ObjDirInfoPtr objDirInfo(
+    reinterpret_cast<OBJECT_DIRECTORY_INFORMATION*>(new char[objDirInfoBufLen]));
+
+  // Now query that directory object for every named object that it contains.
+
+  BOOL firstCall = TRUE;
 
-  return true;
+  do {
+    ntStatus = ::NtQueryDirectoryObject(baseNamedObjects, objDirInfo.get(),
+                                        objDirInfoBufLen, FALSE, firstCall,
+                                        &context, &returnedLen);
+#if defined(HAVE_64BIT_BUILD)
+    if (!NT_SUCCESS(ntStatus)) {
+      return false;
+    }
+#else
+    if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
+      // This case only occurs on 32-bit builds running atop WOW64.
+      // (See https://bugzilla.mozilla.org/show_bug.cgi?id=1423999#c3)
+      objDirInfo.reset(reinterpret_cast<OBJECT_DIRECTORY_INFORMATION*>(new char[returnedLen]));
+      objDirInfoBufLen = returnedLen;
+      continue;
+    } else if (!NT_SUCCESS(ntStatus)) {
+      return false;
+    }
+#endif
+
+    // NtQueryDirectoryObject gave us an array of OBJECT_DIRECTORY_INFORMATION
+    // structures whose final entry is zeroed out.
+    OBJECT_DIRECTORY_INFORMATION* curDir = objDirInfo.get();
+    while (curDir->mName.Length && curDir->mTypeName.Length) {
+      // We use nsDependentSubstring here because UNICODE_STRINGs are not
+      // guaranteed to be null-terminated.
+      nsDependentSubstring objName(curDir->mName.Buffer,
+                                   curDir->mName.Length / sizeof(wchar_t));
+      nsDependentSubstring typeName(curDir->mTypeName.Buffer,
+                                    curDir->mTypeName.Length / sizeof(wchar_t));
+
+      if (!aComparator(objName, typeName)) {
+        return true;
+      }
+
+      ++curDir;
+    }
+
+    firstCall = FALSE;
+  } while (ntStatus == STATUS_MORE_ENTRIES);
+
+  return false;
 }
 
 namespace mozilla {
 namespace a11y {
 
 Maybe<DWORD> Compatibility::sUiaRemotePid;
 
 Maybe<bool>
@@ -69,215 +142,164 @@ Compatibility::OnUIAMessage(WPARAM aWPar
 {
   Maybe<DWORD>& remotePid = sUiaRemotePid;
   auto clearUiaRemotePid = MakeScopeExit([&remotePid]() {
     remotePid = Nothing();
   });
 
   Telemetry::AutoTimer<Telemetry::A11Y_UIA_DETECTION_TIMING_MS> timer;
 
-  static auto pNtQuerySystemInformation =
-    reinterpret_cast<decltype(&::NtQuerySystemInformation)>(
-      ::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"),
-                       "NtQuerySystemInformation"));
-
-  static auto pNtQueryObject =
-    reinterpret_cast<decltype(&::NtQueryObject)>(
-      ::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"), "NtQueryObject"));
-
   // UIA creates a section containing the substring "HOOK_SHMEM_"
   NS_NAMED_LITERAL_STRING(kStrHookShmem, "HOOK_SHMEM_");
 
   // The section name always ends with this suffix, which is derived from the
   // current thread id and the UIA message's WPARAM and LPARAM.
   nsAutoString partialSectionSuffix;
   partialSectionSuffix.AppendPrintf("_%08x_%08x_%08x", ::GetCurrentThreadId(),
-                                    aLParam, aWParam);
+                                    static_cast<DWORD>(aLParam), aWParam);
+
+  // Find any named Section that matches the naming convention of the UIA shared
+  // memory.
+  nsAutoHandle section;
+  auto comparator = [&](const nsDependentSubstring& aName,
+                        const nsDependentSubstring& aType) -> bool {
+    if (aType.Equals(NS_LITERAL_STRING("Section")) &&
+        FindInReadable(kStrHookShmem, aName) &&
+        StringEndsWith(aName, partialSectionSuffix)) {
+      section.own(::OpenFileMapping(GENERIC_READ, FALSE,
+                                    PromiseFlatString(aName).get()));
+      return false;
+    }
+
+    return true;
+  };
+
+  if (!FindNamedObject(comparator) || !section) {
+    return Nothing();
+  }
 
   NTSTATUS ntStatus;
 
   // First we must query for a list of all the open handles in the system.
   UniquePtr<char[]> handleInfoBuf;
   ULONG handleInfoBufLen = sizeof(SYSTEM_HANDLE_INFORMATION_EX) +
                            1024 * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX);
 
   // We must query for handle information in a loop, since we are effectively
   // asking the kernel to take a snapshot of all the handles on the system;
   // the size of the required buffer may fluctuate between successive calls.
   while (true) {
     handleInfoBuf = MakeUnique<char[]>(handleInfoBufLen);
 
-    ntStatus = pNtQuerySystemInformation(
+    ntStatus = ::NtQuerySystemInformation(
                  (SYSTEM_INFORMATION_CLASS) SystemExtendedHandleInformation,
                  handleInfoBuf.get(), handleInfoBufLen, &handleInfoBufLen);
     if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) {
       continue;
     }
 
     if (!NT_SUCCESS(ntStatus)) {
       return Nothing();
     }
 
     break;
   }
 
-  // Now we iterate through the system handle list, searching for a section
-  // handle whose name matches the section name used by UIA.
-
-  static Maybe<USHORT> sSectionObjTypeIndex;
-
   const DWORD ourPid = ::GetCurrentProcessId();
-
   Maybe<PVOID> kernelObject;
-
-  ULONG lastPid = 0;
-  nsAutoHandle process;
+  static Maybe<USHORT> sectionObjTypeIndex;
+  nsTHashtable<nsUint32HashKey> nonSectionObjTypes;
+  nsDataHashtable<nsVoidPtrHashKey, DWORD> objMap;
 
   auto handleInfo = reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(handleInfoBuf.get());
 
   for (ULONG index = 0; index < handleInfo->mHandleCount; ++index) {
     SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& curHandle = handleInfo->mHandles[index];
 
-    if (lastPid && lastPid == curHandle.mPid && !process) {
-      // During the previous iteration, we could not obtain a handle for this
-      // pid. Skip any remaining handles belonging to that pid.
-      continue;
-    }
-
-    // As a perf optimization, we reuse the same process handle as long as we're
-    // still looking at the same pid. Once the pid changes, we need to reset
-    // process so that we open a new handle to the newly-seen process.
-    if (lastPid != curHandle.mPid) {
-      process.reset();
-    }
+    HANDLE handle = reinterpret_cast<HANDLE>(curHandle.mHandle);
 
-    nsAutoHandle handle;
-
-    if (kernelObject.isSome() && kernelObject.value() == curHandle.mObject) {
-      // If we know the value of the underlying kernel object, we can immediately
-      // check for equality by comparing against curHandle.mObject
-      remotePid = Some(static_cast<DWORD>(curHandle.mPid));
-      break;
-    } else if (sSectionObjTypeIndex.isSome()) {
-      // Otherwise, if we know which object type value corresponds to a Section
-      // object, we can use that to eliminate any handles that are not sections.
-      if (curHandle.mObjectTypeIndex != sSectionObjTypeIndex.value()) {
-        // Not a section handle
+    // The mapping of the curHandle.mObjectTypeIndex field depends on the
+    // underlying OS kernel. As we scan through the handle list, we record the
+    // type indices such that we may use those values to skip over handles that
+    // refer to non-section objects.
+    if (sectionObjTypeIndex) {
+      // If we know the type index for Sections, that's the fastest check...
+      if (sectionObjTypeIndex.value() != curHandle.mObjectTypeIndex) {
+        // Not a section
         continue;
       }
-    } else {
-      // Otherwise we need to query the handle to determine its type. Note that
-      // each handle in the system list is relative to its owning process, so
-      // we cannot do anything with it until we duplicate the handle into our
-      // own process.
-
-      lastPid = curHandle.mPid;
-
-      if (!GetLocalObjectHandle((DWORD) curHandle.mPid,
-                                (HANDLE) curHandle.mHandle,
-                                process, handle)) {
-        // We don't have access to do this, assume this handle isn't relevant
-        continue;
-      }
-
-      // Now we have our own handle to the object, lets find out what type of
-      // object this handle represents. Any handle whose type is not "Section"
-      // is of no interest to us.
+    } else if (nonSectionObjTypes.Contains(static_cast<uint32_t>(
+                                             curHandle.mObjectTypeIndex))) {
+      // Otherwise we check whether or not the object type is definitely _not_
+      // a Section...
+      continue;
+    } else if (ourPid == curHandle.mPid) {
+      // Otherwise we need to issue some system calls to find out the object
+      // type corresponding to the current handle's type index.
       ULONG objTypeBufLen;
-      ntStatus = pNtQueryObject(handle, ObjectTypeInformation, nullptr,
-                                0, &objTypeBufLen);
+      ntStatus = ::NtQueryObject(handle, ObjectTypeInformation,
+                                 nullptr, 0, &objTypeBufLen);
       if (ntStatus != STATUS_INFO_LENGTH_MISMATCH) {
         continue;
       }
 
       auto objTypeBuf = MakeUnique<char[]>(objTypeBufLen);
-      ntStatus = pNtQueryObject(handle, ObjectTypeInformation, objTypeBuf.get(),
-                                objTypeBufLen, &objTypeBufLen);
+      ntStatus = ::NtQueryObject(handle, ObjectTypeInformation, objTypeBuf.get(),
+                                 objTypeBufLen, &objTypeBufLen);
       if (!NT_SUCCESS(ntStatus)) {
-        // We don't have access to do this, assume this handle isn't relevant
         continue;
       }
 
       auto objType =
         reinterpret_cast<PUBLIC_OBJECT_TYPE_INFORMATION*>(objTypeBuf.get());
 
-      nsDependentString objTypeName(objType->TypeName.Buffer,
-                                    objType->TypeName.Length / sizeof(wchar_t));
+      // Now we check whether the object's type name matches "Section"
+      nsDependentSubstring objTypeName(objType->TypeName.Buffer,
+                                       objType->TypeName.Length / sizeof(wchar_t));
       if (!objTypeName.Equals(NS_LITERAL_STRING("Section"))) {
-        // Not a section, so we don't care about this handle anymore.
+        nonSectionObjTypes.PutEntry(static_cast<uint32_t>(curHandle.mObjectTypeIndex));
         continue;
       }
 
-      // We have a section, save this handle's type code so that we can go
-      // faster in future iterations.
-      sSectionObjTypeIndex = Some(curHandle.mObjectTypeIndex);
-    }
-
-    // If we reached this point without needing to query the handle, then we
-    // need to open it here so that we can query its name.
-    lastPid = curHandle.mPid;
-
-    if ((!process || !handle) &&
-        !GetLocalObjectHandle((DWORD) curHandle.mPid, (HANDLE) curHandle.mHandle,
-                              process, handle)) {
-      // We don't have access to do this, assume this handle isn't relevant
-      continue;
-    }
-
-    // At this point, |handle| is a valid section handle. Let's try to find
-    // out the name of its underlying object.
-    ULONG objNameBufLen;
-    ntStatus = pNtQueryObject(handle,
-                              (OBJECT_INFORMATION_CLASS)ObjectNameInformation,
-                              nullptr, 0, &objNameBufLen);
-    if (ntStatus != STATUS_INFO_LENGTH_MISMATCH) {
-      continue;
-    }
-
-    auto objNameBuf = MakeUnique<char[]>(objNameBufLen);
-    ntStatus = pNtQueryObject(handle,
-                              (OBJECT_INFORMATION_CLASS)ObjectNameInformation,
-                              objNameBuf.get(), objNameBufLen, &objNameBufLen);
-    if (!NT_SUCCESS(ntStatus)) {
-      continue;
+      sectionObjTypeIndex = Some(curHandle.mObjectTypeIndex);
     }
 
-    auto objNameInfo = reinterpret_cast<OBJECT_NAME_INFORMATION*>(objNameBuf.get());
-    if (!objNameInfo->mName.Length) {
-      // This section is unnamed. We don't care about those.
-      continue;
-    }
+    // At this point we know that curHandle references a Section object.
+    // Now we can do some actual tests on it.
 
-    nsDependentString objName(objNameInfo->mName.Buffer,
-                              objNameInfo->mName.Length / sizeof(wchar_t));
-
-    // Check to see if the section's name matches our expected name.
-    if (!FindInReadable(kStrHookShmem, objName) ||
-        !StringEndsWith(objName, partialSectionSuffix)) {
-      // The names don't match, continue searching.
-      continue;
-    }
+    if (ourPid != curHandle.mPid) {
+      if (kernelObject && kernelObject.value() == curHandle.mObject) {
+        // The kernel objects match -- we have found the remote pid!
+        remotePid = Some(curHandle.mPid);
+        break;
+      }
 
-    // At this point we have a section handle whose name matches the one that
-    // we're looking for.
-
-    if (curHandle.mPid == ourPid) {
-      // Our own process also has a handle to the section of interest. While we
-      // don't want our own pid, this *does* give us an opportunity to speed up
-      // future iterations by examining each handle for its kernel object (which
-      // is the same for all processes) instead of searching by name.
+      // An object that is not ours. Since we do not yet know which kernel
+      // object we're interested in, we'll save the current object for later.
+      objMap.Put(curHandle.mObject, curHandle.mPid);
+    } else if (handle == section.get()) {
+      // This is the file mapping that we opened above. We save this mObject
+      // in order to compare to Section objects opened by other processes.
       kernelObject = Some(curHandle.mObject);
-      continue;
     }
+  }
+
+  if (!kernelObject) {
+    return Nothing();
+  }
 
-    // Bingo! We want this pid!
-    remotePid = Some(static_cast<DWORD>(curHandle.mPid));
+  if (!remotePid) {
+    // We found kernelObject *after* we saw the remote process's copy. Now we
+    // must look it up in objMap.
+    DWORD pid;
+    if (objMap.Get(kernelObject.value(), &pid)) {
+      remotePid = Some(pid);
+    }
+  }
 
-    break;
-  }
 
   if (!remotePid) {
     return Nothing();
   }
 
   a11y::SetInstantiator(remotePid.value());
 
   /* This is where we could block UIA stuff
--- a/accessible/windows/msaa/NtUndoc.h
+++ b/accessible/windows/msaa/NtUndoc.h
@@ -4,20 +4,32 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_NtUndoc_h
 #define mozilla_NtUndoc_h
 
 #include <winternl.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 #ifndef STATUS_INFO_LENGTH_MISMATCH
 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
 #endif
 
+#ifndef STATUS_BUFFER_TOO_SMALL
+#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
+#endif
+
+#ifndef STATUS_MORE_ENTRIES
+#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
+#endif
+
 enum UndocSystemInformationClass
 {
   SystemExtendedHandleInformation = 64
 };
 
 struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
 {
   PVOID       mObject;
@@ -42,9 +54,41 @@ enum UndocObjectInformationClass
   ObjectNameInformation = 1
 };
 
 struct OBJECT_NAME_INFORMATION
 {
   UNICODE_STRING  mName;
 };
 
+// The following declarations are documented on MSDN but are not included in
+// public user-mode headers.
+
+enum DirectoryObjectAccessFlags
+{
+  DIRECTORY_QUERY = 0x0001,
+  DIRECTORY_TRAVERSE = 0x0002,
+  DIRECTORY_CREATE_OBJECT = 0x0004,
+  DIRECTORY_CREATE_SUBDIRECTORY = 0x0008,
+  DIRECTORY_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | 0x000F
+};
+
+NTSTATUS WINAPI
+NtOpenDirectoryObject(PHANDLE aDirectoryHandle, ACCESS_MASK aDesiredAccess,
+                      POBJECT_ATTRIBUTES aObjectAttributes);
+
+struct OBJECT_DIRECTORY_INFORMATION
+{
+  UNICODE_STRING  mName;
+  UNICODE_STRING  mTypeName;
+};
+
+NTSTATUS WINAPI
+NtQueryDirectoryObject(HANDLE aDirectoryHandle, PVOID aOutBuffer,
+                       ULONG aBufferLength, BOOLEAN aReturnSingleEntry,
+                       BOOLEAN aRestartScan, PULONG aContext,
+                       PULONG aOutReturnLength);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
 #endif // mozilla_NtUndoc_h
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -41,16 +41,20 @@ UNIFIED_SOURCES += [
 
 SOURCES += [
     # This file cannot be built in unified mode because it redefines _WIN32_WINNT
     'LazyInstantiator.cpp',
     # This file cannot be built in unified mode because it includes ISimpleDOMNode_i.c.
     'ServiceProvider.cpp',
 ]
 
+OS_LIBS += [
+    'ntdll',
+]
+
 if CONFIG['MOZ_XUL']:
     UNIFIED_SOURCES += [
         'XULListboxAccessibleWrap.cpp',
         'XULMenuAccessibleWrap.cpp',
         'XULTreeGridAccessibleWrap.cpp',
     ]
 
 LOCAL_INCLUDES += [
--- a/browser/base/content/test/general/browser_sanitizeDialog.js
+++ b/browser/base/content/test/general/browser_sanitizeDialog.js
@@ -814,17 +814,26 @@ WindowHelper.prototype = {
             await wh.onunload();
           }
           await PlacesTestUtils.promiseAsyncUpdates();
           wh._resolveClosed();
         })();
       });
     }
     Services.ww.registerNotification(windowObserver);
-    Services.ww.openWindow(null,
+
+    let browserWin = null;
+    if (Services.appinfo.OS !== "Darwin") {
+      // Retrieve the browser window so we can specify it as the parent
+      // of the dialog to simulate the way the user opens the dialog
+      // on Windows and Linux.
+      browserWin = Services.wm.getMostRecentWindow("navigator:browser");
+    }
+
+    Services.ww.openWindow(browserWin,
                            "chrome://browser/content/sanitize.xul",
                            "SanitizeDialog",
                            "chrome,titlebar,dialog,centerscreen,modal",
                            null);
   },
 
   /**
    * Selects a duration in the duration dropdown.
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2829,20 +2829,24 @@ nsDocShell::MaybeCreateInitialClientSour
   nsCOMPtr<nsIDocShell> parent = GetParentDocshell();
   nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
   nsPIDOMWindowInner* parentInner =
     parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
   if (!parentInner) {
     return;
   }
 
+  nsCOMPtr<nsIURI> uri;
+  MOZ_ALWAYS_SUCCEEDS(
+    NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")));
+
   // We're done if there is no parent controller or if this docshell
   // is not permitted to control for some reason.
   Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
-  if (controller.isNothing() || !ServiceWorkerAllowedToControlWindow(nullptr)) {
+  if (controller.isNothing() || !ServiceWorkerAllowedToControlWindow(principal, uri)) {
     return;
   }
 
   nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
   if (!swm) {
     return;
   }
 
@@ -11349,16 +11353,30 @@ nsDocShell::ScrollToAnchor(bool aCurHasR
     // page's charset.
     nsresult rv = NS_ERROR_FAILURE;
     NS_ConvertUTF8toUTF16 uStr(aNewHash);
     if (!uStr.IsEmpty()) {
       rv = shell->GoToAnchor(uStr, scroll,
                              nsIPresShell::SCROLL_SMOOTH_AUTO);
     }
 
+    if (NS_FAILED(rv)) {
+      char* str = ToNewCString(aNewHash);
+      if (!str) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+      nsUnescape(str);
+      NS_ConvertUTF8toUTF16 utf16Str(str);
+      if (!utf16Str.IsEmpty()) {
+        rv = shell->GoToAnchor(utf16Str, scroll,
+                               nsIPresShell::SCROLL_SMOOTH_AUTO);
+      }
+      free(str);
+    }
+
     // Above will fail if the anchor name is not UTF-8.  Need to
     // convert from document charset to unicode.
     if (NS_FAILED(rv)) {
       // Get a document charset
       NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
       nsIDocument* doc = mContentViewer->GetDocument();
       NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
       nsAutoCString charset;
@@ -14093,61 +14111,36 @@ nsDocShell::CanSetOriginAttributes()
       }
     }
   }
 
   return true;
 }
 
 bool
-nsDocShell::ServiceWorkerAllowedToControlWindow(nsIURI* aURI)
-{
-  // NOTE: Ideally this method would call one of the
-  //       nsContentUtils::StorageAllowed*() methods to determine if the
-  //       interception is allowed.  Unfortunately we cannot safely do this
-  //       before the first window loads in the child process because the
-  //       permission manager might not have all its data yet.  Therefore,
-  //       we use this somewhat lame alternate implementation here.  Once
-  //       interception is moved to the parent process we should switch
-  //       to calling nsContentUtils::StorageAllowed*().  See bug 1428130.
+nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
+                                                nsIURI* aURI)
+{
+  MOZ_ASSERT(aPrincipal);
+  MOZ_ASSERT(aURI);
 
   if (UsePrivateBrowsing() || mSandboxFlags) {
     return false;
   }
 
-  uint32_t cookieBehavior = nsContentUtils::CookiesBehavior();
-  uint32_t lifetimePolicy = nsContentUtils::CookiesLifetimePolicy();
-  if (cookieBehavior == nsICookieService::BEHAVIOR_REJECT ||
-      lifetimePolicy == nsICookieService::ACCEPT_SESSION) {
-    return false;
-  }
-
-  if (!aURI || cookieBehavior == nsICookieService::BEHAVIOR_ACCEPT) {
-    return true;
-  }
-
   nsCOMPtr<nsIDocShellTreeItem> parent;
   GetSameTypeParent(getter_AddRefs(parent));
-  nsCOMPtr<nsPIDOMWindowOuter> parentWindow = parent ? parent->GetWindow()
-                                                     : nullptr;
-  if (parentWindow) {
-    nsresult rv = NS_OK;
-    nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
-      do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv);
-    if (thirdPartyUtil) {
-      bool isThirdPartyURI = true;
-      rv = thirdPartyUtil->IsThirdPartyWindow(parentWindow, aURI,
-                                              &isThirdPartyURI);
-      if (NS_SUCCEEDED(rv) && isThirdPartyURI) {
-        return false;
-      }
-    }
-  }
-
-  return true;
+  nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
+  nsPIDOMWindowInner* parentInner =
+    parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
+
+  nsContentUtils::StorageAccess storage =
+    nsContentUtils::StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
+
+  return storage == nsContentUtils::StorageAccess::eAllow;
 }
 
 nsresult
 nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs)
 {
   if (!CanSetOriginAttributes()) {
     return NS_ERROR_FAILURE;
   }
@@ -14364,31 +14357,32 @@ nsDocShell::ShouldPrepareForIntercept(ns
     *aShouldIntercept = doc->GetController().isSome();
     if (NS_WARN_IF(rv.Failed())) {
       return rv.StealNSResult();
     }
 
     return NS_OK;
   }
 
+  nsCOMPtr<nsIPrincipal> principal =
+    BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
+
   // For navigations, first check to see if we are allowed to control a
   // window with the given URL.
-  if (!ServiceWorkerAllowedToControlWindow(aURI)) {
+  if (!ServiceWorkerAllowedToControlWindow(principal, aURI)) {
     return NS_OK;
   }
 
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   if (!swm) {
     return NS_OK;
   }
 
   // We're allowed to control a window, so check with the ServiceWorkerManager
   // for a matching service worker.
-  nsCOMPtr<nsIPrincipal> principal =
-    BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
   *aShouldIntercept = swm->IsAvailable(principal, aURI);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
 {
   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -787,20 +787,18 @@ private: // member functions
   void MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal = nullptr);
 
   // Determine if a service worker is allowed to control a window in this
   // docshell with the given URL.  If there are any reasons it should not,
   // this will return false.  If true is returned then the window *may* be
   // controlled.  The caller must still consult either the parent controller
   // or the ServiceWorkerManager to determine if a service worker should
   // actually control the window.
-  //
-  // A nullptr URL is considered to be an about:blank window and will not
-  // trigger 3rd party iframe checks.
-  bool ServiceWorkerAllowedToControlWindow(nsIURI* aURI);
+  bool ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
+                                           nsIURI* aURI);
 
   // Return the ClientInfo for the initial about:blank window, if it exists
   // or we have speculatively created a ClientSource in
   // MaybeCreateInitialClientSource().  This can return a ClientInfo object
   // even if GetExtantDoc() returns nullptr.
   mozilla::Maybe<mozilla::dom::ClientInfo> GetInitialClientInfo() const;
 
   /**
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -8,17 +8,16 @@
 #include "base/basictypes.h"
 
 #include "Navigator.h"
 #include "nsIXULAppInfo.h"
 #include "nsPluginArray.h"
 #include "nsMimeTypeArray.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/BodyExtractor.h"
-#include "mozilla/dom/DesktopNotification.h"
 #include "mozilla/dom/FetchBinding.h"
 #include "mozilla/dom/File.h"
 #include "nsGeolocation.h"
 #include "nsIClassOfService.h"
 #include "nsIHttpProtocolHandler.h"
 #include "nsIContentPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentPolicyUtils.h"
@@ -190,17 +189,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Na
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
@@ -233,21 +231,16 @@ Navigator::Invalidate()
   mStorageManager = nullptr;
 
   // If there is a page transition, make sure delete the geolocation object.
   if (mGeolocation) {
     mGeolocation->Shutdown();
     mGeolocation = nullptr;
   }
 
-  if (mNotification) {
-    mNotification->Shutdown();
-    mNotification = nullptr;
-  }
-
   if (mBatteryManager) {
     mBatteryManager->Shutdown();
     mBatteryManager = nullptr;
   }
 
   mBatteryPromise = nullptr;
 
   if (mConnection) {
@@ -1311,32 +1304,16 @@ Navigator::MozGetUserMediaDevices(const 
     return;
   }
 
   MediaManager* manager = MediaManager::Get();
   aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
                                      aInnerWindowID, aCallID);
 }
 
-DesktopNotificationCenter*
-Navigator::GetMozNotification(ErrorResult& aRv)
-{
-  if (mNotification) {
-    return mNotification;
-  }
-
-  if (!mWindow || !mWindow->GetDocShell()) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  mNotification = new DesktopNotificationCenter(mWindow);
-  return mNotification;
-}
-
 //*****************************************************************************
 //    Navigator::nsINavigatorBattery
 //*****************************************************************************
 
 Promise*
 Navigator::GetBattery(ErrorResult& aRv)
 {
   if (mBatteryPromise) {
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -54,17 +54,16 @@ namespace dom {
 class Permissions;
 
 namespace battery {
 class BatteryManager;
 } // namespace battery
 
 class Promise;
 
-class DesktopNotificationCenter;
 class MozIdleObserver;
 class Gamepad;
 class GamepadServiceTest;
 class NavigatorUserMediaSuccessCallback;
 class NavigatorUserMediaErrorCallback;
 class MozGetUserMediaDevicesSuccessCallback;
 
 namespace network {
@@ -173,17 +172,16 @@ public:
   uint64_t HardwareConcurrency();
   bool TaintEnabled()
   {
     return false;
   }
   void AddIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
   void RemoveIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
 
-  DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
   already_AddRefed<LegacyMozTCPSocket> MozTCPSocket();
   network::Connection* GetConnection(ErrorResult& aRv);
   MediaDevices* GetMediaDevices(ErrorResult& aRv);
 
   void GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
   GamepadServiceTest* RequestGamepadServiceTest();
   already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
   void GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays) const;
@@ -270,17 +268,16 @@ private:
                           BodyExtractorBase* aBody,
                           BeaconType aType,
                           ErrorResult& aRv);
 
   RefPtr<nsMimeTypeArray> mMimeTypes;
   RefPtr<nsPluginArray> mPlugins;
   RefPtr<Permissions> mPermissions;
   RefPtr<Geolocation> mGeolocation;
-  RefPtr<DesktopNotificationCenter> mNotification;
   RefPtr<battery::BatteryManager> mBatteryManager;
   RefPtr<Promise> mBatteryPromise;
   RefPtr<network::Connection> mConnection;
   RefPtr<CredentialsContainer> mCredentials;
   RefPtr<MediaDevices> mMediaDevices;
   RefPtr<time::TimeManager> mTimeManager;
   RefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -8891,41 +8891,54 @@ nsContentUtils::IsNonSubresourceRequest(
 }
 
 // static, public
 nsContentUtils::StorageAccess
 nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
 {
   if (nsIDocument* document = aWindow->GetExtantDoc()) {
     nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
-    return InternalStorageAllowedForPrincipal(principal, aWindow);
+    return InternalStorageAllowedForPrincipal(principal, aWindow, nullptr);
   }
 
   return StorageAccess::eDeny;
 }
 
 // static, public
 nsContentUtils::StorageAccess
 nsContentUtils::StorageAllowedForDocument(nsIDocument* aDoc)
 {
   MOZ_ASSERT(aDoc);
 
   if (nsPIDOMWindowInner* inner = aDoc->GetInnerWindow()) {
     nsCOMPtr<nsIPrincipal> principal = aDoc->NodePrincipal();
-    return InternalStorageAllowedForPrincipal(principal, inner);
+    return InternalStorageAllowedForPrincipal(principal, inner, nullptr);
   }
 
   return StorageAccess::eDeny;
 }
 
 // static, public
 nsContentUtils::StorageAccess
+nsContentUtils::StorageAllowedForNewWindow(nsIPrincipal* aPrincipal,
+                                           nsIURI* aURI,
+                                           nsPIDOMWindowInner* aParent)
+{
+  MOZ_ASSERT(aPrincipal);
+  MOZ_ASSERT(aURI);
+  // parent may be nullptr
+
+  return InternalStorageAllowedForPrincipal(aPrincipal, aParent, aURI);
+}
+
+// static, public
+nsContentUtils::StorageAccess
 nsContentUtils::StorageAllowedForPrincipal(nsIPrincipal* aPrincipal)
 {
-  return InternalStorageAllowedForPrincipal(aPrincipal, nullptr);
+  return InternalStorageAllowedForPrincipal(aPrincipal, nullptr, nullptr);
 }
 
 // static, private
 void
 nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
                                               uint32_t* aLifetimePolicy,
                                               uint32_t* aBehavior)
 {
@@ -8974,17 +8987,18 @@ nsContentUtils::GetCookieBehaviorForPrin
       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
       break;
   }
 }
 
 // static, private
 nsContentUtils::StorageAccess
 nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
-                                                   nsPIDOMWindowInner* aWindow)
+                                                   nsPIDOMWindowInner* aWindow,
+                                                   nsIURI* aURI)
 {
   MOZ_ASSERT(aPrincipal);
 
   StorageAccess access = StorageAccess::eAllow;
 
   // We don't allow storage on the null principal, in general. Even if the
   // calling context is chrome.
   if (aPrincipal->GetIsNullPrincipal()) {
@@ -9044,19 +9058,21 @@ nsContentUtils::InternalStorageAllowedFo
   // IndexedDB: allowed in 3rd-party iframes by default. Preference can be set to
   //   disable in 3rd-party, which will disallow in about: URIs, unless they are
   //   within a specific whitelist.
   //
   // This means that behavior for storage with internal about: URIs should not be
   // affected, which is desireable due to the lack of automated testing for about:
   // URIs with these preferences set, and the importance of the correct functioning
   // of these URIs even with custom preferences.
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
-  if (NS_SUCCEEDED(rv) && uri) {
+  nsCOMPtr<nsIURI> uri = aURI;
+  if (!uri) {
+    Unused << aPrincipal->GetURI(getter_AddRefs(uri));
+  }
+  if (uri) {
     bool isAbout = false;
     MOZ_ALWAYS_SUCCEEDS(uri->SchemeIs("about", &isAbout));
     if (isAbout) {
       return access;
     }
   }
 
   // We don't want to prompt for every attempt to access permissions.
@@ -9068,17 +9084,17 @@ nsContentUtils::InternalStorageAllowedFo
   if (aWindow && (behavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
                   behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN)) {
     nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
       do_GetService(THIRDPARTYUTIL_CONTRACTID);
     MOZ_ASSERT(thirdPartyUtil);
 
     bool thirdPartyWindow = false;
     if (NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyWindow(
-          aWindow->GetOuterWindow(), nullptr, &thirdPartyWindow)) && thirdPartyWindow) {
+          aWindow->GetOuterWindow(), aURI, &thirdPartyWindow)) && thirdPartyWindow) {
       // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
       // simply rejecting the request to use the storage. In the future, if we
       // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
       // for non-cookie storage types, this may change.
 
       return StorageAccess::eDeny;
     }
   }
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2908,26 +2908,16 @@ public:
    *
    * @param aHeader the response's Referrer-Policy header to parse
    * @return referrer policy from the response header.
    */
   static mozilla::net::ReferrerPolicy GetReferrerPolicyFromHeader(const nsAString& aHeader);
 
   static bool IsNonSubresourceRequest(nsIChannel* aChannel);
 
-  static uint32_t CookiesBehavior()
-  {
-    return sCookiesBehavior;
-  }
-
-  static uint32_t CookiesLifetimePolicy()
-  {
-    return sCookiesLifetimePolicy;
-  }
-
   // The order of these entries matters, as we use std::min for total ordering
   // of permissions. Private Browsing is considered to be more limiting
   // then session scoping
   enum class StorageAccess {
     // Don't allow access to the storage
     eDeny = 0,
     // Allow access to the storage, but only if it is secure to do so in a
     // private browsing context.
@@ -2957,16 +2947,24 @@ public:
    *
    * Note, this may be used on documents during the loading process where
    * the window's extant document has not been set yet.  The code in
    * StorageAllowedForWindow(), however, will not work in these cases.
    */
   static StorageAccess StorageAllowedForDocument(nsIDocument* aDoc);
 
   /*
+   * Checks if storage should be allowed for a new window with the given
+   * principal, load URI, and parent.
+   */
+  static StorageAccess StorageAllowedForNewWindow(nsIPrincipal* aPrincipal,
+                                                  nsIURI* aURI,
+                                                  nsPIDOMWindowInner* aParent);
+
+  /*
    * Checks if storage for the given principal is permitted by the user's
    * preferences. The caller is assumed to not be a third-party iframe.
    * (if that is possible, the caller should use StorageAllowedForWindow)
    */
   static StorageAccess StorageAllowedForPrincipal(nsIPrincipal* aPrincipal);
 
   /*
    * Serializes a HTML nsINode into its markup representation.
@@ -3333,23 +3331,25 @@ private:
   static void GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
                                             uint32_t* aLifetimePolicy,
                                             uint32_t* aBehavior);
 
   /*
    * Checks if storage for a given principal is permitted by the user's
    * preferences. If aWindow is non-null, its principal must be passed as
    * aPrincipal, and the third-party iframe and sandboxing status of the window
-   * are also checked.
+   * are also checked.  If aURI is non-null, then it is used as the comparison
+   * against aWindow to determine if this is a third-party load.
    *
    * Used in the implementation of StorageAllowedForWindow and
    * StorageAllowedForPrincipal.
    */
   static StorageAccess InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
-                                                          nsPIDOMWindowInner* aWindow);
+                                                          nsPIDOMWindowInner* aWindow,
+                                                          nsIURI* aURI);
 
   static nsINode* GetCommonAncestorHelper(nsINode* aNode1, nsINode* aNode2);
   static nsIContent* GetCommonFlattenedTreeAncestorHelper(nsIContent* aContent1,
                                                           nsIContent* aContent2);
 
   static nsIXPConnect *sXPConnect;
 
   static nsIScriptSecurityManager *sSecurityManager;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10030,33 +10030,39 @@ nsDocument::ScrollToRef()
     // Check an empty string which might be caused by the UTF-8 conversion
     if (!ref.IsEmpty()) {
       // Note that GoToAnchor will handle flushing layout as needed.
       rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
     } else {
       rv = NS_ERROR_FAILURE;
     }
 
-    // If UTF-8 URI failed then try to assume the string as a
-    // document's charset.
     if (NS_FAILED(rv)) {
-      auto encoding = GetDocumentCharacterSet();
       char* tmpstr = ToNewCString(mScrollToRef);
       if (!tmpstr) {
         return;
       }
       nsUnescape(tmpstr);
       nsAutoCString unescapedRef;
       unescapedRef.Assign(tmpstr);
       free(tmpstr);
 
-      rv = encoding->DecodeWithoutBOMHandling(unescapedRef, ref);
-
-      if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
-        rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
+      NS_ConvertUTF8toUTF16 utf16Str(unescapedRef);
+      if (!utf16Str.IsEmpty()) {
+        rv = shell->GoToAnchor(utf16Str, mChangeScrollPosWhenScrollingToRef);
+      }
+
+      // If UTF-8 URI failed then try to assume the string as a
+      // document's charset.
+      if (NS_FAILED(rv)) {
+        const Encoding* encoding = GetDocumentCharacterSet();
+        rv = encoding->DecodeWithoutBOMHandling(unescapedRef, ref);
+        if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
+          rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
+        }
       }
     }
     if (NS_SUCCEEDED(rv)) {
       mScrolledToRefAlready = true;
     }
   }
 }
 
deleted file mode 100644
--- a/dom/notification/DesktopNotification.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "mozilla/dom/DesktopNotification.h"
-#include "mozilla/dom/DesktopNotificationBinding.h"
-#include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "mozilla/EventStateManager.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentPermissionHelper.h"
-#include "nsXULAppAPI.h"
-#include "mozilla/dom/PBrowserChild.h"
-#include "mozilla/Preferences.h"
-#include "nsGlobalWindow.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsServiceManagerUtils.h"
-#include "PermissionMessageUtils.h"
-#include "nsILoadContext.h"
-
-namespace mozilla {
-namespace dom {
-
-/*
- * Simple Request
- */
-class DesktopNotificationRequest : public nsIContentPermissionRequest
-                                 , public Runnable
-{
-  virtual ~DesktopNotificationRequest()
-  {
-  }
-
-  nsCOMPtr<nsIContentPermissionRequester> mRequester;
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSICONTENTPERMISSIONREQUEST
-
-  explicit DesktopNotificationRequest(DesktopNotification* aNotification)
-    : Runnable("dom::DesktopNotificationRequest")
-    , mDesktopNotification(aNotification)
-  {
-    mRequester = new nsContentPermissionRequester(mDesktopNotification->GetOwner());
-  }
-
-  NS_IMETHOD Run() override
-  {
-    nsCOMPtr<nsPIDOMWindowInner> window = mDesktopNotification->GetOwner();
-    nsContentPermissionUtils::AskPermission(this, window);
-    return NS_OK;
-  }
-
-  RefPtr<DesktopNotification> mDesktopNotification;
-};
-
-/* ------------------------------------------------------------------------ */
-/* AlertServiceObserver                                                     */
-/* ------------------------------------------------------------------------ */
-
-NS_IMPL_ISUPPORTS(AlertServiceObserver, nsIObserver)
-
-/* ------------------------------------------------------------------------ */
-/* DesktopNotification                                                      */
-/* ------------------------------------------------------------------------ */
-
-uint32_t DesktopNotification::sCount = 0;
-
-nsresult
-DesktopNotification::PostDesktopNotification()
-{
-  if (!mObserver) {
-    mObserver = new AlertServiceObserver(this);
-  }
-
-  nsCOMPtr<nsIAlertsService> alerts = do_GetService("@mozilla.org/alerts-service;1");
-  if (!alerts) {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
-  // Generate a unique name (which will also be used as a cookie) because
-  // the nsIAlertsService will coalesce notifications with the same name.
-  // In the case of IPC, the parent process will use the cookie to map
-  // to nsIObservers, thus cookies must be unique to differentiate observers.
-  nsString uniqueName = NS_LITERAL_STRING("desktop-notification:");
-  uniqueName.AppendInt(sCount++);
-  nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
-  if (!owner) {
-    return NS_ERROR_FAILURE;
-  }
-  nsCOMPtr<nsIDocument> doc = owner->GetDoc();
-  nsIPrincipal* principal = doc->NodePrincipal();
-  nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
-  bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
-  nsCOMPtr<nsIAlertNotification> alert =
-    do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
-  NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
-  nsresult rv = alert->Init(uniqueName, mIconURL, mTitle,
-                            mDescription,
-                            true,
-                            uniqueName,
-                            NS_LITERAL_STRING("auto"),
-                            EmptyString(),
-                            EmptyString(),
-                            principal,
-                            inPrivateBrowsing,
-                            false /* requireInteraction */);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return alerts->ShowAlert(alert, mObserver);
-}
-
-DesktopNotification::DesktopNotification(const nsAString & title,
-                                         const nsAString & description,
-                                         const nsAString & iconURL,
-                                         nsPIDOMWindowInner* aWindow,
-                                         bool aIsHandlingUserInput,
-                                         nsIPrincipal* principal)
-  : DOMEventTargetHelper(aWindow)
-  , mTitle(title)
-  , mDescription(description)
-  , mIconURL(iconURL)
-  , mPrincipal(principal)
-  , mIsHandlingUserInput(aIsHandlingUserInput)
-  , mAllow(false)
-  , mShowHasBeenCalled(false)
-{
-  if (Preferences::GetBool("notification.disabled", false)) {
-    return;
-  }
-
-  // If we are in testing mode (running mochitests, for example)
-  // and we are suppose to allow requests, then just post an allow event.
-  if (Preferences::GetBool("notification.prompt.testing", false) &&
-      Preferences::GetBool("notification.prompt.testing.allow", true)) {
-    mAllow = true;
-  }
-}
-
-void
-DesktopNotification::Init()
-{
-  RefPtr<DesktopNotificationRequest> request = new DesktopNotificationRequest(this);
-
-  NS_DispatchToMainThread(request);
-}
-
-DesktopNotification::~DesktopNotification()
-{
-  if (mObserver) {
-    mObserver->Disconnect();
-  }
-}
-
-void
-DesktopNotification::DispatchNotificationEvent(const nsString& aName)
-{
-  if (NS_FAILED(CheckInnerWindowCorrectness())) {
-    return;
-  }
-
-  RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
-  // it doesn't bubble, and it isn't cancelable
-  event->InitEvent(aName, false, false);
-  event->SetTrusted(true);
-  bool dummy;
-  DispatchEvent(event, &dummy);
-}
-
-nsresult
-DesktopNotification::SetAllow(bool aAllow)
-{
-  mAllow = aAllow;
-
-  // if we have called Show() already, lets go ahead and post a notification
-  if (mShowHasBeenCalled && aAllow) {
-    return PostDesktopNotification();
-  }
-
-  return NS_OK;
-}
-
-void
-DesktopNotification::HandleAlertServiceNotification(const char *aTopic)
-{
-  if (NS_FAILED(CheckInnerWindowCorrectness())) {
-    return;
-  }
-
-  if (!strcmp("alertclickcallback", aTopic)) {
-    DispatchNotificationEvent(NS_LITERAL_STRING("click"));
-  } else if (!strcmp("alertfinished", aTopic)) {
-    DispatchNotificationEvent(NS_LITERAL_STRING("close"));
-  }
-}
-
-void
-DesktopNotification::Show(ErrorResult& aRv)
-{
-  mShowHasBeenCalled = true;
-
-  if (!mAllow) {
-    return;
-  }
-
-  aRv = PostDesktopNotification();
-}
-
-JSObject*
-DesktopNotification::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return DesktopNotificationBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* ------------------------------------------------------------------------ */
-/* DesktopNotificationCenter                                                */
-/* ------------------------------------------------------------------------ */
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(DesktopNotificationCenter)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DesktopNotificationCenter)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DesktopNotificationCenter)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DesktopNotificationCenter)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-already_AddRefed<DesktopNotification>
-DesktopNotificationCenter::CreateNotification(const nsAString& aTitle,
-                                              const nsAString& aDescription,
-                                              const nsAString& aIconURL)
-{
-  MOZ_ASSERT(mOwner);
-
-  RefPtr<DesktopNotification> notification =
-    new DesktopNotification(aTitle,
-                            aDescription,
-                            aIconURL,
-                            mOwner,
-                            EventStateManager::IsHandlingUserInput(),
-                            mPrincipal);
-  notification->Init();
-  return notification.forget();
-}
-
-JSObject*
-DesktopNotificationCenter::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return DesktopNotificationCenterBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* ------------------------------------------------------------------------ */
-/* DesktopNotificationRequest                                               */
-/* ------------------------------------------------------------------------ */
-
-NS_IMPL_ISUPPORTS_INHERITED(DesktopNotificationRequest, Runnable,
-                            nsIContentPermissionRequest)
-
-NS_IMETHODIMP
-DesktopNotificationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
-{
-  if (!mDesktopNotification) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  NS_IF_ADDREF(*aRequestingPrincipal = mDesktopNotification->mPrincipal);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
-{
-  if (!mDesktopNotification) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  NS_IF_ADDREF(*aRequestingWindow = mDesktopNotification->GetOwner());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::GetElement(nsIDOMElement * *aElement)
-{
-  NS_ENSURE_ARG_POINTER(aElement);
-  *aElement = nullptr;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::GetIsHandlingUserInput(bool *aIsHandlingUserInput)
-{
-  *aIsHandlingUserInput = mDesktopNotification->mIsHandlingUserInput;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::Cancel()
-{
-  nsresult rv = mDesktopNotification->SetAllow(false);
-  mDesktopNotification = nullptr;
-  return rv;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::Allow(JS::HandleValue aChoices)
-{
-  MOZ_ASSERT(aChoices.isUndefined());
-  nsresult rv = mDesktopNotification->SetAllow(true);
-  mDesktopNotification = nullptr;
-  return rv;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
-{
-  NS_ENSURE_ARG_POINTER(aRequester);
-
-  nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
-  requester.forget(aRequester);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
-{
-  nsTArray<nsString> emptyOptions;
-  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
-                                                         NS_LITERAL_CSTRING("unused"),
-                                                         emptyOptions,
-                                                         aTypes);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/notification/DesktopNotification.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_DesktopNotification_h
-#define mozilla_dom_DesktopNotification_h
-
-#include "nsIPrincipal.h"
-#include "nsIAlertsService.h"
-#include "nsIContentPermissionPrompt.h"
-
-#include "nsIObserver.h"
-#include "nsString.h"
-#include "nsWeakPtr.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsIDOMWindow.h"
-#include "nsIScriptObjectPrincipal.h"
-
-#include "nsIDOMEvent.h"
-
-#include "mozilla/Attributes.h"
-#include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/ErrorResult.h"
-#include "nsWrapperCache.h"
-
-
-namespace mozilla {
-namespace dom {
-
-class AlertServiceObserver;
-class DesktopNotification;
-
-/*
- * DesktopNotificationCenter
- * Object hangs off of the navigator object and hands out DesktopNotification objects
- */
-class DesktopNotificationCenter final : public nsISupports,
-                                        public nsWrapperCache
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DesktopNotificationCenter)
-
-  explicit DesktopNotificationCenter(nsPIDOMWindowInner* aWindow)
-  {
-    MOZ_ASSERT(aWindow);
-    mOwner = aWindow;
-
-    nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
-    MOZ_ASSERT(sop);
-
-    mPrincipal = sop->GetPrincipal();
-    MOZ_ASSERT(mPrincipal);
-  }
-
-  void Shutdown() {
-    mOwner = nullptr;
-  }
-
-  nsPIDOMWindowInner* GetParentObject() const
-  {
-    return mOwner;
-  }
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-  already_AddRefed<DesktopNotification>
-  CreateNotification(const nsAString& title,
-                     const nsAString& description,
-                     const nsAString& iconURL);
-
-private:
-  virtual ~DesktopNotificationCenter()
-  {
-  }
-
-  nsCOMPtr<nsPIDOMWindowInner> mOwner;
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-};
-
-class DesktopNotificationRequest;
-
-class DesktopNotification final : public DOMEventTargetHelper
-{
-  friend class DesktopNotificationRequest;
-
-public:
-
-  DesktopNotification(const nsAString& aTitle,
-                      const nsAString& aDescription,
-                      const nsAString& aIconURL,
-                      nsPIDOMWindowInner* aWindow,
-                      bool aIsHandlingUserInput,
-                      nsIPrincipal* principal);
-
-  virtual ~DesktopNotification();
-
-  void Init();
-
-  /*
-   * PostDesktopNotification
-   * Uses alert service to display a notification
-   */
-  nsresult PostDesktopNotification();
-
-  nsresult SetAllow(bool aAllow);
-
-  /*
-   * Creates and dispatches a dom event of type aName
-   */
-  void DispatchNotificationEvent(const nsString& aName);
-
-  void HandleAlertServiceNotification(const char *aTopic);
-
-  // WebIDL
-
-  nsPIDOMWindowInner* GetParentObject() const
-  {
-    return GetOwner();
-  }
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-  void Show(ErrorResult& aRv);
-
-  IMPL_EVENT_HANDLER(click)
-  IMPL_EVENT_HANDLER(close)
-
-protected:
-
-  nsString mTitle;
-  nsString mDescription;
-  nsString mIconURL;
-
-  RefPtr<AlertServiceObserver> mObserver;
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-  bool mIsHandlingUserInput;
-  bool mAllow;
-  bool mShowHasBeenCalled;
-
-  static uint32_t sCount;
-};
-
-class AlertServiceObserver: public nsIObserver
-{
- public:
-  NS_DECL_ISUPPORTS
-
-  explicit AlertServiceObserver(DesktopNotification* notification)
-    : mNotification(notification) {}
-
-  void Disconnect() { mNotification = nullptr; }
-
-  NS_IMETHOD
-  Observe(nsISupports* aSubject,
-          const char* aTopic,
-          const char16_t* aData) override
-  {
-
-    // forward to parent
-    if (mNotification) {
-      mNotification->HandleAlertServiceNotification(aTopic);
-    }
-    return NS_OK;
-  };
-
- private:
-  virtual ~AlertServiceObserver() {}
-
-  DesktopNotification* mNotification;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif /* mozilla_dom_DesktopNotification_h */
--- a/dom/notification/moz.build
+++ b/dom/notification/moz.build
@@ -12,34 +12,34 @@ EXTRA_COMPONENTS += [
     'NotificationStorage.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'NotificationDB.jsm'
 ]
 
 EXPORTS.mozilla.dom += [
-    'DesktopNotification.h',
     'Notification.h',
     'NotificationEvent.h',
 ]
 
 UNIFIED_SOURCES += [
-    'DesktopNotification.cpp',
     'Notification.cpp',
     'NotificationEvent.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/ipc',
     '/dom/workers',
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
+MOCHITEST_CHROME_MANIFESTS += ['test/chrome/chrome.ini']
+
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
new file mode 100644
--- /dev/null
+++ b/dom/notification/test/chrome/chrome.ini
@@ -0,0 +1,1 @@
+[test_notification_system_principal.xul]
\ No newline at end of file
rename from dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul
rename to dom/notification/test/chrome/test_notification_system_principal.xul
rename from dom/tests/mochitest/notification/desktop-notification/create_notification.html
rename to dom/notification/test/mochitest/create_notification.html
--- a/dom/notification/test/mochitest/mochitest.ini
+++ b/dom/notification/test/mochitest/mochitest.ini
@@ -1,10 +1,12 @@
 [DEFAULT]
 
 support-files =
+  create_notification.html
   MockServices.js
   NotificationTest.js
 
 [test_notification_basics.html]
 [test_notification_storage.html]
 [test_bug931307.html]
 skip-if = (os == 'android') # Bug 1258975 on android.
+[test_notification_tag.html]
\ No newline at end of file
rename from dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html
rename to dom/notification/test/mochitest/test_notification_tag.html
--- a/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html
+++ b/dom/notification/test/mochitest/test_notification_tag.html
@@ -86,22 +86,21 @@ https://bugzilla.mozilla.org/show_bug.cg
     function showNotifications() {
       SpecialPowers.wrap(SpecialPowers.Components).
         manager.QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar).
         registerFactory(MOCK_CID, "alerts service", ALERTS_SERVICE_CONTRACT_ID, mockAlertsService);
 
       // Load two frames with the same origin that create notification with the same tag.
       // Both pages should generate notifications with the same name, and thus the second
       // notification should replace the first.
-      frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
-      frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
-
+      frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
+      frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
       // Load a frame with a different origin that creates a notification with the same tag.
       // The notification name should be different and thus no notifications should be replaced.
-      frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
+      frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
     }
 
     SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],
                                        ["notification.prompt.testing.allow", true]]},
                               showNotifications);
   } else {
     ok(true, "Notifications are not enabled on the platform.");
   }
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -2380,22 +2380,22 @@ nsSVGElement::DidAnimateTransformList(in
   nsIFrame* frame = GetPrimaryFrame();
 
   if (frame) {
     nsAtom *transformAttr = GetTransformListAttrName();
     frame->AttributeChanged(kNameSpaceID_None,
                             transformAttr,
                             aModType);
     // When script changes the 'transform' attribute, Element::SetAttrAndNotify
-    // will call nsNodeUtills::AttributeChanged, under which
+    // will call nsNodeUtils::AttributeChanged, under which
     // SVGTransformableElement::GetAttributeChangeHint will be called and an
     // appropriate change event posted to update our frame's overflow rects.
     // The SetAttrAndNotify doesn't happen for transform changes caused by
     // 'animateTransform' though (and sending out the mutation events that
-    // nsNodeUtills::AttributeChanged dispatches would be inappropriate
+    // nsNodeUtils::AttributeChanged dispatches would be inappropriate
     // anyway), so we need to post the change event ourself.
     nsChangeHint changeHint = GetAttributeChangeHint(transformAttr, aModType);
     if (changeHint) {
       nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), changeHint);
     }
   }
 }
 
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -266,20 +266,16 @@ var interfaceNamesInGlobalScope =
     "DataTransfer",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransferItem",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransferItemList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DelayNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "DesktopNotification",
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    "DesktopNotificationCenter",
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceLightEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceMotionEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceOrientationEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DeviceProximityEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
deleted file mode 100644
--- a/dom/tests/mochitest/notification/desktop-notification/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
deleted file mode 100644
--- a/dom/tests/mochitest/notification/desktop-notification/notification_common.js
+++ /dev/null
@@ -1,70 +0,0 @@
-const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{48068bc2-40ab-4904-8afd-4cdfb3a385f3}");
-const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
-
-const MOCK_SYSTEM_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{e86d888c-e41b-4b78-9104-2f2742a532de}");
-const SYSTEM_ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/system-alerts-service;1";
-
-var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager.
-  QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar);
-
-var mockAlertsService = {
-  showAlert: function(alert, alertListener) {
-    // probably should do this async....
-    SpecialPowers.wrap(alertListener).observe(null, "alertshow", alert.cookie);
-
-    if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) {
-       SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", alert.cookie);
-    }
-
-    SpecialPowers.wrap(alertListener).observe(null, "alertfinished", alert.cookie);
-  },
-
-  showAlertNotification: function(imageUrl, title, text, textClickable,
-                                  cookie, alertListener, name, bidi,
-                                  lang, data) {
-    return this.showAlert({
-      cookie: cookie
-    }, alertListener);
-  },
-
-  QueryInterface: function(aIID) {
-    if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
-        SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
-      return this;
-    }
-    throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
-  },
-
-  createInstance: function(aOuter, aIID) {
-    if (aOuter != null) {
-      throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
-    }
-    return this.QueryInterface(aIID);
-  }
-};
-mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
-
-function setup_notifications(allowPrompt, forceClick, callback) {
-  SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],
-                                     ["notification.prompt.testing.allow", allowPrompt],
-                                     ["notification.prompt.testing.click_on_notification", forceClick]]},
-                            callback);
-
-  registrar.registerFactory(MOCK_SYSTEM_ALERTS_CID, "system alerts service",
-                            SYSTEM_ALERTS_SERVICE_CONTRACT_ID,
-                            mockAlertsService);
-
-  registrar.registerFactory(MOCK_ALERTS_CID, "alerts service",
-                            ALERTS_SERVICE_CONTRACT_ID,
-                            mockAlertsService);
-}
-
-function reset_notifications() {
-  registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService);
-  registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService);
-}
-
-function is_feature_enabled() {
-  return navigator.mozNotification && SpecialPowers.getBoolPref("notification.feature.enabled");
-}
-
deleted file mode 100644
--- a/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=573588
--->
-<head>
-  <title>Basic functional test</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="notification_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-<script type="text/javascript">
-  if (is_feature_enabled()) {
-    SimpleTest.waitForExplicitFinish();
-
-    function showNotifications() {
-      ok(navigator.mozNotification, "test for notification.");
-
-      var notification = navigator.mozNotification.createNotification("test", "test");
-      ok(notification, "test to ensure we can create a notification");
-
-      notification.onclose = function() {
-        ok(true, "notification was display and is now closing");
-        reset_notifications();
-        SimpleTest.finish();
-      };
-
-      notification.onclick = function() {
-        ok(false, "Click should not have been called.");
-        reset_notifications();
-        SimpleTest.finish();
-      };
-
-      notification.show();
-    }
-
-    setup_notifications(true, false, showNotifications);
-  } else {
-    ok(true, "Desktop notifications not enabled.");
-  }
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=573588
--->
-<head>
-  <title>Basic functional test</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="notification_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-<script type="text/javascript">
-  if (is_feature_enabled()) {
-    SimpleTest.waitForExplicitFinish();
-
-    var click_was_called = false;
-
-    function showNotifications() {
-      ok(navigator.mozNotification, "test for notification.");
-
-      var notification = navigator.mozNotification.createNotification("test", "test");
-      ok(notification, "test to ensure we can create a notification");
-
-      notification.onclose = function() {
-        ok(true, "notification was display and is now closing");
-        ok(click_was_called, "was notification clicked?");
-
-        reset_notifications();
-        SimpleTest.finish();
-      };
-
-      notification.onclick = function() {
-        ok(true, "Click was called.  Good.");
-        click_was_called = true;
-      };
-
-      notification.show();
-    }
-
-    setup_notifications(true, true, showNotifications);
-  } else {
-    ok(true, "Desktop notifications not enabled.");
-  }
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=605309
--->
-<head>
-  <title>Test for leak when window closes</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="notification_common.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-
-<script>
-if (is_feature_enabled()) {
-    SimpleTest.waitForExplicitFinish();
-
-    function boom()
-    {
-        document.documentElement.focus();
-        var x = navigator.mozNotification;
-        document.documentElement.addEventListener('', function(){x});
-        ok(true, "load callback called");
-        SimpleTest.finish();
-    }
-
-    window.addEventListener("load", boom);
-} else {
-    ok(true, "Desktop notifications not enabled.");
-}
-</script>
-</head>
-<body>
-<p> I like to write tests </p>
-</body>
-</html>
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -91,17 +91,17 @@ AssembleClientData(const nsAString& aOri
   }
 
   return NS_OK;
 }
 
 static void
 RegisteredKeysToScopedCredentialList(const nsAString& aAppId,
   const nsTArray<RegisteredKey>& aKeys,
-  nsTArray<WebAuthnScopedCredentialDescriptor>& aList)
+  nsTArray<WebAuthnScopedCredential>& aList)
 {
   for (const RegisteredKey& key : aKeys) {
     // Check for required attributes
     if (!key.mVersion.WasPassed() || !key.mKeyHandle.WasPassed() ||
         key.mVersion.Value() != kRequiredU2FVersion) {
       continue;
     }
 
@@ -111,17 +111,17 @@ RegisteredKeysToScopedCredentialList(con
     }
 
     CryptoBuffer keyHandle;
     nsresult rv = keyHandle.FromJwkBase64(key.mKeyHandle.Value());
     if (NS_WARN_IF(NS_FAILED(rv))) {
       continue;
     }
 
-    WebAuthnScopedCredentialDescriptor c;
+    WebAuthnScopedCredential c;
     c.id() = keyHandle;
     aList.AppendElement(c);
   }
 }
 
 static ErrorCode
 EvaluateAppID(nsPIDOMWindowInner* aParent, const nsString& aOrigin,
               /* in/out */ nsString& aAppId)
@@ -387,17 +387,17 @@ U2F::Register(const nsAString& aAppId,
   if (clientDataJSON.IsEmpty()) {
     RegisterResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::BAD_REQUEST));
     ExecuteCallback(response, callback);
     return;
   }
 
   // Build the exclusion list, if any
-  nsTArray<WebAuthnScopedCredentialDescriptor> excludeList;
+  nsTArray<WebAuthnScopedCredential> excludeList;
   RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
                                        excludeList);
 
   auto clientData = NS_ConvertUTF16toUTF8(clientDataJSON);
 
   CryptoBuffer rpIdHash, clientDataHash;
   if (NS_FAILED(BuildTransactionHashes(cAppId, clientData,
                                        rpIdHash, clientDataHash))) {
@@ -535,17 +535,17 @@ U2F::Sign(const nsAString& aAppId,
   if (NS_WARN_IF(NS_FAILED(rv))) {
     SignResponse response;
     response.mErrorCode.Construct(static_cast<uint32_t>(ErrorCode::BAD_REQUEST));
     ExecuteCallback(response, callback);
     return;
   }
 
   // Build the key list, if any
-  nsTArray<WebAuthnScopedCredentialDescriptor> permittedList;
+  nsTArray<WebAuthnScopedCredential> permittedList;
   RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
                                        permittedList);
 
   auto clientData = NS_ConvertUTF16toUTF8(clientDataJSON);
 
   CryptoBuffer rpIdHash, clientDataHash;
   if (NS_FAILED(BuildTransactionHashes(cAppId, clientData,
                                        rpIdHash, clientDataHash))) {
@@ -568,16 +568,17 @@ U2F::Sign(const nsAString& aAppId,
   nsTArray<WebAuthnExtension> extensions;
 
   uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
 
   WebAuthnGetAssertionInfo info(rpIdHash,
                                 clientDataHash,
                                 adjustedTimeoutMillis,
                                 permittedList,
+                                false, /* requireUserVerification */
                                 extensions);
 
   MOZ_ASSERT(mTransaction.isNothing());
   mTransaction = Some(U2FTransaction(clientData, Move(AsVariant(callback))));
   mChild->SendRequestSign(mTransaction.ref().mId, info);
 }
 
 void
--- a/dom/webauthn/PWebAuthnTransaction.ipdl
+++ b/dom/webauthn/PWebAuthnTransaction.ipdl
@@ -15,43 +15,45 @@
  */
 
 include protocol PBackground;
 
 namespace mozilla {
 namespace dom {
 
 struct WebAuthnAuthenticatorSelection {
-    bool requireResidentKey;
-    bool requireUserVerification;
-    bool requirePlatformAttachment;
+  bool requireResidentKey;
+  bool requireUserVerification;
+  bool requirePlatformAttachment;
 };
 
-struct WebAuthnScopedCredentialDescriptor {
+struct WebAuthnScopedCredential {
   uint8_t[] id;
+  uint8_t transports;
 };
 
 struct WebAuthnExtension {
   /* TODO Fill in with predefined extensions */
 };
 
 struct WebAuthnMakeCredentialInfo {
   uint8_t[] RpIdHash;
   uint8_t[] ClientDataHash;
   uint32_t TimeoutMS;
-  WebAuthnScopedCredentialDescriptor[] ExcludeList;
+  WebAuthnScopedCredential[] ExcludeList;
   WebAuthnExtension[] Extensions;
   WebAuthnAuthenticatorSelection AuthenticatorSelection;
 };
 
 struct WebAuthnGetAssertionInfo {
   uint8_t[] RpIdHash;
   uint8_t[] ClientDataHash;
   uint32_t TimeoutMS;
-  WebAuthnScopedCredentialDescriptor[] AllowList;
+  WebAuthnScopedCredential[] AllowList;
+  bool RequireUserVerification;
   WebAuthnExtension[] Extensions;
 };
 
 async protocol PWebAuthnTransaction {
   manager PBackground;
 
   parent:
     async RequestRegister(uint64_t aTransactionId, WebAuthnMakeCredentialInfo aTransactionInfo);
--- a/dom/webauthn/U2FHIDTokenManager.cpp
+++ b/dom/webauthn/U2FHIDTokenManager.cpp
@@ -95,17 +95,17 @@ U2FHIDTokenManager::~U2FHIDTokenManager(
 // 1      0x05
 // 65     public key
 // 1      key handle length
 // *      key handle
 // ASN.1  attestation certificate
 // *      attestation signature
 //
 RefPtr<U2FRegisterPromise>
-U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
                              const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
                              const nsTArray<uint8_t>& aApplication,
                              const nsTArray<uint8_t>& aChallenge,
                              uint32_t aTimeoutMS)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == gPBackgroundThread);
 
   uint64_t registerFlags = 0;
@@ -125,17 +125,17 @@ U2FHIDTokenManager::Register(const nsTAr
   mTransactionId = rust_u2f_mgr_register(mU2FManager,
                                          registerFlags,
                                          (uint64_t)aTimeoutMS,
                                          u2f_register_callback,
                                          aChallenge.Elements(),
                                          aChallenge.Length(),
                                          aApplication.Elements(),
                                          aApplication.Length(),
-                                         U2FKeyHandles(aDescriptors).Get());
+                                         U2FKeyHandles(aCredentials).Get());
 
   if (mTransactionId == 0) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
   return mRegisterPromise.Ensure(__func__);
 }
 
@@ -151,32 +151,41 @@ U2FHIDTokenManager::Register(const nsTAr
 //
 // The format of the signature data is as follows:
 //
 //  1     User presence
 //  4     Counter
 //  *     Signature
 //
 RefPtr<U2FSignPromise>
-U2FHIDTokenManager::Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+U2FHIDTokenManager::Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
                          const nsTArray<uint8_t>& aApplication,
                          const nsTArray<uint8_t>& aChallenge,
+                         bool aRequireUserVerification,
                          uint32_t aTimeoutMS)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == gPBackgroundThread);
 
+  uint64_t signFlags = 0;
+
+  // Set flags for credential requests.
+  if (aRequireUserVerification) {
+    signFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
+  }
+
   ClearPromises();
   mTransactionId = rust_u2f_mgr_sign(mU2FManager,
+                                     signFlags,
                                      (uint64_t)aTimeoutMS,
                                      u2f_sign_callback,
                                      aChallenge.Elements(),
                                      aChallenge.Length(),
                                      aApplication.Elements(),
                                      aApplication.Length(),
-                                     U2FKeyHandles(aDescriptors).Get());
+                                     U2FKeyHandles(aCredentials).Get());
   if (mTransactionId == 0) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
   }
 
   return mSignPromise.Ensure(__func__);
 }
 
 void
--- a/dom/webauthn/U2FHIDTokenManager.h
+++ b/dom/webauthn/U2FHIDTokenManager.h
@@ -15,22 +15,25 @@
  * for the U2F and WebAuthn APIs, talking to HIDs.
  */
 
 namespace mozilla {
 namespace dom {
 
 class U2FKeyHandles {
 public:
-  explicit U2FKeyHandles(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors)
+  explicit U2FKeyHandles(const nsTArray<WebAuthnScopedCredential>& aCredentials)
   {
     mKeyHandles = rust_u2f_khs_new();
 
-    for (auto desc: aDescriptors) {
-      rust_u2f_khs_add(mKeyHandles, desc.id().Elements(), desc.id().Length());
+    for (auto cred: aCredentials) {
+      rust_u2f_khs_add(mKeyHandles,
+                       cred.id().Elements(),
+                       cred.id().Length(),
+                       cred.transports());
     }
   }
 
   rust_u2f_key_handles* Get() { return mKeyHandles; }
 
   ~U2FKeyHandles() { rust_u2f_khs_free(mKeyHandles); }
 
 private:
@@ -86,26 +89,27 @@ private:
 };
 
 class U2FHIDTokenManager final : public U2FTokenTransport
 {
 public:
   explicit U2FHIDTokenManager();
 
   virtual RefPtr<U2FRegisterPromise>
-  Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+  Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
            const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
            const nsTArray<uint8_t>& aApplication,
            const nsTArray<uint8_t>& aChallenge,
            uint32_t aTimeoutMS) override;
 
   virtual RefPtr<U2FSignPromise>
-  Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+  Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
        const nsTArray<uint8_t>& aApplication,
        const nsTArray<uint8_t>& aChallenge,
+       bool aRequireUserVerification,
        uint32_t aTimeoutMS) override;
 
   void Cancel() override;
 
   void HandleRegisterResult(UniquePtr<U2FResult>&& aResult);
   void HandleSignResult(UniquePtr<U2FResult>&& aResult);
 
 private:
--- a/dom/webauthn/U2FSoftTokenManager.cpp
+++ b/dom/webauthn/U2FSoftTokenManager.cpp
@@ -620,17 +620,17 @@ U2FSoftTokenManager::IsRegistered(const 
 // 1      0x05
 // 65     public key
 // 1      key handle length
 // *      key handle
 // ASN.1  attestation certificate
 // *      attestation signature
 //
 RefPtr<U2FRegisterPromise>
-U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
                               const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
                               const nsTArray<uint8_t>& aApplication,
                               const nsTArray<uint8_t>& aChallenge,
                               uint32_t aTimeoutMS)
 {
   nsNSSShutDownPreventionLock locker;
   if (NS_WARN_IF(isAlreadyShutDown())) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
@@ -647,19 +647,19 @@ U2FSoftTokenManager::Register(const nsTA
   // user verification, nor is it a platform authenticator.
   if (aAuthenticatorSelection.requireResidentKey() ||
       aAuthenticatorSelection.requireUserVerification() ||
       aAuthenticatorSelection.requirePlatformAttachment()) {
     return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
   }
 
   // Optional exclusion list.
-  for (auto desc: aDescriptors) {
+  for (auto cred: aCredentials) {
     bool isRegistered = false;
-    nsresult rv = IsRegistered(desc.id(), aApplication, isRegistered);
+    nsresult rv = IsRegistered(cred.id(), aApplication, isRegistered);
     if (NS_FAILED(rv)) {
       return U2FRegisterPromise::CreateAndReject(rv, __func__);
     }
     if (isRegistered) {
       return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
     }
   }
 
@@ -753,32 +753,38 @@ U2FSoftTokenManager::Register(const nsTA
 //
 // The format of the signature data is as follows:
 //
 //  1     User presence
 //  4     Counter
 //  *     Signature
 //
 RefPtr<U2FSignPromise>
-U2FSoftTokenManager::Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+U2FSoftTokenManager::Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
                           const nsTArray<uint8_t>& aApplication,
                           const nsTArray<uint8_t>& aChallenge,
+                          bool aRequireUserVerification,
                           uint32_t aTimeoutMS)
 {
   nsNSSShutDownPreventionLock locker;
   if (NS_WARN_IF(isAlreadyShutDown())) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
   }
 
+  // The U2F softtoken doesn't support user verification.
+  if (aRequireUserVerification) {
+    return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
+  }
+
   nsTArray<uint8_t> keyHandle;
-  for (auto desc: aDescriptors) {
+  for (auto cred: aCredentials) {
     bool isRegistered = false;
-    nsresult rv = IsRegistered(desc.id(), aApplication, isRegistered);
+    nsresult rv = IsRegistered(cred.id(), aApplication, isRegistered);
     if (NS_SUCCEEDED(rv) && isRegistered) {
-      keyHandle.Assign(desc.id());
+      keyHandle.Assign(cred.id());
       break;
     }
   }
 
   // Fail if we didn't recognize a key id.
   if (keyHandle.IsEmpty()) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
   }
--- a/dom/webauthn/U2FSoftTokenManager.h
+++ b/dom/webauthn/U2FSoftTokenManager.h
@@ -21,26 +21,27 @@ namespace dom {
 
 class U2FSoftTokenManager final : public U2FTokenTransport,
                                   public nsNSSShutDownObject
 {
 public:
   explicit U2FSoftTokenManager(uint32_t aCounter);
 
   virtual RefPtr<U2FRegisterPromise>
-  Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+  Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
            const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
            const nsTArray<uint8_t>& aApplication,
            const nsTArray<uint8_t>& aChallenge,
            uint32_t aTimeoutMS) override;
 
   virtual RefPtr<U2FSignPromise>
-  Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+  Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
        const nsTArray<uint8_t>& aApplication,
        const nsTArray<uint8_t>& aChallenge,
+       bool aRequireUserVerification,
        uint32_t aTimeoutMS) override;
 
   virtual void Cancel() override;
 
   // For nsNSSShutDownObject
   virtual void virtualDestroyNSSReference() override;
   void destructorSafeDestroyNSSReference();
 
--- a/dom/webauthn/U2FTokenManager.cpp
+++ b/dom/webauthn/U2FTokenManager.cpp
@@ -317,16 +317,17 @@ U2FTokenManager::Sign(PWebAuthnTransacti
     return;
   }
 
   uint64_t tid = mLastTransactionId = aTransactionId;
   mozilla::TimeStamp startTime = mozilla::TimeStamp::Now();
   mTokenManagerImpl->Sign(aTransactionInfo.AllowList(),
                           aTransactionInfo.RpIdHash(),
                           aTransactionInfo.ClientDataHash(),
+                          aTransactionInfo.RequireUserVerification(),
                           aTransactionInfo.TimeoutMS())
                    ->Then(GetCurrentThreadSerialEventTarget(), __func__,
                      [tid, startTime](U2FSignResult&& aResult) {
                        U2FTokenManager* mgr = U2FTokenManager::Get();
                        mgr->MaybeConfirmSign(tid, aResult);
                        Telemetry::ScalarAdd(
                          Telemetry::ScalarID::SECURITY_WEBAUTHN_USED,
                          NS_LITERAL_STRING("U2FSignFinish"), 1);
--- a/dom/webauthn/U2FTokenTransport.h
+++ b/dom/webauthn/U2FTokenTransport.h
@@ -58,26 +58,27 @@ typedef MozPromise<U2FSignResult, nsresu
 
 class U2FTokenTransport
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(U2FTokenTransport);
   U2FTokenTransport() {}
 
   virtual RefPtr<U2FRegisterPromise>
-  Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+  Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
            const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
            const nsTArray<uint8_t>& aApplication,
            const nsTArray<uint8_t>& aChallenge,
            uint32_t aTimeoutMS) = 0;
 
   virtual RefPtr<U2FSignPromise>
-  Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
+  Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
        const nsTArray<uint8_t>& aApplication,
        const nsTArray<uint8_t>& aChallenge,
+       bool aRequireUserVerification,
        uint32_t aTimeoutMS) = 0;
 
   virtual void Cancel() = 0;
 
 protected:
   virtual ~U2FTokenTransport() = default;
 };
 
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -356,19 +356,19 @@ WebAuthnManager::MakeCredential(const Ma
   }
 
   srv = HashCString(hashService, clientDataJSON, clientDataHash);
   if (NS_WARN_IF(NS_FAILED(srv))) {
     promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
     return promise.forget();
   }
 
-  nsTArray<WebAuthnScopedCredentialDescriptor> excludeList;
+  nsTArray<WebAuthnScopedCredential> excludeList;
   for (const auto& s: aOptions.mExcludeCredentials) {
-    WebAuthnScopedCredentialDescriptor c;
+    WebAuthnScopedCredential c;
     CryptoBuffer cb;
     cb.Assign(s.mId);
     c.id() = cb;
     excludeList.AppendElement(c);
   }
 
   if (!MaybeCreateBackgroundActor()) {
     promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
@@ -528,42 +528,67 @@ WebAuthnManager::GetAssertion(const Publ
 
   // Note: we only support U2F-style authentication for now, so we effectively
   // require an AllowList.
   if (aOptions.mAllowCredentials.Length() < 1) {
     promise->MaybeReject(NS_ERROR_DOM_NOT_ALLOWED_ERR);
     return promise.forget();
   }
 
-  nsTArray<WebAuthnScopedCredentialDescriptor> allowList;
+  nsTArray<WebAuthnScopedCredential> allowList;
   for (const auto& s: aOptions.mAllowCredentials) {
-    WebAuthnScopedCredentialDescriptor c;
-    CryptoBuffer cb;
-    cb.Assign(s.mId);
-    c.id() = cb;
-    allowList.AppendElement(c);
+    if (s.mType == PublicKeyCredentialType::Public_key) {
+      WebAuthnScopedCredential c;
+      CryptoBuffer cb;
+      cb.Assign(s.mId);
+      c.id() = cb;
+
+      // Serialize transports.
+      if (s.mTransports.WasPassed()) {
+        uint8_t transports = 0;
+        for (const auto& t: s.mTransports.Value()) {
+          if (t == AuthenticatorTransport::Usb) {
+            transports |= U2F_AUTHENTICATOR_TRANSPORT_USB;
+          }
+          if (t == AuthenticatorTransport::Nfc) {
+            transports |= U2F_AUTHENTICATOR_TRANSPORT_NFC;
+          }
+          if (t == AuthenticatorTransport::Ble) {
+            transports |= U2F_AUTHENTICATOR_TRANSPORT_BLE;
+          }
+        }
+        c.transports() = transports;
+      }
+
+      allowList.AppendElement(c);
+    }
   }
 
   if (!MaybeCreateBackgroundActor()) {
     promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
     return promise.forget();
   }
 
+  // Does the RP require user verification?
+  bool requireUserVerification =
+    aOptions.mUserVerification == UserVerificationRequirement::Required;
+
   // TODO: Add extension list building
   // If extensions was specified, process any extensions supported by this
   // client platform, to produce the extension data that needs to be sent to the
   // authenticator. If an error is encountered while processing an extension,
   // skip that extension and do not produce any extension data for it. Call the
   // result of this processing clientExtensions.
   nsTArray<WebAuthnExtension> extensions;
 
   WebAuthnGetAssertionInfo info(rpIdHash,
                                 clientDataHash,
                                 adjustedTimeout,
                                 allowList,
+                                requireUserVerification,
                                 extensions);
 
   ListenForVisibilityEvents();
 
   AbortSignal* signal = nullptr;
   if (aSignal.WasPassed()) {
     signal = &aSignal.Value();
     Follow(signal);
--- a/dom/webauthn/tests/mochitest.ini
+++ b/dom/webauthn/tests/mochitest.ini
@@ -3,16 +3,17 @@ support-files =
   cbor/*
   pkijs/*
   u2futil.js
 skip-if = !e10s
 scheme = https
 
 [test_webauthn_abort_signal.html]
 [test_webauthn_authenticator_selection.html]
+[test_webauthn_authenticator_transports.html]
 [test_webauthn_loopback.html]
 [test_webauthn_no_token.html]
 [test_webauthn_make_credential.html]
 [test_webauthn_get_assertion.html]
 [test_webauthn_override_request.html]
 [test_webauthn_store_credential.html]
 [test_webauthn_sameorigin.html]
 [test_webauthn_isplatformauthenticatoravailable.html]
--- a/dom/webauthn/tests/test_webauthn_authenticator_selection.html
+++ b/dom/webauthn/tests/test_webauthn_authenticator_selection.html
@@ -6,32 +6,37 @@
   <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <script type="text/javascript" src="u2futil.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 
   <h1>W3C Web Authentication - Authenticator Selection Criteria</h1>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406462">Mozilla Bug 1406462</a>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406467">Mozilla Bug 1406467</a>
 
   <script class="testbody" type="text/javascript">
     "use strict";
 
     function arrivingHereIsGood(aResult) {
       ok(true, "Good result! Received a: " + aResult);
     }
 
     function arrivingHereIsBad(aResult) {
       ok(false, "Bad result! Received a: " + aResult);
     }
 
     function expectNotAllowedError(aResult) {
       ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult);
     }
 
+    // We store the credential of the first successful make credential
+    // operation so we can use it for get assertion tests later.
+    let gCredential;
+
     add_task(() => {
       // Enable the softtoken.
       return SpecialPowers.pushPrefEnv({"set": [
         ["security.webauth.webauthn", true],
         ["security.webauth.webauthn_enable_softtoken", true],
         ["security.webauth.webauthn_enable_usbtoken", false],
       ]});
     });
@@ -45,20 +50,44 @@
         timeout: 5000, // the minimum timeout is actually 15 seconds
         pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
         authenticatorSelection,
       };
 
       return navigator.credentials.create({publicKey});
     }
 
-    // Test success cases.
+    // Start a new GetAssertion() request.
+    function requestGetAssertion(userVerification) {
+      let newCredential = {
+        type: "public-key",
+        id: gCredential,
+        transports: ["usb"],
+      };
+
+      let publicKey = {
+        challenge: crypto.getRandomValues(new Uint8Array(16)),
+        timeout: 5000, // the minimum timeout is actually 15 seconds
+        rpId: document.domain,
+        allowCredentials: [newCredential]
+      };
+
+      if (userVerification) {
+        publicKey.userVerification = userVerification;
+      }
+
+      return navigator.credentials.get({publicKey});
+    }
+
+    // Test success cases for make credential.
     add_task(async () => {
       // No selection criteria.
       await requestMakeCredential({})
+         // Save the credential so we can use it for sign success tests.
+        .then(res => gCredential = res.rawId)
         .then(arrivingHereIsGood)
         .catch(arrivingHereIsBad);
 
       // Request a cross-platform authenticator.
       await requestMakeCredential({authenticatorAttachment: "cross-platform"})
         .then(arrivingHereIsGood)
         .catch(arrivingHereIsBad);
 
@@ -73,29 +102,55 @@
         .catch(arrivingHereIsBad);
 
       // Discourage user verification.
       await requestMakeCredential({userVerification: "discouraged"})
         .then(arrivingHereIsGood)
         .catch(arrivingHereIsBad);
     });
 
-    // Test the failure cases.
+    // Test success cases for get assertion.
+    add_task(async () => {
+      // No selection criteria.
+      await requestGetAssertion()
+        .then(arrivingHereIsGood)
+        .catch(arrivingHereIsBad);
+
+      // Prefer user verification.
+      await requestGetAssertion("preferred")
+        .then(arrivingHereIsGood)
+        .catch(arrivingHereIsBad);
+
+      // Discourage user verification.
+      await requestGetAssertion("discouraged")
+        .then(arrivingHereIsGood)
+        .catch(arrivingHereIsBad);
+    });
+
+    // Test failure cases for make credential.
     add_task(async () => {
       // Request a platform authenticator.
       await requestMakeCredential({authenticatorAttachment: "platform"})
         .then(arrivingHereIsBad)
         .catch(expectNotAllowedError);
 
       // Require a resident key.
       await requestMakeCredential({requireResidentKey: true})
         .then(arrivingHereIsBad)
         .catch(expectNotAllowedError);
 
       // Require user verification.
       await requestMakeCredential({userVerification: "required"})
         .then(arrivingHereIsBad)
         .catch(expectNotAllowedError);
     });
+
+    // Test failure cases for get assertion.
+    add_task(async () => {
+      // Require user verification.
+      await requestGetAssertion("required")
+        .then(arrivingHereIsBad)
+        .catch(expectNotAllowedError);
+    });
   </script>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/tests/test_webauthn_authenticator_transports.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<head>
+  <title>W3C Web Authentication - Authenticator Transports</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript" src="u2futil.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+  <h1>W3C Web Authentication - Authenticator Transports</h1>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406467">Mozilla Bug 1406467</a>
+
+  <script class="testbody" type="text/javascript">
+    "use strict";
+
+    function arrivingHereIsGood(aResult) {
+      ok(true, "Good result! Received a: " + aResult);
+    }
+
+    function arrivingHereIsBad(aResult) {
+      ok(false, "Bad result! Received a: " + aResult);
+    }
+
+    function expectNotAllowedError(aResult) {
+      ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult);
+    }
+
+    // Store the credential of the first successful make credential
+    // operation so we can use it to get assertions later.
+    let gCredential;
+
+    add_task(() => {
+      // Enable the softtoken.
+      return SpecialPowers.pushPrefEnv({"set": [
+        ["security.webauth.webauthn", true],
+        ["security.webauth.webauthn_enable_softtoken", true],
+        ["security.webauth.webauthn_enable_usbtoken", false],
+      ]});
+    });
+
+    // Start a new MakeCredential() request.
+    function requestMakeCredential(excludeCredentials) {
+      let publicKey = {
+        rp: {id: document.domain, name: "none", icon: "none"},
+        user: {id: new Uint8Array(), name: "none", icon: "none", displayName: "none"},
+        challenge: crypto.getRandomValues(new Uint8Array(16)),
+        timeout: 5000, // the minimum timeout is actually 15 seconds
+        pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
+        excludeCredentials
+      };
+
+      return navigator.credentials.create({publicKey});
+    }
+
+    // Start a new GetAssertion() request.
+    function requestGetAssertion(allowCredentials) {
+      let publicKey = {
+        challenge: crypto.getRandomValues(new Uint8Array(16)),
+        timeout: 5000, // the minimum timeout is actually 15 seconds
+        rpId: document.domain,
+        allowCredentials
+      };
+
+      return navigator.credentials.get({publicKey});
+    }
+
+    // Test make credential behavior.
+    add_task(async () => {
+      // Make a credential.
+      await requestMakeCredential([])
+         // Save the credential for later.
+        .then(res => gCredential = res.rawId)
+        .then(arrivingHereIsGood)
+        .catch(arrivingHereIsBad);
+
+      // Pass a random credential to exclude.
+      await requestMakeCredential([{
+        type: "public-key",
+        id: crypto.getRandomValues(new Uint8Array(16)),
+        transports: ["usb"],
+      }]).then(arrivingHereIsGood)
+         .catch(arrivingHereIsBad);
+
+      // Pass gCredential with transport=usb.
+      await requestMakeCredential([{
+        type: "public-key",
+        id: gCredential,
+        transports: ["usb"],
+      }]).then(arrivingHereIsBad)
+         .catch(expectNotAllowedError);
+
+      // Pass gCredential with transport=nfc.
+      // The softoken pretends to support all transports.
+      await requestMakeCredential([{
+        type: "public-key",
+        id: gCredential,
+        transports: ["nfc"],
+      }]).then(arrivingHereIsBad)
+         .catch(expectNotAllowedError);
+
+      // Pass gCredential with an empty transports list.
+      await requestMakeCredential([{
+        type: "public-key",
+        id: gCredential,
+        transports: [],
+      }]).then(arrivingHereIsBad)
+         .catch(expectNotAllowedError);
+    });
+
+    // Test get assertion behavior.
+    add_task(async () => {
+      // Request an assertion for gCredential.
+      await requestGetAssertion([{
+        type: "public-key",
+        id: gCredential,
+        transports: ["usb"],
+      }]).then(arrivingHereIsGood)
+         .catch(arrivingHereIsBad);
+
+      // Request an assertion for a random credential.
+      await requestGetAssertion([{
+        type: "public-key",
+        id: crypto.getRandomValues(new Uint8Array(16)),
+        transports: ["usb"],
+      }]).then(arrivingHereIsBad)
+         .catch(expectNotAllowedError);
+
+      // Request an assertion for gCredential with transport=nfc.
+      // The softoken pretends to support all transports.
+      await requestGetAssertion([{
+        type: "public-key",
+        id: gCredential,
+        transports: ["nfc"],
+      }]).then(arrivingHereIsGood)
+         .catch(arrivingHereIsBad);
+
+      // Request an assertion for gCredential with an empty transports list.
+      await requestGetAssertion([{
+        type: "public-key",
+        id: gCredential,
+        transports: [],
+      }]).then(arrivingHereIsGood)
+         .catch(arrivingHereIsBad);
+    });
+  </script>
+
+</body>
+</html>
--- a/dom/webauthn/u2f-hid-rs/examples/main.rs
+++ b/dom/webauthn/u2f-hid-rs/examples/main.rs
@@ -4,17 +4,17 @@
 
 extern crate base64;
 extern crate crypto;
 extern crate u2fhid;
 use crypto::digest::Digest;
 use crypto::sha2::Sha256;
 use std::io;
 use std::sync::mpsc::channel;
-use u2fhid::{RegisterFlags, U2FManager};
+use u2fhid::{AuthenticatorTransports, KeyHandle, RegisterFlags, SignFlags, U2FManager};
 
 extern crate log;
 extern crate env_logger;
 
 fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>> {
     if register_response[0] != 0x05 {
         return Err(io::Error::new(
             io::ErrorKind::InvalidData,
@@ -61,21 +61,27 @@ fn main() {
             vec![],
             move |rv| { tx.send(rv.unwrap()).unwrap(); },
         )
         .unwrap();
 
     let register_data = rx.recv().unwrap();
     println!("Register result: {}", base64::encode(&register_data));
     println!("Asking a security key to sign now, with the data from the register...");
-    let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();
+    let credential = u2f_get_key_handle_from_register_response(&register_data).unwrap();
+    let key_handle = KeyHandle {
+        credential,
+        transports: AuthenticatorTransports::empty(),
+    };
 
+    let flags = SignFlags::empty();
     let (tx, rx) = channel();
     manager
         .sign(
+            flags,
             15_000,
             chall_bytes,
             app_bytes,
             vec![key_handle],
             move |rv| { tx.send(rv.unwrap()).unwrap(); },
         )
         .unwrap();
 
--- a/dom/webauthn/u2f-hid-rs/src/capi.rs
+++ b/dom/webauthn/u2f-hid-rs/src/capi.rs
@@ -4,17 +4,17 @@
 
 use libc::size_t;
 use rand::{thread_rng, Rng};
 use std::collections::HashMap;
 use std::{ptr, slice};
 
 use U2FManager;
 
-type U2FKeyHandles = Vec<Vec<u8>>;
+type U2FKeyHandles = Vec<::KeyHandle>;
 type U2FResult = HashMap<u8, Vec<u8>>;
 type U2FCallback = extern "C" fn(u64, *mut U2FResult);
 
 const RESBUF_ID_REGISTRATION: u8 = 0;
 const RESBUF_ID_KEYHANDLE: u8 = 1;
 const RESBUF_ID_SIGNATURE: u8 = 2;
 
 // Generates a new 64-bit transaction id with collision probability 2^-32.
@@ -47,18 +47,22 @@ pub unsafe extern "C" fn rust_u2f_khs_ne
     Box::into_raw(Box::new(vec![]))
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rust_u2f_khs_add(
     khs: *mut U2FKeyHandles,
     key_handle_ptr: *const u8,
     key_handle_len: usize,
+    transports: u8,
 ) {
-    (*khs).push(from_raw(key_handle_ptr, key_handle_len));
+    (*khs).push(::KeyHandle {
+        credential: from_raw(key_handle_ptr, key_handle_len),
+        transports: ::AuthenticatorTransports::from_bits_truncate(transports),
+    });
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rust_u2f_khs_free(khs: *mut U2FKeyHandles) {
     if !khs.is_null() {
         Box::from_raw(khs);
     }
 }
@@ -151,16 +155,17 @@ pub unsafe extern "C" fn rust_u2f_mgr_re
     );
 
     if res.is_ok() { tid } else { 0 }
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rust_u2f_mgr_sign(
     mgr: *mut U2FManager,
+    flags: u64,
     timeout: u64,
     callback: U2FCallback,
     challenge_ptr: *const u8,
     challenge_len: usize,
     application_ptr: *const u8,
     application_len: usize,
     khs: *const U2FKeyHandles,
 ) -> u64 {
@@ -173,31 +178,39 @@ pub unsafe extern "C" fn rust_u2f_mgr_si
         return 0;
     }
 
     // Need at least one key handle.
     if (*khs).len() < 1 {
         return 0;
     }
 
+    let flags = ::SignFlags::from_bits_truncate(flags);
     let challenge = from_raw(challenge_ptr, challenge_len);
     let application = from_raw(application_ptr, application_len);
     let key_handles = (*khs).clone();
 
     let tid = new_tid();
-    let res = (*mgr).sign(timeout, challenge, application, key_handles, move |rv| {
-        if let Ok((key_handle, signature)) = rv {
-            let mut result = U2FResult::new();
-            result.insert(RESBUF_ID_KEYHANDLE, key_handle);
-            result.insert(RESBUF_ID_SIGNATURE, signature);
-            callback(tid, Box::into_raw(Box::new(result)));
-        } else {
-            callback(tid, ptr::null_mut());
-        };
-    });
+    let res = (*mgr).sign(
+        flags,
+        timeout,
+        challenge,
+        application,
+        key_handles,
+        move |rv| {
+            if let Ok((key_handle, signature)) = rv {
+                let mut result = U2FResult::new();
+                result.insert(RESBUF_ID_KEYHANDLE, key_handle);
+                result.insert(RESBUF_ID_SIGNATURE, signature);
+                callback(tid, Box::into_raw(Box::new(result)));
+            } else {
+                callback(tid, ptr::null_mut());
+            };
+        },
+    );
 
     if res.is_ok() { tid } else { 0 }
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rust_u2f_mgr_cancel(mgr: *mut U2FManager) -> u64 {
     if !mgr.is_null() {
         // Ignore return value.
--- a/dom/webauthn/u2f-hid-rs/src/lib.rs
+++ b/dom/webauthn/u2f-hid-rs/src/lib.rs
@@ -51,15 +51,33 @@ pub use capi::*;
 // Keep this in sync with the constants in u2fhid-capi.h.
 bitflags! {
     pub struct RegisterFlags: u64 {
         const REQUIRE_RESIDENT_KEY        = 1;
         const REQUIRE_USER_VERIFICATION   = 2;
         const REQUIRE_PLATFORM_ATTACHMENT = 4;
     }
 }
+bitflags! {
+    pub struct SignFlags: u64 {
+        const REQUIRE_USER_VERIFICATION = 1;
+    }
+}
+bitflags! {
+    pub struct AuthenticatorTransports: u8 {
+        const USB = 1;
+        const NFC = 2;
+        const BLE = 4;
+    }
+}
+
+#[derive(Clone)]
+pub struct KeyHandle {
+    pub credential: Vec<u8>,
+    pub transports: AuthenticatorTransports,
+}
 
 #[cfg(fuzzing)]
 pub use u2fprotocol::*;
 #[cfg(fuzzing)]
 pub use u2ftypes::*;
 #[cfg(fuzzing)]
 pub use consts::*;
--- a/dom/webauthn/u2f-hid-rs/src/manager.rs
+++ b/dom/webauthn/u2f-hid-rs/src/manager.rs
@@ -12,24 +12,25 @@ use runloop::RunLoop;
 use util::{to_io_err, OnceCallback};
 
 enum QueueAction {
     Register {
         flags: ::RegisterFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
+        key_handles: Vec<::KeyHandle>,
         callback: OnceCallback<Vec<u8>>,
     },
     Sign {
+        flags: ::SignFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
+        key_handles: Vec<::KeyHandle>,
         callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
     },
     Cancel,
 }
 
 pub struct U2FManager {
     queue: RunLoop,
     tx: Sender<QueueAction>,
@@ -59,24 +60,32 @@ impl U2FManager {
                             timeout,
                             challenge,
                             application,
                             key_handles,
                             callback,
                         );
                     }
                     Ok(QueueAction::Sign {
+                           flags,
                            timeout,
                            challenge,
                            application,
                            key_handles,
                            callback,
                        }) => {
                         // This must not block, otherwise we can't cancel.
-                        sm.sign(timeout, challenge, application, key_handles, callback);
+                        sm.sign(
+                            flags,
+                            timeout,
+                            challenge,
+                            application,
+                            key_handles,
+                            callback,
+                        );
                     }
                     Ok(QueueAction::Cancel) => {
                         // Cancelling must block so that we don't start a new
                         // polling thread before the old one has shut down.
                         sm.cancel();
                     }
                     Err(RecvTimeoutError::Disconnected) => {
                         break;
@@ -96,32 +105,32 @@ impl U2FManager {
     }
 
     pub fn register<F>(
         &self,
         flags: ::RegisterFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
+        key_handles: Vec<::KeyHandle>,
         callback: F,
     ) -> io::Result<()>
     where
         F: FnOnce(io::Result<Vec<u8>>),
         F: Send + 'static,
     {
         if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidInput,
                 "Invalid parameter sizes",
             ));
         }
 
         for key_handle in &key_handles {
-            if key_handle.len() > 256 {
+            if key_handle.credential.len() > 256 {
                 return Err(io::Error::new(
                     io::ErrorKind::InvalidInput,
                     "Key handle too large",
                 ));
             }
         }
 
         let callback = OnceCallback::new(callback);
@@ -133,20 +142,21 @@ impl U2FManager {
             key_handles,
             callback,
         };
         self.tx.send(action).map_err(to_io_err)
     }
 
     pub fn sign<F>(
         &self,
+        flags: ::SignFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
+        key_handles: Vec<::KeyHandle>,
         callback: F,
     ) -> io::Result<()>
     where
         F: FnOnce(io::Result<(Vec<u8>, Vec<u8>)>),
         F: Send + 'static,
     {
         if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
             return Err(io::Error::new(
@@ -158,26 +168,27 @@ impl U2FManager {
         if key_handles.len() < 1 {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidInput,
                 "No key handles given",
             ));
         }
 
         for key_handle in &key_handles {
-            if key_handle.len() > 256 {
+            if key_handle.credential.len() > 256 {
                 return Err(io::Error::new(
                     io::ErrorKind::InvalidInput,
                     "Key handle too large",
                 ));
             }
         }
 
         let callback = OnceCallback::new(callback);
         let action = QueueAction::Sign {
+            flags,
             timeout,
             challenge,
             application,
             key_handles,
             callback,
         };
         self.tx.send(action).map_err(to_io_err)
     }
--- a/dom/webauthn/u2f-hid-rs/src/statemachine.rs
+++ b/dom/webauthn/u2f-hid-rs/src/statemachine.rs
@@ -5,33 +5,37 @@
 use consts::PARAMETER_SIZE;
 use platform::device::Device;
 use platform::transaction::Transaction;
 use std::thread;
 use std::time::Duration;
 use util::{io_err, OnceCallback};
 use u2fprotocol::{u2f_init_device, u2f_is_keyhandle_valid, u2f_register, u2f_sign};
 
+fn is_valid_transport(transports: ::AuthenticatorTransports) -> bool {
+    transports.is_empty() || transports.contains(::AuthenticatorTransports::USB)
+}
+
 #[derive(Default)]
 pub struct StateMachine {
     transaction: Option<Transaction>,
 }
 
 impl StateMachine {
     pub fn new() -> Self {
         Default::default()
     }
 
     pub fn register(
         &mut self,
         flags: ::RegisterFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
+        key_handles: Vec<::KeyHandle>,
         callback: OnceCallback<Vec<u8>>,
     ) {
         // Abort any prior register/sign calls.
         self.cancel();
 
         let cbc = callback.clone();
 
         let transaction = Transaction::new(timeout, cbc.clone(), move |info, alive| {
@@ -55,18 +59,19 @@ impl StateMachine {
             // same anyway.
             if !flags.is_empty() {
                 return;
             }
 
             // Iterate the exclude list and see if there are any matches.
             // Abort the state machine if we found a valid key handle.
             if key_handles.iter().any(|key_handle| {
-                u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                    .unwrap_or(false) /* no match on failure */
+                is_valid_transport(key_handle.transports) &&
+                    u2f_is_keyhandle_valid(dev, &challenge, &application, &key_handle.credential)
+                        .unwrap_or(false) /* no match on failure */
             })
             {
                 return;
             }
 
             while alive() {
                 if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
                     callback.call(Ok(bytes));
@@ -80,20 +85,21 @@ impl StateMachine {
 
         self.transaction = Some(try_or!(transaction, |_| {
             cbc.call(Err(io_err("couldn't create transaction")))
         }));
     }
 
     pub fn sign(
         &mut self,
+        flags: ::SignFlags,
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
+        key_handles: Vec<::KeyHandle>,
         callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
     ) {
         // Abort any prior register/sign calls.
         self.cancel();
 
         let cbc = callback.clone();
 
         let transaction = Transaction::new(timeout, cbc.clone(), move |info, alive| {
@@ -103,39 +109,68 @@ impl StateMachine {
                 _ => return,
             };
 
             // Try initializing it.
             if !dev.is_u2f() || !u2f_init_device(dev) {
                 return;
             }
 
+            // We currently don't support user verification because we can't
+            // ask tokens whether they do support that. If the flag is set,
+            // ignore all tokens for now.
+            //
+            // Technically, this is a ConstraintError because we shouldn't talk
+            // to this authenticator in the first place. But the result is the
+            // same anyway.
+            if !flags.is_empty() {
+                return;
+            }
+
             // Find all matching key handles.
             let key_handles = key_handles
                 .iter()
                 .filter(|key_handle| {
-                    u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
+                    u2f_is_keyhandle_valid(dev, &challenge, &application, &key_handle.credential)
                         .unwrap_or(false) /* no match on failure */
                 })
                 .collect::<Vec<_>>();
 
+            // Aggregate distinct transports from all given credentials.
+            let transports = key_handles.iter().fold(
+                ::AuthenticatorTransports::empty(),
+                |t, k| t | k.transports,
+            );
+
+            // We currently only support USB. If the RP specifies transports
+            // and doesn't include USB it's probably lying.
+            if !is_valid_transport(transports) {
+                return;
+            }
+
             while alive() {
                 // If the device matches none of the given key handles
                 // then just make it blink with bogus data.
                 if key_handles.is_empty() {
                     let blank = vec![0u8; PARAMETER_SIZE];
                     if let Ok(_) = u2f_register(dev, &blank, &blank) {
                         callback.call(Err(io_err("invalid key")));
                         break;
                     }
                 } else {
                     // Otherwise, try to sign.
                     for key_handle in &key_handles {
-                        if let Ok(bytes) = u2f_sign(dev, &challenge, &application, key_handle) {
-                            callback.call(Ok((key_handle.to_vec(), bytes)));
+                        if let Ok(bytes) = u2f_sign(
+                            dev,
+                            &challenge,
+                            &application,
+                            &key_handle.credential,
+                        )
+                        {
+                            callback.call(Ok((key_handle.credential.clone(), bytes)));
                             break;
                         }
                     }
                 }
 
                 // Sleep a bit before trying again.
                 thread::sleep(Duration::from_millis(100));
             }
--- a/dom/webauthn/u2f-hid-rs/src/u2fhid-capi.h
+++ b/dom/webauthn/u2f-hid-rs/src/u2fhid-capi.h
@@ -14,16 +14,20 @@ extern "C" {
 const uint8_t U2F_RESBUF_ID_REGISTRATION = 0;
 const uint8_t U2F_RESBUF_ID_KEYHANDLE = 1;
 const uint8_t U2F_RESBUF_ID_SIGNATURE = 2;
 
 const uint64_t U2F_FLAG_REQUIRE_RESIDENT_KEY = 1;
 const uint64_t U2F_FLAG_REQUIRE_USER_VERIFICATION = 2;
 const uint64_t U2F_FLAG_REQUIRE_PLATFORM_ATTACHMENT = 4;
 
+const uint8_t U2F_AUTHENTICATOR_TRANSPORT_USB = 1;
+const uint8_t U2F_AUTHENTICATOR_TRANSPORT_NFC = 2;
+const uint8_t U2F_AUTHENTICATOR_TRANSPORT_BLE = 4;
+
 // NOTE: Preconditions
 // * All rust_u2f_mgr* pointers must refer to pointers which are returned
 //   by rust_u2f_mgr_new, and must be freed with rust_u2f_mgr_free.
 // * All rust_u2f_khs* pointers must refer to pointers which are returned
 //   by rust_u2f_khs_new, and must be freed with rust_u2f_khs_free.
 // * All rust_u2f_res* pointers must refer to pointers passed to the
 //   register() and sign() callbacks. They can be null on failure.
 
@@ -51,33 +55,35 @@ uint64_t rust_u2f_mgr_register(rust_u2f_
                                rust_u2f_callback,
                                const uint8_t* challenge_ptr,
                                size_t challenge_len,
                                const uint8_t* application_ptr,
                                size_t application_len,
                                const rust_u2f_key_handles* khs);
 
 uint64_t rust_u2f_mgr_sign(rust_u2f_manager* mgr,
+                           uint64_t flags,
                            uint64_t timeout,
                            rust_u2f_callback,
                            const uint8_t* challenge_ptr,
                            size_t challenge_len,
                            const uint8_t* application_ptr,
                            size_t application_len,
                            const rust_u2f_key_handles* khs);
 
 uint64_t rust_u2f_mgr_cancel(rust_u2f_manager* mgr);
 
 
 /// U2FKeyHandles functions.
 
 rust_u2f_key_handles* rust_u2f_khs_new();
 void rust_u2f_khs_add(rust_u2f_key_handles* khs,
                       const uint8_t* key_handle,
-                      size_t key_handle_len);
+                      size_t key_handle_len,
+                      uint8_t transports);
 /* unsafe */ void rust_u2f_khs_free(rust_u2f_key_handles* khs);
 
 
 /// U2FResult functions.
 
 // Call this before `[..]_copy()` to allocate enough space.
 bool rust_u2f_resbuf_length(const rust_u2f_result *res, uint8_t bid, size_t* len);
 bool rust_u2f_resbuf_copy(const rust_u2f_result *res, uint8_t bid, uint8_t* dst);
deleted file mode 100644
--- a/dom/webidl/DesktopNotification.webidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-interface MozObserver;
-
-[HeaderFile="mozilla/dom/DesktopNotification.h"]
-interface DesktopNotificationCenter
-{
-  [NewObject]
-  DesktopNotification createNotification(DOMString title,
-                                         DOMString description,
-                                         optional DOMString iconURL = "");
-};
-
-interface DesktopNotification : EventTarget
-{
-  [Throws]
-  void show();
-
-  attribute EventHandler onclick;
-
-  attribute EventHandler onclose;
-};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -195,22 +195,16 @@ partial interface Navigator {
 
   /**
    * Navigator requests to remove an idle observer from the existing window.
    */
   [Throws, ChromeOnly]
   void removeIdleObserver(MozIdleObserver aIdleObserver);
 };
 
-// nsIDOMNavigatorDesktopNotification
-partial interface Navigator {
-  [Throws, Pref="notification.feature.enabled", UnsafeInPrerendering]
-  readonly attribute DesktopNotificationCenter mozNotification;
-};
-
 // NetworkInformation
 partial interface Navigator {
   [Throws, Pref="dom.netinfo.enabled"]
   readonly attribute NetworkInformation connection;
 };
 
 // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension
 partial interface Navigator {
--- a/dom/webidl/WebAuthentication.webidl
+++ b/dom/webidl/WebAuthentication.webidl
@@ -1,15 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
- * https://www.w3.org/TR/webauthn/
+ * https://w3c.github.io/webauthn/
  */
 
 /***** Interfaces to Data *****/
 
 [SecureContext, Pref="security.webauth.webauthn"]
 interface PublicKeyCredential : Credential {
     [SameObject] readonly attribute ArrayBuffer              rawId;
     [SameObject] readonly attribute AuthenticatorResponse    response;
@@ -89,16 +89,17 @@ enum UserVerificationRequirement {
     "discouraged"
 };
 
 dictionary PublicKeyCredentialRequestOptions {
     required BufferSource                challenge;
     unsigned long                        timeout;
     USVString                            rpId;
     sequence<PublicKeyCredentialDescriptor> allowCredentials = [];
+    UserVerificationRequirement          userVerification = "preferred";
     // Extensions are not supported yet.
     // AuthenticationExtensions             extensions; // Add in Bug 1406458
 };
 
 typedef record<DOMString, any>       AuthenticationExtensions;
 
 dictionary CollectedClientData {
     required DOMString           challenge;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -92,19 +92,16 @@ with Files("DecoderDoctorNotification.we
     BUG_COMPONENT = ("Core", "Audio/Video: Playback")
 
 with Files("DelayNode.webidl"):
     BUG_COMPONENT = ("Core", "Web Audio")
 
 with Files("DynamicsCompressorNode.webidl"):
     BUG_COMPONENT = ("Core", "Web Audio")
 
-with Files("DesktopNotification.webidl"):
-    BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
-
 with Files("FakePluginTagInit.webidl"):
     BUG_COMPONENT = ("Core", "Plug-ins")
 
 with Files("Flex.webidl"):
     BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
 
 with Files("FocusEvent.webidl"):
     BUG_COMPONENT = ("Core", "DOM: Events")
@@ -473,17 +470,16 @@ WEBIDL_FILES = [
     'CSSValueList.webidl',
     'CustomElementRegistry.webidl',
     'DataTransfer.webidl',
     'DataTransferItem.webidl',
     'DataTransferItemList.webidl',
     'DecoderDoctorNotification.webidl',
     'DedicatedWorkerGlobalScope.webidl',
     'DelayNode.webidl',
-    'DesktopNotification.webidl',
     'DeviceMotionEvent.webidl',
     'Directory.webidl',
     'Document.webidl',
     'DocumentFragment.webidl',
     'DocumentTimeline.webidl',
     'DocumentType.webidl',
     'DOMCursor.webidl',
     'DOMError.webidl',
--- a/dom/workers/test/serviceworkers/browser.ini
+++ b/dom/workers/test/serviceworkers/browser.ini
@@ -4,17 +4,19 @@ support-files =
   browser_cached_force_refresh.html
   download/window.html
   download/worker.js
   fetch.js
   file_multie10s_update.html
   file_userContextId_openWindow.js
   force_refresh_browser_worker.js
   empty.html
+  empty.js
   server_multie10s_update.sjs
 
 [browser_devtools_serviceworker_interception.js]
 [browser_force_refresh.js]
 [browser_download.js]
 [browser_multie10s_update.js]
 skip-if = !e10s || os != "win" # Bug 1404914
+[browser_storage_permission.js]
 [browser_userContextId_openWindow.js]
 skip-if = !e10s
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/browser_storage_permission.js
@@ -0,0 +1,123 @@
+"use strict";
+
+const { interfaces: Ci } = Components;
+
+const BASE_URI = "http://mochi.test:8888/browser/dom/workers/test/serviceworkers/";
+const PAGE_URI = BASE_URI + "empty.html";
+const SCOPE = PAGE_URI + "?storage_permission";
+const SW_SCRIPT = BASE_URI + "empty.js";
+
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["dom.serviceWorkers.enabled", true],
+    ["dom.serviceWorkers.testing.enabled", true],
+  ]});
+
+  let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  await ContentTask.spawn(browser, { script: SW_SCRIPT, scope: SCOPE },
+    async function(opts) {
+      let reg = await content.navigator.serviceWorker.register(opts.script,
+                                                               { scope: opts.scope });
+      let worker = reg.installing || reg.waiting || reg.active;
+      await new Promise(resolve => {
+        if (worker.state === "activated") {
+          resolve();
+          return;
+        }
+        worker.addEventListener("statechange", function onStateChange() {
+          if (worker.state === "activated") {
+            worker.removeEventListener("statechange", onStateChange);
+            resolve();
+          }
+        });
+      });
+    }
+  );
+
+  await BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_allow_permission() {
+  Services.perms.add(Services.io.newURI(PAGE_URI), "cookie",
+                     Ci.nsICookiePermission.ACCESS_ALLOW);
+
+  let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  let controller = await ContentTask.spawn(browser, null, async function() {
+    return content.navigator.serviceWorker.controller;
+  });
+
+  ok(!!controller, "page should be controlled with storage allowed");
+
+  await BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_deny_permission() {
+  Services.perms.add(Services.io.newURI(PAGE_URI), "cookie",
+                     Ci.nsICookiePermission.ACCESS_DENY);
+
+  let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  let controller = await ContentTask.spawn(browser, null, async function() {
+    return content.navigator.serviceWorker.controller;
+  });
+
+  is(controller, null, "page should be not controlled with storage denied");
+
+  await BrowserTestUtils.removeTab(tab);
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
+});
+
+add_task(async function test_session_permission() {
+  Services.perms.add(Services.io.newURI(PAGE_URI), "cookie",
+                     Ci.nsICookiePermission.ACCESS_SESSION);
+
+  let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  let controller = await ContentTask.spawn(browser, null, async function() {
+    return content.navigator.serviceWorker.controller;
+  });
+
+  is(controller, null, "page should be not controlled with session storage");
+
+  await BrowserTestUtils.removeTab(tab);
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
+});
+
+add_task(async function cleanup() {
+  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
+
+  let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
+  let browser = gBrowser.getBrowserForTab(tab);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  await ContentTask.spawn(browser, SCOPE, async function(uri) {
+    let reg = await content.navigator.serviceWorker.getRegistration(uri);
+    let worker = reg.active;
+    await reg.unregister();
+    await new Promise(resolve => {
+      if (worker.state === "redundant") {
+        resolve();
+        return;
+      }
+      worker.addEventListener("statechange", function onStateChange() {
+        if (worker.state === "redundant") {
+          worker.removeEventListener("statechange", onStateChange);
+          resolve();
+        }
+      });
+    });
+  });
+
+  await BrowserTestUtils.removeTab(tab);
+});
deleted file mode 100644
--- a/editor/reftests/xul/emptytextbox-5.xul
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml"
-        title="Textbox tests">
-
-  <script type="text/javascript" src="platform.js"/>
-
-  <textbox type="timed"/>
-      
-</window>
--- a/editor/reftests/xul/reftest.list
+++ b/editor/reftests/xul/reftest.list
@@ -5,17 +5,16 @@ fails-if(Android) skip-if(winWidget) == 
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == autocomplete-1.xul autocomplete-ref.xul # bug 783658
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658
 != emptymultiline-1.xul emptymultiline-ref.xul
 fails-if(Android) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658
 fails-if(Android) skip-if(winWidget) == emptytextbox-1.xul emptytextbox-ref.xul # Windows: bug 1239170
 fails-if(Android) skip-if(winWidget) == emptytextbox-2.xul emptytextbox-ref.xul # Windows: bug 1239170
 != emptytextbox-3.xul emptytextbox-ref.xul
 != emptytextbox-4.xul emptytextbox-ref.xul
-fails-if(Android) skip-if(winWidget) == emptytextbox-5.xul emptytextbox-ref.xul # Windows: bug 1239170
 # There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
 # Therefore, the equlity tests below should be marked as failing.
 != number-1.xul number-ref.xul
 != number-2.xul number-ref.xul
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-3.xul number-ref.xul # bug 783658
 != number-4.xul number-ref.xul
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == number-5.xul number-ref.xul # bug 783658
 fails-if(Android) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012]|10\.0)/.test(http.oscpu)) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -121,17 +121,23 @@ static const char* kPreloadPermissions[]
   "font",
   "media",
   "websocket",
   "csp_report",
   "xslt",
   "beacon",
   "fetch",
   "image",
-  "manifest"
+  "manifest",
+
+  // This permission is preloaded to support properly blocking service worker
+  // interception when a user has disabled storage for a specific site.  Once
+  // service worker interception moves to the parent process this should be
+  // removed.  See bug 1428130.
+  "cookie"
 };
 
 // A list of permissions that can have a fallback default permission
 // set under the permissions.default.* pref.
 static const char* kPermissionsWithDefaults[] = {
   "camera",
   "microphone",
   "geo",
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -1651,38 +1651,41 @@ GLContext::DebugCallback(GLenum source,
 
 void
 GLContext::InitExtensions()
 {
     MOZ_ASSERT(IsCurrent());
 
     std::vector<nsCString> driverExtensionList;
 
-    if (mSymbols.fGetStringi) {
-        GLuint count = 0;
-        GetUIntegerv(LOCAL_GL_NUM_EXTENSIONS, &count);
-        for (GLuint i = 0; i < count; i++) {
-            // This is UTF-8.
-            const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
-
-            // We CANNOT use nsDependentCString here, because the spec doesn't guarantee
-            // that the pointers returned are different, only that their contents are.
-            // On Flame, each of these index string queries returns the same address.
-            driverExtensionList.push_back(nsCString(rawExt));
+    [&]() {
+        if (mSymbols.fGetStringi) {
+            GLuint count = 0;
+            if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
+                for (GLuint i = 0; i < count; i++) {
+                    // This is UTF-8.
+                    const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
+
+                    // We CANNOT use nsDependentCString here, because the spec doesn't guarantee
+                    // that the pointers returned are different, only that their contents are.
+                    // On Flame, each of these index string queries returns the same address.
+                    driverExtensionList.push_back(nsCString(rawExt));
+                }
+                return;
+            }
         }
-    } else {
-        MOZ_ALWAYS_TRUE(!fGetError());
+
         const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
-        MOZ_ALWAYS_TRUE(!fGetError());
-
         if (rawExts) {
             nsDependentCString exts(rawExts);
             SplitByChar(exts, ' ', &driverExtensionList);
         }
-    }
+    }();
+    const auto err = fGetError();
+    MOZ_ALWAYS_TRUE(!err);
 
     const bool shouldDumpExts = ShouldDumpExts();
     if (shouldDumpExts) {
         printf_stderr("%i GL driver extensions: (*: recognized)\n",
                       (uint32_t)driverExtensionList.size());
     }
 
     MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
@@ -156,33 +156,35 @@ MacIOSurfaceTextureHostOGL::PushResource
   MOZ_ASSERT(mSurface);
 
   auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage
                                               : &wr::ResourceUpdateQueue::UpdateExternalImage;
   auto bufferType = wr::WrExternalImageBufferType::TextureRectHandle;
 
   switch (GetFormat()) {
     case gfx::SurfaceFormat::R8G8B8X8:
-    case gfx::SurfaceFormat::R8G8B8A8:
-    case gfx::SurfaceFormat::B8G8R8A8:
-    case gfx::SurfaceFormat::B8G8R8X8: {
+    case gfx::SurfaceFormat::R8G8B8A8: {
       MOZ_ASSERT(aImageKeys.length() == 1);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
-      wr::ImageDescriptor descriptor(GetSize(), GetFormat());
+      // The internal pixel format of MacIOSurface is always BGRX or BGRA
+      // format.
+      auto format = GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ? gfx::SurfaceFormat::B8G8R8A8
+                                                                : gfx::SurfaceFormat::B8G8R8X8;
+      wr::ImageDescriptor descriptor(GetSize(), format);
       (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
       break;
     }
     case gfx::SurfaceFormat::YUV422: {
       // This is the special buffer format. The buffer contents could be a
       // converted RGB interleaving data or a YCbCr interleaving data depending
       // on the different platform setting. (e.g. It will be RGB at OpenGL 2.1
       // and YCbCr at OpenGL 3.1)
       MOZ_ASSERT(aImageKeys.length() == 1);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
-      wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8);
+      wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::B8G8R8X8);
       (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
       break;
     }
     case gfx::SurfaceFormat::NV12: {
       MOZ_ASSERT(aImageKeys.length() == 2);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 2);
       wr::ImageDescriptor descriptor0(gfx::IntSize(mSurface->GetDevicePixelWidth(0), mSurface->GetDevicePixelHeight(0)),
                                       gfx::SurfaceFormat::A8);
--- a/gfx/thebes/gfxMacFont.cpp
+++ b/gfx/thebes/gfxMacFont.cpp
@@ -503,17 +503,18 @@ already_AddRefed<ScaledFont>
 gfxMacFont::GetScaledFont(DrawTarget *aTarget)
 {
     if (!mAzureScaledFont) {
         mAzureScaledFont =
             Factory::CreateScaledFontForMacFont(GetCGFontRef(),
                                                 GetUnscaledFont(),
                                                 GetAdjustedSize(),
                                                 Color::FromABGR(mFontSmoothingBackgroundColor),
-                                                !mStyle.useGrayscaleAntialiasing);
+                                                !mStyle.useGrayscaleAntialiasing,
+                                                IsSyntheticBold());
         if (!mAzureScaledFont) {
             return nullptr;
         }
 
         mAzureScaledFont->SetCairoScaledFont(mScaledFont);
     }
 
     RefPtr<ScaledFont> scaledFont(mAzureScaledFont);
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -61,19 +61,20 @@ inline DebugFlags NewDebugFlags(uint32_t
   flags.mBits = aFlags;
   return flags;
 }
 
 inline Maybe<wr::ImageFormat>
 SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat) {
   switch (aFormat) {
     case gfx::SurfaceFormat::R8G8B8X8:
-      // TODO: use RGBA + opaque flag
     case gfx::SurfaceFormat::R8G8B8A8:
-      return Some(wr::ImageFormat::BGRA8);
+      // WebRender not support RGBA8 and RGBX8. Assert here.
+      MOZ_ASSERT(false);
+      return Nothing();
     case gfx::SurfaceFormat::B8G8R8X8:
       // TODO: WebRender will have a BGRA + opaque flag for this but does not
       // have it yet (cf. issue #732).
     case gfx::SurfaceFormat::B8G8R8A8:
       return Some(wr::ImageFormat::BGRA8);
     case gfx::SurfaceFormat::A8:
       return Some(wr::ImageFormat::A8);
     case gfx::SurfaceFormat::R8G8:
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -9473,17 +9473,17 @@ CodeGenerator::generateWasm(wasm::SigIdD
 
     masm.bind(&returnLabel_);
     wasm::GenerateFunctionEpilogue(masm, frameSize(), offsets);
 
     if (!omitOverRecursedCheck()) {
         // Since we just overflowed the stack, to be on the safe side, pop the
         // stack so that, when the trap exit stub executes, it is a safe
         // distance away from the end of the native stack.
-        wasm::TrapDesc trap(trapOffset, wasm::Trap::StackOverflow, /* framePushed = */ 0);
+        wasm::OldTrapDesc trap(trapOffset, wasm::Trap::StackOverflow, /* framePushed = */ 0);
         if (frameSize() > 0) {
             masm.bind(&onOverflow);
             masm.addToStackPtr(Imm32(frameSize()));
             masm.jump(trap);
         } else {
             masm.bindLater(&onOverflow, trap);
         }
     }
@@ -9491,17 +9491,17 @@ CodeGenerator::generateWasm(wasm::SigIdD
 #if defined(JS_ION_PERF)
     // Note the end of the inline code and start of the OOL code.
     gen->perfSpewer().noteEndInlineCode(masm);
 #endif
 
     if (!generateOutOfLineCode())
         return false;
 
-    masm.wasmEmitTrapOutOfLineCode();
+    masm.wasmEmitOldTrapOutOfLineCode();
 
     masm.flush();
     if (masm.oom())
         return false;
 
     offsets->end = masm.currentOffset();
 
     MOZ_ASSERT(!masm.failureLabel()->used());
@@ -12345,40 +12345,40 @@ CodeGenerator::visitInterruptCheck(LInte
 }
 
 void
 CodeGenerator::visitWasmTrap(LWasmTrap* lir)
 {
     MOZ_ASSERT(gen->compilingWasm());
     const MWasmTrap* mir = lir->mir();
 
-    masm.jump(trap(mir, mir->trap()));
+    masm.jump(oldTrap(mir, mir->trap()));
 }
 
 void
 CodeGenerator::visitWasmBoundsCheck(LWasmBoundsCheck* ins)
 {
 #ifdef WASM_HUGE_MEMORY
     MOZ_CRASH("No wasm bounds check for huge memory");
 #else
     const MWasmBoundsCheck* mir = ins->mir();
     Register ptr = ToRegister(ins->ptr());
     Register boundsCheckLimit = ToRegister(ins->boundsCheckLimit());
     masm.wasmBoundsCheck(Assembler::AboveOrEqual, ptr, boundsCheckLimit,
-                         trap(mir, wasm::Trap::OutOfBounds));
+                         oldTrap(mir, wasm::Trap::OutOfBounds));
 #endif
 }
 
 void
 CodeGenerator::visitWasmAlignmentCheck(LWasmAlignmentCheck* ins)
 {
     const MWasmAlignmentCheck* mir = ins->mir();
     Register ptr = ToRegister(ins->ptr());
     masm.branchTest32(Assembler::NonZero, ptr, Imm32(mir->byteSize() - 1),
-                      trap(mir, wasm::Trap::UnalignedAccess));
+                      oldTrap(mir, wasm::Trap::UnalignedAccess));
 }
 
 void
 CodeGenerator::visitWasmLoadTls(LWasmLoadTls* ins)
 {
     switch (ins->mir()->type()) {
       case MIRType::Pointer:
         masm.loadPtr(Address(ToRegister(ins->tlsPtr()), ins->mir()->offset()),
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -2839,34 +2839,34 @@ MacroAssembler::callWithABINoProfiler(vo
         assumeUnreachable("callWithABI: callee did not use AutoInUnsafeCallWithABI");
         bind(&ok);
         pop(ReturnReg);
     }
 #endif
 }
 
 void
-MacroAssembler::callWithABI(wasm::BytecodeOffset callOffset, wasm::SymbolicAddress imm,
+MacroAssembler::callWithABI(wasm::BytecodeOffset bytecode, wasm::SymbolicAddress imm,
                             MoveOp::Type result)
 {
     MOZ_ASSERT(wasm::NeedsBuiltinThunk(imm));
 
     // We clobber WasmTlsReg below in the loadWasmTlsRegFromFrame(), but Ion
     // assumes it is non-volatile, so preserve it manually.
     Push(WasmTlsReg);
 
     uint32_t stackAdjust;
     callWithABIPre(&stackAdjust, /* callFromWasm = */ true);
 
     // The TLS register is used in builtin thunks and must be set, by ABI:
     // reload it after passing arguments, which might have used it at spill
     // points when placing arguments.
     loadWasmTlsRegFromFrame();
 
-    call(wasm::CallSiteDesc(callOffset.bytecodeOffset, wasm::CallSite::Symbolic), imm);
+    call(wasm::CallSiteDesc(bytecode.offset, wasm::CallSite::Symbolic), imm);
     callWithABIPost(stackAdjust, result, /* callFromWasm = */ true);
 
     Pop(WasmTlsReg);
 }
 
 // ===============================================================
 // Exit frame footer.
 
@@ -3001,25 +3001,25 @@ MacroAssembler::wasmCallIndirect(const w
     }
 
     wasm::BytecodeOffset trapOffset(desc.lineOrBytecode());
 
     // WebAssembly throws if the index is out-of-bounds.
     if (needsBoundsCheck) {
         loadWasmGlobalPtr(callee.tableLengthGlobalDataOffset(), scratch);
 
-        wasm::TrapDesc oobTrap(trapOffset, wasm::Trap::OutOfBounds, framePushed());
+        wasm::OldTrapDesc oobTrap(trapOffset, wasm::Trap::OutOfBounds, framePushed());
         branch32(Assembler::Condition::AboveOrEqual, index, scratch, oobTrap);
     }
 
     // Load the base pointer of the table.
     loadWasmGlobalPtr(callee.tableBaseGlobalDataOffset(), scratch);
 
     // Load the callee from the table.
-    wasm::TrapDesc nullTrap(trapOffset, wasm::Trap::IndirectCallToNull, framePushed());
+    wasm::OldTrapDesc nullTrap(trapOffset, wasm::Trap::IndirectCallToNull, framePushed());
     if (callee.wasmTableIsExternal()) {
         static_assert(sizeof(wasm::ExternalTableElem) == 8 || sizeof(wasm::ExternalTableElem) == 16,
                       "elements of external tables are two words");
         if (sizeof(wasm::ExternalTableElem) == 8) {
             computeEffectiveAddress(BaseIndex(scratch, index, TimesEight), scratch);
         } else {
             lshift32(Imm32(4), index);
             addPtr(index, scratch);
@@ -3035,31 +3035,31 @@ MacroAssembler::wasmCallIndirect(const w
         loadPtr(BaseIndex(scratch, index, ScalePointer), scratch);
         branchTest32(Assembler::Zero, scratch, scratch, nullTrap);
     }
 
     call(desc, scratch);
 }
 
 void
-MacroAssembler::wasmEmitTrapOutOfLineCode()
+MacroAssembler::wasmEmitOldTrapOutOfLineCode()
 {
-    for (const wasm::TrapSite& site : trapSites()) {
+    for (const wasm::OldTrapSite& site : oldTrapSites()) {
         // Trap out-of-line codes are created for two kinds of trap sites:
         //  - jumps, which are bound directly to the trap out-of-line path
         //  - memory accesses, which can fault and then have control transferred
         //    to the out-of-line path directly via signal handler setting pc
         switch (site.kind) {
-          case wasm::TrapSite::Jump: {
+          case wasm::OldTrapSite::Jump: {
             RepatchLabel jump;
             jump.use(site.codeOffset);
             bind(&jump);
             break;
           }
-          case wasm::TrapSite::MemoryAccess: {
+          case wasm::OldTrapSite::MemoryAccess: {
             append(wasm::MemoryAccess(site.codeOffset, currentOffset()));
             break;
           }
         }
 
         if (site.trap == wasm::Trap::IndirectCallBadSig) {
             // The indirect call bad-signature trap is a special case for two
             // reasons:
@@ -3067,17 +3067,17 @@ MacroAssembler::wasmEmitTrapOutOfLineCod
             //    prologue, before the stack frame has been set up which messes
             //    up everything (stack depth computations, unwinding)
             //  - the check happens in the callee while the trap should be
             //    reported at the caller's call_indirect
             // To solve both problems at once, the out-of-line path (far) jumps
             // directly to the trap exit stub. This takes advantage of the fact
             // that there is already a CallSite for call_indirect and the
             // current pre-prologue stack/register state.
-            append(wasm::TrapFarJump(site.trap, farJumpWithPatch()));
+            append(wasm::OldTrapFarJump(site.trap, farJumpWithPatch()));
         } else {
             // Inherit the frame depth of the trap site. This value is captured
             // by the wasm::CallSite to allow unwinding this frame.
             setFramePushed(site.framePushed);
 
             // Align the stack for a nullary call.
             size_t alreadyPushed = sizeof(wasm::Frame) + framePushed();
             size_t toPush = ABIArgGenerator().stackBytesConsumedSoFar();
@@ -3093,32 +3093,32 @@ MacroAssembler::wasmEmitTrapOutOfLineCod
             // the shared FarJumpIsland generated by patchCallSites.
 
             // Call the trap's exit, using the bytecode offset of the trap site.
             // Note that this code is inside the same CodeRange::Function as the
             // trap site so it's as if the trapping instruction called the
             // trap-handling function. The frame iterator knows to skip the trap
             // exit's frame so that unwinding begins at the frame and offset of
             // the trapping instruction.
-            wasm::CallSiteDesc desc(site.bytecodeOffset, wasm::CallSiteDesc::TrapExit);
+            wasm::CallSiteDesc desc(site.offset, wasm::CallSiteDesc::OldTrapExit);
             call(desc, site.trap);
         }
 
 #ifdef DEBUG
         // Traps do not return, so no need to freeStack().
         breakpoint();
 #endif
     }
 
     // Ensure that the return address of the last emitted call above is always
     // within this function's CodeRange which is necessary for the stack
     // iterator to find the right CodeRange while walking the stack.
     breakpoint();
 
-    trapSites().clear();
+    oldTrapSites().clear();
 }
 
 void
 MacroAssembler::wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow)
 {
     loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, addressOfContext)), scratch);
     loadPtr(Address(scratch, 0), scratch);
     branchPtr(Assembler::AboveOrEqual,
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1501,17 +1501,17 @@ class MacroAssembler : public MacroAssem
     // as the implicit first argument. It preserves TLS and pinned registers.
     // (TLS & pinned regs are non-volatile registers in the system ABI).
     void wasmCallBuiltinInstanceMethod(const wasm::CallSiteDesc& desc, const ABIArg& instanceArg,
                                        wasm::SymbolicAddress builtin);
 
     // Emit the out-of-line trap code to which trapping jumps/branches are
     // bound. This should be called once per function after all other codegen,
     // including "normal" OutOfLineCode.
-    void wasmEmitTrapOutOfLineCode();
+    void wasmEmitOldTrapOutOfLineCode();
 
     // Perform a stack-overflow test, branching to the given Label on overflow.
     void wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow);
 
     void emitPreBarrierFastPath(JSRuntime* rt, MIRType type, Register temp1, Register temp2,
                                 Register temp3, Label* noBarrier);
 
   public:
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -2448,17 +2448,17 @@ Assembler::as_b(Label* l, Condition c)
     if (oom())
         return BufferOffset();
 
     l->use(ret.getOffset());
     return ret;
 }
 
 BufferOffset
-Assembler::as_b(wasm::TrapDesc target, Condition c)
+Assembler::as_b(wasm::OldTrapDesc target, Condition c)
 {
     Label l;
     BufferOffset ret = as_b(&l, c);
     bindLater(&l, target);
     return ret;
 }
 
 BufferOffset
@@ -2889,22 +2889,22 @@ Assembler::bind(Label* label, BufferOffs
             b = next;
         } while (more);
     }
     label->bind(nextOffset().getOffset());
     MOZ_ASSERT(!oom());
 }
 
 void
-Assembler::bindLater(Label* label, wasm::TrapDesc target)
+Assembler::bindLater(Label* label, wasm::OldTrapDesc target)
 {
     if (label->used()) {
         BufferOffset b(label);
         do {
-            append(wasm::TrapSite(target, b.getOffset()));
+            append(wasm::OldTrapSite(target, b.getOffset()));
         } while (nextLink(b, &b));
     }
     label->reset();
 }
 
 void
 Assembler::bind(RepatchLabel* label)
 {
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -1609,17 +1609,17 @@ class Assembler : public AssemblerShared
     // bx can *only* branch to a register never to an immediate.
     BufferOffset as_bx(Register r, Condition c = Always);
 
     // Branch can branch to an immediate *or* to a register. Branches to
     // immediates are pc relative, branches to registers are absolute.
     BufferOffset as_b(BOffImm off, Condition c, Label* documentation = nullptr);
 
     BufferOffset as_b(Label* l, Condition c = Always);
-    BufferOffset as_b(wasm::TrapDesc target, Condition c = Always);
+    BufferOffset as_b(wasm::OldTrapDesc target, Condition c = Always);
     BufferOffset as_b(BOffImm off, Condition c, BufferOffset inst);
 
     // blx can go to either an immediate or a register. When blx'ing to a
     // register, we change processor mode depending on the low bit of the
     // register when blx'ing to an immediate, we *always* change processor
     // state.
     BufferOffset as_blx(Label* l);
 
@@ -1717,17 +1717,17 @@ class Assembler : public AssemblerShared
 
     BufferOffset as_vmrs(Register r, Condition c = Always);
     BufferOffset as_vmsr(Register r, Condition c = Always);
 
     // Label operations.
     bool nextLink(BufferOffset b, BufferOffset* next);
     void bind(Label* label, BufferOffset boff = BufferOffset());
     void bind(RepatchLabel* label);
-    void bindLater(Label* label, wasm::TrapDesc target);
+    void bindLater(Label* label, wasm::OldTrapDesc target);
     uint32_t currentOffset() {
         return nextOffset().getOffset();
     }
     void retarget(Label* label, Label* target);
     // I'm going to pretend this doesn't exist for now.
     void retarget(Label* label, void* target, Relocation::Kind reloc);
 
     static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target);
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -526,17 +526,17 @@ CodeGeneratorARM::divICommon(MDiv* mir, 
         // The integer division will give INT32_MIN, but we want -(double)INT32_MIN.
 
         // Sets EQ if lhs == INT32_MIN.
         masm.ma_cmp(lhs, Imm32(INT32_MIN), scratch);
         // If EQ (LHS == INT32_MIN), sets EQ if rhs == -1.
         masm.ma_cmp(rhs, Imm32(-1), scratch, Assembler::Equal);
         if (mir->canTruncateOverflow()) {
             if (mir->trapOnError()) {
-                masm.ma_b(trap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
+                masm.ma_b(oldTrap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
             } else {
                 // (-INT32_MIN)|0 = INT32_MIN
                 Label skip;
                 masm.ma_b(&skip, Assembler::NotEqual);
                 masm.ma_mov(Imm32(INT32_MIN), output);
                 masm.ma_b(&done);
                 masm.bind(&skip);
             }
@@ -546,17 +546,17 @@ CodeGeneratorARM::divICommon(MDiv* mir, 
         }
     }
 
     // Handle divide by zero.
     if (mir->canBeDivideByZero()) {
         masm.as_cmp(rhs, Imm8(0));
         if (mir->canTruncateInfinities()) {
             if (mir->trapOnError()) {
-                masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
+                masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
             } else {
                 // Infinity|0 == 0
                 Label skip;
                 masm.ma_b(&skip, Assembler::NotEqual);
                 masm.ma_mov(Imm32(0), output);
                 masm.ma_b(&done);
                 masm.bind(&skip);
             }
@@ -709,17 +709,17 @@ CodeGeneratorARM::modICommon(MMod* mir, 
     // because the EQ flag is set.
     // If (Y > 0), we don't set EQ, and we don't trigger LT, so we don't take
     // the bailout.
     if (mir->canBeDivideByZero() || mir->canBeNegativeDividend()) {
         if (mir->trapOnError()) {
             // wasm allows negative lhs and return 0 in this case.
             MOZ_ASSERT(mir->isTruncated());
             masm.as_cmp(rhs, Imm8(0));
-            masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
+            masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
             return;
         }
 
         masm.as_cmp(rhs, Imm8(0));
         masm.as_cmp(lhs, Imm8(0), Assembler::LessThan);
         if (mir->isTruncated()) {
             // NaN|0 == 0 and (0 % -X)|0 == 0
             Label skip;
@@ -2115,17 +2115,17 @@ CodeGeneratorARM::visitWasmAddOffset(LWa
 {
     MWasmAddOffset* mir = lir->mir();
     Register base = ToRegister(lir->base());
     Register out = ToRegister(lir->output());
 
     ScratchRegisterScope scratch(masm);
     masm.ma_add(base, Imm32(mir->offset()), out, scratch, SetCC);
 
-    masm.ma_b(trap(mir, wasm::Trap::OutOfBounds), Assembler::CarrySet);
+    masm.ma_b(oldTrap(mir, wasm::Trap::OutOfBounds), Assembler::CarrySet);
 }
 
 template <typename T>
 void
 CodeGeneratorARM::emitWasmStore(T* lir)
 {
     const MWasmStore* mir = lir->mir();
     Scalar::Type accessType = mir->access().type();
@@ -2412,17 +2412,17 @@ CodeGeneratorARM::generateUDivModZeroChe
                                            LSnapshot* snapshot, T* mir)
 {
     if (!mir)
         return;
     if (mir->canBeDivideByZero()) {
         masm.as_cmp(rhs, Imm8(0));
         if (mir->isTruncated()) {
             if (mir->trapOnError()) {
-                masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
+                masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
             } else {
                 Label skip;
                 masm.ma_b(&skip, Assembler::NotEqual);
                 // Infinity|0 == 0
                 masm.ma_mov(Imm32(0), output);
                 masm.ma_b(done);
                 masm.bind(&skip);
             }
@@ -2763,30 +2763,30 @@ CodeGeneratorARM::visitDivOrModI64(LDivO
     MOZ_ASSERT(output == ReturnReg64);
 
     Label done;
 
     // Handle divide by zero.
     if (lir->canBeDivideByZero()) {
         Register temp = WasmGetTemporaryForDivOrMod(lhs, rhs);
         masm.branchTest64(Assembler::Zero, rhs, rhs, temp,
-                          trap(lir, wasm::Trap::IntegerDivideByZero));
+                          oldTrap(lir, wasm::Trap::IntegerDivideByZero));
     }
 
     auto* mir = lir->mir();
 
     // Handle an integer overflow exception from INT64_MIN / -1.
     if (lir->canBeNegativeOverflow()) {
         Label notmin;
         masm.branch64(Assembler::NotEqual, lhs, Imm64(INT64_MIN), &notmin);
         masm.branch64(Assembler::NotEqual, rhs, Imm64(-1), &notmin);
         if (mir->isMod())
             masm.xor64(output, output);
         else
-            masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
+            masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
         masm.jump(&done);
         masm.bind(&notmin);
     }
 
     masm.setupWasmABICall();
     masm.passABIArg(lhs.high);
     masm.passABIArg(lhs.low);
     masm.passABIArg(rhs.high);
@@ -2809,17 +2809,17 @@ CodeGeneratorARM::visitUDivOrModI64(LUDi
     Register64 rhs = ToRegister64(lir->getInt64Operand(LDivOrModI64::Rhs));
 
     MOZ_ASSERT(ToOutRegister64(lir) == ReturnReg64);
 
     // Prevent divide by zero.
     if (lir->canBeDivideByZero()) {
         Register temp = WasmGetTemporaryForDivOrMod(lhs, rhs);
         masm.branchTest64(Assembler::Zero, rhs, rhs, temp,
-                          trap(lir, wasm::Trap::IntegerDivideByZero));
+                          oldTrap(lir, wasm::Trap::IntegerDivideByZero));
     }
 
     masm.setupWasmABICall();
     masm.passABIArg(lhs.high);
     masm.passABIArg(lhs.low);
     masm.passABIArg(rhs.high);
     masm.passABIArg(rhs.low);
 
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -1385,17 +1385,17 @@ MacroAssemblerARM::ma_dsb(BarrierOption 
 // Branches when done from within arm-specific code.
 BufferOffset
 MacroAssemblerARM::ma_b(Label* dest, Assembler::Condition c)
 {
     return as_b(dest, c);
 }
 
 BufferOffset
-MacroAssemblerARM::ma_b(wasm::TrapDesc target, Assembler::Condition c)
+MacroAssemblerARM::ma_b(wasm::OldTrapDesc target, Assembler::Condition c)
 {
     return as_b(target, c);
 }
 
 void
 MacroAssemblerARM::ma_bx(Register dest, Assembler::Condition c)
 {
     as_bx(dest, c);
@@ -5746,22 +5746,22 @@ MacroAssemblerARM::outOfLineWasmTruncate
         asMasm().branchFloat(maxCond, input, scratch, &fail);
     }
 
     // We had an actual correct value, get back to where we were.
     ma_b(rejoin);
 
     // Handle errors.
     bind(&fail);
-    asMasm().jump(wasm::TrapDesc(trapOffset, wasm::Trap::IntegerOverflow,
-                                 asMasm().framePushed()));
+    asMasm().jump(wasm::OldTrapDesc(trapOffset, wasm::Trap::IntegerOverflow,
+                                    asMasm().framePushed()));
 
     bind(&inputIsNaN);
-    asMasm().jump(wasm::TrapDesc(trapOffset, wasm::Trap::InvalidConversionToInteger,
-                                 asMasm().framePushed()));
+    asMasm().jump(wasm::OldTrapDesc(trapOffset, wasm::Trap::InvalidConversionToInteger,
+                                    asMasm().framePushed()));
 }
 
 void
 MacroAssemblerARM::wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase,
                                 Register ptr, Register ptrScratch, AnyRegister output,
                                 Register64 out64)
 {
     MOZ_ASSERT(ptr == ptrScratch);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -341,17 +341,17 @@ class MacroAssemblerARM : public Assembl
     void ma_vpush(VFPRegister r);
 
     // Barriers.
     void ma_dmb(BarrierOption option=BarrierSY);
     void ma_dsb(BarrierOption option=BarrierSY);
 
     // Branches when done from within arm-specific code.
     BufferOffset ma_b(Label* dest, Condition c = Always);
-    BufferOffset ma_b(wasm::TrapDesc target, Condition c = Always);
+    BufferOffset ma_b(wasm::OldTrapDesc target, Condition c = Always);
     void ma_b(void* target, Condition c = Always);
     void ma_bx(Register dest, Condition c = Always);
 
     // This is almost NEVER necessary, we'll basically never be calling a label
     // except, possibly in the crazy bailout-table case.
     void ma_bl(Label* dest, Condition c = Always);
 
     void ma_blx(Register dest, Condition c = Always);
@@ -672,17 +672,17 @@ class MacroAssemblerARMCompat : public M
         ma_bx(reg);
     }
     void jump(const Address& addr) {
         ScratchRegisterScope scratch(asMasm());
         SecondScratchRegisterScope scratch2(asMasm());
         ma_ldr(addr, scratch, scratch2);
         ma_bx(scratch);
     }
-    void jump(wasm::TrapDesc target) {
+    void jump(wasm::OldTrapDesc target) {
         as_b(target);
     }
 
     void negl(Register reg) {
         ma_neg(reg, reg, SetCC);
     }
     void test32(Register lhs, Register rhs) {
         ma_tst(lhs, rhs);
--- a/js/src/jit/arm64/Assembler-arm64.h
+++ b/js/src/jit/arm64/Assembler-arm64.h
@@ -210,17 +210,17 @@ class Assembler : public vixl::Assembler
     BufferOffset immPool64Branch(RepatchLabel* label, ARMBuffer::PoolEntry* pe, vixl::Condition c);
     BufferOffset fImmPool(ARMFPRegister dest, uint8_t* value, vixl::LoadLiteralOp op);
     BufferOffset fImmPool64(ARMFPRegister dest, double value);
     BufferOffset fImmPool32(ARMFPRegister dest, float value);
 
     void bind(Label* label) { bind(label, nextOffset()); }
     void bind(Label* label, BufferOffset boff);
     void bind(RepatchLabel* label);
-    void bindLater(Label* label, wasm::TrapDesc target) {
+    void bindLater(Label* label, wasm::OldTrapDesc target) {
         MOZ_CRASH("NYI");
     }
 
     bool oom() const {
         return AssemblerShared::oom() ||
             armbuffer_.oom() ||
             jumpRelocations_.oom() ||
             dataRelocations_.oom();
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -488,20 +488,20 @@ class MacroAssemblerCompat : public vixl
     void convertFloat32ToDouble(FloatRegister src, FloatRegister dest) {
         Fcvt(ARMFPRegister(dest, 64), ARMFPRegister(src, 32));
     }
     void convertDoubleToFloat32(FloatRegister src, FloatRegister dest) {
         Fcvt(ARMFPRegister(dest, 32), ARMFPRegister(src, 64));
     }
 
     using vixl::MacroAssembler::B;
-    void B(wasm::TrapDesc) {
+    void B(wasm::OldTrapDesc) {
         MOZ_CRASH("NYI");
     }
-    void B(wasm::TrapDesc, Condition cond) {
+    void B(wasm::OldTrapDesc, Condition cond) {
         MOZ_CRASH("NYI");
     }
 
     void convertDoubleToInt32(FloatRegister src, Register dest, Label* fail,
                               bool negativeZeroCheck = true)
     {
         vixl::UseScratchRegisterScope temps(this);
         const ARMFPRegister scratch64 = temps.AcquireD();
@@ -668,17 +668,17 @@ class MacroAssemblerCompat : public vixl
     }
     void jump(Register reg) {
         Br(ARMRegister(reg, 64));
     }
     void jump(const Address& addr) {
         loadPtr(addr, ip0);
         Br(vixl::ip0);
     }
-    void jump(wasm::TrapDesc target) {
+    void jump(wasm::OldTrapDesc target) {
         MOZ_CRASH("NYI");
     }
 
     void align(int alignment) {
         armbuffer_.align(alignment);
     }
 
     void haltingAlign(int alignment) {
--- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp
@@ -1804,26 +1804,26 @@ AssemblerMIPSShared::bind(Label* label, 
 
             b = BufferOffset(next);
         } while (next != LabelBase::INVALID_OFFSET);
     }
     label->bind(dest.getOffset());
 }
 
 void
-AssemblerMIPSShared::bindLater(Label* label, wasm::TrapDesc target)
+AssemblerMIPSShared::bindLater(Label* label, wasm::OldTrapDesc target)
 {
     if (label->used()) {
         int32_t next;
 
         BufferOffset b(label);
         do {
             Instruction* inst = editSrc(b);
 
-            append(wasm::TrapSite(target, b.getOffset()));
+            append(wasm::OldTrapSite(target, b.getOffset()));
             next = inst[1].encode();
             inst[1].makeNop();
 
             b = BufferOffset(next);
         } while (next != LabelBase::INVALID_OFFSET);
     }
     label->reset();
 }
--- a/js/src/jit/mips-shared/Assembler-mips-shared.h
+++ b/js/src/jit/mips-shared/Assembler-mips-shared.h
@@ -1226,17 +1226,17 @@ class AssemblerMIPSShared : public Assem
                          FPConditionBit fcc = FCC0);
     BufferOffset as_movf(FloatFormat fmt, FloatRegister fd, FloatRegister fs,
                          FPConditionBit fcc = FCC0);
     BufferOffset as_movz(FloatFormat fmt, FloatRegister fd, FloatRegister fs, Register rt);
     BufferOffset as_movn(FloatFormat fmt, FloatRegister fd, FloatRegister fs, Register rt);
 
     // label operations
     void bind(Label* label, BufferOffset boff = BufferOffset());
-    void bindLater(Label* label, wasm::TrapDesc target);
+    void bindLater(Label* label, wasm::OldTrapDesc target);
     virtual void bind(InstImm* inst, uintptr_t branch, uintptr_t target) = 0;
     void bind(CodeOffset* label) {
         label->bind(currentOffset());
     }
     void use(CodeOffset* label) {
         label->bind(currentOffset());
     }
     uint32_t currentOffset() {
--- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
+++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -563,17 +563,17 @@ CodeGeneratorMIPSShared::visitDivI(LDivI
     Register temp = ToRegister(ins->getTemp(0));
     MDiv* mir = ins->mir();
 
     Label done;
 
     // Handle divide by zero.
     if (mir->canBeDivideByZero()) {
         if (mir->trapOnError()) {
-            masm.ma_b(rhs, rhs, trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
+            masm.ma_b(rhs, rhs, oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
         } else if (mir->canTruncateInfinities()) {
             // Truncated division by zero is zero (Infinity|0 == 0)
             Label notzero;
             masm.ma_b(rhs, rhs, &notzero, Assembler::NonZero, ShortJump);
             masm.move32(Imm32(0), dest);
             masm.ma_b(&done, ShortJump);
             masm.bind(&notzero);
         } else {
@@ -585,17 +585,17 @@ CodeGeneratorMIPSShared::visitDivI(LDivI
     // Handle an integer overflow exception from -2147483648 / -1.
     if (mir->canBeNegativeOverflow()) {
         Label notMinInt;
         masm.move32(Imm32(INT32_MIN), temp);
         masm.ma_b(lhs, temp, &notMinInt, Assembler::NotEqual, ShortJump);
 
         masm.move32(Imm32(-1), temp);
         if (mir->trapOnError()) {
-            masm.ma_b(rhs, temp, trap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
+            masm.ma_b(rhs, temp, oldTrap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
         } else if (mir->canTruncateOverflow()) {
             // (-INT32_MIN)|0 == INT32_MIN
             Label skip;
             masm.ma_b(rhs, temp, &skip, Assembler::NotEqual, ShortJump);
             masm.move32(Imm32(INT32_MIN), dest);
             masm.ma_b(&done, ShortJump);
             masm.bind(&skip);
         } else {
@@ -713,17 +713,17 @@ CodeGeneratorMIPSShared::visitModI(LModI
     // There are three cases: (Y < 0), (Y == 0) and (Y > 0)
     // If (Y < 0), then we compare X with 0, and bail if X == 0
     // If (Y == 0), then we simply want to bail.
     // if (Y > 0), we don't bail.
 
     if (mir->canBeDivideByZero()) {
         if (mir->isTruncated()) {
             if (mir->trapOnError()) {
-                masm.ma_b(rhs, rhs, trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
+                masm.ma_b(rhs, rhs, oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
             } else {
                 Label skip;
                 masm.ma_b(rhs, Imm32(0), &skip, Assembler::NotEqual, ShortJump);
                 masm.move32(Imm32(0), dest);
                 masm.ma_b(&done, ShortJump);
                 masm.bind(&skip);
             }
         } else {
@@ -1554,20 +1554,20 @@ CodeGeneratorMIPSShared::visitOutOfLineW
         masm.loadConstantFloat32(float(maxValue), ScratchFloat32Reg);
         masm.branchFloat(maxCond, input, ScratchFloat32Reg, &fail);
     }
 
     masm.jump(ool->rejoin());
 
     // Handle errors.
     masm.bind(&fail);
-    masm.jump(trap(ool, wasm::Trap::IntegerOverflow));
+    masm.jump(oldTrap(ool, wasm::Trap::IntegerOverflow));
 
     masm.bind(&inputIsNaN);
-    masm.jump(trap(ool, wasm::Trap::InvalidConversionToInteger));
+    masm.jump(oldTrap(ool, wasm::Trap::InvalidConversionToInteger));
 }
 
 void
 CodeGeneratorMIPSShared::visitCopySignF(LCopySignF* ins)
 {
     FloatRegister lhs = ToFloatRegister(ins->getOperand(0));
     FloatRegister rhs = ToFloatRegister(ins->getOperand(1));
     FloatRegister output = ToFloatRegister(ins->getDef(0));
@@ -2410,17 +2410,17 @@ CodeGeneratorMIPSShared::visitUDivOrMod(
     Register rhs = ToRegister(ins->rhs());
     Register output = ToRegister(ins->output());
     Label done;
 
     // Prevent divide by zero.
     if (ins->canBeDivideByZero()) {
         if (ins->mir()->isTruncated()) {
             if (ins->trapOnError()) {
-                masm.ma_b(rhs, rhs, trap(ins, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
+                masm.ma_b(rhs, rhs, oldTrap(ins, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
             } else {
                 // Infinity|0 == 0
                 Label notzero;
                 masm.ma_b(rhs, rhs, &notzero, Assembler::NonZero, ShortJump);
                 masm.move32(Imm32(0), output);
                 masm.ma_b(&done, ShortJump);
                 masm.bind(&notzero);
             }
@@ -2762,17 +2762,17 @@ CodeGeneratorMIPSShared::atomicBinopToTy
 
 void
 CodeGeneratorMIPSShared::visitWasmAddOffset(LWasmAddOffset* lir)
 {
     MWasmAddOffset* mir = lir->mir();
     Register base = ToRegister(lir->base());
     Register out = ToRegister(lir->output());
 
-    masm.ma_addTestCarry(out, base, Imm32(mir->offset()), trap(mir, wasm::Trap::OutOfBounds));
+    masm.ma_addTestCarry(out, base, Imm32(mir->offset()), oldTrap(mir, wasm::Trap::OutOfBounds));
 }
 
 template <typename T>
 static inline void
 AtomicBinopToTypedArray(CodeGeneratorMIPSShared* cg, AtomicOp op,
                         Scalar::Type arrayType, const LAllocation* value, const T& mem,
                         Register flagTemp, Register outTemp, Register valueTemp,
                         Register offsetTemp, Register maskTemp, AnyRegister output)
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -332,33 +332,33 @@ MacroAssemblerMIPSShared::ma_addTestCarr
     as_sltu(SecondScratchReg, rd, rs);
     ma_b(SecondScratchReg, SecondScratchReg, overflow, Assembler::NonZero);
 }
 
 template void
 MacroAssemblerMIPSShared::ma_addTestCarry<Label*>(Register rd, Register rs,
                                                   Register rt, Label* overflow);
 template void
-MacroAssemblerMIPSShared::ma_addTestCarry<wasm::TrapDesc>(Register rd, Register rs, Register rt,
-                                                          wasm::TrapDesc overflow);
+MacroAssemblerMIPSShared::ma_addTestCarry<wasm::OldTrapDesc>(Register rd, Register rs, Register rt,
+                                                             wasm::OldTrapDesc overflow);
 
 template <typename L>
 void
 MacroAssemblerMIPSShared::ma_addTestCarry(Register rd, Register rs, Imm32 imm, L overflow)
 {
     ma_li(ScratchRegister, imm);
     ma_addTestCarry(rd, rs, ScratchRegister, overflow);
 }
 
 template void
 MacroAssemblerMIPSShared::ma_addTestCarry<Label*>(Register rd, Register rs,
                                                   Imm32 imm, Label* overflow);
 template void
-MacroAssemblerMIPSShared::ma_addTestCarry<wasm::TrapDesc>(Register rd, Register rs, Imm32 imm,
-                                                          wasm::TrapDesc overflow);
+MacroAssemblerMIPSShared::ma_addTestCarry<wasm::OldTrapDesc>(Register rd, Register rs, Imm32 imm,
+                                                             wasm::OldTrapDesc overflow);
 
 // Subtract.
 void
 MacroAssemblerMIPSShared::ma_subu(Register rd, Register rs, Imm32 imm)
 {
     if (Imm16::IsInSignedRange(-imm.value)) {
         as_addiu(rd, rs, -imm.value);
     } else {
@@ -791,42 +791,42 @@ MacroAssemblerMIPSShared::ma_b(Register 
 void
 MacroAssemblerMIPSShared::ma_b(Register lhs, ImmPtr imm, Label* l, Condition c, JumpKind jumpKind)
 {
     asMasm().ma_b(lhs, ImmWord(uintptr_t(imm.value)), l, c, jumpKind);
 }
 
 template <typename T>
 void
-MacroAssemblerMIPSShared::ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condition c,
+MacroAssemblerMIPSShared::ma_b(Register lhs, T rhs, wasm::OldTrapDesc target, Condition c,
                                JumpKind jumpKind)
 {
     Label label;
     ma_b(lhs, rhs, &label, c, jumpKind);
     bindLater(&label, target);
 }
 
 template void MacroAssemblerMIPSShared::ma_b<Register>(Register lhs, Register rhs,
-                                                       wasm::TrapDesc target, Condition c,
+                                                       wasm::OldTrapDesc target, Condition c,
                                                        JumpKind jumpKind);
 template void MacroAssemblerMIPSShared::ma_b<Imm32>(Register lhs, Imm32 rhs,
-                                                       wasm::TrapDesc target, Condition c,
+                                                       wasm::OldTrapDesc target, Condition c,
                                                        JumpKind jumpKind);
 template void MacroAssemblerMIPSShared::ma_b<ImmTag>(Register lhs, ImmTag rhs,
-                                                       wasm::TrapDesc target, Condition c,
+                                                       wasm::OldTrapDesc target, Condition c,
                                                        JumpKind jumpKind);
 
 void
 MacroAssemblerMIPSShared::ma_b(Label* label, JumpKind jumpKind)
 {
     asMasm().branchWithCode(getBranchCode(BranchIsJump), label, jumpKind);
 }
 
 void
-MacroAssemblerMIPSShared::ma_b(wasm::TrapDesc target, JumpKind jumpKind)
+MacroAssemblerMIPSShared::ma_b(wasm::OldTrapDesc target, JumpKind jumpKind)
 {
     Label label;
     asMasm().branchWithCode(getBranchCode(BranchIsJump), &label, jumpKind);
     bindLater(&label, target);
 }
 
 Assembler::Condition
 MacroAssemblerMIPSShared::ma_cmp(Register scratch, Register lhs, Register rhs, Condition c)
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
@@ -159,21 +159,21 @@ class MacroAssemblerMIPSShared : public 
     void ma_b(Register lhs, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump) {
         MOZ_ASSERT(lhs != ScratchRegister);
         ma_li(ScratchRegister, imm);
         ma_b(lhs, ScratchRegister, l, c, jumpKind);
     }
     template <typename T>
-    void ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condition c,
+    void ma_b(Register lhs, T rhs, wasm::OldTrapDesc target, Condition c,
               JumpKind jumpKind = LongJump);
 
     void ma_b(Label* l, JumpKind jumpKind = LongJump);
-    void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump);
+    void ma_b(wasm::OldTrapDesc target, JumpKind jumpKind = LongJump);
 
     // fp instructions
     void ma_lis(FloatRegister dest, float value);
     void ma_liNegZero(FloatRegister dest);
 
     void ma_sd(FloatRegister fd, BaseIndex address);
     void ma_ss(FloatRegister fd, BaseIndex address);
 
--- a/js/src/jit/mips32/CodeGenerator-mips32.cpp
+++ b/js/src/jit/mips32/CodeGenerator-mips32.cpp
@@ -375,27 +375,27 @@ CodeGeneratorMIPS::visitDivOrModI64(LDiv
         regs.take(rhs.low);
         regs.take(rhs.high);
     }
     Register temp = regs.takeAny();
     Label done;
 
     // Handle divide by zero.
     if (lir->canBeDivideByZero())
-        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
+        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
 
     // Handle an integer overflow exception from INT64_MIN / -1.
     if (lir->canBeNegativeOverflow()) {
         Label notmin;
         masm.branch64(Assembler::NotEqual, lhs, Imm64(INT64_MIN), &notmin);
         masm.branch64(Assembler::NotEqual, rhs, Imm64(-1), &notmin);
         if (lir->mir()->isMod()) {
             masm.xor64(output, output);
         } else {
-            masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
+            masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
         }
         masm.jump(&done);
         masm.bind(&notmin);
     }
 
     masm.setupWasmABICall();
     masm.passABIArg(lhs.high);
     masm.passABIArg(lhs.low);
@@ -428,17 +428,17 @@ CodeGeneratorMIPS::visitUDivOrModI64(LUD
     if (lhs != rhs) {
         regs.take(rhs.low);
         regs.take(rhs.high);
     }
     Register temp = regs.takeAny();
 
     // Prevent divide by zero.
     if (lir->canBeDivideByZero())
-        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
+        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
 
     masm.setupWasmABICall();
     masm.passABIArg(lhs.high);
     masm.passABIArg(lhs.low);
     masm.passABIArg(rhs.high);
     masm.passABIArg(rhs.low);
 
     MOZ_ASSERT(gen->compilingWasm());
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -233,18 +233,18 @@ MacroAssemblerMIPS::ma_addTestOverflow(R
 
     bind(&goodAddition);
 }
 
 template void
 MacroAssemblerMIPS::ma_addTestOverflow<Label*>(Register rd, Register rs,
                                                Register rt, Label* overflow);
 template void
-MacroAssemblerMIPS::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Register rt,
-                                                       wasm::TrapDesc overflow);
+MacroAssemblerMIPS::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Register rt,
+                                                          wasm::OldTrapDesc overflow);
 
 template <typename L>
 void
 MacroAssemblerMIPS::ma_addTestOverflow(Register rd, Register rs, Imm32 imm, L overflow)
 {
     // Check for signed range because of as_addiu
     // Check for unsigned range because of as_xori
     if (Imm16::IsInSignedRange(imm.value) && Imm16::IsInUnsignedRange(imm.value)) {
@@ -265,18 +265,18 @@ MacroAssemblerMIPS::ma_addTestOverflow(R
         ma_addTestOverflow(rd, rs, ScratchRegister, overflow);
     }
 }
 
 template void
 MacroAssemblerMIPS::ma_addTestOverflow<Label*>(Register rd, Register rs,
                                                Imm32 imm, Label* overflow);
 template void
-MacroAssemblerMIPS::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Imm32 imm,
-                                                       wasm::TrapDesc overflow);
+MacroAssemblerMIPS::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Imm32 imm,
+                                                          wasm::OldTrapDesc overflow);
 
 // Subtract.
 void
 MacroAssemblerMIPS::ma_subTestOverflow(Register rd, Register rs, Register rt, Label* overflow)
 {
     Label goodSubtraction;
     // Use second scratch. The instructions generated by ma_b don't use the
     // second scratch register.
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -301,17 +301,17 @@ class MacroAssemblerMIPSCompat : public 
         as_jr(ScratchRegister);
         as_nop();
     }
 
     void jump(JitCode* code) {
         branch(code);
     }
 
-    void jump(wasm::TrapDesc target) {
+    void jump(wasm::OldTrapDesc target) {
         ma_b(target);
     }
 
     void jump(TrampolinePtr code)
     {
         auto target = ImmPtr(code.value);
         BufferOffset bo = m_buffer.nextOffset();
         addPendingJump(bo, target, Relocation::HARDCODED);
--- a/js/src/jit/mips64/CodeGenerator-mips64.cpp
+++ b/js/src/jit/mips64/CodeGenerator-mips64.cpp
@@ -357,27 +357,27 @@ CodeGeneratorMIPS64::visitDivOrModI64(LD
     Register lhs = ToRegister(lir->lhs());
     Register rhs = ToRegister(lir->rhs());
     Register output = ToRegister(lir->output());
 
     Label done;
 
     // Handle divide by zero.
     if (lir->canBeDivideByZero())
-        masm.ma_b(rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
+        masm.ma_b(rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
 
     // Handle an integer overflow exception from INT64_MIN / -1.
     if (lir->canBeNegativeOverflow()) {
         Label notmin;
         masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(INT64_MIN), &notmin);
         masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(-1), &notmin);
         if (lir->mir()->isMod()) {
             masm.ma_xor(output, output);
         } else {
-            masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
+            masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
         }
         masm.jump(&done);
         masm.bind(&notmin);
     }
 
     masm.as_ddiv(lhs, rhs);
 
     if (lir->mir()->isMod())
@@ -394,17 +394,17 @@ CodeGeneratorMIPS64::visitUDivOrModI64(L
     Register lhs = ToRegister(lir->lhs());
     Register rhs = ToRegister(lir->rhs());
     Register output = ToRegister(lir->output());
 
     Label done;
 
     // Prevent divide by zero.
     if (lir->canBeDivideByZero())
-        masm.ma_b(rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
+        masm.ma_b(rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
 
     masm.as_ddivu(lhs, rhs);
 
     if (lir->mir()->isMod())
         masm.as_mfhi(output);
     else
         masm.as_mflo(output);
 
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -484,18 +484,18 @@ MacroAssemblerMIPS64::ma_addTestOverflow
     as_addu(rd, rs, rt);
     ma_b(rd, SecondScratchReg, overflow, Assembler::NotEqual);
 }
 
 template void
 MacroAssemblerMIPS64::ma_addTestOverflow<Label*>(Register rd, Register rs,
                                                  Register rt, Label* overflow);
 template void
-MacroAssemblerMIPS64::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Register rt,
-                                                         wasm::TrapDesc overflow);
+MacroAssemblerMIPS64::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Register rt,
+                                                            wasm::OldTrapDesc overflow);
 
 template <typename L>
 void
 MacroAssemblerMIPS64::ma_addTestOverflow(Register rd, Register rs, Imm32 imm, L overflow)
 {
     // Check for signed range because of as_daddiu
     if (Imm16::IsInSignedRange(imm.value)) {
         as_daddiu(SecondScratchReg, rs, imm.value);
@@ -506,18 +506,18 @@ MacroAssemblerMIPS64::ma_addTestOverflow
         ma_addTestOverflow(rd, rs, ScratchRegister, overflow);
     }
 }
 
 template void
 MacroAssemblerMIPS64::ma_addTestOverflow<Label*>(Register rd, Register rs,
                                                  Imm32 imm, Label* overflow);
 template void
-MacroAssemblerMIPS64::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Imm32 imm,
-                                                         wasm::TrapDesc overflow);
+MacroAssemblerMIPS64::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Imm32 imm,
+                                                            wasm::OldTrapDesc overflow);
 
 // Subtract.
 void
 MacroAssemblerMIPS64::ma_dsubu(Register rd, Register rs, Imm32 imm)
 {
     if (Imm16::IsInSignedRange(-imm.value)) {
         as_daddiu(rd, rs, -imm.value);
     } else {
--- a/js/src/jit/mips64/MacroAssembler-mips64.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64.h
@@ -330,17 +330,17 @@ class MacroAssemblerMIPS64Compat : publi
         as_jr(ScratchRegister);
         as_nop();
     }
 
     void jump(JitCode* code) {
         branch(code);
     }
 
-    void jump(wasm::TrapDesc target) {
+    void jump(wasm::OldTrapDesc target) {
         ma_b(target);
     }
 
     void jump(TrampolinePtr code)
     {
         auto target = ImmPtr(code.value);
         BufferOffset bo = m_buffer.nextOffset();
         addPendingJump(bo, target, Relocation::HARDCODED);
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -205,17 +205,17 @@ class MacroAssemblerNone : public Assemb
     void copyJumpRelocationTable(uint8_t*) { MOZ_CRASH(); }
     void copyDataRelocationTable(uint8_t*) { MOZ_CRASH(); }
     void copyPreBarrierTable(uint8_t*) { MOZ_CRASH(); }
     void processCodeLabels(uint8_t*) { MOZ_CRASH(); }
 
     void flushBuffer() { MOZ_CRASH(); }
 
     template <typename T> void bind(T) { MOZ_CRASH(); }
-    void bindLater(Label*, wasm::TrapDesc) { MOZ_CRASH(); }
+    void bindLater(Label*, wasm::OldTrapDesc) { MOZ_CRASH(); }
     template <typename T> void j(Condition, T) { MOZ_CRASH(); }
     template <typename T> void jump(T) { MOZ_CRASH(); }
     void writeCodePointer(CodeOffset* label) { MOZ_CRASH(); }
     void haltingAlign(size_t) { MOZ_CRASH(); }
     void nopAlign(size_t) { MOZ_CRASH(); }
     void checkStackAlignment() { MOZ_CRASH(); }
     uint32_t currentOffset() { MOZ_CRASH(); }
     CodeOffset labelForPatch() { MOZ_CRASH(); }
--- a/js/src/jit/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -806,78 +806,78 @@ struct CallFarJump
 
     void offsetBy(size_t delta) {
         jump.offsetBy(delta);
     }
 };
 
 typedef Vector<CallFarJump, 0, SystemAllocPolicy> CallFarJumpVector;
 
-// The TrapDesc struct describes a wasm trap that is about to be emitted. This
+// The OldTrapDesc struct describes a wasm trap that is about to be emitted. This
 // includes the logical wasm bytecode offset to report, the kind of instruction
 // causing the trap, and the stack depth right before control is transferred to
 // the trap out-of-line path.
 
-struct TrapDesc : BytecodeOffset
+struct OldTrapDesc : BytecodeOffset
 {
     enum Kind { Jump, MemoryAccess };
     Kind kind;
     Trap trap;
     uint32_t framePushed;
 
-    TrapDesc(BytecodeOffset offset, Trap trap, uint32_t framePushed, Kind kind = Jump)
+    OldTrapDesc(BytecodeOffset offset, Trap trap, uint32_t framePushed, Kind kind = Jump)
       : BytecodeOffset(offset), kind(kind), trap(trap), framePushed(framePushed)
     {}
 };
 
-// A TrapSite captures all relevant information at the point of emitting the
+// An OldTrapSite captures all relevant information at the point of emitting the
 // in-line trapping instruction for the purpose of generating the out-of-line
 // trap code (at the end of the function).
 
-struct TrapSite : TrapDesc
+struct OldTrapSite : OldTrapDesc
 {
     uint32_t codeOffset;
 
-    TrapSite(TrapDesc trap, uint32_t codeOffset)
-      : TrapDesc(trap), codeOffset(codeOffset)
+    OldTrapSite(OldTrapDesc trap, uint32_t codeOffset)
+      : OldTrapDesc(trap), codeOffset(codeOffset)
     {}
 };
 
-typedef Vector<TrapSite, 0, SystemAllocPolicy> TrapSiteVector;
+typedef Vector<OldTrapSite, 0, SystemAllocPolicy> OldTrapSiteVector;
 
-// A TrapFarJump records the offset of a jump that needs to be patched to a trap
+// An OldTrapFarJump records the offset of a jump that needs to be patched to a trap
 // exit at the end of the module when trap exits are emitted.
 
-struct TrapFarJump
+struct OldTrapFarJump
 {
     Trap trap;
     jit::CodeOffset jump;
 
-    TrapFarJump(Trap trap, jit::CodeOffset jump)
+    OldTrapFarJump(Trap trap, jit::CodeOffset jump)
       : trap(trap), jump(jump)
     {}
 
     void offsetBy(size_t delta) {
         jump.offsetBy(delta);
     }
 };
 
-typedef Vector<TrapFarJump, 0, SystemAllocPolicy> TrapFarJumpVector;
+typedef Vector<OldTrapFarJump, 0, SystemAllocPolicy> OldTrapFarJumpVector;
 
 } // namespace wasm
 
 namespace jit {
 
 // The base class of all Assemblers for all archs.
 class AssemblerShared
 {
     wasm::CallSiteVector callSites_;
     wasm::CallSiteTargetVector callSiteTargets_;
-    wasm::TrapSiteVector trapSites_;
-    wasm::TrapFarJumpVector trapFarJumps_;
+    wasm::OldTrapSiteVector oldTrapSites_;
+    wasm::OldTrapFarJumpVector oldTrapFarJumps_;
     wasm::CallFarJumpVector callFarJumps_;
     wasm::MemoryAccessVector memoryAccesses_;
     wasm::SymbolicAccessVector symbolicAccesses_;
 
   protected:
     CodeLabelVector codeLabels_;
 
     bool enoughMemory_;
@@ -925,54 +925,54 @@ class AssemblerShared
     // WebAssembly metadata emitted by masm operations accumulated on the
     // MacroAssembler, and swapped into a wasm::CompiledCode after finish().
 
     template <typename... Args>
     void append(const wasm::CallSiteDesc& desc, CodeOffset retAddr, Args&&... args) {
         enoughMemory_ &= callSites_.emplaceBack(desc, retAddr.offset());
         enoughMemory_ &= callSiteTargets_.emplaceBack(mozilla::Forward<Args>(args)...);
     }
-    void append(wasm::TrapSite trapSite) {
-        enoughMemory_ &= trapSites_.append(trapSite);
+    void append(wasm::OldTrapSite trapSite) {
+        enoughMemory_ &= oldTrapSites_.append(trapSite);
     }
-    void append(wasm::TrapFarJump jmp) {
-        enoughMemory_ &= trapFarJumps_.append(jmp);
+    void append(wasm::OldTrapFarJump jmp) {
+        enoughMemory_ &= oldTrapFarJumps_.append(jmp);
     }
     void append(wasm::CallFarJump jmp) {
         enoughMemory_ &= callFarJumps_.append(jmp);
     }
     void append(wasm::MemoryAccess access) {
         enoughMemory_ &= memoryAccesses_.append(access);
     }
     void append(const wasm::MemoryAccessDesc& access, size_t codeOffset, size_t framePushed) {
         if (access.hasTrap()) {
             // If a memory access is trapping (wasm, SIMD.js, Atomics), create a
-            // TrapSite now which will generate a trap out-of-line path at the end
+            // OldTrapSite now which will generate a trap out-of-line path at the end
             // of the function which will *then* append a MemoryAccess.
-            wasm::TrapDesc trap(access.trapOffset(), wasm::Trap::OutOfBounds, framePushed,
-                                wasm::TrapSite::MemoryAccess);
-            append(wasm::TrapSite(trap, codeOffset));
+            wasm::OldTrapDesc trap(access.trapOffset(), wasm::Trap::OutOfBounds, framePushed,
+                                   wasm::OldTrapSite::MemoryAccess);
+            append(wasm::OldTrapSite(trap, codeOffset));
         } else {
             // Otherwise, this is a plain asm.js access. On WASM_HUGE_MEMORY
             // platforms, asm.js uses signal handlers to remove bounds checks
             // and thus requires a MemoryAccess.
             MOZ_ASSERT(access.isPlainAsmJS());
 #ifdef WASM_HUGE_MEMORY
             append(wasm::MemoryAccess(codeOffset));
 #endif
         }
     }
     void append(wasm::SymbolicAccess access) {
         enoughMemory_ &= symbolicAccesses_.append(access);
     }
 
     wasm::CallSiteVector& callSites() { return callSites_; }
     wasm::CallSiteTargetVector& callSiteTargets() { return callSiteTargets_; }
-    wasm::TrapSiteVector& trapSites() { return trapSites_; }
-    wasm::TrapFarJumpVector& trapFarJumps() { return trapFarJumps_; }
+    wasm::OldTrapSiteVector& oldTrapSites() { return oldTrapSites_; }
+    wasm::OldTrapFarJumpVector& oldTrapFarJumps() { return oldTrapFarJumps_; }
     wasm::CallFarJumpVector& callFarJumps() { return callFarJumps_; }
     wasm::MemoryAccessVector& memoryAccesses() { return memoryAccesses_; }
     wasm::SymbolicAccessVector& symbolicAccesses() { return symbolicAccesses_; }
 };
 
 } // namespace jit
 } // namespace js
 
--- a/js/src/jit/shared/CodeGenerator-shared.h
+++ b/js/src/jit/shared/CodeGenerator-shared.h
@@ -498,18 +498,18 @@ class CodeGeneratorShared : public LElem
     Label* labelForBackedgeWithImplicitCheck(MBasicBlock* mir);
 
 // This function is not used for MIPS. MIPS has branchToBlock.
 #if !defined(JS_CODEGEN_MIPS32) && !defined(JS_CODEGEN_MIPS64)
     void jumpToBlock(MBasicBlock* mir, Assembler::Condition cond);
 #endif
 
     template <class T>
-    wasm::TrapDesc trap(T* mir, wasm::Trap trap) {
-        return wasm::TrapDesc(mir->bytecodeOffset(), trap, masm.framePushed());
+    wasm::OldTrapDesc oldTrap(T* mir, wasm::Trap trap) {
+        return wasm::OldTrapDesc(mir->bytecodeOffset(), trap, masm.framePushed());
     }
 
   private:
     void generateInvalidateEpilogue();
 
   public:
     CodeGeneratorShared(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm);
 
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -280,28 +280,28 @@ CodeGeneratorX64::visitDivOrModI64(LDivO
     Label done;
 
     // Put the lhs in rax.
     if (lhs != rax)
         masm.mov(lhs, rax);
 
     // Handle divide by zero.
     if (lir->canBeDivideByZero()) {
-        masm.branchTestPtr(Assembler::Zero, rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero));
+        masm.branchTestPtr(Assembler::Zero, rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
     }
 
     // Handle an integer overflow exception from INT64_MIN / -1.
     if (lir->canBeNegativeOverflow()) {
         Label notmin;
         masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(INT64_MIN), &notmin);
         masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(-1), &notmin);
         if (lir->mir()->isMod())
             masm.xorl(output, output);
         else
-            masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
+            masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
         masm.jump(&done);
         masm.bind(&notmin);
     }
 
     // Sign extend the lhs into rdx to make rdx:rax.
     masm.cqo();
     masm.idivq(rhs);
 
@@ -323,17 +323,17 @@ CodeGeneratorX64::visitUDivOrModI64(LUDi
     // Put the lhs in rax.
     if (lhs != rax)
         masm.mov(lhs, rax);
 
     Label done;
 
     // Prevent divide by zero.
     if (lir->canBeDivideByZero())
-        masm.branchTestPtr(Assembler::Zero, rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero));
+        masm.branchTestPtr(Assembler::Zero, rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
 
     // Zero extend the lhs into rdx to make (rdx:rax).
     masm.xorl(rdx, rdx);
     masm.udivq(rhs);
 
     masm.bind(&done);
 }
 
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -917,22 +917,22 @@ class AssemblerX86Shared : public Assemb
   public:
     void nop() { masm.nop(); }
     void nop(size_t n) { masm.insert_nop(n); }
     void j(Condition cond, Label* label) { jSrc(cond, label); }
     void jmp(Label* label) { jmpSrc(label); }
     void j(Condition cond, RepatchLabel* label) { jSrc(cond, label); }
     void jmp(RepatchLabel* label) { jmpSrc(label); }
 
-    void j(Condition cond, wasm::TrapDesc target) {
+    void j(Condition cond, wasm::OldTrapDesc target) {
         Label l;
         j(cond, &l);
         bindLater(&l, target);
     }
-    void jmp(wasm::TrapDesc target) {
+    void jmp(wasm::OldTrapDesc target) {
         Label l;
         jmp(&l);
         bindLater(&l, target);
     }
 
     void jmp(const Operand& op) {
         switch (op.kind()) {
           case Operand::MEM_REG_DISP:
@@ -958,21 +958,21 @@ class AssemblerX86Shared : public Assemb
                 JmpSrc next;
                 more = masm.nextJump(jmp, &next);
                 masm.linkJump(jmp, dst);
                 jmp = next;
             } while (more);
         }
         label->bind(dst.offset());
     }
-    void bindLater(Label* label, wasm::TrapDesc target) {
+    void bindLater(Label* label, wasm::OldTrapDesc target) {
         if (label->used()) {
             JmpSrc jmp(label->offset());
             do {
-                append(wasm::TrapSite(target, jmp.offset()));
+                append(wasm::OldTrapSite(target, jmp.offset()));
             } while (masm.nextJump(jmp, &jmp));
         }
         label->reset();
     }
     void bind(RepatchLabel* label) {
         JmpDst dst(masm.label());
         if (label->used()) {
             JmpSrc jmp(label->offset());
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -430,17 +430,17 @@ CodeGeneratorX86Shared::visitWasmAddOffs
     MWasmAddOffset* mir = lir->mir();
     Register base = ToRegister(lir->base());
     Register out = ToRegister(lir->output());
 
     if (base != out)
         masm.move32(base, out);
     masm.add32(Imm32(mir->offset()), out);
 
-    masm.j(Assembler::CarrySet, trap(mir, wasm::Trap::OutOfBounds));
+    masm.j(Assembler::CarrySet, oldTrap(mir, wasm::Trap::OutOfBounds));
 }
 
 void
 CodeGeneratorX86Shared::visitWasmTruncateToInt32(LWasmTruncateToInt32* lir)
 {
     FloatRegister input = ToFloatRegister(lir->input());
     Register output = ToRegister(lir->output());
 
@@ -1021,17 +1021,17 @@ CodeGeneratorX86Shared::visitUDivOrMod(L
     if (lhs != eax)
         masm.mov(lhs, eax);
 
     // Prevent divide by zero.
     if (ins->canBeDivideByZero()) {
         masm.test32(rhs, rhs);
         if (ins->mir()->isTruncated()) {
             if (ins->trapOnError()) {
-                masm.j(Assembler::Zero, trap(ins, wasm::Trap::IntegerDivideByZero));
+                masm.j(Assembler::Zero, oldTrap(ins, wasm::Trap::IntegerDivideByZero));
             } else {
                 ool = new(alloc()) ReturnZero(output);
                 masm.j(Assembler::Zero, ool->entry());
             }
         } else {
             bailoutIf(Assembler::Zero, ins->snapshot());
         }
     }
@@ -1069,17 +1069,17 @@ CodeGeneratorX86Shared::visitUDivOrModCo
     // This emits the division answer into edx or the modulus answer into eax.
     MOZ_ASSERT(output == eax || output == edx);
     MOZ_ASSERT(lhs != eax && lhs != edx);
     bool isDiv = (output == edx);
 
     if (d == 0) {
         if (ins->mir()->isTruncated()) {
             if (ins->trapOnError())
-                masm.jump(trap(ins, wasm::Trap::IntegerDivideByZero));
+                masm.jump(oldTrap(ins, wasm::Trap::IntegerDivideByZero));
             else
                 masm.xorl(output, output);
         } else {
             bailout(ins->snapshot());
         }
         return;
     }
 
@@ -1208,17 +1208,17 @@ CodeGeneratorX86Shared::visitDivPowTwoI(
     }
 
     if (negativeDivisor) {
         // INT32_MIN / -1 overflows.
         masm.negl(lhs);
         if (!mir->isTruncated())
             bailoutIf(Assembler::Overflow, ins->snapshot());
         else if (mir->trapOnError())
-            masm.j(Assembler::Overflow, trap(mir, wasm::Trap::IntegerOverflow));
+            masm.j(Assembler::Overflow, oldTrap(mir, wasm::Trap::IntegerOverflow));
     } else if (mir->isUnsigned() && !mir->isTruncated()) {
         // Unsigned division by 1 can overflow if output is not
         // truncated.
         masm.test32(lhs, lhs);
         bailoutIf(Assembler::Signed, ins->snapshot());
     }
 }
 
@@ -1327,17 +1327,17 @@ CodeGeneratorX86Shared::visitDivI(LDivI*
     // divide case.
     if (lhs != eax)
         masm.mov(lhs, eax);
 
     // Handle divide by zero.
     if (mir->canBeDivideByZero()) {
         masm.test32(rhs, rhs);
         if (mir->trapOnError()) {
-            masm.j(Assembler::Zero, trap(mir, wasm::Trap::IntegerDivideByZero));
+            masm.j(Assembler::Zero, oldTrap(mir, wasm::Trap::IntegerDivideByZero));
         } else if (mir->canTruncateInfinities()) {
             // Truncated division by zero is zero (Infinity|0 == 0)
             if (!ool)
                 ool = new(alloc()) ReturnZero(output);
             masm.j(Assembler::Zero, ool->entry());
         } else {
             MOZ_ASSERT(mir->fallible());
             bailoutIf(Assembler::Zero, ins->snapshot());
@@ -1346,17 +1346,17 @@ CodeGeneratorX86Shared::visitDivI(LDivI*
 
     // Handle an integer overflow exception from -2147483648 / -1.
     if (mir->canBeNegativeOverflow()) {
         Label notmin;
         masm.cmp32(lhs, Imm32(INT32_MIN));
         masm.j(Assembler::NotEqual, &notmin);
         masm.cmp32(rhs, Imm32(-1));
         if (mir->trapOnError()) {
-            masm.j(Assembler::Equal, trap(mir, wasm::Trap::IntegerOverflow));
+            masm.j(Assembler::Equal, oldTrap(mir, wasm::Trap::IntegerOverflow));
         } else if (mir->canTruncateOverflow()) {
             // (-INT32_MIN)|0 == INT32_MIN and INT32_MIN is already in the
             // output register (lhs == eax).
             masm.j(Assembler::Equal, &done);
         } else {
             MOZ_ASSERT(mir->fallible());
             bailoutIf(Assembler::Equal, ins->snapshot());
         }
@@ -1496,17 +1496,17 @@ CodeGeneratorX86Shared::visitModI(LModI*
 
     MMod* mir = ins->mir();
 
     // Prevent divide by zero.
     if (mir->canBeDivideByZero()) {
         masm.test32(rhs, rhs);
         if (mir->isTruncated()) {
             if (mir->trapOnError()) {
-                masm.j(Assembler::Zero, trap(mir, wasm::Trap::IntegerDivideByZero));
+                masm.j(Assembler::Zero, oldTrap(mir, wasm::Trap::IntegerDivideByZero));
             } else {
                 if (!ool)
                     ool = new(alloc()) ReturnZero(edx);
                 masm.j(Assembler::Zero, ool->entry());
             }
         } else {
             bailoutIf(Assembler::Zero, ins->snapshot());
         }
@@ -2518,17 +2518,17 @@ CodeGeneratorX86Shared::visitOutOfLineSi
     masm.vcmpleps(Operand(input), scratch, scratch);
     masm.vmovmskps(scratch, temp);
     masm.cmp32(temp, Imm32(0));
     masm.j(Assembler::NotEqual, &onConversionError);
 
     masm.jump(ool->rejoin());
 
     if (gen->compilingWasm()) {
-        masm.bindLater(&onConversionError, trap(ool, wasm::Trap::ImpreciseSimdConversion));
+        masm.bindLater(&onConversionError, oldTrap(ool, wasm::Trap::ImpreciseSimdConversion));
     } else {
         masm.bind(&onConversionError);
         bailout(ool->ins()->snapshot());
     }
 }
 
 // Convert Float32x4 to Uint32x4.
 //
@@ -2598,17 +2598,17 @@ CodeGeneratorX86Shared::visitFloat32x4To
 
     // We still need to filter out the V-lanes. They would show up as 0x80000000
     // in both A and B. Since we cleared the valid A-lanes in B, the V-lanes are
     // the remaining negative lanes in B.
     masm.vmovmskps(scratch, temp);
     masm.cmp32(temp, Imm32(0));
 
     if (gen->compilingWasm())
-        masm.j(Assembler::NotEqual, trap(mir, wasm::Trap::ImpreciseSimdConversion));
+        masm.j(Assembler::NotEqual, oldTrap(mir, wasm::Trap::ImpreciseSimdConversion));
     else
         bailoutIf(Assembler::NotEqual, ins->snapshot());
 }
 
 void
 CodeGeneratorX86Shared::visitSimdValueInt32x4(LSimdValueInt32x4* ins)
 {
     MOZ_ASSERT(ins->mir()->type() == MIRType::Int32x4 || ins->mir()->type() == MIRType::Bool32x4);
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -681,20 +681,20 @@ struct MOZ_RAII AutoHandleWasmTruncateTo
 
     explicit AutoHandleWasmTruncateToIntErrors(MacroAssembler& masm, wasm::BytecodeOffset off)
       : masm(masm), off(off)
     { }
 
     ~AutoHandleWasmTruncateToIntErrors() {
         // Handle errors.
         masm.bind(&fail);
-        masm.jump(wasm::TrapDesc(off, wasm::Trap::IntegerOverflow, masm.framePushed()));
+        masm.jump(wasm::OldTrapDesc(off, wasm::Trap::IntegerOverflow, masm.framePushed()));
 
         masm.bind(&inputIsNaN);
-        masm.jump(wasm::TrapDesc(off, wasm::Trap::InvalidConversionToInteger, masm.framePushed()));
+        masm.jump(wasm::OldTrapDesc(off, wasm::Trap::InvalidConversionToInteger, masm.framePushed()));
     }
 };
 
 void
 MacroAssembler::wasmTruncateDoubleToInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     vcvttsd2si(input, output);
     cmp32(output, Imm32(1));
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h
@@ -197,17 +197,17 @@ class MacroAssemblerX86Shared : public A
         jmp(label);
     }
     void jump(Register reg) {
         jmp(Operand(reg));
     }
     void jump(const Address& addr) {
         jmp(Operand(addr));
     }
-    void jump(wasm::TrapDesc target) {
+    void jump(wasm::OldTrapDesc target) {
         jmp(target);
     }
 
     void convertInt32ToDouble(Register src, FloatRegister dest) {
         // vcvtsi2sd and friends write only part of their output register, which
         // causes slowdowns on out-of-order processors. Explicitly break
         // dependencies with vxorpd (and vxorps elsewhere), which are handled
         // specially in modern CPUs, for this purpose. See sections 8.14, 9.8,
--- a/js/src/jit/x86/CodeGenerator-x86.cpp
+++ b/js/src/jit/x86/CodeGenerator-x86.cpp
@@ -1026,29 +1026,29 @@ CodeGeneratorX86::visitDivOrModI64(LDivO
     Register64 output = ToOutRegister64(lir);
 
     MOZ_ASSERT(output == ReturnReg64);
 
     Label done;
 
     // Handle divide by zero.
     if (lir->canBeDivideByZero())
-        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
+        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
 
     MDefinition* mir = lir->mir();
 
     // Handle an integer overflow exception from INT64_MIN / -1.
     if (lir->canBeNegativeOverflow()) {
         Label notmin;
         masm.branch64(Assembler::NotEqual, lhs, Imm64(INT64_MIN), &notmin);
         masm.branch64(Assembler::NotEqual, rhs, Imm64(-1), &notmin);
         if (mir->isMod())
             masm.xor64(output, output);
         else
-            masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
+            masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
         masm.jump(&done);
         masm.bind(&notmin);
     }
 
     masm.setupWasmABICall();
     masm.passABIArg(lhs.high);
     masm.passABIArg(lhs.low);
     masm.passABIArg(rhs.high);
@@ -1074,17 +1074,17 @@ CodeGeneratorX86::visitUDivOrModI64(LUDi
     Register64 rhs = ToRegister64(lir->getInt64Operand(LDivOrModI64::Rhs));
     Register temp = ToRegister(lir->temp());
     Register64 output = ToOutRegister64(lir);
 
     MOZ_ASSERT(output == ReturnReg64);
 
     // Prevent divide by zero.
     if (lir->canBeDivideByZero())
-        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
+        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
 
     masm.setupWasmABICall();
     masm.passABIArg(lhs.high);
     masm.passABIArg(lhs.low);
     masm.passABIArg(rhs.high);
     masm.passABIArg(rhs.low);
 
     MOZ_ASSERT(gen->compilingWasm());
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -15,16 +15,19 @@
 #include "js/GCVector.h"
 #include "js/Result.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 #include "threading/ProtectedData.h"
 #include "vm/ErrorReporting.h"
 #include "vm/MallocProvider.h"
 #include "vm/Runtime.h"
+#ifdef XP_DARWIN
+# include "wasm/WasmSignalHandlers.h"
+#endif
 
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
 #endif
 
 struct DtoaState;
 
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -17,19 +17,16 @@
 #include "mozilla/ThreadLocal.h"
 #include "mozilla/Vector.h"
 
 #include <setjmp.h>
 
 #include "jsatom.h"
 #include "jsscript.h"
 
-#ifdef XP_DARWIN
-# include "wasm/WasmSignalHandlers.h"
-#endif
 #include "builtin/AtomicsObject.h"
 #include "builtin/Intl.h"
 #include "builtin/Promise.h"
 #include "frontend/NameCollections.h"
 #include "gc/GCRuntime.h"
 #include "gc/Tracer.h"
 #include "gc/ZoneGroup.h"
 #include "irregexp/RegExpStack.h"
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1704,17 +1704,17 @@ jit::JitActivation::startWasmInterrupt(c
 
     // Execution can only be interrupted in function code. Afterwards, control
     // flow does not reenter function code and thus there should be no
     // interrupt-during-interrupt.
     MOZ_ASSERT(!isWasmInterrupted());
 
     bool ignoredUnwound;
     wasm::UnwindState unwindState;
-    MOZ_ALWAYS_TRUE(wasm::StartUnwinding(*this, state, &unwindState, &ignoredUnwound));
+    MOZ_ALWAYS_TRUE(wasm::StartUnwinding(state, &unwindState, &ignoredUnwound));
 
     void* pc = unwindState.pc;
     MOZ_ASSERT(wasm::LookupCode(pc)->lookupRange(pc)->isFunction());
 
     cx_->runtime()->startWasmInterrupt(state.pc, pc);
     setWasmExitFP(unwindState.fp);
 
     MOZ_ASSERT(compartment() == unwindState.fp->tls->instance->compartment());
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -3015,17 +3015,17 @@ class BaseCompiler final : public BaseCo
         // maintain the invariant that, when debugEnabled_, all wasm::Frames
         // are valid wasm::DebugFrames which is observable by WasmHandleThrow.
         masm.bind(&stackOverflowLabel_);
         uint32_t debugFrameReserved = debugEnabled_ ? DebugFrame::offsetOfFrame() : 0;
         MOZ_ASSERT(fr.initialSize() >= debugFrameReserved);
         if (fr.initialSize() > debugFrameReserved)
             masm.addToStackPtr(Imm32(fr.initialSize() - debugFrameReserved));
         BytecodeOffset prologueTrapOffset(func_.lineOrBytecode);
-        masm.jump(TrapDesc(prologueTrapOffset, Trap::StackOverflow, debugFrameReserved));
+        masm.jump(OldTrapDesc(prologueTrapOffset, Trap::StackOverflow, debugFrameReserved));
 
         masm.bind(&returnLabel_);
 
         if (debugEnabled_) {
             // Store and reload the return value from DebugFrame::return so that
             // it can be clobbered, and/or modified by the debug trap.
             saveResult();
             insertBreakablePoint(CallSiteDesc::Breakpoint);
@@ -3040,17 +3040,17 @@ class BaseCompiler final : public BaseCo
 
         // Note the end of the inline code and start of the OOL code.
         //gen->perfSpewer().noteEndInlineCode(masm);
 #endif
 
         if (!generateOutOfLineCode())
             return false;
 
-        masm.wasmEmitTrapOutOfLineCode();
+        masm.wasmEmitOldTrapOutOfLineCode();
 
         offsets_.end = masm.currentOffset();
 
         if (!fr.checkStackHeight())
             return false;
 
         return !masm.oom();
     }
@@ -3448,46 +3448,46 @@ class BaseCompiler final : public BaseCo
 
     void returnCleanup(bool popStack) {
         if (popStack)
             fr.popStackBeforeBranch(controlOutermost().stackHeight);
         masm.jump(&returnLabel_);
     }
 
     void checkDivideByZeroI32(RegI32 rhs, RegI32 srcDest, Label* done) {
-        masm.branchTest32(Assembler::Zero, rhs, rhs, trap(Trap::IntegerDivideByZero));
+        masm.branchTest32(Assembler::Zero, rhs, rhs, oldTrap(Trap::IntegerDivideByZero));
     }
 
     void checkDivideByZeroI64(RegI64 r) {
         ScratchI32 scratch(*this);
-        masm.branchTest64(Assembler::Zero, r, r, scratch, trap(Trap::IntegerDivideByZero));
+        masm.branchTest64(Assembler::Zero, r, r, scratch, oldTrap(Trap::IntegerDivideByZero));
     }
 
     void checkDivideSignedOverflowI32(RegI32 rhs, RegI32 srcDest, Label* done, bool zeroOnOverflow) {
         Label notMin;
         masm.branch32(Assembler::NotEqual, srcDest, Imm32(INT32_MIN), &notMin);
         if (zeroOnOverflow) {
             masm.branch32(Assembler::NotEqual, rhs, Imm32(-1), &notMin);
             moveImm32(0, srcDest);
             masm.jump(done);
         } else {
-            masm.branch32(Assembler::Equal, rhs, Imm32(-1), trap(Trap::IntegerOverflow));
+            masm.branch32(Assembler::Equal, rhs, Imm32(-1), oldTrap(Trap::IntegerOverflow));
         }
         masm.bind(&notMin);
     }
 
     void checkDivideSignedOverflowI64(RegI64 rhs, RegI64 srcDest, Label* done, bool zeroOnOverflow) {
         Label notmin;
         masm.branch64(Assembler::NotEqual, srcDest, Imm64(INT64_MIN), &notmin);
         masm.branch64(Assembler::NotEqual, rhs, Imm64(-1), &notmin);
         if (zeroOnOverflow) {
             masm.xor64(srcDest, srcDest);
             masm.jump(done);
         } else {
-            masm.jump(trap(Trap::IntegerOverflow));
+            masm.jump(oldTrap(Trap::IntegerOverflow));
         }
         masm.bind(&notmin);
     }
 
 #ifndef RABALDR_INT_DIV_I64_CALLOUT
     void quotientI64(RegI64 rhs, RegI64 srcDest, RegI64 reserved, IsUnsigned isUnsigned,
                      bool isConst, int64_t c)
     {
@@ -3804,17 +3804,17 @@ class BaseCompiler final : public BaseCo
         masm.or32(src.high, src.low);
         masm.cmp32(src.low, Imm32(0));
         masm.emitSet(Assembler::Equal, dest);
 #endif
     }
 
     void unreachableTrap()
     {
-        masm.jump(trap(Trap::Unreachable));
+        masm.jump(oldTrap(Trap::Unreachable));
 #ifdef DEBUG
         masm.breakpoint();
 #endif
     }
 
 
     MOZ_MUST_USE bool
     supportsRoundInstruction(RoundingMode mode)
@@ -3935,28 +3935,28 @@ class BaseCompiler final : public BaseCo
     void prepareMemoryAccess(MemoryAccessDesc* access, AccessCheck* check, RegI32 tls, RegI32 ptr) {
 
         // Fold offset if necessary for further computations.
 
         if (access->offset() >= OffsetGuardLimit ||
             (access->isAtomic() && !check->omitAlignmentCheck && !check->onlyPointerAlignment))
         {
             masm.branchAdd32(Assembler::CarrySet, Imm32(access->offset()), ptr,
-                             trap(Trap::OutOfBounds));
+                             oldTrap(Trap::OutOfBounds));
             access->clearOffset();
             check->onlyPointerAlignment = true;
         }
 
         // Alignment check if required.
 
         if (access->isAtomic() && !check->omitAlignmentCheck) {
             MOZ_ASSERT(check->onlyPointerAlignment);
             // We only care about the low pointer bits here.
             masm.branchTest32(Assembler::NonZero, ptr, Imm32(access->byteSize() - 1),
-                              trap(Trap::UnalignedAccess));
+                              oldTrap(Trap::UnalignedAccess));
         }
 
         // Ensure no tls if we don't need it.
 
 #ifdef WASM_HUGE_MEMORY
         // We have HeapReg and no bounds checking and need load neither
         // memoryBase nor boundsCheckLimit from tls.
         MOZ_ASSERT_IF(check->omitBoundsCheck, tls.isInvalid());
@@ -3967,17 +3967,17 @@ class BaseCompiler final : public BaseCo
 #endif
 
         // Bounds check if required.
 
 #ifndef WASM_HUGE_MEMORY
         if (!check->omitBoundsCheck) {
             masm.wasmBoundsCheck(Assembler::AboveOrEqual, ptr,
                                  Address(tls, offsetof(TlsData, boundsCheckLimit)),
-                                 trap(Trap::OutOfBounds));
+                                 oldTrap(Trap::OutOfBounds));
         }
 #endif
     }
 
 #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM)
     BaseIndex prepareAtomicMemoryAccess(MemoryAccessDesc* access, AccessCheck* check, RegI32 tls,
                                         RegI32 ptr)
     {
@@ -4900,21 +4900,21 @@ class BaseCompiler final : public BaseCo
     bool done() const {
         return iter_.done();
     }
 
     BytecodeOffset bytecodeOffset() const {
         return iter_.bytecodeOffset();
     }
 
-    TrapDesc trap(Trap t) const {
+    OldTrapDesc oldTrap(Trap t) const {
         // Use masm.framePushed() because the value needed by the trap machinery
         // is the size of the frame overall, not the height of the stack area of
         // the frame.
-        return TrapDesc(bytecodeOffset(), t, masm.framePushed());
+        return OldTrapDesc(bytecodeOffset(), t, masm.framePushed());
     }
 
     ////////////////////////////////////////////////////////////
     //
     // Machinery for optimized conditional branches.
     //
     // To disable this optimization it is enough always to return false from
     // sniffConditionalControl{Cmp,Eqz}.
@@ -8390,17 +8390,17 @@ BaseCompiler::emitWait(ValType type, uin
         emitInstanceCall(lineOrBytecode, SigPIIL_, ExprType::I32, SymbolicAddress::WaitI32);
         break;
       case ValType::I64:
         emitInstanceCall(lineOrBytecode, SigPILL_, ExprType::I32, SymbolicAddress::WaitI64);
         break;
       default:
         MOZ_CRASH();
     }
-    masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, trap(Trap::ThrowReported));
+    masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, oldTrap(Trap::ThrowReported));
 
     return true;
 }
 
 bool
 BaseCompiler::emitWake()
 {
     uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
@@ -8409,17 +8409,17 @@ BaseCompiler::emitWake()
     LinearMemoryAddress<Nothing> addr;
     if (!iter_.readWake(&addr, &nothing))
         return false;
 
     if (deadCode_)
         return true;
 
     emitInstanceCall(lineOrBytecode, SigPII_, ExprType::I32, SymbolicAddress::Wake);
-    masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, trap(Trap::ThrowReported));
+    masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, oldTrap(Trap::ThrowReported));
 
     return true;
 }
 
 bool
 BaseCompiler::emitBody()
 {
     if (!iter_.readFunctionStart(sig().ret()))
--- a/js/src/wasm/WasmBuiltins.cpp
+++ b/js/src/wasm/WasmBuiltins.cpp
@@ -91,50 +91,55 @@ WasmHandleExecutionInterrupt()
     activation->finishWasmInterrupt();
     return resumePC;
 }
 
 static bool
 WasmHandleDebugTrap()
 {
     JitActivation* activation = CallingActivation();
-    MOZ_ASSERT(activation);
     JSContext* cx = activation->cx();
+    Frame* fp = activation->wasmExitFP();
+    Instance* instance = fp->tls->instance;
+    const Code& code = instance->code();
+    MOZ_ASSERT(code.metadata().debugEnabled);
 
-    WasmFrameIter frame(activation);
-    MOZ_ASSERT(frame.debugEnabled());
-    const CallSite* site = frame.debugTrapCallsite();
+    // The debug trap stub is the innermost frame. It's return address is the
+    // actual trap site.
+    const CallSite* site = code.lookupCallSite(fp->returnAddress);
     MOZ_ASSERT(site);
+
+    // Advance to the actual trapping frame.
+    fp = fp->callerFP;
+    DebugFrame* debugFrame = DebugFrame::from(fp);
+
     if (site->kind() == CallSite::EnterFrame) {
-        if (!frame.instance()->enterFrameTrapsEnabled())
+        if (!instance->enterFrameTrapsEnabled())
             return true;
-        DebugFrame* debugFrame = frame.debugFrame();
         debugFrame->setIsDebuggee();
         debugFrame->observe(cx);
         // TODO call onEnterFrame
         JSTrapStatus status = Debugger::onEnterFrame(cx, debugFrame);
         if (status == JSTRAP_RETURN) {
             // Ignoring forced return (JSTRAP_RETURN) -- changing code execution
             // order is not yet implemented in the wasm baseline.
             // TODO properly handle JSTRAP_RETURN and resume wasm execution.
             JS_ReportErrorASCII(cx, "Unexpected resumption value from onEnterFrame");
             return false;
         }
         return status == JSTRAP_CONTINUE;
     }
     if (site->kind() == CallSite::LeaveFrame) {
-        DebugFrame* debugFrame = frame.debugFrame();
         debugFrame->updateReturnJSValue();
         bool ok = Debugger::onLeaveFrame(cx, debugFrame, nullptr, true);
         debugFrame->leave(cx);
         return ok;
     }
 
-    DebugFrame* debugFrame = frame.debugFrame();
-    DebugState& debug = frame.instance()->debug();
+    DebugState& debug = instance->debug();
     MOZ_ASSERT(debug.hasBreakpointTrapAtOffset(site->lineOrBytecode()));
     if (debug.stepModeEnabled(debugFrame->funcIndex())) {
         RootedValue result(cx, UndefinedValue());
         JSTrapStatus status = Debugger::onSingleStep(cx, &result);
         if (status == JSTRAP_RETURN) {
             // TODO properly handle JSTRAP_RETURN.
             JS_ReportErrorASCII(cx, "Unexpected resumption value from onSingleStep");
             return false;
@@ -229,17 +234,17 @@ WasmHandleThrow()
 {
     JitActivation* activation = CallingActivation();
     JSContext* cx = activation->cx();
     WasmFrameIter iter(activation);
     return HandleThrow(cx, iter);
 }
 
 static void
-WasmReportTrap(int32_t trapIndex)
+WasmOldReportTrap(int32_t trapIndex)
 {
     JSContext* cx = TlsContext.get();
 
     MOZ_ASSERT(trapIndex < int32_t(Trap::Limit) && trapIndex >= 0);
     Trap trap = Trap(trapIndex);
 
     unsigned errorNumber;
     switch (trap) {
@@ -434,19 +439,19 @@ AddressOf(SymbolicAddress imm, ABIFuncti
         *abiType = Args_General0;
         return FuncCast(WasmHandleExecutionInterrupt, *abiType);
       case SymbolicAddress::HandleDebugTrap:
         *abiType = Args_General0;
         return FuncCast(WasmHandleDebugTrap, *abiType);
       case SymbolicAddress::HandleThrow:
         *abiType = Args_General0;
         return FuncCast(WasmHandleThrow, *abiType);
-      case SymbolicAddress::ReportTrap:
+      case SymbolicAddress::OldReportTrap:
         *abiType = Args_General1;
-        return FuncCast(WasmReportTrap, *abiType);
+        return FuncCast(WasmOldReportTrap, *abiType);
       case SymbolicAddress::ReportOutOfBounds:
         *abiType = Args_General0;
         return FuncCast(WasmReportOutOfBounds, *abiType);
       case SymbolicAddress::ReportUnalignedAccess:
         *abiType = Args_General0;
         return FuncCast(WasmReportUnalignedAccess, *abiType);
       case SymbolicAddress::CallImport_Void:
         *abiType = Args_General4;
@@ -590,17 +595,17 @@ bool
 wasm::NeedsBuiltinThunk(SymbolicAddress sym)
 {
     // Some functions don't want to a thunk, because they already have one or
     // they don't have frame info.
     switch (sym) {
       case SymbolicAddress::HandleExecutionInterrupt: // GenerateInterruptExit
       case SymbolicAddress::HandleDebugTrap:          // GenerateDebugTrapStub
       case SymbolicAddress::HandleThrow:              // GenerateThrowStub
-      case SymbolicAddress::ReportTrap:               // GenerateTrapExit
+      case SymbolicAddress::OldReportTrap:            // GenerateOldTrapExit
       case SymbolicAddress::ReportOutOfBounds:        // GenerateOutOfBoundsExit
       case SymbolicAddress::ReportUnalignedAccess:    // GeneratesUnalignedExit
       case SymbolicAddress::CallImport_Void:          // GenerateImportInterpExit
       case SymbolicAddress::CallImport_I32:
       case SymbolicAddress::CallImport_I64:
       case SymbolicAddress::CallImport_F64:
       case SymbolicAddress::CoerceInPlace_ToInt32:    // GenerateImportJitExit
       case SymbolicAddress::CoerceInPlace_ToNumber:
@@ -886,18 +891,18 @@ wasm::EnsureBuiltinThunksInitialized()
     masm.executableCopy(thunks->codeBase, /* flushICache = */ false);
     memset(thunks->codeBase + masm.bytesNeeded(), 0, allocSize - masm.bytesNeeded());
 
     masm.processCodeLabels(thunks->codeBase);
 #ifdef DEBUG
     MOZ_ASSERT(masm.callSites().empty());
     MOZ_ASSERT(masm.callSiteTargets().empty());
     MOZ_ASSERT(masm.callFarJumps().empty());
-    MOZ_ASSERT(masm.trapSites().empty());
-    MOZ_ASSERT(masm.trapFarJumps().empty());
+    MOZ_ASSERT(masm.oldTrapSites().empty());
+    MOZ_ASSERT(masm.oldTrapFarJumps().empty());
     MOZ_ASSERT(masm.callFarJumps().empty());
     MOZ_ASSERT(masm.memoryAccesses().empty());
     MOZ_ASSERT(masm.symbolicAccesses().empty());
 #endif
 
     ExecutableAllocator::cacheFlush(thunks->codeBase, thunks->codeSize);
     if (!ExecutableAllocator::makeExecutable(thunks->codeBase, thunks->codeSize))
         return false;
--- a/js/src/wasm/WasmCode.cpp
+++ b/js/src/wasm/WasmCode.cpp
@@ -762,56 +762,16 @@ struct CallSiteRetAddrOffset
 {
     const CallSiteVector& callSites;
     explicit CallSiteRetAddrOffset(const CallSiteVector& callSites) : callSites(callSites) {}
     uint32_t operator[](size_t index) const {
         return callSites[index].returnAddressOffset();
     }
 };
 
-size_t
-Code::serializedSize() const
-{
-    return metadata().serializedSize() +
-           segment(Tier::Serialized).serializedSize();
-}
-
-uint8_t*
-Code::serialize(uint8_t* cursor, const LinkData& linkData) const
-{
-    MOZ_RELEASE_ASSERT(!metadata().debugEnabled);
-
-    cursor = metadata().serialize(cursor);
-    cursor = segment(Tier::Serialized).serialize(cursor, linkData.linkData(Tier::Serialized));
-    return cursor;
-}
-
-const uint8_t*
-Code::deserialize(const uint8_t* cursor, const SharedBytes& bytecode, const LinkData& linkData,
-                  Metadata& metadata)
-{
-    cursor = metadata.deserialize(cursor);
-    if (!cursor)
-        return nullptr;
-
-    UniqueCodeSegment codeSegment = js::MakeUnique<CodeSegment>();
-    if (!codeSegment)
-        return nullptr;
-
-    cursor = codeSegment->deserialize(cursor, *bytecode, linkData.linkData(Tier::Serialized),
-                                      metadata);
-    if (!cursor)
-        return nullptr;
-
-    segment1_ = takeOwnership(Move(codeSegment));
-    metadata_ = &metadata;
-
-    return cursor;
-}
-
 const CallSite*
 Code::lookupCallSite(void* returnAddress) const
 {
     for (auto t : tiers()) {
         uint32_t target = ((uint8_t*)returnAddress) - segment(t).base();
         size_t lowerBound = 0;
         size_t upperBound = metadata(t).callSites.length();
 
@@ -954,8 +914,48 @@ Code::addSizeOfMiscIfNotSeen(MallocSizeO
 
     *data += mallocSizeOf(this) +
              metadata().sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenMetadata) +
              profilingLabels_.lock()->sizeOfExcludingThis(mallocSizeOf);
 
     for (auto t : tiers())
         segment(t).addSizeOfMisc(mallocSizeOf, code, data);
 }
+
+size_t
+Code::serializedSize() const
+{
+    return metadata().serializedSize() +
+           segment(Tier::Serialized).serializedSize();
+}
+
+uint8_t*
+Code::serialize(uint8_t* cursor, const LinkData& linkData) const
+{
+    MOZ_RELEASE_ASSERT(!metadata().debugEnabled);
+
+    cursor = metadata().serialize(cursor);
+    cursor = segment(Tier::Serialized).serialize(cursor, linkData.linkData(Tier::Serialized));
+    return cursor;
+}
+
+const uint8_t*
+Code::deserialize(const uint8_t* cursor, const SharedBytes& bytecode, const LinkData& linkData,
+                  Metadata& metadata)
+{
+    cursor = metadata.deserialize(cursor);
+    if (!cursor)
+        return nullptr;
+
+    UniqueCodeSegment codeSegment = js::MakeUnique<CodeSegment>();
+    if (!codeSegment)
+        return nullptr;
+
+    cursor = codeSegment->deserialize(cursor, *bytecode, linkData.linkData(Tier::Serialized),
+                                      metadata);
+    if (!cursor)
+        return nullptr;
+
+    segment1_ = takeOwnership(Move(codeSegment));
+    metadata_ = &metadata;
+
+    return cursor;
+}
--- a/js/src/wasm/WasmCode.h
+++ b/js/src/wasm/WasmCode.h
@@ -125,17 +125,17 @@ class CodeSegment
                                     const LinkDataTier& linkData,
                                     const Metadata& metadata);
 
     void initCode(const Code* code) {
         MOZ_ASSERT(!code_);
         code_ = code;
     }
 
-    const Code* code() const { MOZ_ASSERT(code_); return code_; }
+    const Code& code() const { MOZ_ASSERT(code_); return *code_; }
     Tier tier() const { return tier_; }
 
     uint8_t* base() const { return bytes_.get(); }
     uint32_t length() const { return length_; }
 
     uint8_t* interruptCode() const { return interruptCode_; }
     uint8_t* outOfBoundsCode() const { return outOfBoundsCode_; }
     uint8_t* unalignedAccessCode() const { return unalignedAccessCode_; }
--- a/js/src/wasm/WasmFrameIter.cpp
+++ b/js/src/wasm/WasmFrameIter.cpp
@@ -30,48 +30,50 @@ using mozilla::DebugOnly;
 using mozilla::Swap;
 
 /*****************************************************************************/
 // WasmFrameIter implementation
 
 WasmFrameIter::WasmFrameIter(JitActivation* activation, wasm::Frame* fp)
   : activation_(activation),
     code_(nullptr),
-    callsite_(nullptr),
     codeRange_(nullptr),
+    lineOrBytecode_(0),
     fp_(fp ? fp : activation->wasmExitFP()),
     unwind_(Unwind::False)
 {
     MOZ_ASSERT(fp_);
 
-    // Normally, execution exits wasm code via an exit stub which sets exitFP
-    // to the exit stub's frame. Thus, in this case, we want to start iteration
-    // at the caller of the exit frame, whose Code, CodeRange and CallSite are
-    // indicated by the returnAddress of the exit stub's frame.
-
-    if (!activation->isWasmInterrupted()) {
-        popFrame();
-        MOZ_ASSERT(!done());
-        return;
-    }
-
     // When asynchronously interrupted, exitFP is set to the interrupted frame
     // itself and so we do not want to skip it. Instead, we can recover the
     // Code and CodeRange from the JitActivation, which are set when control
     // flow was interrupted. There is no CallSite (b/c the interrupt was
     // async), but this is fine because CallSite is only used for line number
     // for which we can use the beginning of the function from the CodeRange
     // instead.
 
-    code_ = &fp_->tls->instance->code();
-    MOZ_ASSERT(code_ == LookupCode(activation->wasmUnwindPC()));
+    if (activation->isWasmInterrupted()) {
+        code_ = &fp_->tls->instance->code();
+        MOZ_ASSERT(code_ == LookupCode(activation->wasmUnwindPC()));
+
+        codeRange_ = code_->lookupRange(activation->wasmUnwindPC());
+        MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
+
+        lineOrBytecode_ = codeRange_->funcLineOrBytecode();
 
-    codeRange_ = code_->lookupRange(activation->wasmUnwindPC());
-    MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
+        MOZ_ASSERT(!done());
+        return;
+    }
 
+    // Otherwise, execution exits wasm code via an exit stub which sets exitFP
+    // to the exit stub's frame. Thus, in this case, we want to start iteration
+    // at the caller of the exit frame, whose Code, CodeRange and CallSite are
+    // indicated by the returnAddress of the exit stub's frame.
+
+    popFrame();
     MOZ_ASSERT(!done());
 }
 
 bool
 WasmFrameIter::done() const
 {
     MOZ_ASSERT(!!fp_ == !!code_);
     MOZ_ASSERT(!!fp_ == !!codeRange_);
@@ -107,17 +109,16 @@ WasmFrameIter::popFrame()
 {
     Frame* prevFP = fp_;
     fp_ = prevFP->callerFP;
     MOZ_ASSERT(!(uintptr_t(fp_) & JitActivation::ExitFpWasmBit));
 
     if (!fp_) {
         code_ = nullptr;
         codeRange_ = nullptr;
-        callsite_ = nullptr;
 
         if (unwind_ == Unwind::True) {
             // TODO with bug 1319203, there may be other JIT frames above.
             activation_->setWasmExitFP(nullptr);
             unwoundAddressOfReturnAddress_ = &prevFP->returnAddress;
         }
 
         MOZ_ASSERT(done());
@@ -127,18 +128,20 @@ WasmFrameIter::popFrame()
     void* returnAddress = prevFP->returnAddress;
 
     code_ = &fp_->tls->instance->code();
     MOZ_ASSERT(code_ == LookupCode(returnAddress));
 
     codeRange_ = code_->lookupRange(returnAddress);
     MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
 
-    callsite_ = code_->lookupCallSite(returnAddress);
-    MOZ_ASSERT(callsite_);
+    const CallSite* callsite = code_->lookupCallSite(returnAddress);
+    MOZ_ASSERT(callsite);
+
+    lineOrBytecode_ = callsite->lineOrBytecode();
 
     MOZ_ASSERT(!done());
 }
 
 const char*
 WasmFrameIter::filename() const
 {
     MOZ_ASSERT(!done());
@@ -173,18 +176,17 @@ WasmFrameIter::functionDisplayAtom() con
 
     return atom;
 }
 
 unsigned
 WasmFrameIter::lineOrBytecode() const
 {
     MOZ_ASSERT(!done());
-    MOZ_ASSERT_IF(!callsite_, activation_->isWasmInterrupted());
-    return callsite_ ? callsite_->lineOrBytecode() : codeRange_->funcLineOrBytecode();
+    return lineOrBytecode_;
 }
 
 Instance*
 WasmFrameIter::instance() const
 {
     MOZ_ASSERT(!done());
     return fp_->tls->instance;
 }
@@ -211,30 +213,17 @@ WasmFrameIter::debugEnabled() const
     return code_->metadata().debugEnabled &&
            codeRange_->funcIndex() >= code_->metadata(Tier::Debug).funcImports.length();
 }
 
 DebugFrame*
 WasmFrameIter::debugFrame() const
 {
     MOZ_ASSERT(!done());
-    MOZ_ASSERT(debugEnabled());
-    return reinterpret_cast<DebugFrame*>((uint8_t*)fp_ - DebugFrame::offsetOfFrame());
-}
-
-const CallSite*
-WasmFrameIter::debugTrapCallsite() const
-{
-    MOZ_ASSERT(!done());
-    MOZ_ASSERT(callsite_);
-    MOZ_ASSERT(debugEnabled());
-    MOZ_ASSERT(callsite_->kind() == CallSite::EnterFrame ||
-               callsite_->kind() == CallSite::LeaveFrame ||
-               callsite_->kind() == CallSite::Breakpoint);
-    return callsite_;
+    return DebugFrame::from(fp_);
 }
 
 /*****************************************************************************/
 // Prologue/epilogue code generation
 
 // These constants reflect statically-determined offsets in the
 // prologue/epilogue. The offsets are dynamically asserted during code
 // generation.
@@ -441,17 +430,17 @@ wasm::GenerateFunctionPrologue(MacroAsse
     // 'normalEntry' offsets since the difference must be less than UINT8_MAX
     // to be stored in CodeRange::funcBeginToNormalEntry_.
     masm.flushBuffer();
     masm.haltingAlign(CodeAlignment);
 
     // Generate table entry:
     offsets->begin = masm.currentOffset();
     BytecodeOffset trapOffset(0);  // ignored by masm.wasmEmitTrapOutOfLineCode
-    TrapDesc trap(trapOffset, Trap::IndirectCallBadSig, masm.framePushed());
+    OldTrapDesc trap(trapOffset, Trap::IndirectCallBadSig, masm.framePushed());
     switch (sigId.kind()) {
       case SigIdDesc::Kind::Global: {
         Register scratch = WasmTableCallScratchReg;
         masm.loadWasmGlobalPtr(sigId.globalDataOffset(), scratch);
         masm.branchPtr(Assembler::Condition::NotEqual, WasmTableCallSigReg, scratch, trap);
         break;
       }
       case SigIdDesc::Kind::Immediate: {
@@ -542,54 +531,51 @@ wasm::GenerateJitExitEpilogue(MacroAssem
     GenerateCallableEpilogue(masm, framePushed, ExitReason::None(), &offsets->ret);
     masm.setFramePushed(0);
 }
 
 /*****************************************************************************/
 // ProfilingFrameIterator
 
 ProfilingFrameIterator::ProfilingFrameIterator()
-  : activation_(nullptr),
-    code_(nullptr),
+  : code_(nullptr),
     codeRange_(nullptr),
     callerFP_(nullptr),
     callerPC_(nullptr),
     stackAddress_(nullptr),
     exitReason_(ExitReason::Fixed::None)
 {
     MOZ_ASSERT(done());
 }
 
 ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation)
-  : activation_(&activation),
-    code_(nullptr),
+  : code_(nullptr),
     codeRange_(nullptr),
     callerFP_(nullptr),
     callerPC_(nullptr),
     stackAddress_(nullptr),
     exitReason_(activation.wasmExitReason())
 {
     initFromExitFP(activation.wasmExitFP());
 }
 
 ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation, const Frame* fp)
-  : activation_(&activation),
-    code_(nullptr),
+  : code_(nullptr),
     codeRange_(nullptr),
     callerFP_(nullptr),
     callerPC_(nullptr),
     stackAddress_(nullptr),
     exitReason_(ExitReason::Fixed::ImportJit)
 {
     MOZ_ASSERT(fp);
     initFromExitFP(fp);
 }
 
 static inline void
-AssertMatchesCallSite(const JitActivation& activation, void* callerPC, Frame* callerFP)
+AssertMatchesCallSite(void* callerPC, Frame* callerFP)
 {
 #ifdef DEBUG
     const Code* code = LookupCode(callerPC);
     MOZ_ASSERT(code);
 
     const CodeRange* callerCodeRange = code->lookupRange(callerPC);
     MOZ_ASSERT(callerCodeRange);
 
@@ -628,37 +614,37 @@ ProfilingFrameIterator::initFromExitFP(c
       case CodeRange::InterpEntry:
         callerPC_ = nullptr;
         callerFP_ = nullptr;
         break;
       case CodeRange::Function:
         fp = fp->callerFP;
         callerPC_ = fp->returnAddress;
         callerFP_ = fp->callerFP;
-        AssertMatchesCallSite(*activation_, callerPC_, callerFP_);
+        AssertMatchesCallSite(callerPC_, callerFP_);
         break;
       case CodeRange::ImportJitExit:
       case CodeRange::ImportInterpExit:
       case CodeRange::BuiltinThunk:
-      case CodeRange::TrapExit:
+      case CodeRange::OldTrapExit:
       case CodeRange::DebugTrap:
       case CodeRange::OutOfBoundsExit:
       case CodeRange::UnalignedExit:
       case CodeRange::Throw:
       case CodeRange::Interrupt:
       case CodeRange::FarJumpIsland:
         MOZ_CRASH("Unexpected CodeRange kind");
     }
 
     MOZ_ASSERT(!done());
 }
 
 bool
-js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& registers,
-                         UnwindState* unwindState, bool* unwoundCaller)
+js::wasm::StartUnwinding(const RegisterState& registers, UnwindState* unwindState,
+                         bool* unwoundCaller)
 {
     // Shorthands.
     uint8_t* const pc = (uint8_t*) registers.pc;
     void** const sp = (void**) registers.sp;
 
     // The frame pointer might be in the process of tagging/untagging; make
     // sure it's untagged.
     Frame* const fp = (Frame*) (intptr_t(registers.fp) & ~JitActivation::ExitFpWasmBit);
@@ -668,17 +654,17 @@ js::wasm::StartUnwinding(const JitActiva
     // thunk, then execution must be entering from or leaving to the C++ caller
     // that pushed the JitActivation.
     const CodeRange* codeRange;
     uint8_t* codeBase;
     const Code* code = nullptr;
 
     const CodeSegment* codeSegment = LookupCodeSegment(pc);
     if (codeSegment) {
-        code = codeSegment->code();
+        code = &codeSegment->code();
         codeRange = code->lookupRange(pc);
         codeBase = codeSegment->base();
     } else if (!LookupBuiltinThunk(pc, &codeRange, &codeBase)) {
         return false;
     }
 
     // When the pc is inside the prologue/epilogue, the innermost call's Frame
     // is not complete and thus fp points to the second-to-innermost call's
@@ -712,115 +698,115 @@ js::wasm::StartUnwinding(const JitActiva
     Frame* fixedFP = nullptr;
     void* fixedPC = nullptr;
     switch (codeRange->kind()) {
       case CodeRange::Function:
       case CodeRange::FarJumpIsland:
       case CodeRange::ImportJitExit:
       case CodeRange::ImportInterpExit:
       case CodeRange::BuiltinThunk:
-      case CodeRange::TrapExit:
+      case CodeRange::OldTrapExit:
       case CodeRange::DebugTrap:
 #if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
         if ((offsetFromEntry >= BeforePushRetAddr && offsetFromEntry < PushedFP) || codeRange->isThunk()) {
             // See BUG 1407986.
             // On MIPS push is emulated by two instructions: adjusting the sp
             // and storing the value to sp.
             // Execution might be interrupted in between the two operation so we
             // have to relay on register state instead of state saved on stack
             // until the wasm::Frame is completely built.
             // On entry the return address is in ra (registers.lr) and
             // fp holds the caller's fp.
             fixedPC = (uint8_t*) registers.lr;
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
         } else
 #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
         if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) {
             // The return address is still in lr and fp holds the caller's fp.
             fixedPC = (uint8_t*) registers.lr;
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
         } else
 #endif
         if (offsetFromEntry == PushedRetAddr || codeRange->isThunk()) {
             // The return address has been pushed on the stack but fp still
             // points to the caller's fp.
             fixedPC = sp[0];
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
         } else if (offsetFromEntry >= PushedTLS && offsetFromEntry < PushedFP) {
             // The return address and caller's TLS have been pushed on the
             // stack; fp is still the caller's fp.
             fixedPC = sp[1];
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
         } else if (offsetFromEntry == PushedFP) {
             // The full Frame has been pushed; fp is still the caller's fp.
             MOZ_ASSERT(fp == reinterpret_cast<Frame*>(sp)->callerFP);
             fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress;
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
         } else if (offsetInCode >= codeRange->ret() - PoppedFP &&
                    offsetInCode < codeRange->ret() - PoppedTLSReg)
         {
             // The fixedFP field of the Frame has been popped into fp.
             fixedPC = sp[1];
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
 #if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
         } else if (offsetInCode >= codeRange->ret() - PoppedTLSReg &&
                    offsetInCode < codeRange->ret())
         {
             // The fixedFP field of the Frame has been popped into fp, but the
             // exit reason hasn't been popped yet.
             fixedPC = sp[0];
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
         } else if (offsetInCode == codeRange->ret()) {
             // Both the TLS, fixedFP and ra have been popped and fp now
             // points to the caller's frame.
             fixedPC = (uint8_t*) registers.lr;
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
 #else
         } else if (offsetInCode == codeRange->ret()) {
             // Both the TLS and fixedFP fields have been popped and fp now
             // points to the caller's frame.
             fixedPC = sp[0];
             fixedFP = fp;
-            AssertMatchesCallSite(activation, fixedPC, fixedFP);
+            AssertMatchesCallSite(fixedPC, fixedFP);
 #endif
         } else {
             if (codeRange->kind() == CodeRange::ImportJitExit) {
                 // The jit exit contains a range where the value of FP can't be
                 // trusted. Technically, we could recover fp from sp, but since
                 // the range is so short, for now just drop the stack.
                 if (offsetInCode >= codeRange->jitExitUntrustedFPStart() &&
                     offsetInCode < codeRange->jitExitUntrustedFPEnd())
                 {
                     return false;
                 }
             }
             // Not in the prologue/epilogue.
             fixedPC = pc;
             fixedFP = fp;
             *unwoundCaller = false;
-            AssertMatchesCallSite(activation, fp->returnAddress, fp->callerFP);
+            AssertMatchesCallSite(fp->returnAddress, fp->callerFP);
             break;
         }
         break;
       case CodeRange::OutOfBoundsExit:
       case CodeRange::UnalignedExit:
         // These code stubs execute after the prologue/epilogue have completed
         // so pc/fp contains the right values here.
         fixedPC = pc;
         fixedFP = fp;
         *unwoundCaller = false;
-        AssertMatchesCallSite(activation, fp->returnAddress, fp->callerFP);
+        AssertMatchesCallSite(fp->returnAddress, fp->callerFP);
         break;
       case CodeRange::InterpEntry:
         // The entry trampoline is the final frame in an wasm JitActivation. The
         // entry trampoline also doesn't GeneratePrologue/Epilogue so we can't
         // use the general unwinding logic above.
         break;
       case CodeRange::Throw:
         // The throw stub executes a small number of instructions before popping
@@ -838,18 +824,17 @@ js::wasm::StartUnwinding(const JitActiva
     unwindState->codeRange = codeRange;
     unwindState->fp = fixedFP;
     unwindState->pc = fixedPC;
     return true;
 }
 
 ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation,
                                                const RegisterState& state)
-  : activation_(&activation),
-    code_(nullptr),
+  : code_(nullptr),
     codeRange_(nullptr),
     callerFP_(nullptr),
     callerPC_(nullptr),
     stackAddress_(nullptr),
     exitReason_(ExitReason::Fixed::None)
 {
     // Let wasmExitFP take precedence to StartUnwinding when it is set since
     // during the body of an exit stub, the register state may not be valid
@@ -857,17 +842,17 @@ ProfilingFrameIterator::ProfilingFrameIt
     if (activation.hasWasmExitFP()) {
         exitReason_ = activation.wasmExitReason();
         initFromExitFP(activation.wasmExitFP());
         return;
     }
 
     bool unwoundCaller;
     UnwindState unwindState;
-    if (!StartUnwinding(*activation_, state, &unwindState, &unwoundCaller)) {
+    if (!StartUnwinding(state, &unwindState, &unwoundCaller)) {
         MOZ_ASSERT(done());
         return;
     }
 
     if (unwoundCaller) {
         callerFP_ = unwindState.fp;
         callerPC_ = unwindState.pc;
     } else {
@@ -912,24 +897,24 @@ ProfilingFrameIterator::operator++()
     codeRange_ = code_->lookupRange(callerPC_);
     MOZ_ASSERT(codeRange_);
 
     switch (codeRange_->kind()) {
       case CodeRange::Function:
       case CodeRange::ImportJitExit:
       case CodeRange::ImportInterpExit:
       case CodeRange::BuiltinThunk:
-      case CodeRange::TrapExit:
+      case CodeRange::OldTrapExit:
       case CodeRange::DebugTrap:
       case CodeRange::OutOfBoundsExit:
       case CodeRange::UnalignedExit:
       case CodeRange::FarJumpIsland:
         stackAddress_ = callerFP_;
         callerPC_ = callerFP_->returnAddress;
-        AssertMatchesCallSite(*activation_, callerPC_, callerFP_->callerFP);
+        AssertMatchesCallSite(callerPC_, callerFP_->callerFP);
         callerFP_ = callerFP_->callerFP;
         break;
       case CodeRange::InterpEntry:
         MOZ_CRASH("should have had null caller fp");
       case CodeRange::Interrupt:
       case CodeRange::Throw:
         MOZ_CRASH("code range doesn't have frame");
     }
@@ -940,17 +925,17 @@ ProfilingFrameIterator::operator++()
 static const char*
 ThunkedNativeToDescription(SymbolicAddress func)
 {
     MOZ_ASSERT(NeedsBuiltinThunk(func));
     switch (func) {
       case SymbolicAddress::HandleExecutionInterrupt:
       case SymbolicAddress::HandleDebugTrap:
       case SymbolicAddress::HandleThrow:
-      case SymbolicAddress::ReportTrap:
+      case SymbolicAddress::OldReportTrap:
       case SymbolicAddress::ReportOutOfBounds:
       case SymbolicAddress::ReportUnalignedAccess:
       case SymbolicAddress::CallImport_Void:
       case SymbolicAddress::CallImport_I32:
       case SymbolicAddress::CallImport_I64:
       case SymbolicAddress::CallImport_F64:
       case SymbolicAddress::CoerceInPlace_ToInt32:
       case SymbolicAddress::CoerceInPlace_ToNumber:
@@ -1070,17 +1055,17 @@ ProfilingFrameIterator::label() const
     }
 
     switch (codeRange_->kind()) {
       case CodeRange::Function:          return code_->profilingLabel(codeRange_->funcIndex());
       case CodeRange::InterpEntry:       return "slow entry trampoline (in wasm)";
       case CodeRange::ImportJitExit:     return importJitDescription;
       case CodeRange::BuiltinThunk:      return builtinNativeDescription;
       case CodeRange::ImportInterpExit:  return importInterpDescription;
-      case CodeRange::TrapExit:          return trapDescription;
+      case CodeRange::OldTrapExit:       return trapDescription;
       case CodeRange::DebugTrap:         return debugTrapDescription;
       case CodeRange::OutOfBoundsExit:   return "out-of-bounds stub (in wasm)";
       case CodeRange::UnalignedExit:     return "unaligned trap stub (in wasm)";
       case CodeRange::FarJumpIsland:     return "interstitial (in wasm)";
       case CodeRange::Throw:             MOZ_FALLTHROUGH;
       case CodeRange::Interrupt:         MOZ_CRASH("does not have a frame");
     }
 
@@ -1091,28 +1076,28 @@ Instance*
 wasm::LookupFaultingInstance(const CodeSegment& codeSegment, void* pc, void* fp)
 {
     // Assume bug-caused faults can be raised at any PC and apply the logic of
     // ProfilingFrameIterator to reject any pc outside the (post-prologue,
     // pre-epilogue) body of a wasm function. This is exhaustively tested by the
     // simulators which call this function at every load/store before even
     // knowing whether there is a fault.
 
-    const CodeRange* codeRange = codeSegment.code()->lookupRange(pc);
+    const CodeRange* codeRange = codeSegment.code().lookupRange(pc);
     if (!codeRange || !codeRange->isFunction())
         return nullptr;
 
     size_t offsetInModule = ((uint8_t*)pc) - codeSegment.base();
     if (offsetInModule < codeRange->funcNormalEntry() + SetFP)
         return nullptr;
     if (offsetInModule >= codeRange->ret() - PoppedFP)
         return nullptr;
 
     Instance* instance = reinterpret_cast<Frame*>(fp)->tls->instance;
-    MOZ_RELEASE_ASSERT(&instance->code() == codeSegment.code());
+    MOZ_RELEASE_ASSERT(&instance->code() == &codeSegment.code());
     return instance;
 }
 
 bool
 wasm::InCompiledCode(void* pc)
 {
     if (LookupCodeSegment(pc))
         return true;
--- a/js/src/wasm/WasmFrameIter.h
+++ b/js/src/wasm/WasmFrameIter.h
@@ -61,18 +61,18 @@ struct CallableOffsets;
 class WasmFrameIter
 {
   public:
     enum class Unwind { True, False };
 
   private:
     jit::JitActivation* activation_;
     const Code* code_;
-    const CallSite* callsite_;
     const CodeRange* codeRange_;
+    unsigned lineOrBytecode_;
     Frame* fp_;
     Unwind unwind_;
     void** unwoundAddressOfReturnAddress_;
 
     void popFrame();
 
   public:
     // See comment above this class definition.
@@ -86,17 +86,16 @@ class WasmFrameIter
     bool mutedErrors() const;
     JSAtom* functionDisplayAtom() const;
     unsigned lineOrBytecode() const;
     const CodeRange* codeRange() const { return codeRange_; }
     Instance* instance() const;
     void** unwoundAddressOfReturnAddress() const;
     bool debugEnabled() const;
     DebugFrame* debugFrame() const;
-    const CallSite* debugTrapCallsite() const;
 };
 
 enum class SymbolicAddress;
 
 // An ExitReason describes the possible reasons for leaving compiled wasm
 // code or the state of not having left compiled wasm code
 // (ExitReason::None). It is either a known reason, or a enumeration to a native
 // function that is used for better display in the profiler.
@@ -155,17 +154,16 @@ class ExitReason
         return SymbolicAddress(payload_ >> 1);
     }
 };
 
 // Iterates over the frames of a single wasm JitActivation, given an
 // asynchronously-interrupted thread's state.
 class ProfilingFrameIterator
 {
-    const jit::JitActivation* activation_;
     const Code* code_;
     const CodeRange* codeRange_;
     Frame* callerFP_;
     void* callerPC_;
     void* stackAddress_;
     ExitReason exitReason_;
 
     void initFromExitFP(const Frame* fp);
@@ -248,15 +246,15 @@ typedef JS::ProfilingFrameIterator::Regi
 //
 // unwoundCaller is set to true if we were in a transitional state and had to
 // rewind to the caller's frame instead of the current frame.
 //
 // Returns true if it was possible to get to a clear state, or false if the
 // frame should be ignored.
 
 bool
-StartUnwinding(const jit::JitActivation& activation, const RegisterState& registers,
-               UnwindState* unwindState, bool* unwoundCaller);
+StartUnwinding(const RegisterState& registers, UnwindState* unwindState,
+               bool* unwoundCaller);
 
 } // namespace wasm
 } // namespace js
 
 #endif // wasm_frame_iter_h
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -42,19 +42,19 @@ bool
 CompiledCode::swap(MacroAssembler& masm)
 {
     MOZ_ASSERT(bytes.empty());
     if (!masm.swapBuffer(bytes))
         return false;
 
     callSites.swap(masm.callSites());
     callSiteTargets.swap(masm.callSiteTargets());
-    trapSites.swap(masm.trapSites());
+    oldTrapSites.swap(masm.oldTrapSites());
     callFarJumps.swap(masm.callFarJumps());
-    trapFarJumps.swap(masm.trapFarJumps());
+    oldTrapFarJumps.swap(masm.oldTrapFarJumps());
     memoryAccesses.swap(masm.memoryAccesses());
     symbolicAccesses.swap(masm.symbolicAccesses());
     codeLabels.swap(masm.codeLabels());
     return true;
 }
 
 // ****************************************************************************
 // ModuleGenerator
@@ -70,28 +70,28 @@ ModuleGenerator::ModuleGenerator(const C
     cancelled_(cancelled),
     env_(env),
     linkDataTier_(nullptr),
     metadataTier_(nullptr),
     taskState_(mutexid::WasmCompileTaskState),
     lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE),
     masmAlloc_(&lifo_),
     masm_(MacroAssembler::WasmToken(), masmAlloc_),
-    trapCodeOffsets_(),
+    oldTrapCodeOffsets_(),
     debugTrapCodeOffset_(),
     lastPatchedCallSite_(0),
     startOfUnpatchedCallsites_(0),
     parallel_(false),
     outstanding_(0),
     currentTask_(nullptr),
     batchedBytecode_(0),
     finishedFuncDefs_(false)
 {
     MOZ_ASSERT(IsCompilingWasm());
-    std::fill(trapCodeOffsets_.begin(), trapCodeOffsets_.end(), 0);
+    std::fill(oldTrapCodeOffsets_.begin(), oldTrapCodeOffsets_.end(), 0);
 }
 
 ModuleGenerator::~ModuleGenerator()
 {
     MOZ_ASSERT_IF(finishedFuncDefs_, !batchedBytecode_);
     MOZ_ASSERT_IF(finishedFuncDefs_, !currentTask_);
 
     if (parallel_) {
@@ -201,18 +201,18 @@ ModuleGenerator::init(Metadata* maybeAsm
     uint32_t codeSectionSize = env_->codeSection ? env_->codeSection->size : 0;
 
     if (!masm_.reserve(size_t(1.2 * EstimateCompiledCodeSize(tier(), codeSectionSize))))
         return false;
 
     if (!metadataTier_->codeRanges.reserve(2 * env_->numFuncDefs()))
         return false;
 
-    const size_t CallSitesPerByteCode = 10;
-    if (!metadataTier_->callSites.reserve(codeSectionSize / CallSitesPerByteCode))
+    const size_t ByteCodesPerCallSite = 10;
+    if (!metadataTier_->callSites.reserve(codeSectionSize / ByteCodesPerCallSite))
         return false;
 
     const size_t MemoryAccessesPerByteCode = 10;
     if (!metadataTier_->memoryAccesses.reserve(codeSectionSize / MemoryAccessesPerByteCode))
         return false;
 
     // Allocate space in TlsData for declarations that need it.
 
@@ -431,24 +431,24 @@ ModuleGenerator::linkCallSites()
                     return false;
                 if (!existingCallFarJumps.add(p, target.funcIndex(), offsets.begin))
                     return false;
             }
 
             masm_.patchCall(callerOffset, p->value());
             break;
           }
-          case CallSiteDesc::TrapExit: {
+          case CallSiteDesc::OldTrapExit: {
             if (!existingTrapFarJumps[target.trap()]) {
-                // See MacroAssembler::wasmEmitTrapOutOfLineCode for why we must
+                // See MacroAssembler::wasmEmitOldTrapOutOfLineCode for why we must
                 // reload the TLS register on this path.
                 Offsets offsets;
                 offsets.begin = masm_.currentOffset();
                 masm_.loadPtr(Address(FramePointer, offsetof(Frame, tls)), WasmTlsReg);
-                if (!trapFarJumps_.emplaceBack(target.trap(), masm_.farJumpWithPatch()))
+                if (!oldTrapFarJumps_.emplaceBack(target.trap(), masm_.farJumpWithPatch()))
                     return false;
                 offsets.end = masm_.currentOffset();
                 if (masm_.oom())
                     return false;
                 if (!metadataTier_->codeRanges.emplaceBack(CodeRange::FarJumpIsland, offsets))
                     return false;
                 existingTrapFarJumps[target.trap()] = Some(offsets.begin);
             }
@@ -498,19 +498,19 @@ ModuleGenerator::noteCodeRange(uint32_t 
         metadataTier_->lookupFuncExport(codeRange.funcIndex()).initInterpEntryOffset(codeRange.begin());
         break;
       case CodeRange::ImportJitExit:
         metadataTier_->funcImports[codeRange.funcIndex()].initJitExitOffset(codeRange.begin());
         break;
       case CodeRange::ImportInterpExit:
         metadataTier_->funcImports[codeRange.funcIndex()].initInterpExitOffset(codeRange.begin());
         break;
-      case CodeRange::TrapExit:
-        MOZ_ASSERT(!trapCodeOffsets_[codeRange.trap()]);
-        trapCodeOffsets_[codeRange.trap()] = codeRange.begin();
+      case CodeRange::OldTrapExit:
+        MOZ_ASSERT(!oldTrapCodeOffsets_[codeRange.trap()]);
+        oldTrapCodeOffsets_[codeRange.trap()] = codeRange.begin();
         break;
       case CodeRange::DebugTrap:
         MOZ_ASSERT(!debugTrapCodeOffset_);
         debugTrapCodeOffset_ = codeRange.begin();
         break;
       case CodeRange::OutOfBoundsExit:
         MOZ_ASSERT(!linkDataTier_->outOfBoundsOffset);
         linkDataTier_->outOfBoundsOffset = codeRange.begin();
@@ -575,20 +575,20 @@ ModuleGenerator::linkCompiledCode(const 
 
     auto callSiteOp = [=](uint32_t, CallSite* cs) { cs->offsetBy(offsetInModule); };
     if (!AppendForEach(&metadataTier_->callSites, code.callSites, callSiteOp))
         return false;
 
     if (!callSiteTargets_.appendAll(code.callSiteTargets))
         return false;
 
-    MOZ_ASSERT(code.trapSites.empty());
+    MOZ_ASSERT(code.oldTrapSites.empty());
 
-    auto trapFarJumpOp = [=](uint32_t, TrapFarJump* tfj) { tfj->offsetBy(offsetInModule); };
-    if (!AppendForEach(&trapFarJumps_, code.trapFarJumps, trapFarJumpOp))
+    auto trapFarJumpOp = [=](uint32_t, OldTrapFarJump* tfj) { tfj->offsetBy(offsetInModule); };
+    if (!AppendForEach(&oldTrapFarJumps_, code.oldTrapFarJumps, trapFarJumpOp))
         return false;
 
     auto callFarJumpOp = [=](uint32_t, CallFarJump* cfj) { cfj->offsetBy(offsetInModule); };
     if (!AppendForEach(&callFarJumps_, code.callFarJumps, callFarJumpOp))
         return false;
 
     auto memoryOp = [=](uint32_t, MemoryAccess* ma) { ma->offsetBy(offsetInModule); };
     if (!AppendForEach(&metadataTier_->memoryAccesses, code.memoryAccesses, memoryOp))
@@ -783,28 +783,28 @@ ModuleGenerator::finishCode()
     // can emit tiny far-jump stubs, so there is an ordering dependency here.
 
     if (!linkCallSites())
         return false;
 
     for (CallFarJump far : callFarJumps_)
         masm_.patchFarJump(far.jump, funcCodeRange(far.funcIndex).funcNormalEntry());
 
-    for (TrapFarJump far : trapFarJumps_)
-        masm_.patchFarJump(far.jump, trapCodeOffsets_[far.trap]);
+    for (OldTrapFarJump far : oldTrapFarJumps_)
+        masm_.patchFarJump(far.jump, oldTrapCodeOffsets_[far.trap]);
 
     for (CodeOffset farJump : debugTrapFarJumps_)
         masm_.patchFarJump(farJump, debugTrapCodeOffset_);
 
     // None of the linking or far-jump operations should emit masm metadata.
 
     MOZ_ASSERT(masm_.callSites().empty());
     MOZ_ASSERT(masm_.callSiteTargets().empty());
-    MOZ_ASSERT(masm_.trapSites().empty());
-    MOZ_ASSERT(masm_.trapFarJumps().empty());
+    MOZ_ASSERT(masm_.oldTrapSites().empty());
+    MOZ_ASSERT(masm_.oldTrapFarJumps().empty());
     MOZ_ASSERT(masm_.callFarJumps().empty());
     MOZ_ASSERT(masm_.memoryAccesses().empty());
     MOZ_ASSERT(masm_.symbolicAccesses().empty());
     MOZ_ASSERT(masm_.codeLabels().empty());
 
     masm_.finish();
     return !masm_.oom();
 }
--- a/js/src/wasm/WasmGenerator.h
+++ b/js/src/wasm/WasmGenerator.h
@@ -59,46 +59,46 @@ typedef Vector<FuncCompileInput, 8, Syst
 // input functions or stubs.
 
 struct CompiledCode
 {
     Bytes                bytes;
     CodeRangeVector      codeRanges;
     CallSiteVector       callSites;
     CallSiteTargetVector callSiteTargets;
-    TrapSiteVector       trapSites;
-    TrapFarJumpVector    trapFarJumps;
+    OldTrapSiteVector    oldTrapSites;
+    OldTrapFarJumpVector oldTrapFarJumps;
     CallFarJumpVector    callFarJumps;
     MemoryAccessVector   memoryAccesses;
     SymbolicAccessVector symbolicAccesses;
     jit::CodeLabelVector codeLabels;
 
     MOZ_MUST_USE bool swap(jit::MacroAssembler& masm);
 
     void clear() {
         bytes.clear();
         codeRanges.clear();
         callSites.clear();
         callSiteTargets.clear();
-        trapSites.clear();
-        trapFarJumps.clear();
+        oldTrapSites.clear();
+        oldTrapFarJumps.clear();
         callFarJumps.clear();
         memoryAccesses.clear();
         symbolicAccesses.clear();
         codeLabels.clear();
         MOZ_ASSERT(empty());
     }
 
     bool empty() {
         return bytes.empty() &&
                codeRanges.empty() &&
                callSites.empty() &&
                callSiteTargets.empty() &&
-               trapSites.empty() &&
-               trapFarJumps.empty() &&
+               oldTrapSites.empty() &&
+               oldTrapFarJumps.empty() &&
                callFarJumps.empty() &&
                memoryAccesses.empty() &&
                symbolicAccesses.empty() &&
                codeLabels.empty();
     }
 };
 
 // The CompileTaskState of a ModuleGenerator contains the mutable state shared
@@ -140,17 +140,17 @@ struct CompileTask
 // lifetime of a ModuleGenerator, a sequence of FunctionGenerators are created
 // and destroyed to compile the individual function bodies. After generating all
 // functions, ModuleGenerator::finish() must be called to complete the
 // compilation and extract the resulting wasm module.
 
 class MOZ_STACK_CLASS ModuleGenerator
 {
     typedef Vector<CompileTask, 0, SystemAllocPolicy> CompileTaskVector;
-    typedef EnumeratedArray<Trap, Trap::Limit, uint32_t> Uint32TrapArray;
+    typedef EnumeratedArray<Trap, Trap::Limit, uint32_t> OldTrapOffsetArray;
     typedef Vector<jit::CodeOffset, 0, SystemAllocPolicy> CodeOffsetVector;
 
     // Constant parameters
     SharedCompileArgs const         compileArgs_;
     UniqueChars* const              error_;
     const Atomic<bool>* const       cancelled_;
     ModuleEnvironment* const        env_;
 
@@ -163,19 +163,19 @@ class MOZ_STACK_CLASS ModuleGenerator
 
     // Data scoped to the ModuleGenerator's lifetime
     ExclusiveCompileTaskState       taskState_;
     LifoAlloc                       lifo_;
     jit::JitContext                 jcx_;
     jit::TempAllocator              masmAlloc_;
     jit::MacroAssembler             masm_;
     Uint32Vector                    funcToCodeRange_;
-    Uint32TrapArray                 trapCodeOffsets_;
+    OldTrapOffsetArray              oldTrapCodeOffsets_;
     uint32_t                        debugTrapCodeOffset_;
-    TrapFarJumpVector               trapFarJumps_;
+    OldTrapFarJumpVector            oldTrapFarJumps_;
     CallFarJumpVector               callFarJumps_;
     CallSiteTargetVector            callSiteTargets_;
     uint32_t                        lastPatchedCallSite_;
     uint32_t                        startOfUnpatchedCallsites_;
     CodeOffsetVector                debugTrapFarJumps_;
 
     // Parallel compilation
     bool                            parallel_;
--- a/js/src/wasm/WasmProcess.cpp
+++ b/js/src/wasm/WasmProcess.cpp
@@ -230,16 +230,16 @@ wasm::LookupCodeSegment(const void* pc)
 {
     return processCodeSegmentMap.lookup(pc);
 }
 
 const Code*
 wasm::LookupCode(const void* pc)
 {
     const CodeSegment* found = LookupCodeSegment(pc);
-    return found ? found->code() : nullptr;
+    return found ? &found->code() : nullptr;
 }
 
 void
 wasm::ShutDownProcessStaticData()
 {
     processCodeSegmentMap.freeAll();
 }
--- a/js/src/wasm/WasmSignalHandlers.cpp
+++ b/js/src/wasm/WasmSignalHandlers.cpp
@@ -1427,19 +1427,18 @@ wasm::InInterruptibleCode(JSContext* cx,
 
     if (!cx->compartment())
         return false;
 
     *cs = LookupCodeSegment(pc);
     if (!*cs)
         return false;
 
-    const Code* code = (*cs)->code();
-
-    const CodeRange* codeRange = code->lookupRange(pc);
+    const Code& code = (*cs)->code();
+    const CodeRange* codeRange = code.lookupRange(pc);
     return codeRange && codeRange->isFunction();
 }
 
 // The return value indicates whether the PC was changed, not whether there was
 // a failure.
 static bool
 RedirectJitCodeToInterruptCheck(JSContext* cx, CONTEXT* context)
 {
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -528,17 +528,17 @@ GenerateImportFunction(jit::MacroAssembl
     masm.wasmCallImport(desc, CalleeDesc::import(fi.tlsDataOffset()));
 
     // Restore the TLS register and pinned regs, per wasm function ABI.
     masm.loadWasmTlsRegFromFrame();
     masm.loadWasmPinnedRegsFromTls();
 
     GenerateFunctionEpilogue(masm, framePushed, offsets);
 
-    masm.wasmEmitTrapOutOfLineCode();
+    masm.wasmEmitOldTrapOutOfLineCode();
 
     return FinishOffsets(masm, offsets);
 }
 
 static const unsigned STUBS_LIFO_DEFAULT_CHUNK_SIZE = 4 * 1024;
 
 bool
 wasm::GenerateImportFunctions(const ModuleEnvironment& env, const FuncImportVector& imports,
@@ -996,22 +996,22 @@ wasm::GenerateBuiltinThunk(MacroAssemble
     if (!UseHardFpABI() && IsFloatingPointType(retType))
         masm.ma_vxfer(r0, r1, d0);
 #endif
 
     GenerateExitEpilogue(masm, framePushed, exitReason, offsets);
     return FinishOffsets(masm, offsets);
 }
 
-// Generate a stub that calls into ReportTrap with the right trap reason.
+// Generate a stub that calls into WasmOldReportTrap with the right trap reason.
 // This stub is called with ABIStackAlignment by a trap out-of-line path. An
 // exit prologue/epilogue is used so that stack unwinding picks up the
 // current JitActivation. Unwinding will begin at the caller of this trap exit.
 static bool
-GenerateTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel, CallableOffsets* offsets)
+GenerateOldTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel, CallableOffsets* offsets)
 {
     masm.haltingAlign(CodeAlignment);
 
     masm.setFramePushed(0);
 
     MIRTypeVector args;
     MOZ_ALWAYS_TRUE(args.append(MIRType::Int32));
 
@@ -1023,17 +1023,17 @@ GenerateTrapExit(MacroAssembler& masm, T
     if (i->kind() == ABIArg::GPR)
         masm.move32(Imm32(int32_t(trap)), i->gpr());
     else
         masm.store32(Imm32(int32_t(trap)), Address(masm.getStackPointer(), i->offsetFromArgBase()));
     i++;
     MOZ_ASSERT(i.done());
 
     masm.assertStackAlignment(ABIStackAlignment);
-    masm.call(SymbolicAddress::ReportTrap);
+    masm.call(SymbolicAddress::OldReportTrap);
 
     masm.jump(throwLabel);
 
     GenerateExitEpilogue(masm, framePushed, ExitReason::Fixed::Trap, offsets);
 
     return FinishOffsets(masm, offsets);
 }
 
@@ -1364,17 +1364,17 @@ wasm::GenerateStubs(const ModuleEnvironm
         if (!GenerateInterpEntry(masm, fe, &offsets))
             return false;
         if (!code->codeRanges.emplaceBack(CodeRange::InterpEntry, fe.funcIndex(), offsets))
             return false;
     }
 
     for (Trap trap : MakeEnumeratedRange(Trap::Limit)) {
         CallableOffsets offsets;
-        if (!GenerateTrapExit(masm, trap, &throwLabel, &offsets))
+        if (!GenerateOldTrapExit(masm, trap, &throwLabel, &offsets))
             return false;
         if (!code->codeRanges.emplaceBack(trap, offsets))
             return false;
     }
 
     Offsets offsets;
 
     if (!GenerateOutOfBoundsExit(masm, &throwLabel, &offsets))
--- a/js/src/wasm/WasmTypes.cpp
+++ b/js/src/wasm/WasmTypes.cpp
@@ -557,16 +557,25 @@ wasm::ComputeMappedSize(uint32_t maxSize
 
     MOZ_ASSERT(boundsCheckLimit % gc::SystemPageSize() == 0);
     MOZ_ASSERT(GuardSize % gc::SystemPageSize() == 0);
     return boundsCheckLimit + GuardSize;
 }
 
 #endif  // WASM_HUGE_MEMORY
 
+/* static */ DebugFrame*
+DebugFrame::from(Frame* fp)
+{
+    MOZ_ASSERT(fp->tls->instance->code().metadata().debugEnabled);
+    auto* df = reinterpret_cast<DebugFrame*>((uint8_t*)fp - DebugFrame::offsetOfFrame());
+    MOZ_ASSERT(fp->instance() == df->instance());
+    return df;
+}
+
 void
 DebugFrame::alignmentStaticAsserts()
 {
     // VS2017 doesn't consider offsetOfFrame() to be a constexpr, so we have
     // to use offsetof directly. These asserts can't be at class-level
     // because the type is incomplete.
 
     static_assert(WasmStackAlignment >= Alignment,
@@ -723,17 +732,17 @@ CodeRange::CodeRange(Kind kind, Callable
     end_(offsets.end),
     kind_(kind)
 {
     MOZ_ASSERT(begin_ < ret_);
     MOZ_ASSERT(ret_ < end_);
     PodZero(&u);
 #ifdef DEBUG
     switch (kind_) {
-      case TrapExit:
+      case OldTrapExit:
       case DebugTrap:
       case BuiltinThunk:
         break;
       default:
         MOZ_CRASH("should use more specific constructor");
     }
 #endif
 }
@@ -768,17 +777,17 @@ CodeRange::CodeRange(uint32_t funcIndex,
     MOZ_ASSERT(jitExitUntrustedFPStart() == offsets.untrustedFPStart);
     MOZ_ASSERT(jitExitUntrustedFPEnd() == offsets.untrustedFPEnd);
 }
 
 CodeRange::CodeRange(Trap trap, CallableOffsets offsets)
   : begin_(offsets.begin),
     ret_(offsets.ret),
     end_(offsets.end),
-    kind_(TrapExit)
+    kind_(OldTrapExit)
 {
     MOZ_ASSERT(begin_ < ret_);
     MOZ_ASSERT(ret_ < end_);
     u.trap_ = trap;
 }
 
 CodeRange::CodeRange(uint32_t funcIndex, uint32_t funcLineOrBytecode, FuncOffsets offsets)
   : begin_(offsets.begin),
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -36,18 +36,16 @@
 #include "js/UniquePtr.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 #include "vm/MallocProvider.h"
 #include "wasm/WasmBinaryConstants.h"
 
 namespace js {
 
-class PropertyName;
-class WasmFunctionCallObject;
 namespace jit {
     struct BaselineScript;
     enum class RoundingMode;
 }
 
 // This is a widespread header, so lets keep out the core wasm impl types.
 
 class WasmMemoryObject;
@@ -1008,17 +1006,17 @@ class CodeRange
 {
   public:
     enum Kind {
         Function,          // function definition
         InterpEntry,       // calls into wasm from C++
         ImportJitExit,     // fast-path calling from wasm into JIT code
         ImportInterpExit,  // slow-path calling from wasm into C++ interp
         BuiltinThunk,      // fast-path calling from wasm into a C++ native
-        TrapExit,          // calls C++ to report and jumps to throw stub
+        OldTrapExit,       // calls C++ to report and jumps to throw stub
         DebugTrap,         // calls C++ to handle debug event
         FarJumpIsland,     // inserted to connect otherwise out-of-range insns
         OutOfBoundsExit,   // stub jumped to by non-standard asm.js SIMD/Atomics
         UnalignedExit,     // stub jumped to by wasm Atomics and non-standard
                            // ARM unaligned trap
         Interrupt,         // stub executes asynchronously to interrupt wasm
         Throw              // special stack-unwinding stub jumped to by other stubs
     };
@@ -1084,17 +1082,17 @@ class CodeRange
     }
     bool isImportExit() const {
         return kind() == ImportJitExit || kind() == ImportInterpExit || kind() == BuiltinThunk;
     }
     bool isImportJitExit() const {
         return kind() == ImportJitExit;
     }
     bool isTrapExit() const {
-        return kind() == TrapExit;
+        return kind() == OldTrapExit;
     }
     bool isDebugTrap() const {
         return kind() == DebugTrap;
     }
     bool isThunk() const {
         return kind() == FarJumpIsland;
     }
 
@@ -1184,22 +1182,22 @@ LookupInSorted(const CodeRangeVector& co
 // A wrapper around the bytecode offset of a wasm instruction within a whole
 // module, used for trap offsets or call offsets. These offsets should refer to
 // the first byte of the instruction that triggered the trap / did the call and
 // should ultimately derive from OpIter::bytecodeOffset.
 
 struct BytecodeOffset
 {
     static const uint32_t INVALID = -1;
-    uint32_t bytecodeOffset;
+    uint32_t offset;
 
-    BytecodeOffset() : bytecodeOffset(INVALID) {}
-    explicit BytecodeOffset(uint32_t bytecodeOffset) : bytecodeOffset(bytecodeOffset) {}
+    BytecodeOffset() : offset(INVALID) {}
+    explicit BytecodeOffset(uint32_t offset) : offset(offset) {}
 
-    bool isValid() const { return bytecodeOffset != INVALID; }
+    bool isValid() const { return offset != INVALID; }
 };
 
 // While the frame-pointer chain allows the stack to be unwound without
 // metadata, Error.stack still needs to know the line/column of every call in
 // the chain. A CallSiteDesc describes a single callsite to which CallSite adds
 // the metadata necessary to walk up to the next frame. Lastly CallSiteAndTarget
 // adds the function index of the callee.
 
@@ -1207,17 +1205,17 @@ class CallSiteDesc
 {
     uint32_t lineOrBytecode_ : 29;
     uint32_t kind_ : 3;
   public:
     enum Kind {
         Func,       // pc-relative call to a specific function
         Dynamic,    // dynamic callee called via register
         Symbolic,   // call to a single symbolic callee
-        TrapExit,   // call to a trap exit
+        OldTrapExit,// call to a trap exit (being removed)
         EnterFrame, // call to a enter frame handler
         LeaveFrame, // call to a leave frame handler
         Breakpoint  // call to instruction breakpoint
     };
     CallSiteDesc() {}
     explicit CallSiteDesc(Kind kind)
       : lineOrBytecode_(0), kind_(kind)
     {
@@ -1330,17 +1328,17 @@ enum class SymbolicAddress
     NearbyIntF,
     ExpD,
     LogD,
     PowD,
     ATan2D,
     HandleExecutionInterrupt,
     HandleDebugTrap,
     HandleThrow,
-    ReportTrap,
+    OldReportTrap,
     ReportOutOfBounds,
     ReportUnalignedAccess,
     CallImport_Void,
     CallImport_I32,
     CallImport_I64,
     CallImport_F64,
     CoerceInPlace_ToInt32,
     CoerceInPlace_ToNumber,
@@ -1876,16 +1874,17 @@ class DebugFrame
     uint32_t padding_;  // See alignmentStaticAsserts().
 #endif
 
   private:
     // The Frame goes at the end since the stack grows down.
     Frame frame_;
 
   public:
+    static DebugFrame* from(Frame* fp);
     Frame& frame() { return frame_; }
     uint32_t funcIndex() const { return funcIndex_; }
     Instance* instance() const { return frame_.instance(); }
     GlobalObject* global() const;
     JSObject* environmentChain() const;
     bool getLocal(uint32_t localIndex, MutableHandleValue vp);
 
     // The return value must be written from the unboxed representation in the
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3631,17 +3631,20 @@ nsLayoutUtils::PaintFrame(gfxContext* aR
   }
 
   TimeStamp startBuildDisplayList = TimeStamp::Now();
 
   const bool buildCaret = !(aFlags & PaintFrameFlags::PAINT_HIDE_CARET);
   const bool isForPainting = (aFlags & PaintFrameFlags::PAINT_WIDGET_LAYERS) &&
     aBuilderMode == nsDisplayListBuilderMode::PAINTING;
 
-  const bool retainingEnabled = isForPainting && AreRetainedDisplayListsEnabled();
+  // Only allow retaining for painting when preffed on, and for root frames (since
+  // the modified frame tracking is per-root-frame).
+  const bool retainingEnabled =
+    isForPainting && AreRetainedDisplayListsEnabled() && !aFrame->GetParent();
 
   RetainedDisplayListBuilder* retainedBuilder =
     GetOrCreateRetainedDisplayListBuilder(aFrame, retainingEnabled, buildCaret);
 
   // Only use the retained display list builder if the retaining is currently
   // enabled. This check is needed because it is possible that the pref has been
   // disabled after creating the retained display list builder.
   const bool useRetainedBuilder = retainedBuilder && retainingEnabled;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -992,17 +992,19 @@ nsIFrame::RemoveDisplayItemDataForDeleti
       }
     }
   }
 }
 
 void
 nsIFrame::MarkNeedsDisplayItemRebuild()
 {
-  if (!nsLayoutUtils::AreRetainedDisplayListsEnabled() || IsFrameModified()) {
+  if (!nsLayoutUtils::AreRetainedDisplayListsEnabled() ||
+      IsFrameModified() ||
+      HasAnyStateBits(NS_FRAME_IN_POPUP)) {
     // Skip frames that are already marked modified.
     return;
   }
 
   nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
   MOZ_ASSERT(displayRoot);
 
   RetainedDisplayListBuilder* retainedBuilder =
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 #include "RetainedDisplayListBuilder.h"
 #include "nsSubDocumentFrame.h"
+#include "nsViewManager.h"
 
 /**
  * Code for doing display list building for a modified subset of the window,
  * and then merging it into the existing display list (for the full window).
  *
  * The approach primarily hinges on the observation that the ‘true’ ordering of
  * display items is represented by a DAG (only items that intersect in 2d space
  * have a defined ordering). Our display list is just one of a many possible linear
@@ -513,51 +514,80 @@ TakeAndAddModifiedFramesFromRootFrame(ns
     if (f) {
       aFrames.AppendElement(f);
     }
   }
 
   frames->Clear();
 }
 
+struct CbData {
+  nsDisplayListBuilder* builder;
+  nsTArray<nsIFrame*> modifiedFrames;
+};
+
 static bool
 SubDocEnumCb(nsIDocument* aDocument, void* aData)
 {
   MOZ_ASSERT(aDocument);
   MOZ_ASSERT(aData);
 
-  nsTArray<nsIFrame*>* modifiedFrames =
-    static_cast<nsTArray<nsIFrame*>*>(aData);
+  CbData* data = static_cast<CbData*>(aData);
+
+  // Although this is the actual subdocument, it might not be
+  // what painting uses. Walk up to the nsSubDocumentFrame owning
+  // us, and then ask that which subdoc it's going to paint.
 
   nsIPresShell* presShell = aDocument->GetShell();
-  nsIFrame* rootFrame = presShell ? presShell->GetRootFrame() : nullptr;
+  if (presShell) {
+    nsView* rootView = presShell->GetViewManager()->GetRootView();
+    MOZ_ASSERT(rootView);
+
+    // There should be an anonymous inner view between the root view
+    // of the subdoc, and the view for the nsSubDocumentFrame.
+    nsView* innerView = rootView->GetParent();
+    MOZ_ASSERT(innerView);
+
+    nsView* subDocView = innerView->GetParent();
+    MOZ_ASSERT(subDocView);
 
-  if (rootFrame) {
-    TakeAndAddModifiedFramesFromRootFrame(*modifiedFrames, rootFrame);
+    nsIFrame* subDocFrame = subDocView->GetFrame();
+    MOZ_ASSERT(subDocFrame);
+    nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(subDocFrame);
+    MOZ_ASSERT(subdocumentFrame);
+
+    presShell = subdocumentFrame->GetSubdocumentPresShellForPainting(
+      data->builder->IsIgnoringPaintSuppression() ? nsSubDocumentFrame::IGNORE_PAINT_SUPPRESSION : 0);
+    nsIFrame* rootFrame = presShell ? presShell->GetRootFrame() : nullptr;
+
+    if (rootFrame) {
+      TakeAndAddModifiedFramesFromRootFrame(data->modifiedFrames, rootFrame);
+    }
   }
 
   aDocument->EnumerateSubDocuments(SubDocEnumCb, aData);
   return true;
 }
 
 static nsTArray<nsIFrame*>
-GetModifiedFrames(nsIFrame* aDisplayRootFrame)
+GetModifiedFrames(nsDisplayListBuilder* aBuilder)
 {
-  MOZ_ASSERT(aDisplayRootFrame);
+  MOZ_ASSERT(aBuilder->RootReferenceFrame());
 
-  nsTArray<nsIFrame*> modifiedFrames;
-  TakeAndAddModifiedFramesFromRootFrame(modifiedFrames, aDisplayRootFrame);
+  CbData data;
+  data.builder = aBuilder;
+  TakeAndAddModifiedFramesFromRootFrame(data.modifiedFrames, aBuilder->RootReferenceFrame());
 
-  nsIDocument* rootdoc = aDisplayRootFrame->PresContext()->Document();
+  nsIDocument* rootdoc = aBuilder->RootReferenceFrame()->PresContext()->Document();
 
   if (rootdoc) {
-    rootdoc->EnumerateSubDocuments(SubDocEnumCb, &modifiedFrames);
+    rootdoc->EnumerateSubDocuments(SubDocEnumCb, &data);
   }
 
-  return modifiedFrames;
+  return Move(data.modifiedFrames);
 }
 
 // ComputeRebuildRegion  debugging
 // #define CRR_DEBUG 1
 #if CRR_DEBUG
 #  define CRR_LOG(...) printf_stderr(__VA_ARGS__)
 #else
 #  define CRR_LOG(...)
@@ -598,16 +628,20 @@ RetainedDisplayListBuilder::ComputeRebui
   CRR_LOG("Computing rebuild regions for %d frames:\n", aModifiedFrames.size());
   for (nsIFrame* f : aModifiedFrames) {
     MOZ_ASSERT(f);
 
     if (f->HasOverrideDirtyRegion()) {
       aOutFramesWithProps->AppendElement(f);
     }
 
+    if (f->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
+      continue;
+    }
+
     // TODO: There is almost certainly a faster way of doing this, probably can be combined with the ancestor
     // walk for TransformFrameRectToAncestor.
     AnimatedGeometryRoot* agr = mBuilder.FindAnimatedGeometryRootFor(f)->GetAsyncAGR();
 
     CRR_LOG("Processing frame %p with agr %p\n", f, agr->mFrame);
 
 
     // Convert the frame's overflow rect into the coordinate space
@@ -777,33 +811,33 @@ ClearFrameProps(nsTArray<nsIFrame*>& aFr
     f->SetFrameIsModified(false);
   }
 }
 
 void
 RetainedDisplayListBuilder::ClearModifiedFrameProps()
 {
   nsTArray<nsIFrame*> modifiedFrames =
-    GetModifiedFrames(mBuilder.RootReferenceFrame());
+    GetModifiedFrames(&mBuilder);
 
   ClearFrameProps(modifiedFrames);
 }
 
 bool
 RetainedDisplayListBuilder::AttemptPartialUpdate(nscolor aBackstop)
 {
   mBuilder.RemoveModifiedWindowDraggingRegion();
   if (mBuilder.ShouldSyncDecodeImages()) {
     MarkFramesWithItemsAndImagesModified(&mList);
   }
 
   mBuilder.EnterPresShell(mBuilder.RootReferenceFrame());
 
   nsTArray<nsIFrame*> modifiedFrames =
-    GetModifiedFrames(mBuilder.RootReferenceFrame());
+    GetModifiedFrames(&mBuilder);
 
   // Do not allow partial builds if the retained display list is empty, or if
   // ShouldBuildPartial heuristic fails.
   const bool shouldBuildPartial = !mList.IsEmpty() && ShouldBuildPartial(modifiedFrames);
 
   if (mPreviousCaret != mBuilder.GetCaretFrame()) {
     if (mPreviousCaret) {
       if (mBuilder.MarkFrameModifiedDuringBuilding(mPreviousCaret)) {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1164,63 +1164,37 @@ nsDisplayListBuilder::FindAnimatedGeomet
       aItem->Frame(), LayoutFrameType::Viewport, RootReferenceFrame());
     if (viewportFrame) {
       return FindAnimatedGeometryRootFor(viewportFrame);
     }
   }
   return FindAnimatedGeometryRootFor(aItem->Frame());
 }
 
-static bool
-AnyContentAncestorModified(nsIFrame* aFrame,
-                           nsIFrame* aStopAtFrame = nullptr)
-{
-  for (nsIFrame* f = aFrame; f;
-       f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
-    if (f->IsFrameModified()) {
-      return true;
-    }
-
-    if (aStopAtFrame && f == aStopAtFrame) {
-      break;
-    }
-  }
-
-  return false;
-}
-
 bool nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
                                                         nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame->GetParent() == aDirtyFrame);
   nsRect dirty;
   nsRect visible =
     OutOfFlowDisplayData::ComputeVisibleRectForFrame(this, aFrame, GetVisibleRect(),
                                                      GetDirtyRect(), &dirty);
   if (!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) &&
       visible.IsEmpty()) {
     return false;
   }
 
-  // If the nearest stacking context for the modified frame is an ancestor of
-  // of it, and if the stacking context is a descendant of the containing block
-  // of this OOF frame, we override the dirty rect to ensure that the frame will
-  // get marked.
-  if (AnyContentAncestorModified(aFrame, aDirtyFrame)) {
-    dirty = visible;
-  }
-
   // Only MarkFrameForDisplay if we're dirty. If this is a nested out-of-flow frame, then it will
   // also mark any outer frames to ensure that building reaches the dirty feame.
   if (!dirty.IsEmpty() ||
       aFrame->ForceDescendIntoIfVisible()) {
     MarkFrameForDisplay(aFrame, aDirtyFrame);
   }
 
-  return (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
+  return true;
 }
 
 static void UnmarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
   for (nsIFrame* f = aFrame; f;
        f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
     if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
       return;
     f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1453,16 +1453,33 @@ public:
       , mDirtyRect(aDirtyRect)
     {}
     const DisplayItemClipChain* mContainingBlockClipChain;
     const DisplayItemClipChain* mCombinedClipChain; // only necessary for the special case of top layer
     const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot;
     nsRect mVisibleRect;
     nsRect mDirtyRect;
 
+    static bool
+    AnyContentAncestorModified(nsIFrame* aFrame,
+                               nsIFrame* aStopAtFrame = nullptr)
+    {
+      for (nsIFrame* f = aFrame; f;
+           f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
+        if (f->IsFrameModified()) {
+          return true;
+        }
+
+        if (aStopAtFrame && f == aStopAtFrame) {
+          break;
+        }
+      }
+
+      return false;
+    }
 
     static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
                                              nsIFrame* aFrame,
                                              const nsRect& aVisibleRect,
                                              const nsRect& aDirtyRect,
                                              nsRect* aOutDirtyRect) {
       nsRect visible = aVisibleRect;
       nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
@@ -1498,16 +1515,24 @@ public:
         * out of view are pulled into the display list, so they can be
         * prerendered if necessary.
         */
         overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32));
       }
 
       visible.IntersectRect(visible, overflowRect);
       aOutDirtyRect->IntersectRect(*aOutDirtyRect, overflowRect);
+
+      // If the nearest stacking context for the modified frame is an ancestor of
+      // of it, and if the stacking context is a descendant of the containing block
+      // of this OOF frame, we override the dirty rect to ensure that the frame will
+      // get marked.
+      if (AnyContentAncestorModified(aFrame, aFrame->GetParent())) {
+        *aOutDirtyRect = visible;
+      }
       return visible;
     }
 
     nsRect GetVisibleRectForFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                                   nsRect* aDirtyRect) {
       return ComputeVisibleRectForFrame(aBuilder, aFrame, mVisibleRect, mDirtyRect, aDirtyRect);
     }
   };
@@ -1520,18 +1545,17 @@ public:
     nsRect mDirtyRect;
   };
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingRect, DisplayListBuildingData)
 
   NS_DECLARE_FRAME_PROPERTY_DELETABLE(DisplayListBuildingDisplayPortRect, nsRect)
 
   static OutOfFlowDisplayData* GetOutOfFlowData(nsIFrame* aFrame)
   {
-    if (!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
-        !aFrame->GetParent()) {
+    if (!aFrame->GetParent()) {
       return nullptr;
     }
     return aFrame->GetParent()->GetProperty(OutOfFlowDisplayDataProperty());
   }
 
   nsPresContext* CurrentPresContext() {
     return CurrentPresShellState()->mPresShell->GetPresContext();
   }
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5023,19 +5023,16 @@ pref("extensions.webcompat-reporter.newI
 pref("extensions.webcompat-reporter.enabled", true);
 #else
 pref("extensions.webcompat-reporter.enabled", false);
 #endif
 
 pref("network.buffer.cache.count", 24);
 pref("network.buffer.cache.size",  32768);
 
-// Desktop Notification
-pref("notification.feature.enabled", false);
-
 // Web Notification
 pref("dom.webnotifications.enabled", true);
 pref("dom.webnotifications.serviceworker.enabled", true);
 pref("dom.webnotifications.requireinteraction.count", 3);
 #ifdef NIGHTLY_BUILD
 pref("dom.webnotifications.requireinteraction.enabled", true);
 #else
 pref("dom.webnotifications.requireinteraction.enabled", false);
--- a/mozglue/build/WindowsDllServices.h
+++ b/mozglue/build/WindowsDllServices.h
@@ -59,18 +59,18 @@ protected:
 
 #if defined(MOZILLA_INTERNAL_API)
 
 class DllServices : public detail::DllServicesBase
 {
 public:
   virtual void DispatchDllLoadNotification(PCUNICODE_STRING aDllName) override final
   {
-    nsDependentString strDllName(aDllName->Buffer,
-                                 aDllName->Length / sizeof(wchar_t));
+    nsDependentSubstring strDllName(aDllName->Buffer,
+                                    aDllName->Length / sizeof(wchar_t));
 
     nsCOMPtr<nsIRunnable> runnable(
       NewRunnableMethod<bool, nsString>("DllServices::NotifyDllLoad",
                                         this, &DllServices::NotifyDllLoad,
                                         NS_IsMainThread(), strDllName));
 
     SystemGroup::Dispatch(TaskCategory::Other, runnable.forget());
   }
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -4330,20 +4330,20 @@ nsHalfOpenSocket::OnOutputStreamReady(ns
     }
 
     if (((mFastOpenStatus == TFO_DISABLED) ||
         (mFastOpenStatus == TFO_HTTP)) && !mBackupConnStatsSet) {
         // Collect telemetry for backup connection being faster than primary
         // connection. We want to collect this telemetry only for cases where
         // TFO is not used.
         mBackupConnStatsSet = true;
-        Telemetry::ScalarSet(Telemetry::ScalarID::NETWORK_HTTP_BACKUP_CONN_WON,
-                             (out == mBackupStreamOut));
-    }
-        
+        Telemetry::Accumulate(Telemetry::NETWORK_HTTP_BACKUP_CONN_WON_1,
+                              (out == mBackupStreamOut));
+    }
+
     nsresult rv =  SetupConn(out, false);
     if (mEnt) {
         mEnt->mDoNotDestroy = false;
     }
     return rv;
 }
 
 bool
--- a/security/manager/ssl/nsCertOverrideService.cpp
+++ b/security/manager/ssl/nsCertOverrideService.cpp
@@ -6,16 +6,17 @@
 
 #include "nsCertOverrideService.h"
 
 #include "NSSCertDBTrustDomain.h"
 #include "ScopedNSSTypes.h"
 #include "SharedSSLState.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/Unused.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsCRT.h"
 #include "nsILineInputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIOutputStream.h"
 #include "nsISafeOutputStream.h"
 #include "nsIX509Cert.h"
@@ -373,21 +374,23 @@ nsCertOverrideService::RememberValidityO
   nsAutoCString nickname;
   nsresult rv = DefaultServerNicknameForCert(nsscert.get(), nickname);
   if (!aTemporary && NS_SUCCEEDED(rv)) {
     UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
     if (!slot) {
       return NS_ERROR_FAILURE;
     }
 
-    SECStatus srv = PK11_ImportCert(slot.get(), nsscert.get(), CK_INVALID_HANDLE,
-                                    nickname.get(), false);
-    if (srv != SECSuccess) {
-      return NS_ERROR_FAILURE;
-    }
+    // This can fail (for example, if we're in read-only mode). Luckily, we
+    // don't even need it to succeed - we always match on the stored hash of the
+    // certificate rather than the full certificate. It makes the display a bit
+    // less informative (since we won't have a certificate to display), but it's
+    // better than failing the entire operation.
+    Unused << PK11_ImportCert(slot.get(), nsscert.get(), CK_INVALID_HANDLE,
+                              nickname.get(), false);
   }
 
   nsAutoCString fpStr;
   rv = GetCertFingerprintByOidTag(nsscert.get(), mOidTagForStoringNewHashes,
                                   fpStr);
   if (NS_FAILED(rv))
     return rv;
 
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -334,19 +334,19 @@ function run_test() {
                       function(aTransport) { ... });
   [...]
   add_connection_test("<test-name-n>.example.com", PRErrorCodeSuccess);
 
   run_next_test();
 }
 */
 
-function add_tls_server_setup(serverBinName, certsPath) {
+function add_tls_server_setup(serverBinName, certsPath, addDefaultRoot = true) {
   add_test(function() {
-    _setupTLSServerTest(serverBinName, certsPath);
+    _setupTLSServerTest(serverBinName, certsPath, addDefaultRoot);
   });
 }
 
 /**
  * Add a TLS connection test case.
  *
  * @param {String} aHost
  *   The hostname to pass in the SNI TLS extension; this should unambiguously
@@ -486,21 +486,23 @@ function _getBinaryUtil(binaryUtilName) 
     utilBin.initWithPath("/data/local/xpcb/");
     utilBin.append(binaryUtilName);
   }
   Assert.ok(utilBin.exists(), `Binary util ${binaryUtilName} should exist`);
   return utilBin;
 }
 
 // Do not call this directly; use add_tls_server_setup
-function _setupTLSServerTest(serverBinName, certsPath) {
+function _setupTLSServerTest(serverBinName, certsPath, addDefaultRoot) {
   let certdb = Cc["@mozilla.org/security/x509certdb;1"]
                   .getService(Ci.nsIX509CertDB);
   // The trusted CA that is typically used for "good" certificates.
-  addCertFromFile(certdb, `${certsPath}/test-ca.pem`, "CTu,u,u");
+  if (addDefaultRoot) {
+    addCertFromFile(certdb, `${certsPath}/test-ca.pem`, "CTu,u,u");
+  }
 
   const CALLBACK_PORT = 8444;
 
   let envSvc = Cc["@mozilla.org/process/environment;1"]
                  .getService(Ci.nsIEnvironment);
   let greBinDir = Services.dirsvc.get("GreBinD", Ci.nsIFile);
   envSvc.set("DYLD_LIBRARY_PATH", greBinDir.path);
   // TODO(bug 1107794): Android libraries are in /data/local/xpcb, but "GreBinD"
copy from security/manager/ssl/tests/unit/test_cert_overrides.js
copy to security/manager/ssl/tests/unit/test_cert_overrides_read_only.js
--- a/security/manager/ssl/tests/unit/test_cert_overrides.js
+++ b/security/manager/ssl/tests/unit/test_cert_overrides_read_only.js
@@ -1,352 +1,93 @@
 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 "use strict";
 
-// Tests the certificate overrides we allow.
-// add_cert_override_test will queue a test that does the following:
-// 1. Attempt to connect to the given host. This should fail with the
-//    given error and override bits.
-// 2. Add an override for that host/port/certificate/override bits.
-// 3. Connect again. This should succeed.
-
-do_get_profile();
+// Tests that permanent certificate error overrides can be added even if the
+// certificate/key databases are in read-only mode.
 
-function check_telemetry() {
-  let histogram = Services.telemetry
-                    .getHistogramById("SSL_CERT_ERROR_OVERRIDES")
-                    .snapshot();
-  equal(histogram.counts[0], 0, "Should have 0 unclassified counts");
-  equal(histogram.counts[2], 9,
-        "Actual and expected SEC_ERROR_UNKNOWN_ISSUER counts should match");
-  equal(histogram.counts[3], 1,
-        "Actual and expected SEC_ERROR_CA_CERT_INVALID counts should match");
-  equal(histogram.counts[4], 0,
-        "Actual and expected SEC_ERROR_UNTRUSTED_ISSUER counts should match");
-  equal(histogram.counts[5], 1,
-        "Actual and expected SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE counts should match");
-  equal(histogram.counts[6], 0,
-        "Actual and expected SEC_ERROR_UNTRUSTED_CERT counts should match");
-  equal(histogram.counts[7], 0,
-        "Actual and expected SEC_ERROR_INADEQUATE_KEY_USAGE counts should match");
-  equal(histogram.counts[8], 2,
-        "Actual and expected SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED counts should match");
-  equal(histogram.counts[9], 13,
-        "Actual and expected SSL_ERROR_BAD_CERT_DOMAIN counts should match");
-  equal(histogram.counts[10], 5,
-        "Actual and expected SEC_ERROR_EXPIRED_CERTIFICATE counts should match");
-  equal(histogram.counts[11], 2,
-        "Actual and expected MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY counts should match");
-  equal(histogram.counts[12], 1,
-        "Actual and expected MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA counts should match");
-  equal(histogram.counts[13], 1,
-        "Actual and expected MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE counts should match");
-  equal(histogram.counts[14], 2,
-        "Actual and expected MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE counts should match");
-  equal(histogram.counts[15], 1,
-        "Actual and expected MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE counts should match");
-  equal(histogram.counts[16], 2,
-        "Actual and expected SEC_ERROR_INVALID_TIME counts should match");
-  equal(histogram.counts[17], 1,
-        "Actual and expected MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME counts should match");
+// Helper function for add_read_only_cert_override_test. Probably doesn't need
+// to be called directly.
+function add_read_only_cert_override(aHost, aExpectedBits, aSecurityInfo) {
+  let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider)
+                               .SSLStatus;
+  let bits =
+    (sslstatus.isUntrusted ? Ci.nsICertOverrideService.ERROR_UNTRUSTED : 0) |
+    (sslstatus.isDomainMismatch ? Ci.nsICertOverrideService.ERROR_MISMATCH : 0) |
+    (sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0);
 
-  let keySizeHistogram = Services.telemetry
-                           .getHistogramById("CERT_CHAIN_KEY_SIZE_STATUS")
-                           .snapshot();
-  equal(keySizeHistogram.counts[0], 0,
-        "Actual and expected unchecked key size counts should match");
-  equal(keySizeHistogram.counts[1], 16,
-        "Actual and expected successful verifications of 2048-bit keys should match");
-  equal(keySizeHistogram.counts[2], 0,
-        "Actual and expected successful verifications of 1024-bit keys should match");
-  equal(keySizeHistogram.counts[3], 60,
-        "Actual and expected verification failures unrelated to key size should match");
-
-  run_next_test();
+  Assert.equal(bits, aExpectedBits,
+               "Actual and expected override bits should match");
+  let cert = sslstatus.serverCert;
+  let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
+                              .getService(Ci.nsICertOverrideService);
+  // Setting the last argument to false here ensures that we attempt to store a
+  // permanent override (which is what was failing in bug 1427273).
+  certOverrideService.rememberValidityOverride(aHost, 8443, cert, aExpectedBits,
+                                               false);
 }
 
-// Internally, specifying "port" -1 is the same as port 443. This tests that.
-function run_port_equivalency_test(inPort, outPort) {
-  Assert.ok((inPort == 443 && outPort == -1) || (inPort == -1 && outPort == 443),
-            "The two specified ports must be -1 and 443 (in any order)");
-  let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
-                              .getService(Ci.nsICertOverrideService);
-  let cert = constructCertFromFile("bad_certs/default-ee.pem");
-  let expectedBits = Ci.nsICertOverrideService.ERROR_UNTRUSTED;
-  let expectedTemporary = true;
-  certOverrideService.rememberValidityOverride("example.com", inPort, cert,
-                                               expectedBits, expectedTemporary);
-  let actualBits = {};
-  let actualTemporary = {};
-  Assert.ok(certOverrideService.hasMatchingOverride("example.com", outPort,
-                                                    cert, actualBits,
-                                                    actualTemporary),
-            `override set on port ${inPort} should match port ${outPort}`);
-  equal(actualBits.value, expectedBits,
-        "input override bits should match output bits");
-  equal(actualTemporary.value, expectedTemporary,
-        "input override temporary value should match output temporary value");
-  Assert.ok(!certOverrideService.hasMatchingOverride("example.com", 563,
-                                                     cert, {}, {}),
-            `override set on port ${inPort} should not match port 563`);
-  certOverrideService.clearValidityOverride("example.com", inPort);
-  Assert.ok(!certOverrideService.hasMatchingOverride("example.com", outPort,
-                                                     cert, actualBits, {}),
-            `override cleared on port ${inPort} should match port ${outPort}`);
-  equal(actualBits.value, 0, "should have no bits set if there is no override");
+// Given a host, expected error bits (see nsICertOverrideService.idl), and an
+// expected error code, tests that an initial connection to the host fails with
+// the expected errors and that adding an override results in a subsequent
+// connection succeeding.
+function add_read_only_cert_override_test(aHost, aExpectedBits, aExpectedError) {
+  add_connection_test(aHost, aExpectedError, null,
+                      add_read_only_cert_override.bind(this, aHost, aExpectedBits));
+  add_connection_test(aHost, PRErrorCodeSuccess, null, aSecurityInfo => {
+    Assert.ok(aSecurityInfo.securityState &
+              Ci.nsIWebProgressListener.STATE_CERT_USER_OVERRIDDEN,
+              "Cert override flag should be set on the security state");
+  });
 }
 
 function run_test() {
-  run_port_equivalency_test(-1, 443);
-  run_port_equivalency_test(443, -1);
+  let profile = do_get_profile();
+  const KEY_DB_NAME = "key4.db";
+  const CERT_DB_NAME = "cert9.db";
+  let srcKeyDBFile = do_get_file(`test_cert_overrides_read_only/${KEY_DB_NAME}`);
+  srcKeyDBFile.copyTo(profile, KEY_DB_NAME);
+  let srcCertDBFile = do_get_file(`test_cert_overrides_read_only/${CERT_DB_NAME}`);
+  srcCertDBFile.copyTo(profile, CERT_DB_NAME);
+
+  // set the databases to read-only
+  let keyDBFile = do_get_profile();
+  keyDBFile.append(KEY_DB_NAME);
+  keyDBFile.permissions = 0o400;
+  let certDBFile = do_get_profile();
+  certDBFile.append(CERT_DB_NAME);
+  certDBFile.permissions = 0o400;
 
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
-  add_tls_server_setup("BadCertServer", "bad_certs");
+  // Specifying false as the last argument means we don't try to add the default
+  // test root CA (which would fail).
+  add_tls_server_setup("BadCertServer", "bad_certs", false);
 
   let fakeOCSPResponder = new HttpServer();
   fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
     response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
   });
   fakeOCSPResponder.start(8888);
 
-  add_simple_tests();
-  add_localhost_tests();
-  add_combo_tests();
-  add_distrust_tests();
+  // Since we can't add the root CA to the (read-only) trust db, all of these
+  // will result in an "unknown issuer error" and need the "untrusted" error bit
+  // set in addition to whatever other specific error bits are necessary.
+  add_read_only_cert_override_test("expired.example.com",
+                         Ci.nsICertOverrideService.ERROR_TIME |
+                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                         SEC_ERROR_UNKNOWN_ISSUER);
+  add_read_only_cert_override_test("selfsigned.example.com",
+                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                         SEC_ERROR_UNKNOWN_ISSUER);
+  add_read_only_cert_override_test("mismatch.example.com",
+                         Ci.nsICertOverrideService.ERROR_MISMATCH |
+                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                         SEC_ERROR_UNKNOWN_ISSUER);
 
   add_test(function () {
-    fakeOCSPResponder.stop(check_telemetry);
+    fakeOCSPResponder.stop(run_next_test);
   });
 
   run_next_test();
 }
-
-function add_simple_tests() {
-  add_cert_override_test("expired.example.com",
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SEC_ERROR_EXPIRED_CERTIFICATE);
-  add_cert_override_test("notyetvalid.example.com",
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE);
-  add_cert_override_test("before-epoch.example.com",
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SEC_ERROR_INVALID_TIME);
-  add_cert_override_test("selfsigned.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-  add_cert_override_test("unknownissuer.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-  add_cert_override_test("expiredissuer.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
-  add_cert_override_test("notyetvalidissuer.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE);
-  add_cert_override_test("before-epoch-issuer.example.com",
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SEC_ERROR_INVALID_TIME);
-  add_cert_override_test("md5signature.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
-  add_cert_override_test("emptyissuername.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME);
-  // This has name information in the subject alternative names extension,
-  // but not the subject common name.
-  add_cert_override_test("mismatch.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN,
-                         /The certificate is only valid for the following names:\s*doesntmatch\.example\.com, \*\.alsodoesntmatch\.example\.com/);
-  // This has name information in the subject common name but not the subject
-  // alternative names extension.
-  add_cert_override_test("mismatch-CN.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN,
-                         /The certificate is not valid for the name mismatch-CN\.example\.com/);
-
-  // A Microsoft IIS utility generates self-signed certificates with
-  // properties similar to the one this "host" will present.
-  add_cert_override_test("selfsigned-inadequateEKU.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-
-  add_prevented_cert_override_test("inadequatekeyusage.example.com",
-                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                                   SEC_ERROR_INADEQUATE_KEY_USAGE);
-
-  // This is intended to test the case where a verification has failed for one
-  // overridable reason (e.g. unknown issuer) but then, in the process of
-  // reporting that error, a non-overridable error is encountered. The
-  // non-overridable error should be prioritized.
-  add_test(function() {
-    let rootCert = constructCertFromFile("bad_certs/test-ca.pem");
-    setCertTrust(rootCert, ",,");
-    run_next_test();
-  });
-  add_prevented_cert_override_test("nsCertTypeCritical.example.com",
-                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                                   SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
-  add_test(function() {
-    let rootCert = constructCertFromFile("bad_certs/test-ca.pem");
-    setCertTrust(rootCert, "CTu,,");
-    run_next_test();
-  });
-
-  // Bug 990603: Apache documentation has recommended generating a self-signed
-  // test certificate with basic constraints: CA:true. For compatibility, this
-  // is a scenario in which an override is allowed.
-  add_cert_override_test("self-signed-end-entity-with-cA-true.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-
-  add_cert_override_test("ca-used-as-end-entity.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY);
-
-  // If an X.509 version 1 certificate is not a trust anchor, we will
-  // encounter an overridable error.
-  add_cert_override_test("end-entity-issued-by-v1-cert.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA);
-  // If we make that certificate a trust anchor, the connection will succeed.
-  add_test(function() {
-    let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
-                                .getService(Ci.nsICertOverrideService);
-    certOverrideService.clearValidityOverride("end-entity-issued-by-v1-cert.example.com", 8443);
-    let v1Cert = constructCertFromFile("bad_certs/v1Cert.pem");
-    setCertTrust(v1Cert, "CTu,,");
-    clearSessionCache();
-    run_next_test();
-  });
-  add_connection_test("end-entity-issued-by-v1-cert.example.com",
-                      PRErrorCodeSuccess);
-  // Reset the trust for that certificate.
-  add_test(function() {
-    let v1Cert = constructCertFromFile("bad_certs/v1Cert.pem");
-    setCertTrust(v1Cert, ",,");
-    clearSessionCache();
-    run_next_test();
-  });
-
-  // Due to compatibility issues, we allow overrides for certificates issued by
-  // certificates that are not valid CAs.
-  add_cert_override_test("end-entity-issued-by-non-CA.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_CA_CERT_INVALID);
-
-  // This host presents a 1016-bit RSA key.
-  add_cert_override_test("inadequate-key-size-ee.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE);
-
-  add_cert_override_test("ipAddressAsDNSNameInSAN.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN);
-  add_cert_override_test("noValidNames.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN,
-                         /The certificate is not valid for the name noValidNames\.example\.com/);
-  add_cert_override_test("badSubjectAltNames.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN);
-
-  add_cert_override_test("bug413909.xn--hxajbheg2az3al.xn--jxalpdlp",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-  add_test(function() {
-    // At this point, the override for bug413909.xn--hxajbheg2az3al.xn--jxalpdlp
-    // is still valid. Do some additional tests relating to IDN handling.
-    let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
-                                .getService(Ci.nsICertOverrideService);
-    let uri = Services.io.newURI("https://bug413909.xn--hxajbheg2az3al.xn--jxalpdlp");
-    let cert = constructCertFromFile("bad_certs/idn-certificate.pem");
-    Assert.ok(certOverrideService.hasMatchingOverride(uri.asciiHost, 8443, cert, {}, {}),
-              "IDN certificate should have matching override using ascii host");
-    Assert.ok(!certOverrideService.hasMatchingOverride(uri.displayHost, 8443, cert, {}, {}),
-              "IDN certificate should not have matching override using (non-ascii) host");
-    run_next_test();
-  });
-}
-
-function add_localhost_tests() {
-  add_cert_override_test("localhost",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH |
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-  add_cert_override_test("127.0.0.1",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN);
-  add_cert_override_test("::1",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH,
-                         SSL_ERROR_BAD_CERT_DOMAIN);
-}
-
-function add_combo_tests() {
-  add_cert_override_test("mismatch-expired.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH |
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SSL_ERROR_BAD_CERT_DOMAIN,
-                         /The certificate is only valid for <a id="cert_domain_link" title="doesntmatch\.example\.com">doesntmatch\.example\.com<\/a>/);
-  add_cert_override_test("mismatch-notYetValid.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH |
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SSL_ERROR_BAD_CERT_DOMAIN);
-  add_cert_override_test("mismatch-untrusted.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH |
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-  add_cert_override_test("untrusted-expired.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED |
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-  add_cert_override_test("mismatch-untrusted-expired.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH |
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED |
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SEC_ERROR_UNKNOWN_ISSUER);
-
-  add_cert_override_test("md5signature-expired.example.com",
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED |
-                         Ci.nsICertOverrideService.ERROR_TIME,
-                         SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
-
-  add_cert_override_test("ca-used-as-end-entity-name-mismatch.example.com",
-                         Ci.nsICertOverrideService.ERROR_MISMATCH |
-                         Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                         MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY);
-}
-
-function add_distrust_tests() {
-  // Before we specifically distrust this certificate, it should be trusted.
-  add_connection_test("untrusted.example.com", PRErrorCodeSuccess);
-
-  add_distrust_test("bad_certs/default-ee.pem", "untrusted.example.com",
-                    SEC_ERROR_UNTRUSTED_CERT);
-
-  add_distrust_test("bad_certs/other-test-ca.pem",
-                    "untrustedissuer.example.com", SEC_ERROR_UNTRUSTED_ISSUER);
-
-  add_distrust_test("bad_certs/test-ca.pem",
-                    "ca-used-as-end-entity.example.com",
-                    SEC_ERROR_UNTRUSTED_ISSUER);
-}
-
-function add_distrust_test(certFileName, hostName, expectedResult) {
-  let certToDistrust = constructCertFromFile(certFileName);
-
-  add_test(function () {
-    // Add an entry to the NSS certDB that says to distrust the cert
-    setCertTrust(certToDistrust, "pu,,");
-    clearSessionCache();
-    run_next_test();
-  });
-  add_prevented_cert_override_test(hostName,
-                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
-                                   expectedResult);
-  add_test(function () {
-    setCertTrust(certToDistrust, "u,,");
-    run_next_test();
-  });
-}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3d452f335c286da96cd47711ed7bcbb92ed9f841
GIT binary patch
literal 28672
zc%1FmQA^uU6bJA`YdY46J`Bp(L-V-87|FfKZTd2-TA|EU?JCTNAxRsdTc^ynuurhP
z?OW|_Ut-^4kIVgE%~ki{lMKrL2RWSN-g9z{8pyk&{mDG{&n_-Mr*mIAn~v)`TfXl&
zj$0g6$670n%8hf^xu5I2dir~P<B#LjD$bLQji0q&wQse(TIK#yA|fIpqKC2NdG&h3
zJ(--3^RJ^%>12F9n;kB)>10&h8FV|tuHWnLcHjG0^AGxdx$eJ6!$34&uc5;+I!x0n
zpO!nkTOF`=w}Wi%R=oQ2hWi2avqknXAI-}hYqvUFt^PYj*zBx&^=H>V$7D8J<d@}^
z%B?15@otYKY<`z+wccpBKjL|sP4jZKOjfS?3_IKV-J8|LgE<`Z-gX8j{+sTJf86gK
z9e4E|b`JV``@Nl^-`PGG3}5<bP#j@#h~khs#|3>Q)Rz){n&{I6r+P~g=@9FnbZF_2
z=+M?7)gdcF8?6Ep(J>H+<~|W(jHnP>hzVjFF-6P}M;OeEXXZmLOpeY1odr4zbQb6=
z&{?3fM3qF9M3qF9M3us-!m7fm!m2W>=&8`Ng`J6sc!KyzMPPDWD==*o6a+@TO7X0*
zTVl7w?kF(3%|>%YB1VWYqP};8yGFQcgx^by+8DKQV6N!eQ69@k#-UAxO>b<7Y#Q5C
z*|cTTq)e49Q?^XmGG)uub(yl`C_9d_<0w0hvg0T_j<Vw@J5G_dZJOFNv+2mDW1HqS
zJu6fEA(%9?<79fAahwL@3{N}>z&>BqZiXvfz1wgd^ZNKQExzba)5ZJ(=cnaA>1kM|
ztHo>Yk$(5B>#+G>U%x~|L_|bHMD)NO>%i}SA|fIpA|j%t#_xY3A|fIpBBJHT?|&j9
hA|fIpqUFc$e<C6xA|fK9<;U-TA|fIpA|j&Y_ZNs~P}%?h
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..44d0cb172812d17b8f8de88bce066142d1c0cf2f
GIT binary patch
literal 36864
zc%1Fr&u`mg7zc1WKio7~)gC6Ifim9Q8rZ<`k2j9kVQK0?MAvqq6P;j+?8K7-={g!0
zxNz7G+XZol3rGG9rU`_`PUFOlX-5u#HZ-`+@8f1qs|{_JX(IZ56hC?F_kEu{wcE6A
zrM`D&Wf(`|!uHNq5DQyd&~#lpDTJnJnPi*Qn2~I`efzrhbQ$f9!*}N9|IrG?P3=%|
z{zmDC(if$-iVupL#UGzxJpcdz0Q^skW@gHjihlX^I0#44Rul)zK^#n;3+=Ao+VI6j
zYiY$7lcQpBI1uaI&goY7oOstiC(f>R&Ybnd+Nx-;t)5!xv^PZ8Utejp{bM5esdcNK
zK3TOl3r4wJ(Y4{lLG=0flTmWC7wpE{wBMW5@6{*S?2=)W%T@gYn$Z6^7!EFu$Ll-8
zPlGs`*=w$|y6kTX8dNRt1hE*@O{;b?Pc`1B8lxbLMm)thP=f{^t6|qp<&5$xRlS$C
zy&HZM^<$orKTu<D_z9iVYwfI2J~H`ehU4*Ww8L|92g;<Qk5%#NwQEwJDOaodR}H#k
zJj_|<z-8NC;OQ5xwY1jVI3@x!*^=uPSjlFqoDQfXb#=&7yPn$hXje_~92Hy@qzVlc
zJQbQM1S*6{Xi_ONja1RJD5kIDP;@CuiVcb$#U{moVo0%1jiv3S{ZVeEIaRi(vPG3G
zs%%kZiz-`G*``%Ct+HvAO{;8LC23UBsH9OzqcR<(nv!ZZXr`A&I)n6)T4tK7wH9^j
zm<fwo-b?9R(`=h&+ceuT)7k07^oUK-q3BXnukFyQI`pazT^E<uy0q3c(<5qaKXPry
zcI%v4obH?8aO!d@Ic;$2JxV1nle|pwGRe#2WSQi4B)22E9m(xTZbx!ElG~BoPLeh`
z4LA)s?Q=TdG~)Eaqm(`o(lq3DLe<W|4a`AEXWTOhpI_Om*%_n!cJ;sB{P?T1SLZyN
zyhRt(`}CX&3orCr1poj500000JZD7}aQ_bg0000005H{X{|^8F00000F#T}<4*&oF
z0000m{c!&e00000001!kaQ_bg0000005JX3|NqzLztxfl000000002I7(G2-aV{4w
z1>^B&+dG4Aelj%wrB^@v`{weW-@W|rm9Nj=KX0Be7md<uSKqn%U`{`j*R$r4+~J>p
z`Q!NQqnB=7zm>fmHitJ)-?^91=z4D9MrZfh_i^LI-7oL`_Um7Fe^-D1*XQqR$pZiY
S000000H#POTbZ5wM&TjL;kpt4
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -5,16 +5,17 @@ support-files =
   bad_certs/**
   ocsp_certs/**
   test_baseline_requirements/**
   test_broken_fips/**
   test_cert_eku/**
   test_cert_embedded_null/**
   test_cert_isBuiltInRoot_reload/**
   test_cert_keyUsage/**
+  test_cert_overrides_read_only/**
   test_cert_sha1/**
   test_cert_signatures/**
   test_cert_trust/**
   test_cert_version/**
   test_certDB_import/**
   test_certviewer_invalid_oids/**
   test_content_signing/**
   test_ct/**
@@ -52,16 +53,18 @@ run-sequentially = hardcoded ports
 [test_cert_dbKey.js]
 [test_cert_eku.js]
 [test_cert_embedded_null.js]
 [test_cert_keyUsage.js]
 [test_cert_isBuiltInRoot.js]
 [test_cert_isBuiltInRoot_reload.js]
 [test_cert_overrides.js]
 run-sequentially = hardcoded ports
+[test_cert_overrides_read_only.js]
+run-sequentially = hardcoded ports
 [test_cert_override_bits_mismatches.js]
 run-sequentially = hardcoded ports
 [test_cert_sha1.js]
 [test_cert_signatures.js]
 [test_cert_trust.js]
 [test_cert_version.js]
 [test_certDB_import.js]
 [test_certDB_import_pkcs12.js]
--- a/taskcluster/taskgraph/transforms/diffoscope.py
+++ b/taskcluster/taskgraph/transforms/diffoscope.py
@@ -48,19 +48,20 @@ diff_description_schema = Schema({
     # Extra arguments to pass to diffoscope, that can be set per job.
     Optional('extra-args'): basestring,
 })
 
 
 @transforms.add
 def validate(config, tasks):
     for task in tasks:
-        yield validate_schema(
+        validate_schema(
             diff_description_schema, task,
             "In diff task {!r}:".format(task.get('name', 'unknown')))
+        yield task
 
 
 @transforms.add
 def fill_template(config, tasks):
     dummy_tasks = {}
 
     for task in tasks:
         name = task['name']
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/service-worker/fetch-response-taint.https.html.ini
+++ /dev/null
@@ -1,20 +0,0 @@
-[fetch-response-taint.https.html]
-  type: testharness
-  [fetching url:"https://web-platform.test:8443/?url=https%3A%2F%2Fwww1.web-platform.test%3A8443%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FACAOrigin%3D*&mode=cors&credentials=omit&" mode:"same-origin" credentials:"omit" should succeed.]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
-  [fetching url:"https://web-platform.test:8443/?url=https%3A%2F%2Fwww1.web-platform.test%3A8443%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FACAOrigin%3D*&mode=cors&credentials=omit&" mode:"same-origin" credentials:"same-origin" should succeed.]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
-  [fetching url:"https://web-platform.test:8443/?url=https%3A%2F%2Fwww1.web-platform.test%3A8443%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FACAOrigin%3D*&mode=cors&credentials=omit&" mode:"same-origin" credentials:"include" should succeed.]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
-  [fetching url:"https://web-platform.test:8443/?url=https%3A%2F%2Fwww1.web-platform.test%3A8443%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8443%26ACACredentials%3Dtrue&mode=cors&credentials=include&" mode:"same-origin" credentials:"omit" should succeed.]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
-  [fetching url:"https://web-platform.test:8443/?url=https%3A%2F%2Fwww1.web-platform.test%3A8443%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8443%26ACACredentials%3Dtrue&mode=cors&credentials=include&" mode:"same-origin" credentials:"same-origin" should succeed.]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
-  [fetching url:"https://web-platform.test:8443/?url=https%3A%2F%2Fwww1.web-platform.test%3A8443%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8443%26ACACredentials%3Dtrue&mode=cors&credentials=include&" mode:"same-origin" credentials:"include" should succeed.]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/service-worker/worker-interception.https.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[worker-interception.https.html]
-  type: testharness
-  [Verify worker script intercepted by cors response succeeds]
-    expected: FAIL # issue: https://github.com/whatwg/fetch/issues/629
-
--- a/testing/web-platform/tests/html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-anchor-name.html
+++ b/testing/web-platform/tests/html/browsers/browsing-the-web/scroll-to-fragid/scroll-to-anchor-name.html
@@ -3,29 +3,35 @@
 <meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <div></div>
 <a name="anchor1" style="position:absolute; top:200px;"></a>
 <div id="id-equals-anchor" style="position:absolute; top:300px;"></div>
 <a name="id-equals-anchor" style="position:absolute; top:400px;"></a>
+<a name="§1" style="position:absolute; top:400px;"></a>
 <div style="height:200em;"></div>
 <script>
 var steps = [{
     fragid:'anchor1',
       handler: function(){
         assert_equals( scrollPosition(), 200 );
       }
     },{
       fragid:'id-equals-anchor',
       handler: function(){
         // id still takes precedence over anchor name
         assert_equals( scrollPosition(), 300 );
       }
+    },{
+      fragid:'§1',
+      handler: function(){
+        assert_equals( scrollPosition(), 400 );
+      }
     }];
 
 function scrollPosition(){
   return document.documentElement.scrollTop || document.body.scrollTop;
 }
 
 function runNextStep(){
     if( steps.length > 0 ) {
--- a/testing/web-platform/tests/service-workers/service-worker/fetch-response-taint.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/fetch-response-taint.https.html
@@ -188,30 +188,36 @@ for_each_origin_mode_credentials(functio
 
 for_each_origin_mode_credentials(function(origin, mode, credentials) {
   var url = build_rewrite_url(
       origin, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit');
 
   // Fetch to the other origin with same-origin mode should fail.
   if (origin == OTHER_ORIGIN && mode == 'same-origin') {
     ng_test(url, mode, credentials);
+  } else if (origin == BASE_ORIGIN && mode == 'same-origin') {
+    // Cors type response to a same-origin mode request should fail
+    ng_test(url, mode, credentials);
   } else {
     // The response from the SW should be cors.
     ok_test(url, mode, credentials, 'cors', 'undefined');
   }
 });
 
 for_each_origin_mode_credentials(function(origin, mode, credentials) {
   var url = build_rewrite_url(
       origin,
       OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN +
       '&ACACredentials=true',
       'cors', 'include');
   // Fetch to the other origin with same-origin mode should fail.
   if (origin == OTHER_ORIGIN && mode == 'same-origin') {
     ng_test(url, mode, credentials);
+  } else if (origin == BASE_ORIGIN && mode == 'same-origin') {
+    // Cors type response to a same-origin mode request should fail
+    ng_test(url, mode, credentials);
   } else {
     // The response from the SW should be cors.
     ok_test(url, mode, credentials, 'cors', 'username1s');
   }
 });
 </script>
 </body>
--- a/testing/web-platform/tests/service-workers/service-worker/worker-interception.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/worker-interception.https.html
@@ -76,20 +76,26 @@ promise_test(function(t) {
               }
 
               w.onerror = function(e) {
                 reject(e.message);
               }
             });
         })
       .then(function(data) {
-          assert_equals(data, 'dummy-worker-script loaded');
+          assert_unreached('intercepted cors response to a same-origin mode ' +
+                           'worker load should fail');
           service_worker_unregister_and_done(t, scope);
-        });
-  }, 'Verify worker script intercepted by cors response succeeds');
+        })
+      .catch(function(e) {
+          assert_true(true, 'intercepted cors response to a same-origin mode ' +
+                            'worker load should fail');
+          service_worker_unregister_and_done(t, scope);
+       });
+  }, 'Verify worker script intercepted by cors response fails');
 
 promise_test(function(t) {
     var worker_url = 'resources/dummy-no-cors-worker.js';
     var service_worker = 'resources/dummy-worker-interceptor.js';
     var scope = worker_url;
 
     return service_worker_unregister_and_register(t, service_worker, scope)
       .then(function(r) {
--- a/toolkit/components/extensions/schemas/extension_protocol_handlers.json
+++ b/toolkit/components/extensions/schemas/extension_protocol_handlers.json
@@ -11,18 +11,18 @@
             "description": "A user-readable title string for the protocol handler. This will be displayed to the user in interface objects as needed.",
             "type": "string"
           },
           "protocol": {
             "description": "The protocol the site wishes to handle, specified as a string. For example, you can register to handle SMS text message links by registering to handle the \"sms\" scheme.",
             "choices": [{
               "type": "string",
               "enum": [
-                "bitcoin", "geo", "gopher", "im", "irc", "ircs", "magnet",
-                "mailto", "mms", "news", "nntp", "sip", "sms", "smsto", "ssh",
+                "bitcoin", "dat", "dweb", "geo", "gopher", "im", "ipfs", "ipns", "irc", "ircs", "magnet",
+                "mailto", "mms", "news", "nntp", "sip", "sms", "smsto", "ssb", "ssh",
                 "tel", "urn", "webcal", "wtai", "xmpp"
               ]
             }, {
               "type": "string",
               "pattern": "^(ext|web)\\+[a-z0-9.+-]+$"
             }]
           },
           "uriTemplate": {
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2436,16 +2436,24 @@
     "record_in_processes": ["main", "content"],
     "expires_in_version": "61",
     "kind": "enumerated",
     "n_values": 8,
     "description": "TCP Fast Open was: 0=enabled during the session, 1=not available or disabled in the os, 2=disabled by the pref, 3=disabled based on the too many connection failures, 4=disable based on too many http transaction stalls after a connection was idle.",
     "alert_emails": ["necko@mozilla.com", "ddamjanovic@mozilla.com"],
     "bug_numbers": [1390881]
   },
+  "NETWORK_HTTP_BACKUP_CONN_WON_1" : {
+    "record_in_processes": ["main"],
+    "expires_in_version": "61",
+    "kind": "boolean",
+    "description": "For connection where TFO has not be use, collect telemetry on whether the backup connection or the primary connection was faster.",
+    "alert_emails": ["necko@mozilla.com", "ddamjanovic@mozilla.com"],
+    "bug_numbers": [1426710]
+  },
   "TLS_EARLY_DATA_NEGOTIATED": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "62",
     "kind": "enumerated",
     "n_values": 3,
     "description": "Sending TLS early data was possible: 0 - not possible, 1 - possible but not used, 2 - possible and used.",
     "alert_emails": ["necko@mozilla.com"],
     "bug_numbers": [1296288]
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -1262,31 +1262,16 @@ screenshots:
     notification_emails:
       - jhirsch@mozilla.com
       - ibicking@mozilla.com
       - clouserw@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'main'
 
-network.http:
-  backup_conn_won:
-    bug_numbers:
-      - 1402811
-    description: >
-      For connection where TFO has not be use, collect telemetry on whether the
-      backup connection or the primary connection was faster.
-    expires: "61"
-    kind: boolean
-    notification_emails:
-      - necko@mozilla.com
-      - ddamjanovic@mozilla.com
-    record_in_processes:
-      - 'main'
-
 idb.type:
   persistent_count:
     bug_numbers:
       - 1360567
     description: >
       Number of times indexeddb.open(name, {storage: "persistent"}) has been used.
     expires: "60"
     kind: uint
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -1926,16 +1926,22 @@ SetHistogramRecordingEnabled(HistogramID
 
 void
 Accumulate(HistogramID aHistogram, uint32_t aSample)
 {
   TelemetryHistogram::Accumulate(aHistogram, aSample);
 }
 
 void
+Accumulate(HistogramID aHistogram, const nsTArray<uint32_t>& aSamples)
+{
+  TelemetryHistogram::Accumulate(aHistogram, aSamples);
+}
+
+void
 Accumulate(HistogramID aID, const nsCString& aKey, uint32_t aSample)
 {
   TelemetryHistogram::Accumulate(aID, aKey, aSample);
 }
 
 void
 Accumulate(const char* name, uint32_t sample)
 {
--- a/toolkit/components/telemetry/Telemetry.h
+++ b/toolkit/components/telemetry/Telemetry.h
@@ -54,16 +54,23 @@ void Init();
  * Adds sample to a histogram defined in TelemetryHistogramEnums.h
  *
  * @param id - histogram id
  * @param sample - value to record.
  */
 void Accumulate(HistogramID id, uint32_t sample);
 
 /**
+ * Adds an array of samples to a histogram defined in TelemetryHistograms.h
+ * @param id - histogram id
+ * @param samples - values to record.
+ */
+void Accumulate(HistogramID id, const nsTArray<uint32_t>& samples);
+
+/**
  * Adds sample to a keyed histogram defined in TelemetryHistogramEnums.h
  *
  * @param id - keyed histogram id
  * @param key - the string key
  * @param sample - (optional) value to record, defaults to 1.
  */
 void Accumulate(HistogramID id, const nsCString& key, uint32_t sample = 1);
 
--- a/toolkit/components/telemetry/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/TelemetryHistogram.cpp
@@ -1870,16 +1870,32 @@ TelemetryHistogram::Accumulate(Histogram
     return;
   }
 
   StaticMutexAutoLock locker(gTelemetryHistogramMutex);
   internal_Accumulate(aID, aSample);
 }
 
 void
+TelemetryHistogram::Accumulate(HistogramID aID, const nsTArray<uint32_t>& aSamples)
+{
+  if (NS_WARN_IF(!internal_IsHistogramEnumId(aID))) {
+    MOZ_ASSERT_UNREACHABLE("Histogram usage requires valid ids.");
+    return;
+  }
+
+  MOZ_ASSERT(!gHistogramInfos[aID].keyed, "Cannot accumulate into a keyed histogram. No key given.");
+
+  StaticMutexAutoLock locker(gTelemetryHistogramMutex);
+  for(uint32_t sample: aSamples){
+    internal_Accumulate(aID, sample);
+  }
+}
+
+void
 TelemetryHistogram::Accumulate(HistogramID aID,
                                const nsCString& aKey, uint32_t aSample)
 {
   if (NS_WARN_IF(!internal_IsHistogramEnumId(aID))) {
     MOZ_ASSERT_UNREACHABLE("Histogram usage requires valid ids.");
     return;
   }
 
--- a/toolkit/components/telemetry/TelemetryHistogram.h
+++ b/toolkit/components/telemetry/TelemetryHistogram.h
@@ -31,16 +31,17 @@ bool CanRecordExtended();
 void SetCanRecordExtended(bool b);
 
 void InitHistogramRecordingEnabled();
 void SetHistogramRecordingEnabled(mozilla::Telemetry::HistogramID aID, bool aEnabled);
 
 nsresult SetHistogramRecordingEnabled(const nsACString &id, bool aEnabled);
 
 void Accumulate(mozilla::Telemetry::HistogramID aHistogram, uint32_t aSample);
+void Accumulate(mozilla::Telemetry::HistogramID aHistogram, const nsTArray<uint32_t>& aSamples);
 void Accumulate(mozilla::Telemetry::HistogramID aID, const nsCString& aKey,
                                             uint32_t aSample);
 void Accumulate(const char* name, uint32_t sample);
 void Accumulate(const char* name, const nsCString& key, uint32_t sample);
 
 void AccumulateCategorical(mozilla::Telemetry::HistogramID aId, const nsCString& aLabel);
 
 void AccumulateChild(mozilla::Telemetry::ProcessID aProcessType,
--- a/toolkit/components/telemetry/tests/gtest/TestHistograms.cpp
+++ b/toolkit/components/telemetry/tests/gtest/TestHistograms.cpp
@@ -233,8 +233,119 @@ TEST_F(TelemetryTestFixture, AccumulateK
   GetElement(cx.GetJSContext(),
              static_cast<uint32_t>(Telemetry::LABELS_TELEMETRY_TEST_KEYED_CATEGORICAL::CommonLabel),
              otherCounts, &otherValue);
   // Check that the value stored in the histogram matches with |kOtherSampleExpectedValue|
   uint32_t uOtherValue = 0;
   JS::ToUint32(cx.GetJSContext(), otherValue, &uOtherValue);
   ASSERT_EQ(uOtherValue, kOtherSampleExpectedValue) << "The other-sample histogram is not returning expected value";
 }
+
+TEST_F(TelemetryTestFixture, AccumulateCountHistogram_MultipleSamples)
+{
+  nsTArray<uint32_t> samples({4,4,4});
+  const uint32_t kExpectedSum = 12;
+
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_COUNT"),
+                        false);
+
+  // Accumulate in histogram
+  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_COUNT, samples);
+
+  // Get a snapshot of all the histograms
+  JS::RootedValue snapshot(cx.GetJSContext());
+  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_COUNT", &snapshot, false);
+
+  // Get histogram from snapshot
+  JS::RootedValue histogram(cx.GetJSContext());
+  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_COUNT", snapshot, &histogram);
+
+  // Get "sum" from histogram
+  JS::RootedValue sum(cx.GetJSContext());
+  GetProperty(cx.GetJSContext(), "sum", histogram, &sum);
+
+  // Check that sum matches with aValue
+  uint32_t uSum = 0;
+  JS::ToUint32(cx.GetJSContext(), sum, &uSum);
+  ASSERT_EQ(uSum, kExpectedSum) << "This histogram is not returning expected value";
+}
+
+TEST_F(TelemetryTestFixture, AccumulateLinearHistogram_MultipleSamples)
+{
+  nsTArray<uint32_t> samples({4,4,4});
+  const uint32_t kExpectedCount = 3;
+
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_LINEAR"),
+                        false);
+
+  // Accumulate in the histogram
+  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_LINEAR, samples);
+
+  // Get a snapshot of all the histograms
+  JS::RootedValue snapshot(cx.GetJSContext());
+  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_LINEAR", &snapshot, false);
+
+  // Get histogram from snapshot
+  JS::RootedValue histogram(cx.GetJSContext());
+  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_LINEAR", snapshot, &histogram);
+
+  // Get "counts" array from histogram
+  JS::RootedValue counts(cx.GetJSContext());
+  GetProperty(cx.GetJSContext(), "counts", histogram, &counts);
+
+  // Index 0 is only for values less than 'low'. Values within range start at index 1
+  JS::RootedValue count(cx.GetJSContext());
+  const uint32_t index = 1;
+  GetElement(cx.GetJSContext(), index, counts, &count);
+
+  // Check that this count matches with nSamples
+  uint32_t uCount = 0;
+  JS::ToUint32(cx.GetJSContext(), count, &uCount);
+  ASSERT_EQ(uCount, kExpectedCount) << "The histogram did not accumulate the correct number of values";
+}
+
+TEST_F(TelemetryTestFixture, AccumulateLinearHistogram_DifferentSamples)
+{
+  nsTArray<uint32_t> samples({4, 8, 2147483646});
+
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  GetAndClearHistogram(cx.GetJSContext(), mTelemetry, NS_LITERAL_CSTRING("TELEMETRY_TEST_LINEAR"),
+                        false);
+
+  // Accumulate in histogram
+  Telemetry::Accumulate(Telemetry::TELEMETRY_TEST_LINEAR, samples);
+
+  // Get a snapshot of all histograms
+  JS::RootedValue snapshot(cx.GetJSContext());
+  GetSnapshots(cx.GetJSContext(), mTelemetry, "TELEMETRY_TEST_LINEAR", &snapshot, false);
+
+  // Get histogram from snapshot
+  JS::RootedValue histogram(cx.GetJSContext());
+  GetProperty(cx.GetJSContext(), "TELEMETRY_TEST_LINEAR", snapshot, &histogram);
+
+  // Get counts array from histogram
+  JS::RootedValue counts(cx.GetJSContext());
+  GetProperty(cx.GetJSContext(), "counts", histogram, &counts);
+
+  // Get counts in first and last buckets
+  JS::RootedValue countFirst(cx.GetJSContext());
+  JS::RootedValue countLast(cx.GetJSContext());
+  const uint32_t firstIndex = 1;
+  const uint32_t lastIndex = 9;
+  GetElement(cx.GetJSContext(), firstIndex, counts, &countFirst);
+  GetElement(cx.GetJSContext(), lastIndex, counts, &countLast);
+
+  // Check that the counts match
+  uint32_t uCountFirst = 0;
+  uint32_t uCountLast = 0;
+  JS::ToUint32(cx.GetJSContext(), countFirst, &uCountFirst);
+  JS::ToUint32(cx.GetJSContext(), countLast, &uCountLast);
+
+  const uint32_t kExpectedCountFirst = 2;
+  const uint32_t kExpectedCountLast = 1;
+  ASSERT_EQ(uCountFirst, kExpectedCountFirst) << "The first bucket did not accumulate the correct number of values";
+  ASSERT_EQ(uCountLast, kExpectedCountLast) << "The last bucket did not accumulate the correct number of values";
+}
--- a/toolkit/content/preferencesBindings.js
+++ b/toolkit/content/preferencesBindings.js
@@ -297,16 +297,17 @@ const Preferences = window.Preferences =
         throw new Error(`preference with id '${id}' doesn't have name`);
       }
 
       // In non-instant apply mode, we must try and use the last saved state
       // from any previous opens of a child dialog instead of the value from
       // preferences, to pick up any edits a user may have made.
 
       if (Preferences.type == "child" && window.opener &&
+          window.opener.Preferences &&
           Services.scriptSecurityManager.isSystemPrincipal(window.opener.document.nodePrincipal)) {
         // Try to find the preference in the parent window.
         const preference = window.opener.Preferences.get(this.name);
 
         // Don't use the value setter here, we don't want updateElements to be
         // prematurely fired.
         this._value = preference ? preference.value : this.valueFromPreferences;
       } else
--- a/toolkit/content/tests/chrome/test_preferences_beforeaccept.xul
+++ b/toolkit/content/tests/chrome/test_preferences_beforeaccept.xul
@@ -8,16 +8,21 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
   <script type="application/javascript">
   <![CDATA[
     SimpleTest.waitForExplicitFinish();
     SpecialPowers.pushPrefEnv({"set":[["browser.preferences.instantApply", false]]}, function() {
 
+    SimpleTest.registerCleanupFunction(() => {
+      SpecialPowers.clearUserPref("tests.beforeaccept.dialogShown");
+      SpecialPowers.clearUserPref("tests.beforeaccept.called");
+    });
+
     // No instant-apply for this test
     var prefWindow = openDialog("window_preferences_beforeaccept.xul", "", "", windowOnload);
 
     function windowOnload() {
       var dialogShown = prefWindow.Preferences.get("tests.beforeaccept.dialogShown");
       var called = prefWindow.Preferences.get("tests.beforeaccept.called");
       is(dialogShown.value, true, "dialog opened, shown pref set");
       is(dialogShown.valueFromPreferences, null, "shown pref not committed");
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -252,72 +252,16 @@
         let box = this.inputField.parentNode;
         let menu = document.getAnonymousElementByAttribute(box, "anonid", "input-box-contextmenu");
         box._doPopupItemEnabling(menu);
       </handler>
 #endif
     </handlers>
   </binding>
 
-  <binding id="timed-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
-    <implementation>
-      <constructor><![CDATA[
-        try {
-          var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
-                                         .getService(Components.interfaces.nsIConsoleService);
-          var scriptError = Components.classes["@mozilla.org/scripterror;1"]
-                                      .createInstance(Components.interfaces.nsIScriptError);
-          scriptError.init("Timed textboxes are deprecated. Consider using type=\"search\" instead.",
-                           this.ownerDocument.location.href, null, null,
-                           null, scriptError.warningFlag, "XUL Widgets");
-          consoleService.logMessage(scriptError);
-        } catch (e) {}
-      ]]></constructor>
-      <field name="_timer">null</field>
-      <property name="timeout"
-                onset="this.setAttribute('timeout', val); return val;"
-                onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
-      <property name="value"
-                onget="return this.inputField.value;">
-        <setter><![CDATA[
-          this.inputField.value = val;
-          if (this._timer)
-            clearTimeout(this._timer);
-          return val;
-        ]]></setter>
-      </property>
-      <method name="_fireCommand">
-        <parameter name="me"/>
-        <body>
-          <![CDATA[
-            me._timer = null;
-            me.doCommand();
-          ]]>
-        </body>
-      </method>
-    </implementation>
-    <handlers>
-      <handler event="input">
-        <![CDATA[
-          if (this._timer)
-            clearTimeout(this._timer);
-          this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this);
-        ]]>
-      </handler>
-      <handler event="keypress" keycode="VK_RETURN">
-        <![CDATA[
-          if (this._timer)
-            clearTimeout(this._timer);
-          this._fireCommand(this);
-          event.preventDefault();
-        ]]>
-      </handler>
-    </handlers>
-  </binding>
-
   <binding id="search-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
     <content>
       <children/>
       <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck" align="center">
         <xul:image class="textbox-search-sign"/>
         <html:input class="textbox-input" anonid="input" mozactionhint="search"
                     xbl:inherits="value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint,spellcheck"/>
         <xul:deck class="textbox-search-icons" anonid="search-icons">
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -773,20 +773,16 @@ html|textarea.textbox-textarea {
 textbox[resizable="true"] > .textbox-input-box > html|textarea.textbox-textarea {
   resize: both;
 }
 
 .textbox-input-box[spellcheck="true"] {
   -moz-binding: url("chrome://global/content/bindings/textbox.xml#input-box-spell");
 }
 
-textbox[type="timed"] {
-  -moz-binding: url("chrome://global/content/bindings/textbox.xml#timed-textbox");
-}
-
 textbox[type="search"] {
   -moz-binding: url("chrome://global/content/bindings/textbox.xml#search-textbox");
 }
 
 textbox[type="number"] {
   -moz-binding: url("chrome://global/content/bindings/numberbox.xml#numberbox");
 }
 
--- a/widget/cocoa/OSXNotificationCenter.h
+++ b/widget/cocoa/OSXNotificationCenter.h
@@ -8,16 +8,21 @@
 
 #import <Foundation/Foundation.h>
 #include "nsIAlertsService.h"
 #include "imgINotificationObserver.h"
 #include "nsITimer.h"
 #include "nsTArray.h"
 #include "mozilla/RefPtr.h"
 
+// mozNotificationCenterDelegate is used to access the macOS notification
+// center. It is not related to the DesktopNotificationCenter object, which was
+// removed in bug 952453. While there are no direct references to this class
+// elsewhere, removing this will cause push notifications on macOS to stop
+// working.
 @class mozNotificationCenterDelegate;
 
 #if !defined(MAC_OS_X_VERSION_10_8) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8)
 typedef NSInteger NSUserNotificationActivationType;
 #endif
 
 namespace mozilla {
 
--- a/widget/windows/nsAppShell.cpp
+++ b/widget/windows/nsAppShell.cpp
@@ -165,39 +165,53 @@ nsAppShell::~nsAppShell()
     SendMessage(mEventWnd, WM_CLOSE, 0, 0);
   }
 }
 
 #if defined(ACCESSIBILITY)
 
 static ULONG gUiaMsg;
 static HHOOK gUiaHook;
+static uint32_t gUiaAttempts;
+static const uint32_t kMaxUiaAttempts = 5;
 
 static void InitUIADetection();
 
 static LRESULT CALLBACK
 UiaHookProc(int aCode, WPARAM aWParam, LPARAM aLParam)
 {
   if (aCode < 0) {
     return ::CallNextHookEx(nullptr, aCode, aWParam, aLParam);
   }
 
   auto cwp = reinterpret_cast<CWPSTRUCT*>(aLParam);
   if (gUiaMsg && cwp->message == gUiaMsg) {
-    Maybe<bool> shouldCallNextHook =
-      a11y::Compatibility::OnUIAMessage(cwp->wParam, cwp->lParam);
+    if (gUiaAttempts < kMaxUiaAttempts) {
+      ++gUiaAttempts;
+
+      Maybe<bool> shouldCallNextHook =
+        a11y::Compatibility::OnUIAMessage(cwp->wParam, cwp->lParam);
+      if (shouldCallNextHook.isSome()) {
+        // We've got an instantiator, disconnect this hook.
+        if (::UnhookWindowsHookEx(gUiaHook)) {
+          gUiaHook = nullptr;
+        }
 
-    // Unconditionally remove the hook, as UIA detection is too expensive to
-    // leave running for every single request.
-    if (::UnhookWindowsHookEx(gUiaHook)) {
-      gUiaHook = nullptr;
-    }
-
-    if (shouldCallNextHook.isSome() && !shouldCallNextHook.value()) {
-      return 0;
+        if (!shouldCallNextHook.value()) {
+          return 0;
+        }
+      } else {
+        // Our hook might be firing after UIA; let's try reinstalling ourselves.
+        InitUIADetection();
+      }
+    } else {
+      // We've maxed out our attempts. Let's unhook.
+      if (::UnhookWindowsHookEx(gUiaHook)) {
+        gUiaHook = nullptr;
+      }
     }
   }
 
   return ::CallNextHookEx(nullptr, aCode, aWParam, aLParam);
 }
 
 static void
 InitUIADetection()