Merge autoland to mozilla-central. a=merge
authorNorisz Fay <nfay@mozilla.com>
Fri, 28 Jan 2022 11:46:56 +0200
changeset 605803 559c2c231f2187c471b1e482e85ad9b96218800f
parent 605771 a1eacaa51e292d7af90e44d105f91c03ded0c3c7 (current diff)
parent 605802 ca59b09ea1e4fbde0c1e3b3d9ad3245452465dae (diff)
child 605827 9ff7796619fe2c6f78d6c6d30bd8fb4fa92a11bd
push id39207
push usernfay@mozilla.com
push dateFri, 28 Jan 2022 09:47:30 +0000
treeherdermozilla-central@559c2c231f21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone98.0a1
first release with
nightly linux32
559c2c231f21 / 98.0a1 / 20220128094730 / files
nightly linux64
559c2c231f21 / 98.0a1 / 20220128094730 / files
nightly mac
559c2c231f21 / 98.0a1 / 20220128094730 / files
nightly win32
559c2c231f21 / 98.0a1 / 20220128094730 / files
nightly win64
559c2c231f21 / 98.0a1 / 20220128094730 / 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 autoland to mozilla-central. a=merge
--- a/browser/components/downloads/DownloadsViewUI.jsm
+++ b/browser/components/downloads/DownloadsViewUI.jsm
@@ -319,16 +319,20 @@ var DownloadsViewUI = {
      * There are also cases where download.contentType is undefined (ex. when opening
      * the context menu on a previously downloaded item via download history).
      * Using mimeInfo ensures that content type exists and prevents intermittence.
      */
     let shouldNotRememberChoice =
       !mimeInfo?.type ||
       mimeInfo.type === "application/octet-stream" ||
       mimeInfo.type === "application/x-msdownload" ||
+      mimeInfo.type === "application/x-msdos-program" ||
+      gReputationService.isExecutable(
+        PathUtils.filename(download.target.path)
+      ) ||
       (mimeInfo.type === "text/plain" &&
         gReputationService.isBinary(download.target.path));
 
     if (DownloadsViewUI.improvementsIsOn && !canViewInternally) {
       alwaysOpenSimilarFilesItem.hidden =
         state !== DOWNLOAD_FINISHED || shouldNotRememberChoice;
     } else {
       alwaysOpenSimilarFilesItem.hidden = true;
--- a/build/autoconf/toolchain.m4
+++ b/build/autoconf/toolchain.m4
@@ -77,20 +77,18 @@ case "${TOOLCHAIN_PREFIX}" in
     ;;
 esac
 AC_PROG_CC
 AC_PROG_CXX
 
 AC_CHECK_PROGS(RANLIB, "${TOOLCHAIN_PREFIX}ranlib", :)
 AC_CHECK_PROGS(AS, "${TOOLCHAIN_PREFIX}as", :)
 AC_CHECK_PROGS(LIPO, "${TOOLCHAIN_PREFIX}lipo", :)
-AC_CHECK_PROGS(STRIP, "${TOOLCHAIN_PREFIX}strip", :)
 AC_CHECK_PROGS(OTOOL, "${TOOLCHAIN_PREFIX}otool", :)
 AC_CHECK_PROGS(INSTALL_NAME_TOOL, "${TOOLCHAIN_PREFIX}install_name_tool", :)
-AC_CHECK_PROGS(OBJCOPY, "${TOOLCHAIN_PREFIX}objcopy", :)
 PATH=$_SAVE_PATH
 ])
 
 AC_DEFUN([MOZ_CXX11],
 [
 dnl Updates to the test below should be duplicated further below for the
 dnl cross-compiling case.
 AC_LANG_CPLUSPLUS
--- a/dom/canvas/OffscreenCanvasDisplayHelper.cpp
+++ b/dom/canvas/OffscreenCanvasDisplayHelper.cpp
@@ -114,37 +114,37 @@ bool OffscreenCanvasDisplayHelper::Commi
     RefPtr<layers::TextureClient> texture =
         layers::SharedSurfaceTextureData::CreateTextureClient(
             *desc, format, mData.mSize, flags, imageBridge);
     if (texture) {
       image = new layers::TextureWrapperImage(
           texture, gfx::IntRect(gfx::IntPoint(0, 0), mData.mSize));
     }
   } else {
-    surface = aContext->GetFrontBufferSnapshot(/* requireAlphaPremult */ false);
+    surface = aContext->GetFrontBufferSnapshot(/* requireAlphaPremult */ true);
     if (surface) {
-      auto surfaceImage = MakeRefPtr<layers::SourceSurfaceImage>(surface);
-      surfaceImage->SetTextureFlags(flags);
-      image = surfaceImage;
+      image = new layers::SourceSurfaceImage(surface);
     }
   }
 
   if (mData.mDoPaintCallbacks) {
     aContext->OnDidPaintTransaction();
   }
 
   if (image) {
     AutoTArray<layers::ImageContainer::NonOwningImage, 1> imageList;
     imageList.AppendElement(layers::ImageContainer::NonOwningImage(
         image, TimeStamp(), mLastFrameID++, mImageProducerID));
     mImageContainer->SetCurrentImages(imageList);
   } else {
     mImageContainer->ClearAllImages();
   }
 
+  mFrontBufferDesc = std::move(desc);
+  mFrontBufferSurface = std::move(surface);
   return true;
 }
 
 void OffscreenCanvasDisplayHelper::MaybeQueueInvalidateElement() {
   mMutex.AssertCurrentThreadOwns();
 
   if (!mPendingInvalidate) {
     mPendingInvalidate = true;
@@ -182,16 +182,21 @@ OffscreenCanvasDisplayHelper::GetSurface
   Maybe<layers::SurfaceDescriptor> desc;
 
   bool hasAlpha;
   uint32_t managerId;
   int32_t childId;
 
   {
     MutexAutoLock lock(mMutex);
+    if (mFrontBufferSurface) {
+      RefPtr<gfx::SourceSurface> surface = mFrontBufferSurface;
+      return surface.forget();
+    }
+
     hasAlpha = !mData.mIsOpaque;
     managerId = mContextManagerId;
     childId = mContextChildId;
   }
 
   if (NS_WARN_IF(!managerId || !childId)) {
     return nullptr;
   }
--- a/dom/canvas/OffscreenCanvasDisplayHelper.h
+++ b/dom/canvas/OffscreenCanvasDisplayHelper.h
@@ -55,16 +55,18 @@ class OffscreenCanvasDisplayHelper final
  private:
   ~OffscreenCanvasDisplayHelper();
   void MaybeQueueInvalidateElement();
   void InvalidateElement();
 
   mutable Mutex mMutex;
   HTMLCanvasElement* MOZ_NON_OWNING_REF mCanvasElement;
   RefPtr<layers::ImageContainer> mImageContainer;
+  RefPtr<gfx::SourceSurface> mFrontBufferSurface;
+  Maybe<layers::SurfaceDescriptor> mFrontBufferDesc;
 
   OffscreenCanvasDisplayData mData;
   CanvasContextType mType = CanvasContextType::NoContext;
   uint32_t mContextManagerId = 0;
   int32_t mContextChildId = 0;
   mozilla::layers::ImageContainer::ProducerID mImageProducerID;
   mozilla::layers::ImageContainer::FrameID mLastFrameID = 0;
   bool mPendingInvalidate = false;
--- a/dom/canvas/test/reftest/reftest.list
+++ b/dom/canvas/test/reftest/reftest.list
@@ -107,86 +107,16 @@ fuzzy(0-1,0-30000) pref(webgl.force-laye
 fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
 fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
 fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
                                                                 pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&________&premult&alpha wrapper.html?colors-premult.png
                                                                 pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
                                                                 pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
                                                                 pref(webgl.force-layers-readback,true) == webgl-color-test.html?frame=6&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
 
-# OffscreenCanvas variant of the above.
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&________&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&________&premult&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&________&premult&alpha wrapper.html?colors-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&________&premult&alpha wrapper.html?colors-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&__&preserve&premult&alpha wrapper.html?colors-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&aa&preserve&premult&alpha wrapper.html?colors-premult.png
-
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&________&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&________&premult&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&________&premult&alpha wrapper.html?colors-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&________&premult&alpha wrapper.html?colors-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&__&preserve&premult&alpha wrapper.html?colors-premult.png
-skip-if(Android) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&aa&preserve&premult&alpha wrapper.html?colors-premult.png
-
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&________&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&________&premult&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&________&premult&alpha wrapper.html?colors-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=1&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
-
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&________&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&________&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&preserve&_______&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&________&premult&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&________&premult&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&preserve&premult&_____ wrapper.html?colors-no-alpha.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&________&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&preserve&_______&alpha wrapper.html?colors-non-premult.png
-fuzzy(0-1,0-30000) pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&preserve&_______&alpha wrapper.html?colors-non-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&________&premult&alpha wrapper.html?colors-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&________&premult&alpha wrapper.html?colors-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&__&preserve&premult&alpha wrapper.html?colors-premult.png
-pref(webgl.force-layers-readback,true) pref(gfx.offscreencanvas.enabled,true) == webgl-color-offscreen-test.html?frame=6&readback&aa&preserve&premult&alpha wrapper.html?colors-premult.png
-
-
 # Check for hanging bindings/state settings:
 skip-if(Android) == webgl-hanging-fb-test.html?__&________  wrapper.html?green.png
 skip-if(Android) == webgl-hanging-fb-test.html?aa&________  wrapper.html?green.png
 skip-if(Android) == webgl-hanging-fb-test.html?__&preserve  wrapper.html?green.png
 skip-if(Android) == webgl-hanging-fb-test.html?aa&preserve  wrapper.html?green.png
 pref(webgl.force-layers-readback,true)  == webgl-hanging-fb-test.html?readback&__&________  wrapper.html?green.png
 pref(webgl.force-layers-readback,true)  == webgl-hanging-fb-test.html?readback&aa&________  wrapper.html?green.png
 pref(webgl.force-layers-readback,true)  == webgl-hanging-fb-test.html?readback&__&preserve  wrapper.html?green.png
deleted file mode 100644
--- a/dom/canvas/test/reftest/webgl-color-offscreen-test.html
+++ /dev/null
@@ -1,124 +0,0 @@
-<!DOCTYPE html>
-<meta charset='UTF-8'>
-<!--
-Color Test
-
-Clear the four quadrants of the canvas as follows:
-+------+------+
-| blue |black |
-|      |      |
-+------+------+
-| red  |green |
-|      |      |
-+------+------+
-
-Clear with a given alpha value. What effect this has depends on the
-context-creation args passed to this page.
--->
-<html class='reftest-wait'>
-
-<head>
-  <script type='text/javascript' src='webgl-utils.js'></script>
-  <script type='text/javascript'>
-'use strict';
-
-var COLOR_VALUE = 127.0 / 255.0;
-var ALPHA_VALUE = 127.0 / 255.0;
-
-function renderFrame(gl) {
-  gl.enable(gl.SCISSOR_TEST);
-
-  gl.scissor(0, 0, 100, 100);
-  gl.clearColor(COLOR_VALUE, 0.0, 0.0, ALPHA_VALUE);
-  gl.clear(gl.COLOR_BUFFER_BIT);
-
-  gl.scissor(100, 0, 100, 100);
-  gl.clearColor(0.0, COLOR_VALUE, 0.0, ALPHA_VALUE);
-  gl.clear(gl.COLOR_BUFFER_BIT);
-
-  gl.scissor(0, 100, 100, 100);
-  gl.clearColor(0.0, 0.0, COLOR_VALUE, ALPHA_VALUE);
-  gl.clear(gl.COLOR_BUFFER_BIT);
-
-  gl.scissor(100, 100, 100, 100);
-  gl.clearColor(0.0, 0.0, 0.0, ALPHA_VALUE);
-  gl.clear(gl.COLOR_BUFFER_BIT);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Boilerplate
-
-var TIMEOUT_MS = 30 * 1000;
-
-function setStatus(text) {
-  var elem = document.getElementById('status');
-  elem.innerHTML = text;
-}
-
-var gIsComplete = false;
-
-function markComplete(statusText) {
-  if (!statusText)
-    statusText = '';
-
-  if (gIsComplete)
-    return;
-  gIsComplete = true;
-
-  setStatus(statusText);
-  document.documentElement.removeAttribute('class');
-}
-
-function markError(text) {
-  markComplete('Error: ' + text);
-}
-
-function markTimedOut() {
-  markError('Timed out waiting on test completion.');
-}
-
-function runFrame(gl, frameCount, maxFrameCount) {
-  renderFrame(gl);
-  frameCount++;
-
-  if (frameCount >= maxFrameCount) {
-    console.log('Rendered ' + frameCount + ' frames.');
-    markComplete();
-    return;
-  }
-
-  requestAnimationFrame(function(){
-    runFrame(gl, frameCount, maxFrameCount);
-  });
-}
-
-function runTest() {
-  var canvas = document.getElementById('canvas');
-  var offscreenCanvas = canvas.transferControlToOffscreen();
-
-  var gl = initGL(offscreenCanvas);
-  if (!gl) {
-    markError('WebGL context creation failed.');
-    return;
-  }
-
-  var maxFrameCount = arg('frame', 1);
-  if (maxFrameCount < 1) {
-    markError('Invalid `frame` arg: ' + maxFrameCount);
-    return;
-  }
-
-  setStatus('Waiting...');
-
-  runFrame(gl, 0, maxFrameCount);
-  setTimeout(markTimedOut, TIMEOUT_MS);
-}
-  </script>
-</head>
-
-<body onload='runTest();'>
-  <canvas id='canvas' width='200' height='200'></canvas>
-  <div id='status'></div>
-</body>
-
-</html>
--- a/dom/canvas/test/reftest/webgl-utils.js
+++ b/dom/canvas/test/reftest/webgl-utils.js
@@ -50,17 +50,17 @@ function initGL(canvas) {
     var argDict = {
       alpha: withAlpha,
       depth: withDepth,
       stencil: withStencil,
       antialias: withAA,
       premultipliedAlpha: withPremult,
       preserveDrawingBuffer: withPreserve,
     };
-    gl = canvas.getContext("webgl", argDict);
+    gl = canvas.getContext("experimental-webgl", argDict);
   } catch(e) {}
 
   return gl;
 }
 
 function rAF(func) {
   var raf = window.requestAnimationFrame;
   raf(func);
--- a/dom/webgpu/Adapter.cpp
+++ b/dom/webgpu/Adapter.cpp
@@ -81,29 +81,50 @@ const RefPtr<SupportedLimits>& Adapter::
 already_AddRefed<dom::Promise> Adapter::RequestDevice(
     const dom::GPUDeviceDescriptor& aDesc, ErrorResult& aRv) {
   RefPtr<dom::Promise> promise = dom::Promise::Create(GetParentObject(), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   ffi::WGPULimits limits = {};
-  Maybe<RawId> id = mBridge->AdapterRequestDevice(mId, aDesc, &limits);
-  if (id.isSome()) {
+  auto request = mBridge->AdapterRequestDevice(mId, aDesc, &limits);
+  if (request) {
     RefPtr<Device> device =
-        new Device(this, id.value(), MakeUnique<ffi::WGPULimits>(limits));
+        new Device(this, request->mId, MakeUnique<ffi::WGPULimits>(limits));
     // copy over the features
     for (const auto& feature : aDesc.mRequiredFeatures) {
       NS_ConvertASCIItoUTF16 string(
           dom::GPUFeatureNameValues::GetString(feature));
       dom::GPUSupportedFeatures_Binding::SetlikeHelpers::Add(device->mFeatures,
                                                              string, aRv);
     }
-    promise->MaybeResolve(device);
+
+    request->mPromise->Then(
+        GetCurrentSerialEventTarget(), __func__,
+        [promise, device](bool aSuccess) {
+          if (aSuccess) {
+            promise->MaybeResolve(device);
+          } else {
+            // In this path, request->mId has an error entry in the wgpu
+            // registry, so let Device::~Device clean things up on both the
+            // child and parent side.
+            promise->MaybeRejectWithInvalidStateError(
+                "Unable to fulfill requested features and limits");
+          }
+        },
+        [promise, device](const ipc::ResponseRejectReason& aReason) {
+          // We can't be sure how far along the WebGPUParent got in handling
+          // our AdapterRequestDevice message, but we can't communicate with it,
+          // so clear up our client state for this Device without trying to
+          // communicate with the parent about it.
+          device->CleanupUnregisteredInParent();
+          promise->MaybeRejectWithNotSupportedError("IPC error");
+        });
   } else {
-    promise->MaybeRejectWithNotSupportedError("Unable to instanciate a Device");
+    promise->MaybeRejectWithNotSupportedError("Unable to instantiate a Device");
   }
 
   return promise.forget();
 }
 
 }  // namespace webgpu
 }  // namespace mozilla
--- a/dom/webgpu/Device.cpp
+++ b/dom/webgpu/Device.cpp
@@ -58,28 +58,35 @@ Device::Device(Adapter* const aParent, R
                UniquePtr<ffi::WGPULimits> aRawLimits)
     : DOMEventTargetHelper(aParent->GetParentObject()),
       mId(aId),
       // features are filled in Adapter::RequestDevice
       mFeatures(new SupportedFeatures(aParent)),
       mLimits(new SupportedLimits(aParent, std::move(aRawLimits))),
       mBridge(aParent->mBridge),
       mQueue(new class Queue(this, aParent->mBridge, aId)) {
-  mBridge->RegisterDevice(mId, this);
+  mBridge->RegisterDevice(this);
 }
 
 Device::~Device() { Cleanup(); }
 
 void Device::Cleanup() {
   if (mValid && mBridge) {
     mValid = false;
     mBridge->UnregisterDevice(mId);
   }
 }
 
+void Device::CleanupUnregisteredInParent() {
+  if (mBridge) {
+    mBridge->FreeUnregisteredInParentDevice(mId);
+  }
+  mValid = false;
+}
+
 void Device::GetLabel(nsAString& aValue) const { aValue = mLabel; }
 void Device::SetLabel(const nsAString& aLabel) { mLabel = aLabel; }
 
 already_AddRefed<Buffer> Device::CreateBuffer(
     const dom::GPUBufferDescriptor& aDesc, ErrorResult& aRv) {
   ipc::Shmem shmem;
   bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE |
                                      dom::GPUBufferUsage_Binding::MAP_READ);
--- a/dom/webgpu/Device.h
+++ b/dom/webgpu/Device.h
@@ -101,16 +101,18 @@ class Device final : public DOMEventTarg
   void UnmapBuffer(RawId aId, ipc::Shmem&& aShmem, bool aFlush,
                    bool aKeepShmem);
   already_AddRefed<Texture> InitSwapChain(
       const dom::GPUCanvasConfiguration& aDesc,
       wr::ExternalImageId aExternalImageId, gfx::SurfaceFormat aFormat,
       gfx::IntSize* aDefaultSize);
   bool CheckNewWarning(const nsACString& aMessage);
 
+  void CleanupUnregisteredInParent();
+
  private:
   ~Device();
   void Cleanup();
 
   RefPtr<WebGPUChild> mBridge;
   bool mValid = true;
   nsString mLabel;
   RefPtr<Queue> mQueue;
--- a/dom/webgpu/ipc/PWebGPU.ipdl
+++ b/dom/webgpu/ipc/PWebGPU.ipdl
@@ -33,17 +33,17 @@ async protocol PWebGPU
 parent:
   async DeviceAction(RawId selfId, ByteBuf buf);
   async DeviceActionWithAck(RawId selfId, ByteBuf buf) returns (bool dummy);
   async TextureAction(RawId selfId, RawId aDeviceId, ByteBuf buf);
   async CommandEncoderAction(RawId selfId, RawId aDeviceId, ByteBuf buf);
   async BumpImplicitBindGroupLayout(RawId pipelineId, bool isCompute, uint32_t index, RawId assignId);
 
   async InstanceRequestAdapter(GPURequestAdapterOptions options, RawId[] ids) returns (ByteBuf byteBuf);
-  async AdapterRequestDevice(RawId selfId, ByteBuf buf, RawId newId);
+  async AdapterRequestDevice(RawId selfId, ByteBuf buf, RawId newId) returns (bool success);
   async AdapterDestroy(RawId selfId);
   async BufferReturnShmem(RawId selfId, Shmem shmem);
   async BufferMap(RawId selfId, WGPUHostMap hostMap, uint64_t offset, uint64_t size) returns (Shmem sm);
   async BufferUnmap(RawId selfId, Shmem shmem, bool flush, bool keepShmem);
   async BufferDestroy(RawId selfId);
   async TextureDestroy(RawId selfId);
   async TextureViewDestroy(RawId selfId);
   async SamplerDestroy(RawId selfId);
--- a/dom/webgpu/ipc/WebGPUChild.cpp
+++ b/dom/webgpu/ipc/WebGPUChild.cpp
@@ -197,27 +197,25 @@ RefPtr<AdapterPromise> WebGPUChild::Inst
                                                           __func__)
                        : AdapterPromise::CreateAndReject(Nothing(), __func__);
           },
           [](const ipc::ResponseRejectReason& aReason) {
             return AdapterPromise::CreateAndReject(Some(aReason), __func__);
           });
 }
 
-Maybe<RawId> WebGPUChild::AdapterRequestDevice(
+Maybe<DeviceRequest> WebGPUChild::AdapterRequestDevice(
     RawId aSelfId, const dom::GPUDeviceDescriptor& aDesc,
     ffi::WGPULimits* aLimits) {
-  RawId id = ffi::wgpu_client_make_device_id(mClient, aSelfId);
-
   ffi::WGPUDeviceDescriptor desc = {};
   ffi::wgpu_client_fill_default_limits(&desc.limits);
 
   const auto featureBits = Adapter::MakeFeatureBits(aDesc.mRequiredFeatures);
   if (!featureBits) {
-    return {};
+    return Nothing();
   }
   desc.features = *featureBits;
 
   if (aDesc.mRequiredLimits.WasPassed()) {
     for (const auto& entry : aDesc.mRequiredLimits.Value().Entries()) {
       const uint32_t valueU32 =
           entry.mValue < std::numeric_limits<uint32_t>::max()
               ? entry.mValue
@@ -278,24 +276,27 @@ Maybe<RawId> WebGPUChild::AdapterRequest
       }
 
       // TODO: maxInterStageShaderComponents
       // TODO: maxComputeWorkgroupStorageSize
       // TODO: maxComputeInvocationsPerWorkgroup
     }
   }
 
+  RawId id = ffi::wgpu_client_make_device_id(mClient, aSelfId);
+
   ByteBuf bb;
   ffi::wgpu_client_serialize_device_descriptor(&desc, ToFFI(&bb));
-  if (SendAdapterRequestDevice(aSelfId, std::move(bb), id)) {
-    *aLimits = desc.limits;
-    return Some(id);
-  }
-  ffi::wgpu_client_kill_device_id(mClient, id);
-  return Nothing();
+
+  DeviceRequest request;
+  request.mId = id;
+  request.mPromise = SendAdapterRequestDevice(aSelfId, std::move(bb), id);
+  *aLimits = desc.limits;
+
+  return Some(std::move(request));
 }
 
 RawId WebGPUChild::DeviceCreateBuffer(RawId aSelfId,
                                       const dom::GPUBufferDescriptor& aDesc) {
   ffi::WGPUBufferDescriptor desc = {};
   nsCString label;
   if (aDesc.mLabel.WasPassed()) {
     LossyCopyUTF16toASCII(aDesc.mLabel.Value(), label);
@@ -974,21 +975,26 @@ void WebGPUChild::DeviceCreateSwapChain(
 void WebGPUChild::SwapChainPresent(wr::ExternalImageId aExternalImageId,
                                    RawId aTextureId) {
   // Hack: the function expects `DeviceId`, but it only uses it for `backend()`
   // selection.
   RawId encoderId = ffi::wgpu_client_make_encoder_id(mClient, aTextureId);
   SendSwapChainPresent(aExternalImageId, aTextureId, encoderId);
 }
 
-void WebGPUChild::RegisterDevice(RawId aId, Device* aDevice) {
-  mDeviceMap.insert({aId, aDevice});
+void WebGPUChild::RegisterDevice(Device* const aDevice) {
+  mDeviceMap.insert({aDevice->mId, aDevice});
 }
 
 void WebGPUChild::UnregisterDevice(RawId aId) {
   mDeviceMap.erase(aId);
   if (IsOpen()) {
     SendDeviceDestroy(aId);
   }
 }
 
+void WebGPUChild::FreeUnregisteredInParentDevice(RawId aId) {
+  ffi::wgpu_client_kill_device_id(mClient, aId);
+  mDeviceMap.erase(aId);
+}
+
 }  // namespace webgpu
 }  // namespace mozilla
--- a/dom/webgpu/ipc/WebGPUChild.h
+++ b/dom/webgpu/ipc/WebGPUChild.h
@@ -22,42 +22,50 @@ namespace ffi {
 struct WGPUClient;
 struct WGPULimits;
 struct WGPUTextureViewDescriptor;
 }  // namespace ffi
 
 using AdapterPromise =
     MozPromise<ipc::ByteBuf, Maybe<ipc::ResponseRejectReason>, true>;
 using PipelinePromise = MozPromise<RawId, ipc::ResponseRejectReason, true>;
+using DevicePromise = MozPromise<bool, ipc::ResponseRejectReason, true>;
 
 struct PipelineCreationContext {
   RawId mParentId = 0;
   RawId mImplicitPipelineLayoutId = 0;
   nsTArray<RawId> mImplicitBindGroupLayoutIds;
 };
 
+struct DeviceRequest {
+  RawId mId = 0;
+  RefPtr<DevicePromise> mPromise;
+  // Note: we could put `ffi::WGPULimits` in here as well,
+  //  but we don't want to #include ffi stuff in this header
+};
+
 ffi::WGPUByteBuf* ToFFI(ipc::ByteBuf* x);
 
 class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
  public:
   friend class layers::CompositorBridgeChild;
 
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(WebGPUChild)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGPUChild)
 
  public:
   explicit WebGPUChild();
 
   bool IsOpen() const { return mIPCOpen; }
 
   RefPtr<AdapterPromise> InstanceRequestAdapter(
       const dom::GPURequestAdapterOptions& aOptions);
-  Maybe<RawId> AdapterRequestDevice(RawId aSelfId,
-                                    const dom::GPUDeviceDescriptor& aDesc,
-                                    ffi::WGPULimits* aLimtis);
+  Maybe<DeviceRequest> AdapterRequestDevice(
+      RawId aSelfId, const dom::GPUDeviceDescriptor& aDesc,
+      ffi::WGPULimits* aLimits);
   RawId DeviceCreateBuffer(RawId aSelfId,
                            const dom::GPUBufferDescriptor& aDesc);
   RawId DeviceCreateTexture(RawId aSelfId,
                             const dom::GPUTextureDescriptor& aDesc);
   RawId TextureCreateView(RawId aSelfId, RawId aDeviceId,
                           const dom::GPUTextureViewDescriptor& aDesc);
   RawId DeviceCreateSampler(RawId aSelfId,
                             const dom::GPUSamplerDescriptor& aDesc);
@@ -90,18 +98,19 @@ class WebGPUChild final : public PWebGPU
       PipelineCreationContext* const aContext,
       const dom::GPURenderPipelineDescriptor& aDesc);
 
   void DeviceCreateSwapChain(RawId aSelfId, const RGBDescriptor& aRgbDesc,
                              size_t maxBufferCount,
                              wr::ExternalImageId aExternalImageId);
   void SwapChainPresent(wr::ExternalImageId aExternalImageId, RawId aTextureId);
 
-  void RegisterDevice(RawId aId, Device* aDevice);
+  void RegisterDevice(Device* const aDevice);
   void UnregisterDevice(RawId aId);
+  void FreeUnregisteredInParentDevice(RawId aId);
 
   static void ConvertTextureFormatRef(const dom::GPUTextureFormat& aInput,
                                       ffi::WGPUTextureFormat& aOutput);
 
  private:
   virtual ~WebGPUChild();
 
   void JsWarning(nsIGlobalObject* aGlobal, const nsACString& aMessage);
--- a/dom/webgpu/ipc/WebGPUParent.cpp
+++ b/dom/webgpu/ipc/WebGPUParent.cpp
@@ -276,22 +276,27 @@ ipc::IPCResult WebGPUParent::RecvInstanc
   }
   if (dropByteBuf.mData && !SendDropAction(std::move(dropByteBuf))) {
     NS_ERROR("Unable to free free unused adapter IDs");
   }
   return IPC_OK();
 }
 
 ipc::IPCResult WebGPUParent::RecvAdapterRequestDevice(
-    RawId aSelfId, const ipc::ByteBuf& aByteBuf, RawId aNewId) {
+    RawId aSelfId, const ipc::ByteBuf& aByteBuf, RawId aNewId,
+    AdapterRequestDeviceResolver&& resolver) {
   ErrorBuffer error;
   ffi::wgpu_server_adapter_request_device(mContext, aSelfId, ToFFI(&aByteBuf),
                                           aNewId, error.ToFFI());
-  mErrorScopeMap.insert({aSelfId, ErrorScopeStack()});
-  ForwardError(0, error);
+  if (ForwardError(0, error)) {
+    resolver(false);
+  } else {
+    mErrorScopeMap.insert({aSelfId, ErrorScopeStack()});
+    resolver(true);
+  }
   return IPC_OK();
 }
 
 ipc::IPCResult WebGPUParent::RecvAdapterDestroy(RawId aSelfId) {
   ffi::wgpu_server_adapter_drop(mContext, aSelfId);
   return IPC_OK();
 }
 
--- a/dom/webgpu/ipc/WebGPUParent.h
+++ b/dom/webgpu/ipc/WebGPUParent.h
@@ -25,19 +25,19 @@ class WebGPUParent final : public PWebGP
 
  public:
   explicit WebGPUParent();
 
   ipc::IPCResult RecvInstanceRequestAdapter(
       const dom::GPURequestAdapterOptions& aOptions,
       const nsTArray<RawId>& aTargetIds,
       InstanceRequestAdapterResolver&& resolver);
-  ipc::IPCResult RecvAdapterRequestDevice(RawId aSelfId,
-                                          const ipc::ByteBuf& aByteBuf,
-                                          RawId aNewId);
+  ipc::IPCResult RecvAdapterRequestDevice(
+      RawId aSelfId, const ipc::ByteBuf& aByteBuf, RawId aNewId,
+      AdapterRequestDeviceResolver&& resolver);
   ipc::IPCResult RecvAdapterDestroy(RawId aSelfId);
   ipc::IPCResult RecvDeviceDestroy(RawId aSelfId);
   ipc::IPCResult RecvBufferReturnShmem(RawId aSelfId, Shmem&& aShmem);
   ipc::IPCResult RecvBufferMap(RawId aSelfId, ffi::WGPUHostMap aHostMap,
                                uint64_t aOffset, uint64_t size,
                                BufferMapResolver&& aResolver);
   ipc::IPCResult RecvBufferUnmap(RawId aSelfId, Shmem&& aShmem, bool aFlush,
                                  bool aKeepShmem);
--- a/gfx/2d/Swizzle.cpp
+++ b/gfx/2d/Swizzle.cpp
@@ -5,28 +5,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Swizzle.h"
 #include "Logging.h"
 #include "Orientation.h"
 #include "Tools.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/EndianUtils.h"
-#include "mozilla/UniquePtr.h"
 
 #ifdef USE_SSE2
 #  include "mozilla/SSE.h"
 #endif
 
 #ifdef USE_NEON
 #  include "mozilla/arm.h"
 #endif
 
-#include <new>
-
 namespace mozilla {
 namespace gfx {
 
 /**
  * Convenience macros for dispatching to various format combinations.
  */
 
 // Hash the formats to a relatively dense value to optimize jump table
@@ -1185,102 +1182,16 @@ bool SwizzleData(const uint8_t* aSrc, in
   }
 
 #undef FORMAT_CASE_CALL
 
   MOZ_ASSERT(false, "Unsupported swizzle formats");
   return false;
 }
 
-static bool SwizzleYFlipDataInternal(const uint8_t* aSrc, int32_t aSrcStride,
-                                     SurfaceFormat aSrcFormat, uint8_t* aDst,
-                                     int32_t aDstStride,
-                                     SurfaceFormat aDstFormat,
-                                     const IntSize& aSize,
-                                     SwizzleRowFn aSwizzleFn) {
-  if (!aSwizzleFn) {
-    return false;
-  }
-
-  // Guarantee our width and height are both greater than zero.
-  if (aSize.IsEmpty()) {
-    return true;
-  }
-
-  // Unlike SwizzleData/PremultiplyData, we don't use the stride gaps directly,
-  // but we can use it to verify that the stride is valid for our width and
-  // format.
-  int32_t srcGap = GetStrideGap(aSize.width, aSrcFormat, aSrcStride);
-  int32_t dstGap = GetStrideGap(aSize.width, aDstFormat, aDstStride);
-  MOZ_ASSERT(srcGap >= 0 && dstGap >= 0);
-  if (srcGap < 0 || dstGap < 0) {
-    return false;
-  }
-
-  // Swapping/swizzling to a new buffer is trivial.
-  if (aSrc != aDst) {
-    const uint8_t* src = aSrc;
-    const uint8_t* srcEnd = aSrc + aSize.height * aSrcStride;
-    uint8_t* dst = aDst + (aSize.height - 1) * aDstStride;
-    while (src < srcEnd) {
-      aSwizzleFn(src, dst, aSize.width);
-      src += aSrcStride;
-      dst -= aDstStride;
-    }
-    return true;
-  }
-
-  if (aSrcStride != aDstStride) {
-    return false;
-  }
-
-  // If we are swizzling in place, then we need a temporary row buffer.
-  UniquePtr<uint8_t[]> rowBuffer(new (std::nothrow) uint8_t[aDstStride]);
-  if (!rowBuffer) {
-    return false;
-  }
-
-  // Swizzle and swap the top and bottom rows until we meet in the middle.
-  int32_t middleRow = aSize.height / 2;
-  uint8_t* top = aDst;
-  uint8_t* bottom = aDst + (aSize.height - 1) * aDstStride;
-  for (int32_t row = 0; row < middleRow; ++row) {
-    memcpy(rowBuffer.get(), bottom, aDstStride);
-    aSwizzleFn(top, bottom, aSize.width);
-    aSwizzleFn(rowBuffer.get(), top, aSize.width);
-    top += aDstStride;
-    bottom -= aDstStride;
-  }
-
-  // If there is an odd numbered row, we haven't swizzled it yet.
-  if (aSize.height % 2 == 1) {
-    top = aDst + middleRow * aDstStride;
-    aSwizzleFn(top, top, aSize.width);
-  }
-  return true;
-}
-
-bool SwizzleYFlipData(const uint8_t* aSrc, int32_t aSrcStride,
-                      SurfaceFormat aSrcFormat, uint8_t* aDst,
-                      int32_t aDstStride, SurfaceFormat aDstFormat,
-                      const IntSize& aSize) {
-  return SwizzleYFlipDataInternal(aSrc, aSrcStride, aSrcFormat, aDst,
-                                  aDstStride, aDstFormat, aSize,
-                                  SwizzleRow(aSrcFormat, aDstFormat));
-}
-
-bool PremultiplyYFlipData(const uint8_t* aSrc, int32_t aSrcStride,
-                          SurfaceFormat aSrcFormat, uint8_t* aDst,
-                          int32_t aDstStride, SurfaceFormat aDstFormat,
-                          const IntSize& aSize) {
-  return SwizzleYFlipDataInternal(aSrc, aSrcStride, aSrcFormat, aDst,
-                                  aDstStride, aDstFormat, aSize,
-                                  PremultiplyRow(aSrcFormat, aDstFormat));
-}
-
 SwizzleRowFn SwizzleRow(SurfaceFormat aSrcFormat, SurfaceFormat aDstFormat) {
 #ifdef USE_SSE2
   if (mozilla::supports_avx2()) switch (FORMAT_KEY(aSrcFormat, aDstFormat)) {
       UNPACK_ROW_RGB_AVX2(SurfaceFormat::R8G8B8X8)
       UNPACK_ROW_RGB_AVX2(SurfaceFormat::R8G8B8A8)
       UNPACK_ROW_RGB_AVX2(SurfaceFormat::B8G8R8X8)
       UNPACK_ROW_RGB_AVX2(SurfaceFormat::B8G8R8A8)
       default:
--- a/gfx/2d/Swizzle.h
+++ b/gfx/2d/Swizzle.h
@@ -42,37 +42,16 @@ GFX2D_API bool UnpremultiplyData(const u
  * the same to swizzle in-place.
  */
 GFX2D_API bool SwizzleData(const uint8_t* aSrc, int32_t aSrcStride,
                            SurfaceFormat aSrcFormat, uint8_t* aDst,
                            int32_t aDstStride, SurfaceFormat aDstFormat,
                            const IntSize& aSize);
 
 /**
- * Flips rows of source and swizzles it to destination. Source and destination
- * may be the same to swizzle in-place; this will fail if it cannot allocate a
- * temporary buffer.
- */
-GFX2D_API bool SwizzleYFlipData(const uint8_t* aSrc, int32_t aSrcStride,
-                                SurfaceFormat aSrcFormat, uint8_t* aDst,
-                                int32_t aDstStride, SurfaceFormat aDstFormat,
-                                const IntSize& aSize);
-
-/**
- * Flips rows of source and premultiplies/swizzles it to destination. Source and
- * destination may be the same to premultiply/swizzle in-place; this will fail
- * if it cannot allocate a temporary buffer.
- */
-GFX2D_API bool PremultiplyYFlipData(const uint8_t* aSrc, int32_t aSrcStride,
-                                    SurfaceFormat aSrcFormat, uint8_t* aDst,
-                                    int32_t aDstStride,
-                                    SurfaceFormat aDstFormat,
-                                    const IntSize& aSize);
-
-/**
  * Swizzles source and writes it to destination. Source and destination may be
  * the same to swizzle in-place.
  */
 typedef void (*SwizzleRowFn)(const uint8_t* aSrc, uint8_t* aDst,
                              int32_t aLength);
 
 /**
  * Get a function pointer to perform premultiplication between two formats.
--- a/gfx/ipc/CanvasManagerChild.cpp
+++ b/gfx/ipc/CanvasManagerChild.cpp
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CanvasManagerChild.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRef.h"
 #include "mozilla/gfx/2D.h"
-#include "mozilla/gfx/Swizzle.h"
 #include "mozilla/ipc/Endpoint.h"
 #include "mozilla/layers/CompositorManagerChild.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
 namespace mozilla::gfx {
 
@@ -160,45 +159,27 @@ already_AddRefed<DataSourceSurface> Canv
   }
 
   CheckedInt32 length = stride * size.height;
   if (!length.isValid() ||
       size_t(length.value()) != res.shmem->Size<uint8_t>()) {
     return nullptr;
   }
 
-  SurfaceFormat format =
-      aHasAlpha ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8;
   RefPtr<DataSourceSurface> surface =
-      Factory::CreateDataSourceSurfaceWithStride(size, format, stride.value(),
+      Factory::CreateDataSourceSurfaceWithStride(size, SurfaceFormat::B8G8R8A8,
+                                                 stride.value(),
                                                  /* aZero */ false);
   if (!surface) {
     return nullptr;
   }
 
   gfx::DataSourceSurface::ScopedMap map(surface,
                                         gfx::DataSourceSurface::READ_WRITE);
   if (!map.IsMapped()) {
     return nullptr;
   }
 
-  // The buffer we read back from WebGL is R8G8B8A8, not premultiplied and has
-  // its rows inverted. For the general case, we want surfaces represented as
-  // premultiplied B8G8R8A8, with its rows ordered top to bottom. Given this
-  // path is used for screenshots/SurfaceFromElement, that's the representation
-  // we need.
-  if (aHasAlpha) {
-    if (!PremultiplyYFlipData(res.shmem->get<uint8_t>(), stride.value(),
-                              SurfaceFormat::R8G8B8A8, map.GetData(),
-                              map.GetStride(), format, size)) {
-      return nullptr;
-    }
-  } else {
-    if (!SwizzleYFlipData(res.shmem->get<uint8_t>(), stride.value(),
-                          SurfaceFormat::R8G8B8X8, map.GetData(),
-                          map.GetStride(), format, size)) {
-      return nullptr;
-    }
-  }
+  memcpy(map.GetData(), res.shmem->get<uint8_t>(), res.shmem->Size<uint8_t>());
   return surface.forget();
 }
 
 }  // namespace mozilla::gfx
--- a/gfx/layers/NativeLayer.h
+++ b/gfx/layers/NativeLayer.h
@@ -53,18 +53,16 @@ class NativeLayerRoot {
       const gfx::IntSize& aSize, bool aIsOpaque,
       SurfacePoolHandle* aSurfacePoolHandle) = 0;
   virtual already_AddRefed<NativeLayer> CreateLayerForExternalTexture(
       bool aIsOpaque) = 0;
 
   virtual void AppendLayer(NativeLayer* aLayer) = 0;
   virtual void RemoveLayer(NativeLayer* aLayer) = 0;
   virtual void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) = 0;
-  virtual void PauseCompositor() {}
-  virtual bool ResumeCompositor() { return true; }
 
   // Called before any layer content changes
   virtual void PrepareForCommit() {}
 
   // Publish the layer changes to the screen. Returns whether the commit was
   // successful.
   virtual bool CommitToScreen() = 0;
 
--- a/gfx/layers/NativeLayerWayland.cpp
+++ b/gfx/layers/NativeLayerWayland.cpp
@@ -201,18 +201,16 @@ bool NativeLayerRootWayland::CommitToScr
       layer->SetSubsurfacePosition(floor(surfaceRectClipped.x / bufferScale),
                                    floor(surfaceRectClipped.y / bufferScale));
       layer->SetViewportDestinationSize(
           ceil(surfaceRectClipped.width / bufferScale),
           ceil(surfaceRectClipped.height / bufferScale));
 
       auto transform2DInversed = transform2D.Inverse();
       Rect bufferClip = transform2DInversed.TransformBounds(surfaceRectClipped);
-      // avoid floating point issues - we always expect integer values here
-      bufferClip.Round();
       layer->SetViewportSourceRect(bufferClip);
 
       layer->Commit();
     } else {
       layer->Unmap();
     }
   }
 
@@ -346,24 +344,16 @@ void NativeLayerRootWayland::UpdateLayer
   if (!mGdkAfterPaintId && gdkWindow) {
     GdkFrameClock* frameClock = gdk_window_get_frame_clock(gdkWindow);
     mGdkAfterPaintId =
         g_signal_connect_after(frameClock, "after-paint",
                                G_CALLBACK(sAfterFrameClockAfterPaint), this);
   }
 }
 
-void NativeLayerRootWayland::PauseCompositor() {
-  MutexAutoLock lock(mMutex);
-
-  for (RefPtr<NativeLayerWayland>& layer : mSublayers) {
-    layer->EnsureParentSurface(nullptr);
-  }
-}
-
 NativeLayerWayland::NativeLayerWayland(
     const IntSize& aSize, bool aIsOpaque,
     SurfacePoolHandleWayland* aSurfacePoolHandle)
     : mMutex("NativeLayerWayland"),
       mSurfacePoolHandle(aSurfacePoolHandle),
       mSize(aSize),
       mIsOpaque(aIsOpaque) {
   MOZ_RELEASE_ASSERT(mSurfacePoolHandle,
@@ -693,21 +683,24 @@ void NativeLayerWayland::SetSubsurfacePo
   mSubsurfacePosition.y = aY;
   wl_subsurface_set_position(mWlSubsurface, mSubsurfacePosition.x,
                              mSubsurfacePosition.y);
 }
 
 void NativeLayerWayland::SetViewportSourceRect(const Rect aSourceRect) {
   MutexAutoLock lock(mMutex);
 
-  if (aSourceRect == mViewportSourceRect) {
+  Rect bufferRect = Rect(0, 0, mSize.width, mSize.height);
+  Rect sourceRect = aSourceRect.Intersect(bufferRect);
+
+  if (mViewportSourceRect == sourceRect) {
     return;
   }
 
-  mViewportSourceRect = aSourceRect;
+  mViewportSourceRect = sourceRect;
   wp_viewport_set_source(mViewport, wl_fixed_from_double(mViewportSourceRect.x),
                          wl_fixed_from_double(mViewportSourceRect.y),
                          wl_fixed_from_double(mViewportSourceRect.width),
                          wl_fixed_from_double(mViewportSourceRect.height));
 }
 
 void NativeLayerWayland::SetViewportDestinationSize(int aWidth, int aHeight) {
   MutexAutoLock lock(mMutex);
--- a/gfx/layers/NativeLayerWayland.h
+++ b/gfx/layers/NativeLayerWayland.h
@@ -58,22 +58,16 @@ class NativeLayerRootWayland final : pub
 
   void AppendLayer(NativeLayer* aLayer) override;
   void RemoveLayer(NativeLayer* aLayer) override;
   void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) override;
 
   void PrepareForCommit() override { mFrameInProcess = true; };
   bool CommitToScreen() override;
 
-  // When the compositor is paused the wl_surface of the MozContainer will
-  // get destroyed. We thus have to recreate subsurface relationships for
-  // all tiles after resume. This is a implementation specific quirk of
-  // our GTK-Wayland backend.
-  void PauseCompositor() override;
-
   void UpdateLayersOnMainThread();
   void AfterFrameClockAfterPaint();
   void RequestFrameCallback(CallbackFunc aCallbackFunc, void* aCallbackData);
 
  private:
   explicit NativeLayerRootWayland(MozContainer* aContainer);
   ~NativeLayerRootWayland();
 
--- a/gfx/tests/gtest/TestSwizzle.cpp
+++ b/gfx/tests/gtest/TestSwizzle.cpp
@@ -77,85 +77,16 @@ TEST(Moz2D, PremultiplyRow)
   func(in_bgra, out, 5);
   EXPECT_TRUE(ArrayEqual(out, check_rgba));
 
   func = PremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::A8R8G8B8);
   func(in_bgra, out, 5);
   EXPECT_TRUE(ArrayEqual(out, check_argb));
 }
 
-TEST(Moz2D, PremultiplyYFlipData)
-{
-  const uint8_t stride = 2 * 4;
-  const uint8_t in_bgra[6 * 4] = {
-      255, 255, 0,   255,  // row 1: verify 255 alpha leaves RGB unchanged
-      0,   0,   255, 255,
-      0,   255, 255, 0,  // row 2: verify 0 alpha zeroes out RGB
-      0,   0,   0,   0,
-      255, 0,   0,   128,  // row 3: verify that 255 RGB maps to alpha
-      255, 255, 255, 128,
-  };
-  const uint8_t in_bgra_2[4 * 4] = {
-      255, 255, 0,   255,  // row 1: verify 255 alpha leaves RGB unchanged
-      0,   0,   255, 255,
-      0,   255, 255, 0,  // row 2: verify 0 alpha zeroes out RGB
-      0,   0,   0,   0,
-  };
-  const uint8_t in_bgra_3[2 * 4] = {
-      255, 0,   0,   128,  // row 1: verify that 255 RGB maps to alpha
-      255, 255, 255, 128,
-  };
-  uint8_t out[6 * 4];
-  uint8_t out_2[4 * 4];
-  uint8_t out_3[2 * 4];
-  const uint8_t check_bgra[6 * 4] = {
-      128, 0, 0, 128, 128, 128, 128, 128, 0, 0, 0,   0,
-      0,   0, 0, 0,   255, 255, 0,   255, 0, 0, 255, 255,
-  };
-  const uint8_t check_bgra_2[4 * 4] = {
-      0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 255, 0, 0, 255, 255,
-  };
-  const uint8_t check_bgra_3[2 * 4] = {
-      128, 0, 0, 128, 128, 128, 128, 128,
-  };
-  // check swizzled output
-  const uint8_t check_rgba[6 * 4] = {
-      0, 0, 128, 128, 128, 128, 128, 128, 0,   0, 0, 0,
-      0, 0, 0,   0,   0,   255, 255, 255, 255, 0, 0, 255,
-  };
-
-  // Premultiply.
-  PremultiplyYFlipData(in_bgra, stride, SurfaceFormat::B8G8R8A8, out, stride,
-                       SurfaceFormat::B8G8R8A8, IntSize(2, 3));
-  EXPECT_TRUE(ArrayEqual(out, check_bgra));
-
-  // Premultiply in-place with middle row.
-  memcpy(out, in_bgra, sizeof(out));
-  PremultiplyYFlipData(out, stride, SurfaceFormat::B8G8R8A8, out, stride,
-                       SurfaceFormat::B8G8R8A8, IntSize(2, 3));
-  EXPECT_TRUE(ArrayEqual(out, check_bgra));
-
-  // Premultiply in-place without middle row.
-  memcpy(out_2, in_bgra_2, sizeof(out_2));
-  PremultiplyYFlipData(out_2, stride, SurfaceFormat::B8G8R8A8, out_2, stride,
-                       SurfaceFormat::B8G8R8A8, IntSize(2, 2));
-  EXPECT_TRUE(ArrayEqual(out_2, check_bgra_2));
-
-  // Premultiply in-place only middle row.
-  memcpy(out_3, in_bgra_3, sizeof(out_3));
-  PremultiplyYFlipData(out_3, stride, SurfaceFormat::B8G8R8A8, out_3, stride,
-                       SurfaceFormat::B8G8R8A8, IntSize(2, 1));
-  EXPECT_TRUE(ArrayEqual(out_3, check_bgra_3));
-
-  // Premultiply and swizzle with middle row.
-  PremultiplyYFlipData(in_bgra, stride, SurfaceFormat::B8G8R8A8, out, stride,
-                       SurfaceFormat::R8G8B8A8, IntSize(2, 3));
-  EXPECT_TRUE(ArrayEqual(out, check_rgba));
-}
-
 TEST(Moz2D, UnpremultiplyData)
 {
   const uint8_t in_bgra[5 * 4] = {
       255, 255, 0,   255,              // verify 255 alpha leaves RGB unchanged
       0,   0,   255, 255, 0, 0, 0, 0,  // verify 0 alpha leaves RGB at 0
       0,   0,   0,   64,   // verify 0 RGB stays 0 with non-zero alpha
       128, 0,   0,   128,  // verify that RGB == alpha maps to 255
 
@@ -299,72 +230,16 @@ TEST(Moz2D, SwizzleData)
 #endif
 
   SwizzleData(uint32_argb, sizeof(in_bgra), SurfaceFormat::A8R8G8B8_UINT32,
               reinterpret_cast<uint8_t*>(out16), sizeof(out16),
               SurfaceFormat::R5G6B5_UINT16, IntSize(5, 1));
   EXPECT_TRUE(ArrayEqual(out16, check_16));
 }
 
-TEST(Moz2D, SwizzleYFlipData)
-{
-  const uint8_t stride = 2 * 4;
-  const uint8_t in_bgra[6 * 4] = {
-      255, 255, 0,   255,                      // row 1
-      0,   0,   255, 255, 0,   255, 255, 0,    // row 2
-      0,   0,   0,   0,   255, 0,   0,   128,  // row 3
-      255, 255, 255, 128,
-  };
-  const uint8_t in_bgra_2[4 * 4] = {
-      255, 255, 0,   255,                  // row 1
-      0,   0,   255, 255, 0, 255, 255, 0,  // row 2
-      0,   0,   0,   0,
-  };
-  const uint8_t in_bgra_3[2 * 4] = {
-      255, 0,   0,   128,  // row 1
-      255, 255, 255, 128,
-  };
-  uint8_t out[6 * 4];
-  uint8_t out_2[4 * 4];
-  uint8_t out_3[2 * 4];
-  const uint8_t check_rgba[6 * 4] = {
-      0, 0, 255, 128, 255, 255, 255, 128, 255, 255, 0, 0,
-      0, 0, 0,   0,   0,   255, 255, 255, 255, 0,   0, 255,
-  };
-  const uint8_t check_rgba_2[4 * 4] = {
-      255, 255, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 255,
-  };
-  const uint8_t check_rgba_3[2 * 4] = {
-      0, 0, 255, 128, 255, 255, 255, 128,
-  };
-
-  // Swizzle.
-  SwizzleYFlipData(in_bgra, stride, SurfaceFormat::B8G8R8A8, out, stride,
-                   SurfaceFormat::R8G8B8A8, IntSize(2, 3));
-  EXPECT_TRUE(ArrayEqual(out, check_rgba));
-
-  // Swizzle in-place with middle row.
-  memcpy(out, in_bgra, sizeof(out));
-  SwizzleYFlipData(out, stride, SurfaceFormat::B8G8R8A8, out, stride,
-                   SurfaceFormat::R8G8B8A8, IntSize(2, 3));
-  EXPECT_TRUE(ArrayEqual(out, check_rgba));
-
-  // Swizzle in-place without middle row.
-  memcpy(out_2, in_bgra_2, sizeof(out_2));
-  SwizzleYFlipData(out_2, stride, SurfaceFormat::B8G8R8A8, out_2, stride,
-                   SurfaceFormat::R8G8B8A8, IntSize(2, 2));
-  EXPECT_TRUE(ArrayEqual(out_2, check_rgba_2));
-
-  // Swizzle in-place only middle row.
-  memcpy(out_3, in_bgra_3, sizeof(out_3));
-  SwizzleYFlipData(out_3, stride, SurfaceFormat::B8G8R8A8, out_3, stride,
-                   SurfaceFormat::R8G8B8A8, IntSize(2, 1));
-  EXPECT_TRUE(ArrayEqual(out_3, check_rgba_3));
-}
-
 TEST(Moz2D, SwizzleRow)
 {
   const uint8_t in_bgra[5 * 4] = {
       253, 254, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 1, 2, 3, 64, 127, 0, 9, 128,
 
   };
   uint8_t out[5 * 4];
   // check swaps
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -165,18 +165,16 @@ using namespace mozilla::gfx;
 
 gfxPlatform* gPlatform = nullptr;
 static bool gEverInitialized = false;
 
 static int32_t gLastUsedFrameRate = -1;
 
 const ContentDeviceData* gContentDeviceInitData = nullptr;
 
-static Mutex* gGfxPlatformPrefsLock = nullptr;
-
 Atomic<bool, MemoryOrdering::ReleaseAcquire> gfxPlatform::gCMSInitialized;
 CMSMode gfxPlatform::gCMSMode = CMSMode::Off;
 
 // These two may point to the same profile
 qcms_profile* gfxPlatform::gCMSOutputProfile = nullptr;
 qcms_profile* gfxPlatform::gCMSsRGBProfile = nullptr;
 
 qcms_transform* gfxPlatform::gCMSRGBTransform = nullptr;
@@ -873,18 +871,16 @@ void gfxPlatform::Init() {
                              StaticPrefs::gfx_android_rgb16_force_AtStartup(),
                              StaticPrefs::gfx_canvas_accelerated(),
                              StaticPrefs::layers_force_shmem_tiles_AtStartup());
     ScopedGfxFeatureReporter::AppNote(forcedPrefs);
   }
 
   InitMoz2DLogging();
 
-  gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
-
   /* Initialize the GfxInfo service.
    * Note: we can't call functions on GfxInfo that depend
    * on gPlatform until after it has been initialized
    * below. GfxInfo initialization annotates our
    * crash reports so we want to do it before
    * we try to load any drivers and do device detection
    * incase that code crashes. See bug #591561. */
   nsCOMPtr<nsIGfxInfo> gfxInfo;
@@ -1261,19 +1257,16 @@ void gfxPlatform::Shutdown() {
 
   if (XRE_IsParentProcess()) {
     GPUProcessManager::Shutdown();
     VRProcessManager::Shutdown();
     RDDProcessManager::Shutdown();
   }
 
   gfx::Factory::ShutDown();
-
-  delete gGfxPlatformPrefsLock;
-
   gfxVars::Shutdown();
   gfxFont::DestroySingletons();
 
   gfxConfig::Shutdown();
 
   gPlatform->WillShutdown();
 
   delete gPlatform;
--- a/gfx/webrender_bindings/RenderCompositorNative.cpp
+++ b/gfx/webrender_bindings/RenderCompositorNative.cpp
@@ -91,21 +91,19 @@ RenderedFrameId RenderCompositorNative::
   if (mNativeLayerForEntireWindow) {
     mNativeLayerForEntireWindow->NotifySurfaceReady();
     mNativeLayerRoot->CommitToScreen();
   }
 
   return frameId;
 }
 
-void RenderCompositorNative::Pause() { mNativeLayerRoot->PauseCompositor(); }
+void RenderCompositorNative::Pause() {}
 
-bool RenderCompositorNative::Resume() {
-  return mNativeLayerRoot->ResumeCompositor();
-}
+bool RenderCompositorNative::Resume() { return true; }
 
 inline layers::WebRenderCompositor RenderCompositorNative::CompositorType()
     const {
   if (gfx::gfxVars::UseWebRenderCompositor()) {
 #if defined(XP_MACOSX)
     return layers::WebRenderCompositor::CORE_ANIMATION;
 #elif defined(MOZ_WAYLAND)
     return layers::WebRenderCompositor::WAYLAND;
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -87,17 +87,16 @@ AC_EXEEXT
 #     - $target (in its correct usage) is for compilers who generate code for a
 #       different platform than $host, so it would not be used by Mozilla.
 if test "$target" != "$host"; then
     MOZ_CROSS_COMPILER
 else
     AC_PROG_CC
     AC_PROG_CXX
     MOZ_PATH_PROGS(AS, $AS as, $CC)
-    AC_CHECK_PROGS(STRIP, strip, :)
 fi
 
 MOZ_TOOL_VARIABLES
 
 dnl Special win32 checks
 dnl ========================================================
 
 # Target the Windows 8.1 SDK by default
@@ -399,17 +398,16 @@ case "$target" in
         LDFLAGS="$LDFLAGS -Wl,--no-insert-timestamp"
 
         MOZ_OPTIMIZE_FLAGS="-O2"
 
         WIN32_CONSOLE_EXE_LDFLAGS=-mconsole
         WIN32_GUI_EXE_LDFLAGS=-mwindows
     else
         TARGET_COMPILER_ABI=msvc
-        STRIP='echo not_strip'
         # aarch64 doesn't support subsystems below 6.02
         if test "$CPU_ARCH" = "aarch64"; then
             WIN32_SUBSYSTEM_VERSION=6.02
         else
             WIN32_SUBSYSTEM_VERSION=6.01
         fi
         WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
         WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -1475,17 +1475,21 @@
   value: "#FFADFF"
   mirror: never
 
 # When true, soft reloads (including location.reload())
 # will only froce validate the top level document, subresources will
 # be loaded normally as-if users normally navigated to the page.
 - name: browser.soft_reload.only_force_validate_top_level_document
   type: bool
-  value: true
+#if defined(EARLY_BETA_OR_EARLIER)
+  value: true
+#else
+  value: false
+#endif
   mirror: always
 
 #---------------------------------------------------------------------------
 # Prefs starting with "canvas."
 #---------------------------------------------------------------------------
 
 # Limit for the canvas image cache. 0 means unlimited.
 - name: canvas.image.cache.limit
--- a/moz.configure
+++ b/moz.configure
@@ -822,22 +822,48 @@ def readelf_when(compile_env, target, ho
     return compile_env and any(
         x.kernel not in ("Darwin", "WINNT") for x in (target, host)
     )
 
 
 check_prog(
     "READELF",
     readelf,
-    what="readelf",
     when=readelf_when,
     paths=clang_search_path,
     validate=validate_readelf,
 )
 
+
+@depends(llvm_tool("llvm-objcopy"), toolchain_prefix)
+def objcopy(llvm_objcopy, toolchain_prefix):
+    commands = [llvm_objcopy[0], "objcopy"]
+    for prefix in toolchain_prefix or ():
+        commands.insert(1, "%sreadelf" % prefix)
+    return tuple(commands)
+
+
+def validate_objcopy(path):
+    if "llvm-objcopy" not in path:
+        return True
+    # llvm-objcopy doesn't support --only-keep-debug before llvm 9.0.
+    retcode, stdout, stderr = get_cmd_output(path, "--help")
+    return retcode == 0 and any(
+        l.startswith("  --only-keep-debug ") for l in stdout.splitlines()
+    )
+
+
+check_prog(
+    "OBJCOPY",
+    objcopy,
+    when=readelf_when,
+    paths=clang_search_path,
+    validate=validate_objcopy,
+)
+
 option("--enable-dtrace", help="Build with dtrace support")
 
 dtrace = check_header(
     "sys/sdt.h",
     when="--enable-dtrace",
     onerror=lambda: die("dtrace enabled but sys/sdt.h not found"),
 )
 
@@ -916,16 +942,51 @@ def strip_flags(flags, profiling, target
     # On Darwin, it tries to strip things it can't, so we need to limit its scope.
     elif target.kernel == "Darwin":
         return ["-x", "-S"]
 
 
 set_config("STRIP_FLAGS", strip_flags)
 
 
+@depends(llvm_tool("llvm-strip"), toolchain_prefix, target)
+def strip(llvm_strip, toolchain_prefix, target):
+    commands = ["strip"]
+    for prefix in toolchain_prefix or ():
+        commands.insert(0, "%sstrip" % prefix)
+    # llvm-strip causes some problems on macos targets.
+    if target.kernel == "Darwin":
+        commands.append(llvm_strip[0])
+    else:
+        commands.insert(0, llvm_strip[0])
+    return tuple(commands)
+
+
+def validate_strip(path):
+    if "llvm-strip" not in path:
+        return True
+    # llvm-strip doesn't support -S before llvm 8.0.
+    retcode, stdout, stderr = get_cmd_output(path, "--help")
+    return retcode == 0 and any(l.startswith("  -S ") for l in stdout.splitlines())
+
+
+@depends("--enable-compile-environment", target, host)
+def strip_when(compile_env, target, host):
+    return compile_env and any(x.kernel != "WINNT" for x in (target, host))
+
+
+check_prog(
+    "STRIP",
+    strip,
+    when=strip_when,
+    paths=clang_search_path,
+    validate=validate_strip,
+)
+
+
 @depends(js_standalone, target)
 def system_zlib_default(js_standalone, target):
     return js_standalone and target.kernel not in ("WINNT", "Darwin")
 
 
 option(
     "--with-system-zlib",
     nargs="?",
--- a/old-configure.in
+++ b/old-configure.in
@@ -58,26 +58,16 @@ MOZ_USE_PTHREADS=
 _PTHREAD_LDFLAGS=""
 
 LDFLAGS="$LDFLAGS $LINKER_LDFLAGS"
 
 if test "$COMPILE_ENVIRONMENT"; then
     MOZ_ANDROID_NDK
 fi # COMPILE_ENVIRONMENT
 
-case "$target" in
-*-android*|*-linuxandroid*)
-    ;;
-*-linux*)
-    AC_PATH_PROG(OBJCOPY,objcopy)
-    ;;
-esac
-
-AC_SUBST(OBJCOPY)
-
 dnl ========================================================
 dnl Checks for compilers.
 dnl ========================================================
 
 if test "$COMPILE_ENVIRONMENT"; then
 
 # Run some logic to figure out exe extensions (mostly for mingw's sake)
 AC_EXEEXT
@@ -88,17 +78,16 @@ else
     AC_PROG_CC
     case "$target" in
     *-mingw*)
       # Work around the conftest.exe access problem on Windows
       sleep 2
     esac
     AC_PROG_CXX
     MOZ_PATH_PROGS(AS, $AS as, $CC)
-    AC_CHECK_PROGS(STRIP, strip, :)
     AC_CHECK_PROGS(OTOOL, otool, :)
 fi
 
 MOZ_TOOL_VARIABLES
 
 dnl ========================================================
 dnl Special win32 checks
 dnl ========================================================
@@ -482,17 +471,16 @@ case "$target" in
         WIN32_CONSOLE_EXE_LDFLAGS=-mconsole
         WIN32_GUI_EXE_LDFLAGS=-mwindows
 
         # Silence problematic clang warnings
         CXXFLAGS="$CXXFLAGS -Wno-incompatible-ms-struct"
         LDFLAGS="$LDFLAGS -Wl,--no-insert-timestamp"
     else
         TARGET_COMPILER_ABI=msvc
-        STRIP='echo not_strip'
         # aarch64 doesn't support subsystems below 6.02
         if test "$CPU_ARCH" = "aarch64"; then
             WIN32_SUBSYSTEM_VERSION=6.02
         else
             WIN32_SUBSYSTEM_VERSION=6.01
         fi
         WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
         WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
@@ -717,19 +705,16 @@ case "${OS_TARGET}" in
 Darwin)
   ;;
 *)
   STL_FLAGS="-I${DIST}/stl_wrappers"
   WRAP_STL_INCLUDES=1
   ;;
 esac
 
-if test "$MOZ_BUILD_APP" = "tools/crashreporter"; then
-    WRAP_STL_INCLUDES=
-fi
 if test "$MOZ_BUILD_APP" = "tools/crashreporter/injector"; then
     WRAP_STL_INCLUDES=
 fi
 
 dnl Checks for header files.
 dnl ========================================================
 AC_HEADER_DIRENT
 
deleted file mode 100644
--- a/python/mozbuild/mozbuild/action/make_zip.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-from __future__ import absolute_import, print_function
-
-import sys
-import subprocess
-import buildconfig
-
-
-def make_zip(source, package):
-    subprocess.check_call(
-        [buildconfig.substs["ZIP"], "-r9D", package, source, "-x", "\*/.mkdir.done"]
-    )
-
-
-def main(args):
-    if len(args) != 2:
-        print("Usage: make_zip.py <source> <package>", file=sys.stderr)
-        return 1
-    else:
-        make_zip(args[0], args[1])
-        return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main(sys.argv[1:]))
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -728,17 +728,16 @@ def gtest(
             cwd,
             shuffle,
             gtest_filter,
             package,
             adb_path,
             device_serial,
             remote_test_root,
             libxul_path,
-            enable_webrender,
             InstallIntent.NO if no_install else InstallIntent.YES,
         )
 
     if (
         package
         or adb_path
         or device_serial
         or remote_test_root
@@ -841,17 +840,16 @@ def android_gtest(
     test_dir,
     shuffle,
     gtest_filter,
     package,
     adb_path,
     device_serial,
     remote_test_root,
     libxul_path,
-    enable_webrender,
     install,
 ):
     # setup logging for mozrunner
     from mozlog.commandline import setup_logging
 
     format_args = {"level": command_context._mach_context.settings["test"]["level"]}
     default_format = command_context._mach_context.settings["test"]["format"]
     setup_logging("mach-gtest", {}, {default_format: sys.stdout}, format_args)
@@ -885,17 +883,16 @@ def android_gtest(
         shuffle,
         gtest_filter,
         package,
         adb_path,
         device_serial,
         remote_test_root,
         libxul_path,
         None,
-        enable_webrender,
     ):
         exit_code = 1
     tester.cleanup()
 
     return exit_code
 
 
 @Command(
--- a/python/mozbuild/mozpack/packager/l10n.py
+++ b/python/mozbuild/mozpack/packager/l10n.py
@@ -96,27 +96,35 @@ class LocaleManifestFinder(object):
 
 
 class L10NRepackFormatterMixin(object):
     def __init__(self, *args, **kwargs):
         super(L10NRepackFormatterMixin, self).__init__(*args, **kwargs)
         self._dictionaries = {}
 
     def add(self, path, file):
+        base, relpath = self._get_base(path)
         if path.endswith(".dic"):
-            base, relpath = self._get_base(path)
             if relpath.startswith("dictionaries/"):
                 root, ext = mozpath.splitext(mozpath.basename(path))
                 self._dictionaries[root] = path
         elif path.endswith("/built_in_addons.json"):
             data = json.loads(six.ensure_text(file.open().read()))
             data["dictionaries"] = self._dictionaries
             # The GeneratedFile content is only really generated after
             # all calls to formatter.add.
             file = GeneratedFile(lambda: json.dumps(data))
+        elif relpath.startswith("META-INF/"):
+            # Ignore signatures inside omnijars.  We drop these items: if we
+            # don't treat them as omnijar resources, they will be included in
+            # the top-level package, and that's not how omnijars are signed (Bug
+            # 1750676).  If we treat them as omnijar resources, they will stay
+            # in the omnijar, as expected -- but the signatures won't be valid
+            # after repacking.  Therefore, drop them.
+            return
         super(L10NRepackFormatterMixin, self).add(path, file)
 
 
 def L10NRepackFormatter(klass):
     class L10NRepackFormatter(L10NRepackFormatterMixin, klass):
         pass
 
     return L10NRepackFormatter
--- a/python/mozbuild/mozpack/test/test_packager_l10n.py
+++ b/python/mozbuild/mozpack/test/test_packager_l10n.py
@@ -14,17 +14,16 @@ from mozpack.files import (
     ManifestFile,
 )
 from mozpack.chrome.manifest import (
     Manifest,
     ManifestLocale,
     ManifestContent,
 )
 from mozpack.copier import FileRegistry
-from mozpack.packager.formats import FlatFormatter
 
 
 class TestL10NRepack(unittest.TestCase):
     def test_l10n_repack(self):
         foo = GeneratedFile(b"foo")
         foobar = GeneratedFile(b"foobar")
         qux = GeneratedFile(b"qux")
         bar = GeneratedFile(b"bar")
@@ -58,16 +57,20 @@ class TestL10NRepack(unittest.TestCase):
                 "app/chrome.manifest": ManifestFile(
                     "app", [Manifest("app", "chrome/chrome.manifest")]
                 ),
                 "app/dict/bb": dict_bb,
                 "app/dict/cc": dict_cc,
                 "app/chrome/bar/search/foo.xml": foo,
                 "app/chrome/bar/search/bar.xml": bar,
                 "app/chrome/bar/search/lst.txt": lst,
+                "META-INF/foo": foo,  # Stripped.
+                "inner/META-INF/foo": foo,  # Not stripped.
+                "app/META-INF/foo": foo,  # Stripped.
+                "app/inner/META-INF/foo": foo,  # Not stripped.
             }
         )
         app_finder.jarlogs = {}
         app_finder.base = "app"
         foo_l10n = GeneratedFile(b"foo_l10n")
         qux_l10n = GeneratedFile(b"qux_l10n")
         baz_l10n = GeneratedFile(b"baz_l10n")
         barbaz_l10n = GeneratedFile(b"barbaz_l10n")
@@ -98,17 +101,17 @@ class TestL10NRepack(unittest.TestCase):
                 "app/dict/aa": dict_aa,
                 "app/chrome/bar-l10n/search/foo.xml": foo_l10n,
                 "app/chrome/bar-l10n/search/qux.xml": qux_l10n,
                 "app/chrome/bar-l10n/search/lst.txt": lst_l10n,
             }
         )
         l10n_finder.base = "l10n"
         copier = FileRegistry()
-        formatter = FlatFormatter(copier)
+        formatter = l10n.FlatFormatter(copier)
 
         l10n._repack(
             app_finder,
             l10n_finder,
             copier,
             formatter,
             ["dict", "chrome/**/search/*.xml"],
         )
@@ -138,16 +141,18 @@ class TestL10NRepack(unittest.TestCase):
             ),
             "app/chrome.manifest": ManifestFile(
                 "app", [Manifest("app", "chrome/chrome.manifest")]
             ),
             "app/dict/aa": dict_aa,
             "app/chrome/bar-l10n/search/foo.xml": foo_l10n,
             "app/chrome/bar-l10n/search/qux.xml": qux_l10n,
             "app/chrome/bar-l10n/search/lst.txt": lst_l10n,
+            "inner/META-INF/foo": foo,
+            "app/inner/META-INF/foo": foo,
         }
 
         self.assertEqual(
             dict((p, f.open().read()) for p, f in copier),
             dict((p, f.open().read()) for p, f in six.iteritems(repacked)),
         )
 
 
--- a/taskcluster/ci/test/reftest.yml
+++ b/taskcluster/ci/test/reftest.yml
@@ -5,20 +5,17 @@
 job-defaults:
     suite:
         category: reftest
     target:
         by-test-platform:
             android-em-7.*: geckoview-test_runner.apk
             android-hw-.*: geckoview-test_runner.apk
             default: null
-    tier:
-        by-variant:
-            fission: 2
-            default: default
+    tier: default
     test-manifest-loader: null  # don't load tests in the taskgraph
     mozharness:
         script:
             by-test-platform:
                 android-em.*: android_emulator_unittest.py
                 android-hw.*: android_hardware_unittest.py
                 default: desktop_unittest.py
         config:
@@ -50,18 +47,18 @@ crashtest:
         - fission
         - wayland
         - webrender-sw
         - webrender-sw+fission
     run-on-projects:
         by-variant:
             fission:
                 by-test-platform:
-                    (windows10|linux1804|macosx1).*-qr/.*: ['trunk']
-                    default: []
+                    android.*: []
+                    default: built-projects
             wayland:
                 by-test-platform:
                     linux1804-64-qr/debug: built-projects
                     linux1804-64(-tsan|-asan)-qr/opt: built-projects
                     default: []
             webrender-sw:
                 by-test-platform:
                     android-em-7.0-x86_64-qr/debug: built-projects
@@ -76,30 +73,27 @@ crashtest:
                     macosx101.*64-qr/debug: built-projects
                     linux.*-64-qr/debug: built-projects
                     linux.*-64(-tsan|-asan)-qr/opt: built-projects
                     windows10-64-2004-asan-qr/opt: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
             default:
                 by-test-platform:
-                    windows10-aarch64-qr/.*: ['mozilla-central', 'mozilla-beta', 'mozilla-release']
                     android-em-7.0-x86_64-qr/debug-isolated-process: []
-                    linux.*asan/opt: []
-                    .*(-asan|-tsan|10-32|7-32).*: built-projects
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
                     android.*: built-projects
-                    (linux|windows|macos)(?!.*-qr).*: []
-                    default: built-projects
+                    default: []
     max-run-time: 3600
     tier:
         by-variant:
-            fission:
-                by-test-platform:
-                    linux1804-64-qr/debug: 1
-                    default: 2
+            fission: default
             default:
                 by-test-platform:
                     windows10-aarch64-qr.*: 2
                     android-hw-.*-qr/.*: 2
                     android-em-7.0-x86_64-qr/debug-isolated-process: 3
                     default: default
 
 crashtest-qr:
@@ -132,32 +126,35 @@ jsreftest:
             linux1804-64-qr/opt: 4
             linux1804-64-qr/debug: 5
             linux1804-64/debug: 5
             macosx.*-64-ccov.*/.*: 5
             macosx.*-64(-shippable)?/opt: 2
             default: 3
     max-run-time:
         by-test-platform:
-            windows10-64-2004-ccov.*/.*: 7200
-            macosx.*64-ccov.*/.*: 7200
-            linux.*64-ccov.*/.*: 7200
+            .*ccov.*: 7200
             default: 3600
     variants: ['fission']
     run-on-projects:
         by-variant:
             fission:
                 by-test-platform:
                     android.*/.*: []
                     default: built-projects
             default:
                 by-test-platform:
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
                     android-hw-.*-aarch64(?:-shippable)?-qr/.*: ['mozilla-central', 'release']
                     android-hw-.*-arm7(?:-shippable)?-qr/.*: ['mozilla-central', 'release']
-                    default: built-projects
+                    android.*: built-projects
+                    default: []
     virtualization: virtual
 
 reftest:
     description: "Reftest run"
     treeherder-symbol: R(R)
     virtualization: virtual-with-gpu
     chunks:
         by-test-platform:
@@ -180,18 +177,16 @@ reftest:
         - webrender-sw+fission
     run-on-projects:
         by-variant:
             fission:
                 by-test-platform:
                     android.*/.*: []
                     linux.*asan/opt: []
                     windows10-aarch64-qr/opt: []
-                    .*(mingwclang|-asan|-tsan|10-32|7-32).*: built-projects
-                    (linux|windows|macos|android-em)(?!.*-qr).*: []
                     default: built-projects
             wayland:
                 by-test-platform:
                     linux1804-64-qr/debug: built-projects
                     linux1804-64(-asan|-tsan)-qr/opt: built-projects
                     default: []
             webrender-sw:
                 by-test-platform:
@@ -207,43 +202,40 @@ reftest:
                     linux1804-64-qr/debug: built-projects
                     linux1804-64(-asan|-tsan)-qr/opt: built-projects
                     macosx101.*64-qr/debug: built-projects
                     windows10-64-2004(-asan)?-qr/opt: built-projects
                     windows7-32(?:-shippable)?-qr/opt: built-projects
                     default: []
             default:
                 by-test-platform:
-                    windows10-aarch64-qr/.*: []
                     android-em-7.0-x86_64-qr/debug-isolated-process: []
-                    linux.*asan/opt: []
-                    .*(mingwclang|-asan|-tsan|10-32|7-32).*: built-projects
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
                     android.*: built-projects
-                    (linux|windows|macos|android-em)(?!.*-qr).*: []
-                    default: built-projects
+                    default: []
     max-run-time:
         by-test-platform:
             windows10-32-mingwclang-qr/debug: 5400
             windows10-64-2004-ccov.*/.*: 5400
             windows10-64-2004-asan-qr/opt: 5400
             macosx.*64-ccov.*/.*: 5400
             default: 3600
     mozharness:
         chunked:
             by-test-platform:
                 android-em.*: false
                 macosx.*64/opt: false
                 windows10-64-2004.*/opt: false
                 default: true
     tier:
         by-variant:
-            fission:
-                by-test-platform:
-                    linux1804-64-qr/debug: 1
-                    default: 2
+            fission: default
             default:
                 by-test-platform:
                     windows10-aarch64-qr.*: 2
                     android-hw-.*-qr/.*: 2
                     android-em-7.0-x86_64-qr/debug-isolated-process: 3
                     default: default
 
 reftest-qr:
--- a/taskcluster/ci/test/web-platform.yml
+++ b/taskcluster/ci/test/web-platform.yml
@@ -33,22 +33,17 @@ job-defaults:
 
 web-platform-tests:
     description: "Web platform test run"
     suite: web-platform-tests
     treeherder-symbol: W(wpt)
     virtualization: virtual
     tier:
         by-variant:
-            fission:
-                by-test-platform:
-                    linux.*64-qr/debug: 1
-                    linux.*64(-shippable)?-qr/opt: 1
-                    windows10-64-2004(-shippable)?-qr/opt: 1
-                    default: 2
+            fission: default
             default:
                 by-test-platform:
                     android-em-7.0-x86_64-qr/debug-isolated-process: 3
                     default: default
     chunks:
         by-test-platform:
             android.*: 16
             linux.*64-tsan-qr/opt: 32
@@ -76,39 +71,41 @@ web-platform-tests:
     run-on-projects:
         by-variant:
             dynamic-first-party-isolation+fission:
                 by-test-platform:
                     (linux.*64|macosx.*64|windows10-64-2004)(-shippable)?-qr/(opt|debug): ['mozilla-central']
                     default: []
             fission:
                 by-test-platform:
-                    linux.*: ['trunk']
-                    windows.*: ['trunk']
-                    macosx.*: ['trunk']
-                    default: []
+                    android.*: []
+                    .*-tsan-qr/opt: ['trunk']
+                    default: built-projects
             webrender-sw+fission:
                 by-test-platform:
                     (linux1804|windows10)-32.*/.*: []
                     linux.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
             webrender-sw:
                 by-test-platform:
                     (linux1804|windows10)-32.*/.*: []
                     android-em-7.0-x86_64-qr/debug: built-projects
                     linux.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
             default:
                 by-test-platform:
-                    .*-tsan-qr/opt: ['trunk']
                     android-em-7.0-x86_64-qr/debug-isolated-process: []
                     linux.*64-ccov-qr/opt: []
-                    default: built-projects
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    android.*: built-projects
+                    linux.*: ['trunk']  # linux opt/debug/asan
+                    default: []
     mozharness:
         chunked: true
         extra-options:
             - --test-type=testharness
             - --skip-implementation-status=backlog
             - --skip-implementation-status=not-implementing
 
 web-platform-tests-backlog:
@@ -124,17 +121,20 @@ web-platform-tests-backlog:
             default: 3600
     variants: [fission]
     run-on-projects:
         by-variant:
             fission:
                 by-test-platform:
                     android.*: []
                     default: ['mozilla-central']
-            default: ['mozilla-central']
+            default:
+                by-test-platform:
+                    android.*: ['mozilla-central']
+                    default: []
     test-manifest-loader: null  # don't load tests in the taskgraph
     tier: 2
     mozharness:
         chunked: true
         extra-options:
             - --test-type=testharness
             - --skip-implementation-status=implementing
             - --skip-implementation-status=not-implementing
@@ -166,46 +166,43 @@ web-platform-tests-reftest:
     run-on-projects:
         by-variant:
             dynamic-first-party-isolation+fission:
                 by-test-platform:
                     (linux.*64|macosx.*64|windows10-64-2004)(-shippable)?-qr/(opt|debug): ['mozilla-central']
                     default: []
             fission:
                 by-test-platform:
-                    linux.*: ['trunk']
-                    windows.*: ['trunk']
-                    macosx.*: ['trunk']
-                    default: []
+                    android.*: []
+                    default: built-projects
             webrender-sw+fission:
                 by-test-platform:
                     (linux1804|windows10)-32.*/.*: []
                     linux.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
             webrender-sw:
                 by-test-platform:
                     (linux1804|windows10)-32.*/.*: []
                     android-em-7.0-x86_64-qr/debug: built-projects
                     linux.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
             default:
                 by-test-platform:
-                    .*-tsan-qr/opt: ['trunk']
                     android-em-7.0-x86_64-qr/debug-isolated-process: []
-                    default: built-projects
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
+                    android.*: built-projects
+                    default: []
     tier:
         by-variant:
-            fission:
-                by-test-platform:
-                    linux.*64-qr/debug: 1
-                    linux.*64(-shippable)?-qr/opt: 1
-                    windows10-64-2004(-shippable)?-qr/opt: 1
-                    default: 2
+            fission: default
             default:
                 by-test-platform:
                     linux1804-64-asan(-qr)?/opt: 2
                     android-em-7.0-x86_64-qr/debug-isolated-process: 3
                     default: default
     mozharness:
         extra-options:
             - --test-type=reftest
@@ -220,17 +217,20 @@ web-platform-tests-reftest-backlog:
     chunks: 1
     variants: [fission]
     run-on-projects:
         by-variant:
             fission:
                 by-test-platform:
                     android.*: []
                     default: ['mozilla-central']
-            default: ['mozilla-central']
+            default:
+                by-test-platform:
+                    android.*: ['mozilla-central']
+                    default: []
     test-manifest-loader: null  # don't load tests in the taskgraph
     tier: 2
     mozharness:
         extra-options:
             - --test-type=reftest
             - --skip-implementation-status=implementing
             - --skip-implementation-status=not-implementing
             - --backlog
@@ -276,25 +276,27 @@ web-platform-tests-wdspec:
                     linux.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
             headless: built-projects
             headless+fission:
                 by-test-platform:
                     android.*: []
                     default: built-projects
-            default: built-projects
+            default:
+                by-test-platform:
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
+                    android.*: built-projects
+                    default: []
     tier:
         by-variant:
-            fission:
-                by-test-platform:
-                    linux.*64-qr/debug: 1
-                    linux.*64(-shippable)?-qr/opt: 1
-                    windows10-64-2004(-shippable)?-qr/opt: 1
-                    default: 2
+            fission: default
             default:
                 by-test-platform:
                     android.*: 3
                     default: default
     fetches:
         toolchain:
             by-test-platform:
                 linux.*64.*:
@@ -355,42 +357,34 @@ web-platform-tests-crashtest:
             webrender-sw:
                 by-test-platform:
                     (linux1804|windows10)-32.*/.*: []
                     android-em-7.0-x86_64-qr/debug: built-projects
                     linux.*64-qr/debug: built-projects
                     macosx101.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
-            default: built-projects
-    tier:
-        by-variant:
-            fission:
+            default:
                 by-test-platform:
-                    linux.*64-qr/debug: 1
-                    linux.*64(-shippable)?-qr/opt: 1
-                    windows10-64-2004(-shippable)?-qr/opt: 1
-                    default: 2
-            default: default
+                    android-em-7.0-x86_64-qr/debug-isolated-process: []
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
+                    android.*: built-projects
+                    default: []
+    tier: default
 
 web-platform-tests-print-reftest:
     description: "Web platform print-reftest run"
     schedules-component: web-platform-tests-print-reftest
     treeherder-symbol: W(Wp)
     chunks: 1
     test-manifest-loader: null  # don't load tests in the taskgraph
-    tier:
-        by-variant:
-            fission:
-                by-test-platform:
-                    linux.*64-qr/debug: 1
-                    linux.*64(-shippable)?-qr/opt: 1
-                    windows10-64-2004(-shippable)?-qr/opt: 1
-                    default: 2
-            default: default
+    tier: default
     variants:
         - dynamic-first-party-isolation+fission
         - fission
         - webrender-sw+fission
         - webrender-sw
     run-on-projects:
         by-variant:
             dynamic-first-party-isolation+fission:
@@ -410,17 +404,24 @@ web-platform-tests-print-reftest:
                     default: []
             webrender-sw:
                 by-test-platform:
                     (linux1804|windows10)-32.*/.*: []
                     android-em-7.0-x86_64-qr/debug: built-projects
                     linux.*64-qr/debug: built-projects
                     windows10-64-2004-qr/debug: built-projects
                     default: []
-            default: built-projects
+            default:
+                by-test-platform:
+                    linux.*64-ccov-qr/opt: []
+                    linux1804-32.*: []
+                    .*-tsan-qr/opt: []
+                    linux.*: ['trunk']  # linux opt/debug/asan
+                    android.*: built-projects
+                    default: []
     mozharness:
         extra-options:
             - --test-type=print-reftest
 
 test-verify-wpt:
     description: "Extra verification of web-platform tests modified on this push"
     suite:
         category: test-verify
--- a/taskcluster/ci/toolchain/clang.yml
+++ b/taskcluster/ci/toolchain/clang.yml
@@ -239,25 +239,27 @@ linux64-clang-13-win-cross:
     worker-type: b-linux
     worker:
         max-run-time: 600
     run:
         script: repack-clang-linux-win-cross.sh
         toolchain-alias: linux64-clang-win-cross
         toolchain-artifact: public/build/clang.tar.zst
     dependencies:
-        win64-clang-13-2stage: toolchain-win64-clang-13-2stage
+        win32-compiler-rt-13: toolchain-win32-compiler-rt-13
+        win64-compiler-rt-13: toolchain-win64-compiler-rt-13
     fetches:
         toolchain:
             - linux64-clang-13
-        win64-clang-13-2stage:
-            # Put this into a new directory so it doesn't conflict with the linux toolchain
-            - artifact: clang.tar.zst
-              dest: clang-cl
-              extract: false
+        win32-compiler-rt-13:
+            - artifact: compiler-rt.tar.zst
+              dest: x86
+        win64-compiler-rt-13:
+            - artifact: compiler-rt.tar.zst
+              dest: x86_64
 
 macosx64-clang-13-raw:
     description: "Clang 13 toolchain build"
     treeherder:
         symbol: TM(clang-13-raw)
     worker-type: b-linux-large
     worker:
         max-run-time: 3600
--- a/taskcluster/ci/toolchain/compiler-rt.yml
+++ b/taskcluster/ci/toolchain/compiler-rt.yml
@@ -13,125 +13,175 @@ job-defaults:
 
 android-aarch64-compiler-rt-13:
     description: "android aarch64 Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TA(aarch64-crt-13)
     run:
         arguments:
             - aarch64-linux-android
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
         resources:
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-clang-13-stage1
             - linux64-android-ndk-linux-repack
 
 android-arm-compiler-rt-13:
     description: "android arm Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TA(arm-crt-13)
     run:
         arguments:
             - armv7-linux-android
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
         resources:
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-clang-13-stage1
             - linux64-android-ndk-linux-repack
 
 android-x86-compiler-rt-13:
     description: "android x86 Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TA(x86-crt-13)
     run:
         arguments:
             - i686-linux-android
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
         resources:
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-clang-13-stage1
             - linux64-android-ndk-linux-repack
 
 android-x64-compiler-rt-13:
     description: "android x64 Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TA(x64-crt-13)
     run:
         arguments:
             - x86_64-linux-android
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
         resources:
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-clang-13-stage1
             - linux64-android-ndk-linux-repack
 
 linux64-aarch64-compiler-rt-13:
     description: "Linux aarch64 Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TL(aarch64-crt-13)
     run:
         arguments:
             - aarch64-unknown-linux-gnu
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
         resources:
-            - 'build/build-clang/find_symbolizer_linux_clang_10.patch'
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-binutils
             - linux64-clang-13-stage1
             - sysroot-aarch64-linux-gnu
 
 macosx64-x64-compiler-rt-13:
     description: "macOS x64 Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TM(x64-crt-13)
     run:
         arguments:
             - x86_64-apple-darwin
+            - build/build-clang/clang-13.json
+        resources:
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-cctools-port-clang-13
             - linux64-clang-13-stage1
             - macosx64-sdk-11.0
 
 macosx64-aarch64-compiler-rt-13:
     description: "macOS aarch64 Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TM(aarch64-crt-13)
     run:
         arguments:
             - aarch64-apple-darwin
+            - build/build-clang/clang-13.json
+        resources:
+            - build/build-clang/clang-13.json
     fetches:
         fetch:
             - clang-13
         toolchain:
             - linux64-cctools-port-clang-13
             - linux64-clang-13-stage1
             - macosx64-sdk-11.0
 
+win32-compiler-rt-13:
+    description: "win32 x86 Compiler-rt for Clang 13 toolchain build"
+    treeherder:
+        symbol: TW32(crt-13)
+    worker:
+        env:
+            TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/vs2017-15.9.manifest"
+    run:
+        arguments:
+            - i686-pc-windows-msvc
+            - build/build-clang/clang-13.json
+        resources:
+            - 'taskcluster/scripts/misc/tooltool-download.sh'
+            - build/build-clang/clang-13.json
+        tooltool-downloads: internal
+    fetches:
+        fetch:
+            - clang-13
+        toolchain:
+            - linux64-clang-13-stage1
+            - linux64-liblowercase
+
+win64-compiler-rt-13:
+    description: "win64 x64 Compiler-rt for Clang 13 toolchain build"
+    treeherder:
+        symbol: TW64(crt-13)
+    worker:
+        env:
+            TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/vs2017-15.9.manifest"
+    run:
+        arguments:
+            - x86_64-pc-windows-msvc
+            - build/build-clang/clang-13.json
+        resources:
+            - 'taskcluster/scripts/misc/tooltool-download.sh'
+            - build/build-clang/clang-13.json
+        tooltool-downloads: internal
+    fetches:
+        fetch:
+            - clang-13
+        toolchain:
+            - linux64-clang-13-stage1
+            - linux64-liblowercase
+
 wasm32-wasi-compiler-rt-13:
     description: "wasm32-wasi Compiler-rt for Clang 13 toolchain build"
     treeherder:
         symbol: TL(wasi-crt-13)
     worker-type: b-linux-xlarge
     run:
         script: build-compiler-rt-wasi.sh
         toolchain-alias: wasm32-wasi-compiler-rt
--- a/taskcluster/scripts/misc/build-compiler-rt.sh
+++ b/taskcluster/scripts/misc/build-compiler-rt.sh
@@ -1,11 +1,11 @@
 #!/bin/sh
 
-set -e
+set -e -x
 
 target=$1
 shift
 
 clang=$MOZ_FETCHES_DIR/clang/bin/clang
 
 case "$target" in
 aarch64-apple-darwin)
@@ -57,16 +57,17 @@ case "$target" in
     -DCMAKE_LIPO=$MOZ_FETCHES_DIR/cctools/bin/lipo
     -DCMAKE_SYSTEM_NAME=Darwin
     -DCMAKE_SYSTEM_VERSION=$MACOSX_DEPLOYMENT_TARGET
     -DCMAKE_OSX_SYSROOT=$MOZ_FETCHES_DIR/MacOSX11.0.sdk
     -DDARWIN_osx_ARCHS=$arch
     -DDARWIN_osx_SYSROOT=$MOZ_FETCHES_DIR/MacOSX11.0.sdk
     -DDARWIN_macosx_OVERRIDE_SDK_VERSION=11.0
     -DDARWIN_osx_BUILTIN_ARCHS=$arch
+    -DLLVM_DEFAULT_TARGET_TRIPLE=$target
   "
   # compiler-rt build script expects to find `codesign` in $PATH.
   # Give it a fake one.
   echo "#!/bin/sh" > codesign
   chmod +x codesign
   PATH="$PWD:$MOZ_FETCHES_DIR/cctools/bin:$PATH"
   ;;
 *-linux-android)
@@ -102,42 +103,83 @@ case "$target" in
 aarch64-unknown-linux-gnu)
   libdir=lib/linux
   EXTRA_CMAKE_FLAGS="
     -DCMAKE_SYSROOT=$MOZ_FETCHES_DIR/sysroot-aarch64-linux-gnu
     -DCMAKE_LINKER=$MOZ_FETCHES_DIR/clang/bin/ld.lld
   "
   PATH="$MOZ_FETCHES_DIR/binutils/bin:$PATH"
   ;;
+*-pc-windows-msvc)
+  VSPATH="$MOZ_FETCHES_DIR/vs2017_15.9.6"
+  SDK_VERSION=10.0.17134.0
+
+  export INCLUDE="${VSPATH}/VC/include;${VSPATH}/VC/atlmfc/include;${VSPATH}/SDK/Include/${SDK_VERSION}/ucrt;${VSPATH}/SDK/Include/${SDK_VERSION}/shared;${VSPATH}/SDK/Include/${SDK_VERSION}/um"
+  case "$target" in
+  i686-pc-windows-msvc)
+    VCARCH=x86
+    ;;
+  x86_64-pc-windows-msvc)
+    VCARCH=x64
+    ;;
+  aarch64-pc-windows-msvc)
+    VCARCH=arm64
+    ;;
+  esac
+  export LIB="${VSPATH}/VC/lib/${VCARCH};${VSPATH}/VC/atlmfc/lib/${VCARCH};${VSPATH}/SDK/Lib/${SDK_VERSION}/um/${VCARCH};${VSPATH}/SDK/Lib/${SDK_VERSION}/ucrt/${VCARCH}"
+  export LD_PRELOAD=$MOZ_FETCHES_DIR/liblowercase/liblowercase.so
+  export LOWERCASE_DIRS=$VSPATH
+  clang=$MOZ_FETCHES_DIR/clang/bin/clang-cl
+  clangxx=$clang
+  ar=lib
+  EXTRA_CMAKE_FLAGS="
+    -DCMAKE_SYSTEM_NAME=Windows
+    -DCMAKE_LINKER=$MOZ_FETCHES_DIR/clang/bin/lld-link
+    -DCMAKE_MT=$MOZ_FETCHES_DIR/clang/bin/llvm-mt
+    -DCMAKE_RC_COMPILER=$MOZ_FETCHES_DIR/clang/bin/llvm-rc
+    -DCMAKE_C_FLAGS='--target=$target -fms-compatibility-version=19.15.26726'
+    -DCMAKE_CXX_FLAGS='--target=$target -fms-compatibility-version=19.15.26726'
+    -DCMAKE_ASM_FLAGS=--target=$target
+  "
+  ;;
 *)
   echo $target is not supported yet
   exit 1
   ;;
 esac
 
 if [ -n "$TOOLTOOL_MANIFEST" ]; then
   . $GECKO_PATH/taskcluster/scripts/misc/tooltool-download.sh
 fi
 
 mkdir compiler-rt
 cd compiler-rt
 
 for patchfile in "$@"; do
-  patch -d $MOZ_FETCHES_DIR/llvm-project -p1 < $GECKO_PATH/$patchfile
+  case $patchfile in
+  *.json)
+      jq -r '.patches[]' $GECKO_PATH/$patchfile | while read p; do
+        patch -d $MOZ_FETCHES_DIR/llvm-project -p1 < $GECKO_PATH/$(dirname $patchfile)/$p
+      done
+      ;;
+  *)
+      patch -d $MOZ_FETCHES_DIR/llvm-project -p1 < $GECKO_PATH/$patchfile
+      ;;
+  esac
 done
 
 eval cmake \
   $MOZ_FETCHES_DIR/llvm-project/compiler-rt \
   -GNinja \
   -DCMAKE_C_COMPILER=$clang \
-  -DCMAKE_CXX_COMPILER=$clang++ \
+  -DCMAKE_CXX_COMPILER=${clangxx:-$clang++} \
   -DCMAKE_C_COMPILER_TARGET=$target \
   -DCMAKE_CXX_COMPILER_TARGET=$target \
   -DCMAKE_ASM_COMPILER_TARGET=$target \
-  -DCMAKE_AR=$MOZ_FETCHES_DIR/clang/bin/llvm-ar \
+  -DCMAKE_AR=$MOZ_FETCHES_DIR/clang/bin/llvm-${ar:-ar} \
   -DCMAKE_RANLIB=$MOZ_FETCHES_DIR/clang/bin/llvm-ranlib \
   -DCMAKE_BUILD_TYPE=Release \
   -DLLVM_ENABLE_ASSERTIONS=OFF \
   -DLLVM_CONFIG_PATH=$MOZ_FETCHES_DIR/clang/bin/llvm-config \
   -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
   $EXTRA_CMAKE_FLAGS
 
 ninja -v
--- a/taskcluster/scripts/misc/repack-clang-linux-win-cross.sh
+++ b/taskcluster/scripts/misc/repack-clang-linux-win-cross.sh
@@ -1,17 +1,21 @@
 #!/bin/bash
 set -x -e -v
 
-# This script is to repack a linux clang with Windows clang-cl.exe and compiler runtime.
+# This script is for building clang for windows targets on a Linux host,
+# including native Windows Compiler-RT libraries.
 
 cd $MOZ_FETCHES_DIR
 
-# We already have the Linux clang extracted in $MOZ_FETCHES_DIR/clang by fetch-content
-# We have a non-extracted clang-cl/clang.tar.zst for Windows clang-cl that we need to extract
-# files from.
+# We have a native linux64 toolchain in $MOZ_FETCHES_DIR/clang
+# We have a native x86 windows compiler-rt in $MOZ_FETCHES_DIR/x86/compiler-rt
+# We have a native x86_64 windows compiler-rt in $MOZ_FETCHES_DIR/x86_64/compiler-rt
+clang_lib=$(echo clang/lib/clang/*/lib)
+mkdir -p $clang_lib/windows
+cp x86/compiler-rt/lib/windows/* $clang_lib/windows
+cp x86_64/compiler-rt/lib/windows/* $clang_lib/windows
 
-$GECKO_PATH/taskcluster/scripts/misc/zstdpy -d clang-cl/clang.tar.zst | tar -x --wildcards clang/lib/clang/*/lib/windows
 tar caf clang.tar.zst clang
 
 # Put a tarball in the artifacts dir
 mkdir -p $UPLOAD_DIR
 cp clang.tar.zst $UPLOAD_DIR
--- a/toolkit/components/extensions/ExtensionCommon.jsm
+++ b/toolkit/components/extensions/ExtensionCommon.jsm
@@ -18,17 +18,16 @@ var EXPORTED_SYMBOLS = ["ExtensionCommon
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 
 XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
 
 XPCOMUtils.defineLazyModuleGetters(this, {
-  AppConstants: "resource://gre/modules/AppConstants.jsm",
   ConsoleAPI: "resource://gre/modules/Console.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   Schemas: "resource://gre/modules/Schemas.jsm",
   SchemaRoot: "resource://gre/modules/Schemas.jsm",
 });
 
 XPCOMUtils.defineLazyServiceGetter(
   this,
@@ -54,22 +53,16 @@ function getConsole() {
   return new ConsoleAPI({
     maxLogLevelPref: "extensions.webextensions.log.level",
     prefix: "WebExtensions",
   });
 }
 
 XPCOMUtils.defineLazyGetter(this, "console", getConsole);
 
-XPCOMUtils.defineLazyPreferenceGetter(
-  this,
-  "DELAYED_BG_STARTUP",
-  "extensions.webextensions.background-delayed-startup"
-);
-
 var ExtensionCommon;
 
 // Run a function and report exceptions.
 function runSafeSyncWithoutClone(f, ...args) {
   try {
     return f(...args);
   } catch (e) {
     dump(
@@ -2127,74 +2120,96 @@ defineLazyGetter(LocaleData.prototype, "
  *
  * The result is an object with addListener, removeListener, and
  * hasListener methods. `context` is an add-on scope (either an
  * ExtensionContext in the chrome process or ExtensionContext in a
  * content process).
  */
 class EventManager {
   /*
+   * A persistent event must provide module and name.  Additionally the
+   * module must implement primeListeners in the ExtensionAPI class.
+   *
+   * A startup blocking event must also add the startupBlocking flag in
+   * ext-toolkit.json or ext-browser.json.
+   *
+   * Listeners synchronously added from a background extension context
+   * will be persisted, for a persistent background script only the
+   * "startup blocking" events will be persisted.
+   *
+   * EventManager instances created in a child process can't persist any listener.
+   *
    * @param {object} params
    *        Parameters that control this EventManager.
    * @param {BaseContext} params.context
    *        An object representing the extension instance using this event.
-   * @param {string} params.name
-   *        A name used only for debugging.
+   * @param {string} params.module
+   *        The API module name, required for persistent events.
+   * @param {string} params.event
+   *        The API event name, required for persistent events.
+   * @param {string} [params.name]
+   *        A name used only for debugging.  If not provided, name is built from module and event.
    * @param {functon} params.register
    *        A function called whenever a new listener is added.
    * @param {boolean} [params.inputHandling=false]
    *        If true, the "handling user input" flag is set while handlers
    *        for this event are executing.
-   * @param {object} [params.persistent]
-   *        Details for persistent event listeners
-   * @param {string} params.persistent.module
-   *        The name of the module in which this event is defined.
-   * @param {string} params.persistent.event
-   *        The name of this event.
    */
   constructor(params) {
     let {
       context,
+      module,
+      event,
       name,
       register,
       inputHandling = false,
-      persistent = null,
     } = params;
     this.context = context;
+    this.module = module;
+    this.event = event;
     this.name = name;
     this.register = register;
     this.inputHandling = inputHandling;
-    this.persistent = persistent;
+
+    if (!name) {
+      this.name = `${module}.${event}`;
+    }
+
+    this.canPersistEvents =
+      module &&
+      event &&
+      ["background", "background_worker"].includes(this.context.viewType) &&
+      this.context.envType == "addon_parent";
 
-    // Don't bother with persistent event handling if delayed background
-    // startup is not enabled.
-    if (!DELAYED_BG_STARTUP) {
-      this.persistent = null;
+    if (this.canPersistEvents) {
+      let { extension } = context;
+      if (extension.persistentBackground) {
+        // Persistent backgrounds will only persist startup blocking APIs.
+        let api_module = extension.apiManager.getModule(this.module);
+        if (!api_module?.startupBlocking) {
+          this.canPersistEvents = false;
+        }
+      } else {
+        // Event pages will persist all APIs that implement primeListener.
+        // The api is already loaded so this does not have performance effect.
+        let api = extension.apiManager.getAPI(
+          this.module,
+          extension,
+          "addon_parent"
+        );
+
+        // If the api doesn't implement primeListener we do not persist the events.
+        if (!api?.primeListener) {
+          this.canPersistEvents = false;
+        }
+      }
     }
 
     this.unregister = new Map();
     this.remove = new Map();
-
-    if (this.persistent) {
-      if (AppConstants.DEBUG) {
-        if (this.context.envType !== "addon_parent") {
-          throw new Error(
-            "Persistent event managers can only be created for addon_parent"
-          );
-        }
-        if (!this.persistent.module || !this.persistent.event) {
-          throw new Error(
-            "Persistent event manager must specify module and event"
-          );
-        }
-      }
-      if (this.context.viewType !== "background") {
-        this.persistent = null;
-      }
-    }
   }
 
   /*
    * Information about listeners to persistent events is associated with
    * the extension to which they belong.  Any extension thas has such
    * listeners has a property called `persistentListeners` that is a
    * 3-level Map.  The first 2 keys are the module name (e.g., webRequest)
    * and the name of the event within the module (e.g., onBeforeRequest).
@@ -2217,17 +2232,17 @@ class EventManager {
   static _initPersistentListeners(extension) {
     if (extension.persistentListeners) {
       return !!extension.persistentListeners.size;
     }
 
     let listeners = new DefaultMap(() => new DefaultMap(() => new Map()));
     extension.persistentListeners = listeners;
 
-    let { persistentListeners } = extension.startupData;
+    let persistentListeners = extension.startupData?.persistentListeners;
     if (!persistentListeners) {
       return false;
     }
 
     let found = false;
     for (let [module, entry] of Object.entries(persistentListeners)) {
       for (let [event, paramlists] of Object.entries(entry)) {
         for (let paramlist of paramlists) {
@@ -2267,17 +2282,27 @@ class EventManager {
   // This function is only called during browser startup, it stores details
   // about all primed listeners in the extension's persistentListeners Map.
   static primeListeners(extension, isInStartup = false) {
     if (!EventManager._initPersistentListeners(extension)) {
       return;
     }
 
     for (let [module, moduleEntry] of extension.persistentListeners) {
+      // If we're in startup, we only want to continue attempting to prime a
+      // subset of events that should be startup blocking.
+      if (isInStartup) {
+        let api_module = extension.apiManager.getModule(module);
+        if (!api_module.startupBlocking) {
+          continue;
+        }
+      }
+
       let api = extension.apiManager.getAPI(module, extension, "addon_parent");
+
       // If an extension is upgraded and a permission, such as webRequest, is
       // removed, we will have been called but the API is no longer available.
       if (!api?.primeListener) {
         // The runtime module no longer implements primed listeners, drop them.
         extension.persistentListeners.delete(module);
         EventManager._writePersistentListeners(extension);
         continue;
       }
@@ -2429,26 +2454,28 @@ class EventManager {
             this.context.logActivity("api_event", this.name, { args, result });
             return result;
           }
         });
       },
     };
 
     let { extension } = this.context;
+    let { module, event } = this;
 
     let unregister = null;
     let recordStartupData = false;
 
     // If this is a persistent event, check for a listener that was already
     // created during startup.  If there is one, use it and don't create a
     // new one.
-    if (this.persistent) {
-      recordStartupData = true;
-      let { module, event } = this.persistent;
+    if (this.canPersistEvents) {
+      // Once a background is started, listenerPromises is set to null. At
+      // that point, we stop recording startup data.
+      recordStartupData = !!this.context.listenerPromises;
 
       let key = uneval(args);
       EventManager._initPersistentListeners(extension);
       let listener = extension.persistentListeners
         .get(module)
         .get(event)
         .get(key);
 
@@ -2486,17 +2513,16 @@ class EventManager {
     }
 
     this.unregister.set(callback, unregister);
     this.context.callOnClose(this);
 
     // If this is a new listener for a persistent event, record
     // the details for subsequent startups.
     if (recordStartupData) {
-      let { module, event } = this.persistent;
       EventManager.savePersistentListener(extension, module, event, args);
       this.remove.set(callback, () => {
         EventManager.clearPersistentListener(
           extension,
           module,
           event,
           uneval(args)
         );
--- a/toolkit/components/extensions/docs/events.rst
+++ b/toolkit/components/extensions/docs/events.rst
@@ -159,17 +159,18 @@ For example, extending our example above
 .. code-block:: js
 
    this.myapi = class extends ExtensionAPI {
      getAPI(context) {
        return {
          myapi: {
            onSomething: new EventManager({
              context,
-             name: "myapi.onSomething",
+             module: "myapi",
+             event: "onSomething",
              register: (fire, minValue) => {
                const callback = value => {
                  if (value >= minValue) {
                    fire.async(value);
                  }
                };
                RegisterSomeInternalCallback(callback);
                return () => {
@@ -220,17 +221,18 @@ which is a Promise that resolves to the 
 .. code-block:: js
 
    this.myapi = class extends ExtensionAPI {
      getAPI(context) {
        return {
          myapi: {
            onSomething: new EventManager({
              context,
-             name: "myapi.onSomething",
+             module: "myapi",
+             event: "onSomething",
              register: fire => {
                const callback = async (value) => {
                  let rv = await fire.async(value);
                  log(`The onSomething listener returned the string ${rv}`);
                };
                RegisterSomeInternalCallback(callback);
                return () => {
                  UnregisterInternalCallback(callback);
@@ -306,9 +308,83 @@ to dispatch listeners:
   value returned by the listener
 
 - ``fire.raw()`` This runs the listener synchronously without cloning
   the listener arguments into the extension's Javascript compartment.
   This is used as a performance optimization, it should not be used
   unless you have a detailed understanding of Javascript compartments
   and cross-compartment wrappers.
 
+Event Persistence
+-----------------
 
+Events are persisted in some circumstances.  Persisted events can either
+block startup, and/or cause an event page or service worker to be started.
+
+The event listener must be registered synchronously in the top level scope
+of the background.  Event listeners registered later, or asynchronously, are
+not persisted.
+
+Currently only WebRequestBlocking and Proxy events are able to block
+at startup, causing an addon to start earlier in Firefox startup.  Whether
+a module can block startup is defined by a ``startupBlocking`` flag in
+the module definition files (``ext-toolkit.json`` or ``ext-browser.json``).
+As well, these are the only events persisted for persistent background scripts.
+
+Events implemented only in a child process, without a parent process counterpart,
+cannot be persisted.
+
+To make a persistent listener, the ExtensionAPI class in the module must also
+provide a ``primeListeners`` method.  The ``module`` and ``event`` params are
+required for the ``EventManager`` constructor.
+
+This requires structuring the listener registration code in a way that it can
+be used by both the ``primeListener`` call and in the constructor for ``EventManager``.
+
+``primeListener`` must return an object with an ``unregister`` and ``convert`` method, while
+the ``register`` callback passed to  the ``EventManager`` constructor is expected to return
+the ``unregister`` method.
+
+.. code-block:: js
+
+   function somethingListener(fire, minValue) => {
+     const callback = value => {
+       if (value >= minValue) {
+         fire.async(value);
+       }
+     };
+     RegisterSomeInternalCallback(callback);
+     return {
+       unregister() {
+         UnregisterInternalCallback(callback);
+       },
+       convert(_fire, context) {
+         fire = _fire;
+       }
+     };
+   }
+
+   this.myapi = class extends ExtensionAPI {
+     primeListener(extension, event, fire, params, isInStartup) {
+       if (event == "onSomething") {
+         // Note that we return the object with unregister and convert here.
+         return somethingListener(fire, ...params);
+       }
+       // If an event other than onSomething was requested, we are not returning
+       // anything for it, thus it would not be persistable.
+     }
+     getAPI(context) {
+       return {
+         myapi: {
+           onSomething: new EventManager({
+             context,
+             module: "myapi",
+             event: "onSomething",
+             register: (fire, minValue) => {
+               // Note that we return unregister here.
+               return somethingListener(fire, minValue).unregister;
+             }
+           }).api()
+         }
+       }
+     }
+   }
+
--- a/toolkit/components/extensions/ext-toolkit.json
+++ b/toolkit/components/extensions/ext-toolkit.json
@@ -157,17 +157,18 @@
   },
   "proxy": {
     "url": "chrome://extensions/content/parent/ext-proxy.js",
     "schema": "chrome://extensions/content/schemas/proxy.json",
     "scopes": ["addon_parent"],
     "settings": true,
     "paths": [
       ["proxy"]
-    ]
+    ],
+    "startupBlocking": true
   },
   "runtime": {
     "url": "chrome://extensions/content/parent/ext-runtime.js",
     "schema": "chrome://extensions/content/schemas/runtime.json",
     "scopes": ["addon_parent", "content_parent", "devtools_parent"],
     "paths": [
       ["runtime"]
     ]
@@ -233,11 +234,12 @@
     ]
   },
   "webRequest": {
     "url": "chrome://extensions/content/parent/ext-webRequest.js",
     "schema": "chrome://extensions/content/schemas/web_request.json",
     "scopes": ["addon_parent"],
     "paths": [
       ["webRequest"]
-    ]
+    ],
+    "startupBlocking": true
   }
 }
--- a/toolkit/components/extensions/parent/ext-backgroundPage.js
+++ b/toolkit/components/extensions/parent/ext-backgroundPage.js
@@ -86,17 +86,18 @@ class BackgroundPage extends HiddenExten
       extension.emit("background-script-aborted");
       return;
     }
 
     ExtensionTelemetry.backgroundPageLoad.stopwatchFinish(extension, this);
 
     if (context) {
       // Wait until all event listeners registered by the script so far
-      // to be handled.
+      // to be handled. We then set listenerPromises to null, which indicates
+      // to addListener that the background script has finished loading.
       await Promise.all(context.listenerPromises);
       context.listenerPromises = null;
     }
 
     if (extension.persistentListeners) {
       // |this.extension| may be null if the extension was shut down.
       // In that case, we still want to clear the primed listeners,
       // but not update the persistent listeners in the startupData.
--- a/toolkit/components/extensions/parent/ext-proxy.js
+++ b/toolkit/components/extensions/parent/ext-proxy.js
@@ -133,21 +133,18 @@ this.proxy = class extends ExtensionAPI 
 
   getAPI(context) {
     let { extension } = context;
 
     return {
       proxy: {
         onRequest: new EventManager({
           context,
-          name: `proxy.onRequest`,
-          persistent: {
-            module: "proxy",
-            event: "onRequest",
-          },
+          module: "proxy",
+          event: "onRequest",
           register: (fire, filter, info) => {
             return registerProxyFilterEvent(
               context,
               context.extension,
               fire,
               filter,
               info
             ).unregister;
--- a/toolkit/components/extensions/parent/ext-webRequest.js
+++ b/toolkit/components/extensions/parent/ext-webRequest.js
@@ -99,28 +99,25 @@ function registerEvent(
     },
     convert(_fire, context) {
       fire = _fire;
       remoteTab = context.xulBrowser.frameLoader.remoteTab;
     },
   };
 }
 
-function makeWebRequestEvent(context, name) {
+function makeWebRequestEvent(context, event) {
   return new EventManager({
     context,
-    name: `webRequest.${name}`,
-    persistent: {
-      module: "webRequest",
-      event: name,
-    },
+    module: "webRequest",
+    event,
     register: (fire, filter, info) => {
       return registerEvent(
         context.extension,
-        name,
+        event,
         fire,
         filter,
         info,
         context.xulBrowser.frameLoader.remoteTab
       ).unregister;
     },
   }).api();
 }
--- a/toolkit/components/extensions/test/xpcshell/test_ext_persistent_events.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_persistent_events.js
@@ -67,37 +67,31 @@ const API = class extends ExtensionAPI {
     };
   }
 
   getAPI(context) {
     return {
       eventtest: {
         onEvent1: new EventManager({
           context,
-          name: "test.event1",
-          persistent: {
-            module: "eventtest",
-            event: "onEvent1",
-          },
+          module: "eventtest",
+          event: "onEvent1",
           register: (fire, ...params) => {
             let data = { event: "onEvent1", params };
             Services.obs.notifyObservers(data, "register-event-listener");
             return () => {
               Services.obs.notifyObservers(data, "unregister-event-listener");
             };
           },
         }).api(),
 
         onEvent2: new EventManager({
           context,
-          name: "test.event1",
-          persistent: {
-            module: "eventtest",
-            event: "onEvent2",
-          },
+          module: "eventtest",
+          event: "onEvent2",
           register: (fire, ...params) => {
             let data = { event: "onEvent2", params };
             Services.obs.notifyObservers(data, "register-event-listener");
             return () => {
               Services.obs.notifyObservers(data, "unregister-event-listener");
             };
           },
         }).api(),
@@ -108,16 +102,17 @@ const API = class extends ExtensionAPI {
 
 const API_SCRIPT = `this.eventtest = ${API.toString()}`;
 
 const MODULE_INFO = {
   eventtest: {
     schema: `data:,${JSON.stringify(SCHEMA)}`,
     scopes: ["addon_parent"],
     paths: [["eventtest"]],
+    startupBlocking: true,
     url: URL.createObjectURL(new Blob([API_SCRIPT])),
   },
 };
 
 const global = this;
 
 // Wait for the given event (topic) to occur a specific number of times
 // (count).  If fn is not supplied, the Promise returned from this function
@@ -578,76 +573,116 @@ add_task(async function test_background_
 
   await extension.unload();
   await AddonTestUtils.promiseShutdownManager();
 });
 
 // This test checks whether primed listeners are correctly primed to
 // restart the background once the background has been shutdown or
 // put to sleep.
-add_task(async function test_eventpage_startup() {
-  Services.prefs.setBoolPref("extensions.eventPages.enabled", true);
-  await AddonTestUtils.promiseStartupManager();
-  // ensure normal delayed startup notification had already happened at some point
-  Services.obs.notifyObservers(null, "browser-delayed-startup-finished");
+add_task(
+  { prefs_set: [["extensions.eventPages.enabled", true]] },
+  async function test_eventpage_startup() {
+    await AddonTestUtils.promiseStartupManager();
+    // ensure normal delayed startup notification had already happened at some point
+    Services.obs.notifyObservers(null, "browser-delayed-startup-finished");
 
-  let extension = ExtensionTestUtils.loadExtension({
-    useAddonManager: "permanent",
-    manifest: {
-      applications: { gecko: { id: "eventpage@test" } },
-      background: { persistent: false },
-    },
-    background() {
-      let listener = arg => browser.test.sendMessage("triggered", arg);
-      browser.eventtest.onEvent1.addListener(listener, "triggered");
-      browser.test.sendMessage("bg_started");
-    },
-  });
-  await Promise.all([
-    promiseObservable("register-event-listener", 1),
-    extension.startup(),
-  ]);
-  await extension.awaitMessage("bg_started");
+    let extension = ExtensionTestUtils.loadExtension({
+      useAddonManager: "permanent",
+      manifest: {
+        applications: { gecko: { id: "eventpage@test" } },
+        background: { persistent: false },
+      },
+      background() {
+        let listener = arg => browser.test.sendMessage("triggered", arg);
+        browser.eventtest.onEvent1.addListener(listener, "triggered");
+        browser.test.onMessage.addListener(() => {
+          let listener = arg => browser.test.sendMessage("triggered2", arg);
+          browser.eventtest.onEvent2.addListener(listener, "triggered2");
+          browser.test.sendMessage("async-registered-listener");
+        });
+        browser.test.sendMessage("bg_started");
+      },
+    });
+    await Promise.all([
+      promiseObservable("register-event-listener", 1),
+      extension.startup(),
+    ]);
+    await extension.awaitMessage("bg_started");
+    extension.sendMessage("async-register-listener");
+    await extension.awaitMessage("async-registered-listener");
 
-  async function testAfterRestart() {
-    assertPersistentListeners(extension, "eventtest", "onEvent1", {
-      primed: true,
-    });
+    async function testAfterRestart() {
+      assertPersistentListeners(extension, "eventtest", "onEvent1", {
+        primed: true,
+      });
+      // async registration should not be primed or persisted
+      assertPersistentListeners(extension, "eventtest", "onEvent2", {
+        primed: false,
+        persisted: false,
+      });
+
+      let events = trackEvents(extension);
+      ok(
+        !events.get("background-script-event"),
+        "Should not have received a background script event"
+      );
+      ok(
+        !events.get("start-background-script"),
+        "Background script should not be started"
+      );
 
-    let events = trackEvents(extension);
-    ok(
-      !events.get("background-script-event"),
-      "Should not have received a background script event"
-    );
-    ok(
-      !events.get("start-background-script"),
-      "Background script should not be started"
-    );
+      info("Triggering persistent event to force the background page to start");
+      let converted = promiseObservable("convert-event-listener", 1);
+      Services.obs.notifyObservers({ listenerArgs: 123 }, "fire-onEvent1");
+      await extension.awaitMessage("bg_started");
+      await converted;
+      equal(await extension.awaitMessage("triggered"), 123, "triggered event");
+      ok(
+        events.get("background-script-event"),
+        "Should have received a background script event"
+      );
+      ok(
+        events.get("start-background-script"),
+        "Background script should be started"
+      );
+    }
+
+    // Shutdown the background page
+    await Promise.all([
+      promiseObservable("unregister-event-listener", 2),
+      new Promise(resolve => extension.extension.once("shutdown", resolve)),
+      AddonTestUtils.promiseShutdownManager(),
+    ]);
+    await AddonTestUtils.promiseStartupManager();
+    await extension.awaitStartup();
+    await testAfterRestart();
 
-    info("Triggering persistent event to force the background page to start");
-    Services.obs.notifyObservers({ listenerArgs: 123 }, "fire-onEvent1");
-    await extension.awaitMessage("bg_started");
-    equal(await extension.awaitMessage("triggered"), 123, "triggered event");
-    ok(
-      events.get("background-script-event"),
-      "Should have received a background script event"
-    );
-    ok(
-      events.get("start-background-script"),
-      "Background script should be started"
-    );
-  }
+    extension.sendMessage("async-register-listener");
+    await extension.awaitMessage("async-registered-listener");
+
+    // We sleep twice to ensure startup and shutdown work correctly
+    info("test event listener registration during termination");
+    let registrationEvents = Promise.all([
+      promiseObservable("unregister-event-listener", 1),
+      promiseObservable("unregister-primed-listener", 1),
+      promiseObservable("prime-event-listener", 1),
+    ]);
+    await extension.terminateBackground();
+    await registrationEvents;
 
-  // Shutdown the background page
-  await AddonTestUtils.promiseRestartManager();
-  await extension.awaitStartup();
-  await testAfterRestart();
+    // Ensure onEvent2 does not fire, testAfterRestart will fail otherwise.
+    Services.obs.notifyObservers({ listenerArgs: 123 }, "fire-onEvent2");
+    await testAfterRestart();
 
-  // We sleep twice to ensure startup and shutdown work correctly
-  await extension.terminateBackground();
-  await testAfterRestart();
-  await extension.terminateBackground();
-  await testAfterRestart();
+    registrationEvents = Promise.all([
+      promiseObservable("unregister-primed-listener", 1),
+      promiseObservable("prime-event-listener", 1),
+    ]);
+    await extension.terminateBackground();
+    await registrationEvents;
+    await testAfterRestart();
 
-  await extension.unload();
-  await AddonTestUtils.promiseShutdownManager();
-  Services.prefs.setBoolPref("extensions.eventPages.enabled", false);
-});
+    await extension.unload();
+    await AddonTestUtils.promiseShutdownManager();
+    Services.prefs.setBoolPref("extensions.eventPages.enabled", false);
+  }
+);
--- a/toolkit/components/reputationservice/ApplicationReputation.cpp
+++ b/toolkit/components/reputationservice/ApplicationReputation.cpp
@@ -1966,8 +1966,15 @@ nsresult ApplicationReputationService::Q
   return lookup->StartLookup();
 }
 
 nsresult ApplicationReputationService::IsBinary(const nsACString& aFileName,
                                                 bool* aBinary) {
   *aBinary = ::IsBinary(aFileName);
   return NS_OK;
 }
+
+nsresult ApplicationReputationService::IsExecutable(const nsACString& aFileName,
+                                                    bool* aExecutable) {
+  *aExecutable =
+      ::IsFileType(aFileName, sExecutableExts, ArrayLength(sExecutableExts));
+  return NS_OK;
+}
--- a/toolkit/components/reputationservice/nsIApplicationReputation.idl
+++ b/toolkit/components/reputationservice/nsIApplicationReputation.idl
@@ -55,16 +55,27 @@ interface nsIApplicationReputationServic
    * - in kBinaryFileExtensions in ApplicationReputation.cpp
    * - in sExecutableExts in nsLocalFileCommon.h *and* not in
    *   kNonBinaryExecutables in ApplicationReputation.cpp
    *
    * @param aFilename
    *        The filename to check.
    */
   bool isBinary(in AUTF8String aFilename);
+
+  /**
+   * Check if a file with this name should be treated as an executable,
+   * and should not be opened without caution.
+   * Will return true if the filename's extension is in sExecutableExts
+   * in nsLocalFileCommon.h.
+   *
+   * @param aFilename
+   *        The filename to check.
+   */
+  bool isExecutable(in AUTF8String aFilename);
 };
 
 /**
  * A single-use, write-once interface for recording the metadata of the
  * downloaded file. nsIApplicationReputationService.Start() may only be called
  * once with a single query.
  */
 [scriptable, uuid(812d7509-a9a3-446e-a66f-3ed8cc91ebd0)]
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -811,17 +811,16 @@ system_gpsd = pkg_check_modules("MOZ_GPS
 
 set_config("MOZ_GPSD", depends_if(system_gpsd)(lambda _: True))
 
 # Miscellaneous programs
 # ==============================================================
 
 check_prog("TAR", ("gnutar", "gtar", "tar"))
 check_prog("UNZIP", ("unzip",))
-check_prog("ZIP", ("zip",))
 check_prog("GN", ("gn",), allow_missing=True)
 
 # Key files
 # ==============================================================
 include("../build/moz.configure/keyfiles.configure")
 
 simple_keyfile("Mozilla API")
 
--- a/toolkit/mozapps/downloads/HelperAppDlg.jsm
+++ b/toolkit/mozapps/downloads/HelperAppDlg.jsm
@@ -780,16 +780,17 @@ nsUnknownContentTypeDialog.prototype = {
     // We don't let users open .exe files or random binary data directly
     // from the browser at the moment because of security concerns.
     var openWithDefaultOK = this.openWithDefaultOK();
     var mimeType = this.mLauncher.MIMEInfo.MIMEType;
     var openHandler = this.dialogElement("openHandler");
     if (
       this.mLauncher.targetFileIsExecutable ||
       ((mimeType == "application/octet-stream" ||
+        mimeType == "application/x-msdos-program" ||
         mimeType == "application/x-msdownload") &&
         !openWithDefaultOK)
     ) {
       this.dialogElement("open").disabled = true;
       openHandler.disabled = true;
       openHandler.selectedItem = null;
       modeGroup.selectedItem = this.dialogElement("save");
       return;
--- a/toolkit/mozapps/installer/upload-files.mk
+++ b/toolkit/mozapps/installer/upload-files.mk
@@ -125,17 +125,17 @@ ifeq ($(MOZ_PKG_FORMAT),BZ2)
   else
     INNER_MAKE_PACKAGE 	= $(CREATE_FINAL_TAR) - $(MOZ_PKG_DIR) | bzip2 -vf > $(PACKAGE)
   endif
   INNER_UNMAKE_PACKAGE	= bunzip2 -c $(UNPACKAGE) | $(UNPACK_TAR)
 endif
 
 ifeq ($(MOZ_PKG_FORMAT),ZIP)
   PKG_SUFFIX	= .zip
-  INNER_MAKE_PACKAGE = $(call py_action,make_zip,'$(MOZ_PKG_DIR)' '$(PACKAGE)')
+  INNER_MAKE_PACKAGE = $(call py_action,zip,'$(PACKAGE)' '$(MOZ_PKG_DIR)' -x '**/.mkdir.done')
   INNER_UNMAKE_PACKAGE = $(call py_action,make_unzip,$(UNPACKAGE))
 endif
 
 #Create an RPM file
 ifeq ($(MOZ_PKG_FORMAT),RPM)
   PKG_SUFFIX  = .rpm
   MOZ_NUMERIC_APP_VERSION = $(shell echo $(MOZ_PKG_VERSION) | sed 's/[^0-9.].*//' )
   MOZ_RPM_RELEASE = $(shell echo $(MOZ_PKG_VERSION) | sed 's/[0-9.]*//' )
deleted file mode 100644
--- a/tools/crashreporter/app.mozbuild
+++ /dev/null
@@ -1,8 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += [
-    '/config/external/zlib',
-    '/toolkit/crashreporter/google-breakpad/src/processor',
-]
deleted file mode 100644
--- a/tools/crashreporter/moz.configure
+++ /dev/null
@@ -1,3 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1965,16 +1965,49 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
   // Additionally, if we are asked by the OS to open a local file,
   // automatically downloading it to create a second copy of that file doesn't
   // really make sense. We should ask the user what they want to do.
   if (mSourceUrl->SchemeIs("file") && !alwaysAsk &&
       action == nsIMIMEInfo::saveToDisk) {
     alwaysAsk = true;
   }
 
+  // If adding new checks, make sure this is the last check before telemetry
+  // and going ahead with opening the file!
+#ifdef XP_WIN
+  /* We need to see whether the file we've got here could be
+   * executable.  If it could, we had better not try to open it!
+   * We can skip this check, though, if we have a setting to open in a
+   * helper app.
+   */
+  if (!alwaysAsk && action != nsIMIMEInfo::saveToDisk &&
+      !shouldAutomaticallyHandleInternally) {
+    nsCOMPtr<nsIHandlerApp> prefApp;
+    mMimeInfo->GetPreferredApplicationHandler(getter_AddRefs(prefApp));
+    if (action != nsIMIMEInfo::useHelperApp || !prefApp) {
+      nsCOMPtr<nsIFile> fileToTest;
+      GetTargetFile(getter_AddRefs(fileToTest));
+      if (fileToTest) {
+        bool isExecutable;
+        rv = fileToTest->IsExecutable(&isExecutable);
+        if (NS_FAILED(rv) || mTempFileIsExecutable ||
+            isExecutable) {  // checking NS_FAILED, because paranoia is good
+          alwaysAsk = true;
+        }
+      } else {  // Paranoia is good here too, though this really should not
+                // happen
+        NS_WARNING(
+            "GetDownloadInfo returned a null file after the temp file has been "
+            "set up! ");
+        alwaysAsk = true;
+      }
+    }
+  }
+#endif
+
   nsAutoCString actionTelem;
   if (alwaysAsk) {
     actionTelem.AssignLiteral("ask");
   } else if (shouldAutomaticallyHandleInternally) {
     actionTelem.AssignLiteral("internal");
   } else if (action == nsIMIMEInfo::useHelperApp ||
              action == nsIMIMEInfo::useSystemDefault) {
     actionTelem.AssignLiteral("external");
@@ -1993,49 +2026,16 @@ NS_IMETHODIMP nsExternalAppHandler::OnSt
     // nsIHelperAppLauncher), which will be broken in Cancel or CreateTransfer.
     nsCOMPtr<nsIInterfaceRequestor> dialogParent = GetDialogParent();
     rv = mDialog->Show(this, dialogParent, mReason);
 
     // what do we do if the dialog failed? I guess we should call Cancel and
     // abort the load....
   } else {
     // We need to do the save/open immediately, then.
-#ifdef XP_WIN
-    /* We need to see whether the file we've got here could be
-     * executable.  If it could, we had better not try to open it!
-     * We can skip this check, though, if we have a setting to open in a
-     * helper app.
-     * This code mirrors the code in
-     * nsExternalAppHandler::SetDownloadToLaunch so that what we
-     * test here is as close as possible to what will really be
-     * happening if we decide to execute
-     */
-    nsCOMPtr<nsIHandlerApp> prefApp;
-    mMimeInfo->GetPreferredApplicationHandler(getter_AddRefs(prefApp));
-    if (action != nsIMIMEInfo::useHelperApp || !prefApp) {
-      nsCOMPtr<nsIFile> fileToTest;
-      GetTargetFile(getter_AddRefs(fileToTest));
-      if (fileToTest) {
-        bool isExecutable;
-        rv = fileToTest->IsExecutable(&isExecutable);
-        if (NS_FAILED(rv) ||
-            isExecutable) {  // checking NS_FAILED, because paranoia is good
-          action = nsIMIMEInfo::saveToDisk;
-        }
-      } else {  // Paranoia is good here too, though this really should not
-                // happen
-        NS_WARNING(
-            "GetDownloadInfo returned a null file after the temp file has been "
-            "set up! ");
-        action = nsIMIMEInfo::saveToDisk;
-      }
-    }
-
-#endif
-
     if (action == nsIMIMEInfo::useHelperApp ||
         action == nsIMIMEInfo::useSystemDefault ||
         shouldAutomaticallyHandleInternally) {
       // Check if the file is local, in which case just launch it from where it
       // is. Otherwise, set the file to launch once it's finished downloading.
       rv = mIsFileChannel ? LaunchLocalFile()
                           : SetDownloadToLaunch(
                                 shouldAutomaticallyHandleInternally, nullptr);
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -8507,22 +8507,17 @@ void nsWindow::SetDrawsInTitlebar(bool a
     }
 
     // Using GTK_WINDOW_POPUP rather than
     // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
     // initialization and window manager interaction.
     GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP);
     gtk_widget_realize(tmpWindow);
 
-    g_object_ref(mContainer);
-    gtk_container_remove(
-        GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(mContainer))),
-        GTK_WIDGET(mContainer));
-    gtk_container_add(GTK_CONTAINER(tmpWindow), GTK_WIDGET(mContainer));
-    g_object_unref(mContainer);
+    gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow);
     gtk_widget_unrealize(GTK_WIDGET(mShell));
 
     if (aState) {
       // Add a hidden titlebar widget to trigger CSD, but disable the default
       // titlebar.  GtkFixed is a somewhat random choice for a simple unused
       // widget. gtk_window_set_titlebar() takes ownership of the titlebar
       // widget.
       gtk_window_set_titlebar(GTK_WINDOW(mShell), gtk_fixed_new());
@@ -8538,22 +8533,17 @@ void nsWindow::SetDrawsInTitlebar(bool a
     GtkAllocation allocation = {0, 0, 0, 0};
     gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr,
                                    &allocation.width);
     gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr,
                                     &allocation.height);
     gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation);
 
     gtk_widget_realize(GTK_WIDGET(mShell));
-    g_object_ref(mContainer);
-    gtk_container_remove(
-        GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(mContainer))),
-        GTK_WIDGET(mContainer));
-    gtk_container_add(GTK_CONTAINER(mShell), GTK_WIDGET(mContainer));
-    g_object_unref(mContainer);
+    gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
 
     // Label mShell toplevel window so property_notify_event_cb callback
     // can find its way home.
     g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)), "nsWindow",
                       this);
 
     if (AreBoundsSane()) {
       GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size());