Merge inbound to mozilla-central. a=merge
authorGurzau Raul <rgurzau@mozilla.com>
Thu, 03 May 2018 00:04:54 +0300
changeset 472826 2d83e1843241d869a2fc5cf06f96d3af44c70e70
parent 472819 a0f7e5f1bea6466277ba96a2bd22eee6f72930c3 (current diff)
parent 472825 04e165cb504fe603c1b61e1b59342bc0556a25dd (diff)
child 472829 4cd21995f6d93788eeb72e5f62f59dd2861a0a2f
child 472864 cb245b9a8b2ce1dbe877f85566cf16613d8d9b44
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone61.0a1
first release with
nightly linux32
2d83e1843241 / 61.0a1 / 20180502220059 / files
nightly linux64
2d83e1843241 / 61.0a1 / 20180502220059 / files
nightly mac
2d83e1843241 / 61.0a1 / 20180502220059 / files
nightly win32
2d83e1843241 / 61.0a1 / 20180502220059 / files
nightly win64
2d83e1843241 / 61.0a1 / 20180502220059 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
taskcluster/ci/release-source/source.yml
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6935,17 +6935,17 @@ var WebAuthnPromptHelper = {
       this.sign(mgr, data);
     } else if (data.action == "cancel") {
       this.cancel(data);
     }
   },
 
   register(mgr, {origin, tid}) {
     let mainAction = this.buildCancelAction(mgr, tid);
-    this.show(tid, "register", "webauthn.registerPrompt", origin, mainAction);
+    this.show(tid, "register", "webauthn.registerPrompt2", origin, mainAction);
   },
 
   registerDirect(mgr, {origin, tid}) {
     let mainAction = this.buildProceedAction(mgr, tid);
     let secondaryActions = [this.buildCancelAction(mgr, tid)];
 
     let learnMoreURL =
       Services.urlFormatter.formatURLPref("app.support.baseURL") +
@@ -6953,23 +6953,23 @@ var WebAuthnPromptHelper = {
 
     let options = {
       learnMoreURL,
       checkbox: {
         label: gNavigatorBundle.getString("webauthn.anonymize")
       }
     };
 
-    this.show(tid, "register-direct", "webauthn.registerDirectPrompt",
+    this.show(tid, "register-direct", "webauthn.registerDirectPrompt2",
               origin, mainAction, secondaryActions, options);
   },
 
   sign(mgr, {origin, tid}) {
     let mainAction = this.buildCancelAction(mgr, tid);
-    this.show(tid, "sign", "webauthn.signPrompt", origin, mainAction);
+    this.show(tid, "sign", "webauthn.signPrompt2", origin, mainAction);
   },
 
   show(tid, id, stringId, origin, mainAction, secondaryActions = [], options = {}) {
     this.reset();
 
     try {
       origin = Services.io.newURI(origin).asciiHost;
     } catch (e) {
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -2493,18 +2493,19 @@ var gMainPane = {
       // compute index to display download folder label and icon to avoid
       // displaying blank downloadFolder label and icon on load of preferences UI
       // Set folderIndex to 1 if currentDirPref is unspecified
       folderIndex = currentDirPref.value ? await this._folderToIndex(currentDirPref.value) : 1;
     }
 
     // Display a 'pretty' label or the path in the UI.
     if (folderIndex == 2) {
-      // Custom path selected and is configured
-      downloadFolder.value = currentDirPref.value ? currentDirPref.value.path : "";
+      // Force the left-to-right direction when displaying a custom path.
+      downloadFolder.value = currentDirPref.value ?
+        `\u2066${currentDirPref.value.path}\u2069` : "";
       iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value);
     } else if (folderIndex == 1) {
       // 'Downloads'
       downloadFolder.value = bundlePreferences.getString("downloadsFolderName");
       iconUrlSpec = fph.getURLSpecFromFile(await this._indexToFolder(1));
     } else {
       // 'Desktop'
       downloadFolder.value = bundlePreferences.getString("desktopFolderName");
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -482,31 +482,31 @@ offlineApps.manageUsageAccessKey=S
 canvas.siteprompt=Will you allow %S to use your HTML5 canvas image data? This may be used to uniquely identify your computer.
 canvas.notAllow=Don’t Allow
 canvas.notAllow.accesskey=n
 canvas.allow=Allow Data Access
 canvas.allow.accesskey=A
 canvas.remember=Always remember my decision
 
 # WebAuthn prompts
-# LOCALIZATION NOTE (webauthn.registerPrompt): %S is hostname
-webauthn.registerPrompt=%S wants to register an account with one of your security tokens. You can connect and authorize one now, or cancel.
-# LOCALIZATION NOTE (webauthn.registerDirectPrompt):
+# LOCALIZATION NOTE (webauthn.registerPrompt2): %S is hostname
+webauthn.registerPrompt2=%S wants to register an account with one of your security keys. You can connect and authorize one now, or cancel.
+# LOCALIZATION NOTE (webauthn.registerDirectPrompt2):
 # %1$S is hostname. %2$S is brandShortName.
 # The website is asking for extended information about your
 # hardware authenticator that shouldn't be generally necessary. Permitting
 # this is safe if you only use one account at this website. If you have
 # multiple accounts at this website, and you use the same hardware
 # authenticator, then the website could link those accounts together.
 # And this is true even if you use a different profile / browser (or even Tor
 # Browser). To avoid this, you should use different hardware authenticators
 # for different accounts on this website.
-webauthn.registerDirectPrompt=%1$S is requesting extended information about your authenticator, which may affect your privacy.\n\n%2$S can anonymize this for you, but the website might decline this authenticator. If declined, you can try again.
-# LOCALIZATION NOTE (webauthn.signPrompt): %S is hostname
-webauthn.signPrompt=%S wants to authenticate you using a registered security token. You can connect and authorize one now, or cancel.
+webauthn.registerDirectPrompt2=%1$S is requesting extended information about your security key, which may affect your privacy.\n\n%2$S can anonymize this for you, but the website might decline this key. If declined, you can try again.
+# LOCALIZATION NOTE (webauthn.signPrompt2): %S is hostname
+webauthn.signPrompt2=%S wants to authenticate you using a registered security key. You can connect and authorize one now, or cancel.
 webauthn.cancel=Cancel
 webauthn.cancel.accesskey=c
 webauthn.proceed=Proceed
 webauthn.proceed.accesskey=p
 webauthn.anonymize=Anonymize anyway
 
 # Spoof Accept-Language prompt
 privacy.spoof_english=Changing your language setting to English will make you more difficult to identify and enhance your privacy. Do you want to request English language versions of web pages?
--- a/dom/base/DOMMozPromiseRequestHolder.h
+++ b/dom/base/DOMMozPromiseRequestHolder.h
@@ -37,16 +37,26 @@ namespace dom {
  *
  *      RefPtr<DOMMozPromiseRequestHolder> holder =
  *        new DOMMozPromiseRequestHolder(global);
  *
  *      DoAsyncStuff()->Then(
  *        global->EventTargetFor(TaskCategory::Other), __func__,
  *        [holder, outer] (const Result& aResult) {
  *          holder->Complete();
+ *
+ *          // Note, you can access the holder's bound global in
+ *          // your reaction handler.  Its mostly likely set if
+ *          // the handler fires, but you still must check for
+ *          // its existence since something could disconnect
+ *          // the global between when the MozPromise reaction
+ *          // runnable is queued and when it actually runs.
+ *          nsIGlobalObject* global = holder->GetParentObject();
+ *          NS_ENSURE_TRUE_VOID(global);
+ *
  *          outer->MaybeResolve(aResult);
  *        }, [holder, outer] (nsresult aRv) {
  *          holder->Complete();
  *          outer->MaybeReject(aRv);
  *        })->Track(*holder);
  *
  *      return outer.forget();
  *    }
@@ -96,17 +106,16 @@ public:
   {
     return mHolder;
   }
 
   void
   Complete()
   {
     mHolder.Complete();
-    DisconnectFromOwner();
   }
 
   void
   DisconnectIfExists()
   {
     mHolder.DisconnectIfExists();
   }
 
--- a/dom/clients/api/Client.cpp
+++ b/dom/clients/api/Client.cpp
@@ -6,16 +6,17 @@
 
 #include "Client.h"
 
 #include "ClientDOMUtil.h"
 #include "mozilla/dom/ClientHandle.h"
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientState.h"
+#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "nsIGlobalObject.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -167,40 +168,33 @@ Client::Focus(ErrorResult& aRv)
     return outerPromise.forget();
   }
 
   if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
     outerPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return outerPromise.forget();
   }
 
-  // Hold the worker thread alive while we perform the async operation
-  // and also avoid invoking callbacks if the worker starts shutting
-  // down.
-  RefPtr<WorkerHolderToken> token =
-    WorkerHolderToken::Create(GetCurrentThreadWorkerPrivate(), Closing);
+  EnsureHandle();
 
-  EnsureHandle();
-  RefPtr<ClientStatePromise> innerPromise = mHandle->Focus();
-  RefPtr<Client> self = this;
+  IPCClientInfo ipcClientInfo(mData->info());
+  auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<ClientStatePromise>>(mGlobal);
 
-  innerPromise->Then(mGlobal->EventTargetFor(TaskCategory::Other), __func__,
-    [self, token, outerPromise] (const ClientState& aResult) {
-      if (token->IsShuttingDown()) {
-        return;
-      }
-      RefPtr<Client> newClient =
-        new Client(self->mGlobal, ClientInfoAndState(self->mData->info(), aResult.ToIPC()));
+  mHandle->Focus()->Then(mGlobal->EventTargetFor(TaskCategory::Other), __func__,
+    [ipcClientInfo, holder, outerPromise] (const ClientState& aResult) {
+      holder->Complete();
+      NS_ENSURE_TRUE_VOID(holder->GetParentObject());
+      RefPtr<Client> newClient = new Client(holder->GetParentObject(),
+                                            ClientInfoAndState(ipcClientInfo,
+                                                               aResult.ToIPC()));
       outerPromise->MaybeResolve(newClient);
-    }, [self, token, outerPromise] (nsresult aResult) {
-      if (token->IsShuttingDown()) {
-        return;
-      }
+    }, [holder, outerPromise] (nsresult aResult) {
+      holder->Complete();
       outerPromise->MaybeReject(aResult);
-    });
+    })->Track(*holder);
 
   return outerPromise.forget();
 }
 
 already_AddRefed<Promise>
 Client::Navigate(const nsAString& aURL, ErrorResult& aRv)
 {
   MOZ_ASSERT(!NS_IsMainThread());
@@ -213,18 +207,17 @@ Client::Navigate(const nsAString& aURL, 
   if (aRv.Failed()) {
     return outerPromise.forget();
   }
 
   ClientNavigateArgs args(mData->info(), NS_ConvertUTF16toUTF8(aURL),
                           workerPrivate->GetLocationInfo().mHref);
   RefPtr<Client> self = this;
 
-  StartClientManagerOp(&ClientManager::Navigate, args,
-    mGlobal->EventTargetFor(TaskCategory::Other),
+  StartClientManagerOp(&ClientManager::Navigate, args, mGlobal,
     [self, outerPromise] (const ClientOpResult& aResult) {
       if (aResult.type() != ClientOpResult::TClientInfoAndState) {
         outerPromise->MaybeResolve(JS::NullHandleValue);
         return;
       }
       RefPtr<Client> newClient =
         new Client(self->mGlobal, aResult.get_ClientInfoAndState());
       outerPromise->MaybeResolve(newClient);
--- a/dom/clients/api/ClientDOMUtil.h
+++ b/dom/clients/api/ClientDOMUtil.h
@@ -3,49 +3,47 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _mozilla_dom_ClientDOMUtil_h
 #define _mozilla_dom_ClientDOMUtil_h
 
 #include "mozilla/dom/ClientIPCTypes.h"
 #include "mozilla/dom/ClientOpPromise.h"
+#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
 #include "mozilla/dom/WorkerHolderToken.h"
 #include "mozilla/dom/WorkerPrivate.h"
 
 class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
 
 // Utility method to properly execute a ClientManager operation.  It
 // will properly hold a worker thread alive and avoid executing callbacks
 // if the thread is shutting down.
 template<typename Func, typename Arg, typename Resolve, typename Reject>
 void
-StartClientManagerOp(Func aFunc, const Arg& aArg, nsISerialEventTarget* aTarget,
+StartClientManagerOp(Func aFunc, const Arg& aArg, nsIGlobalObject* aGlobal,
                      Resolve aResolve, Reject aReject)
 {
-  RefPtr<WorkerHolderToken> token;
-  if (!NS_IsMainThread()) {
-    token = WorkerHolderToken::Create(GetCurrentThreadWorkerPrivate(),
-                                      WorkerStatus::Closing);
-  }
+  MOZ_DIAGNOSTIC_ASSERT(aGlobal);
+
+  nsCOMPtr<nsISerialEventTarget> target =
+    aGlobal->EventTargetFor(TaskCategory::Other);
+
+  auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<ClientOpPromise>>(aGlobal);
 
-  RefPtr<ClientOpPromise> promise = aFunc(aArg, aTarget);
-  promise->Then(aTarget, __func__,
-    [aResolve, token](const ClientOpResult& aResult) {
-      if (token && token->IsShuttingDown()) {
-        return;
-      }
+  aFunc(aArg, target)->Then(
+    target, __func__,
+    [aResolve, holder](const ClientOpResult& aResult) {
+      holder->Complete();
       aResolve(aResult);
-    }, [aReject, token](nsresult aResult) {
-      if (token && token->IsShuttingDown()) {
-        return;
-      }
+    }, [aReject, holder](nsresult aResult) {
+      holder->Complete();
       aReject(aResult);
-    });
+    })->Track(*holder);
 }
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientDOMUtil_h
--- a/dom/clients/api/Clients.cpp
+++ b/dom/clients/api/Clients.cpp
@@ -79,37 +79,41 @@ Clients::Get(const nsAString& aClientID,
   const PrincipalInfo& principalInfo = workerPrivate->GetPrincipalInfo();
   nsCOMPtr<nsISerialEventTarget> target =
     mGlobal->EventTargetFor(TaskCategory::Other);
 
   RefPtr<ClientOpPromise> innerPromise =
     ClientManager::GetInfoAndState(ClientGetInfoAndStateArgs(id, principalInfo),
                                    target);
 
-  nsCOMPtr<nsIGlobalObject> global = mGlobal;
   nsCString scope = workerPrivate->ServiceWorkerScope();
+  auto holder = MakeRefPtr<DOMMozPromiseRequestHolder<ClientOpPromise>>(mGlobal);
 
   innerPromise->Then(target, __func__,
-    [outerPromise, global, scope] (const ClientOpResult& aResult) {
-      RefPtr<Client> client = new Client(global, aResult.get_ClientInfoAndState());
+    [outerPromise, holder, scope] (const ClientOpResult& aResult) {
+      holder->Complete();
+      NS_ENSURE_TRUE_VOID(holder->GetParentObject());
+      RefPtr<Client> client = new Client(holder->GetParentObject(),
+                                         aResult.get_ClientInfoAndState());
       if (client->GetStorageAccess() == nsContentUtils::StorageAccess::eAllow) {
         outerPromise->MaybeResolve(Move(client));
         return;
       }
       nsCOMPtr<nsIRunnable> r =
-        NS_NewRunnableFunction("Clients::MatchAll() storage denied",
+        NS_NewRunnableFunction("Clients::Get() storage denied",
         [scope] {
           ServiceWorkerManager::LocalizeAndReportToAllClients(
             scope, "ServiceWorkerGetClientStorageError", nsTArray<nsString>());
         });
       SystemGroup::Dispatch(TaskCategory::Other, r.forget());
       outerPromise->MaybeResolveWithUndefined();
-    }, [outerPromise] (nsresult aResult) {
+    }, [outerPromise, holder] (nsresult aResult) {
+      holder->Complete();
       outerPromise->MaybeResolveWithUndefined();
-    });
+    })->Track(*holder);
 
   return outerPromise.forget();
 }
 
 namespace {
 
 class MatchAllComparator final
 {
@@ -161,18 +165,17 @@ Clients::MatchAll(const ClientQueryOptio
   }
 
   nsCOMPtr<nsIGlobalObject> global = mGlobal;
   nsCString scope = workerPrivate->ServiceWorkerScope();
 
   ClientMatchAllArgs args(workerPrivate->GetServiceWorkerDescriptor().ToIPC(),
                           aOptions.mType,
                           aOptions.mIncludeUncontrolled);
-  StartClientManagerOp(&ClientManager::MatchAll, args,
-    mGlobal->EventTargetFor(TaskCategory::Other),
+  StartClientManagerOp(&ClientManager::MatchAll, args, mGlobal,
     [outerPromise, global, scope] (const ClientOpResult& aResult) {
       nsTArray<RefPtr<Client>> clientList;
       bool storageDenied = false;
       for (const ClientInfoAndState& value : aResult.get_ClientList().values()) {
         RefPtr<Client> client = new Client(global, value);
         if (client->GetStorageAccess() != nsContentUtils::StorageAccess::eAllow) {
           storageDenied = true;
           continue;
@@ -224,18 +227,17 @@ Clients::OpenWindow(const nsAString& aUR
 
   const PrincipalInfo& principalInfo = workerPrivate->GetPrincipalInfo();
   nsCString baseURL = workerPrivate->GetLocationInfo().mHref;
   ClientOpenWindowArgs args(principalInfo, NS_ConvertUTF16toUTF8(aURL),
                             baseURL);
 
   nsCOMPtr<nsIGlobalObject> global = mGlobal;
 
-  StartClientManagerOp(&ClientManager::OpenWindow, args,
-    mGlobal->EventTargetFor(TaskCategory::Other),
+  StartClientManagerOp(&ClientManager::OpenWindow, args, mGlobal,
     [outerPromise, global] (const ClientOpResult& aResult) {
       if (aResult.type() != ClientOpResult::TClientInfoAndState) {
         outerPromise->MaybeResolve(JS::NullHandleValue);
         return;
       }
       RefPtr<Client> client =
         new Client(global, aResult.get_ClientInfoAndState());
       outerPromise->MaybeResolve(client);
@@ -266,18 +268,18 @@ Clients::Claim(ErrorResult& aRv)
     workerPrivate->GetServiceWorkerDescriptor();
 
   if (serviceWorker.State() != ServiceWorkerState::Activating &&
       serviceWorker.State() != ServiceWorkerState::Activated) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return outerPromise.forget();
   }
 
-  StartClientManagerOp(&ClientManager::Claim, ClientClaimArgs(serviceWorker.ToIPC()),
-    mGlobal->EventTargetFor(TaskCategory::Other),
+  StartClientManagerOp(
+    &ClientManager::Claim, ClientClaimArgs(serviceWorker.ToIPC()), mGlobal,
     [outerPromise] (const ClientOpResult& aResult) {
       outerPromise->MaybeResolveWithUndefined();
     }, [outerPromise] (nsresult aResult) {
       outerPromise->MaybeReject(aResult);
     });
 
   return outerPromise.forget();
 }
--- a/dom/clients/manager/ClientHandle.cpp
+++ b/dom/clients/manager/ClientHandle.cpp
@@ -32,42 +32,37 @@ ClientHandle::Shutdown()
     return;
   }
 
   ShutdownThing();
 
   mManager = nullptr;
 }
 
-already_AddRefed<ClientOpPromise>
-ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs)
+void
+ClientHandle::StartOp(const ClientOpConstructorArgs& aArgs,
+                      const ClientOpCallback&& aResolveCallback,
+                      const ClientOpCallback&& aRejectCallback)
 {
-  RefPtr<ClientOpPromise::Private> promise =
-    new ClientOpPromise::Private(__func__);
-
   // Hold a ref to the client until the remote operation completes.  Otherwise
   // the ClientHandle might get de-refed and teardown the actor before we
   // get an answer.
   RefPtr<ClientHandle> kungFuGrip = this;
-  promise->Then(mSerialEventTarget, __func__,
-                [kungFuGrip] (const ClientOpResult &) { },
-                [kungFuGrip] (nsresult) { });
 
-  MaybeExecute([aArgs, promise] (ClientHandleChild* aActor) {
-    ClientHandleOpChild* actor = new ClientHandleOpChild(aArgs, promise);
+  MaybeExecute([aArgs, kungFuGrip, aRejectCallback,
+                resolve = Move(aResolveCallback)] (ClientHandleChild* aActor) {
+    ClientHandleOpChild* actor =
+      new ClientHandleOpChild(aArgs, Move(resolve), Move(aRejectCallback));
     if (!aActor->SendPClientHandleOpConstructor(actor, aArgs)) {
-      // Constructor failure will reject promise via ActorDestroy()
+      // Constructor failure will call reject callback via ActorDestroy()
       return;
     }
-  }, [promise] {
-    promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+  }, [aRejectCallback, kungFuGrip] {
+    aRejectCallback(NS_ERROR_DOM_INVALID_STATE_ERR);
   });
-
-  RefPtr<ClientOpPromise> ref = promise.get();
-  return ref.forget();
 }
 
 void
 ClientHandle::OnShutdownThing()
 {
   NS_ASSERT_OWNINGTHREAD(ClientHandle);
   if (!mDetachPromise) {
     return;
@@ -119,39 +114,34 @@ ClientHandle::Info() const
 }
 
 RefPtr<GenericPromise>
 ClientHandle::Control(const ServiceWorkerDescriptor& aServiceWorker)
 {
   RefPtr<GenericPromise::Private> outerPromise =
     new GenericPromise::Private(__func__);
 
-  RefPtr<ClientOpPromise> innerPromise =
-    StartOp(ClientControlledArgs(aServiceWorker.ToIPC()));
-
-  innerPromise->Then(mSerialEventTarget, __func__,
+  StartOp(ClientControlledArgs(aServiceWorker.ToIPC()),
     [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Resolve(true, __func__);
     },
     [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Reject(aResult.get_nsresult(), __func__);
     });
 
   return outerPromise.forget();
 }
 
 RefPtr<ClientStatePromise>
 ClientHandle::Focus()
 {
   RefPtr<ClientStatePromise::Private> outerPromise =
     new ClientStatePromise::Private(__func__);
 
-  RefPtr<ClientOpPromise> innerPromise = StartOp(ClientFocusArgs());
-
-  innerPromise->Then(mSerialEventTarget, __func__,
+  StartOp(ClientFocusArgs(),
     [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Resolve(ClientState::FromIPC(aResult.get_IPCClientState()), __func__);
     }, [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Reject(aResult.get_nsresult(), __func__);
     });
 
   RefPtr<ClientStatePromise> ref = outerPromise.get();
   return ref.forget();
@@ -175,18 +165,17 @@ ClientHandle::PostMessage(StructuredClon
                                                       args.clonedData())) {
     ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
     return ref.forget();
   }
 
   RefPtr<GenericPromise::Private> outerPromise =
     new GenericPromise::Private(__func__);
 
-  RefPtr<ClientOpPromise> innerPromise = StartOp(args);
-  innerPromise->Then(mSerialEventTarget, __func__,
+  StartOp(args,
     [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Resolve(true, __func__);
     }, [outerPromise](const ClientOpResult& aResult) {
       outerPromise->Reject(aResult.get_nsresult(), __func__);
     });
 
   ref = outerPromise.get();
   return ref.forget();
--- a/dom/clients/manager/ClientHandle.h
+++ b/dom/clients/manager/ClientHandle.h
@@ -45,18 +45,20 @@ class ClientHandle final : public Client
   RefPtr<GenericPromise::Private> mDetachPromise;
   ClientInfo mClientInfo;
 
   ~ClientHandle();
 
   void
   Shutdown();
 
-  already_AddRefed<ClientOpPromise>
-  StartOp(const ClientOpConstructorArgs& aArgs);
+  void
+  StartOp(const ClientOpConstructorArgs& aArgs,
+          const ClientOpCallback&& aResolveCallback,
+          const ClientOpCallback&& aRejectCallback);
 
   // ClientThing interface
   void
   OnShutdownThing() override;
 
   // Private methods called by ClientHandleChild
   void
   ExecutionReady(const ClientInfo& aClientInfo);
--- a/dom/clients/manager/ClientHandleOpChild.cpp
+++ b/dom/clients/manager/ClientHandleOpChild.cpp
@@ -7,42 +7,35 @@
 #include "ClientHandleOpChild.h"
 
 namespace mozilla {
 namespace dom {
 
 void
 ClientHandleOpChild::ActorDestroy(ActorDestroyReason aReason)
 {
-  if (mPromise) {
-    mPromise->Reject(NS_ERROR_ABORT, __func__);
-    mPromise = nullptr;
-  }
+  mRejectCallback(NS_ERROR_DOM_ABORT_ERR);
 }
 
 mozilla::ipc::IPCResult
 ClientHandleOpChild::Recv__delete__(const ClientOpResult& aResult)
 {
   if (aResult.type() == ClientOpResult::Tnsresult &&
       NS_FAILED(aResult.get_nsresult())) {
-    mPromise->Reject(aResult.get_nsresult(), __func__);
-    mPromise = nullptr;
+    mRejectCallback(aResult.get_nsresult());
     return IPC_OK();
   }
-  mPromise->Resolve(aResult, __func__);
-  mPromise = nullptr;
+  mResolveCallback(aResult);
   return IPC_OK();
 }
 
 ClientHandleOpChild::ClientHandleOpChild(const ClientOpConstructorArgs& aArgs,
-                                         ClientOpPromise::Private* aPromise)
-  : mPromise(aPromise)
+                                         const ClientOpCallback&& aResolveCallback,
+                                         const ClientOpCallback&& aRejectCallback)
+  : mResolveCallback(Move(aResolveCallback))
+  , mRejectCallback(Move(aRejectCallback))
 {
-  MOZ_DIAGNOSTIC_ASSERT(mPromise);
-}
-
-ClientHandleOpChild::~ClientHandleOpChild()
-{
-  MOZ_DIAGNOSTIC_ASSERT(!mPromise);
+  MOZ_DIAGNOSTIC_ASSERT(mResolveCallback);
+  MOZ_DIAGNOSTIC_ASSERT(mRejectCallback);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientHandleOpChild.h
+++ b/dom/clients/manager/ClientHandleOpChild.h
@@ -3,35 +3,36 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _mozilla_dom_ClientHandleOpChild_h
 #define _mozilla_dom_ClientHandleOpChild_h
 
 #include "mozilla/dom/ClientOpPromise.h"
 #include "mozilla/dom/PClientHandleOpChild.h"
-#include "mozilla/MozPromise.h"
 
 namespace mozilla {
 namespace dom {
 
 class ClientHandleOpChild final : public PClientHandleOpChild
 {
-  RefPtr<ClientOpPromise::Private> mPromise;
+  const ClientOpCallback mResolveCallback;
+  const ClientOpCallback mRejectCallback;
 
   // PClientHandleOpChild interface
   void
   ActorDestroy(ActorDestroyReason aReason) override;
 
   mozilla::ipc::IPCResult
   Recv__delete__(const ClientOpResult& aResult) override;
 
 public:
   ClientHandleOpChild(const ClientOpConstructorArgs& aArgs,
-                      ClientOpPromise::Private* aPromise);
+                      const ClientOpCallback&& aResolveCallback,
+                      const ClientOpCallback&& aRejectCallback);
 
-  ~ClientHandleOpChild();
+  ~ClientHandleOpChild() = default;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientHandleOpChild_h
--- a/dom/clients/manager/ClientManager.cpp
+++ b/dom/clients/manager/ClientManager.cpp
@@ -40,18 +40,25 @@ ClientManager::ClientManager()
     return;
   }
 
   RefPtr<WorkerHolderToken> workerHolderToken;
   if (!NS_IsMainThread()) {
     WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
 
+    // Note, it would be nice to replace this with a WorkerRef, but
+    // currently there is no WorkerRef option that matches what we
+    // need here.  We need something like a StrongWorkerRef that will
+    // let us keep the worker alive until our actor is destroyed, but
+    // we also need to use AllowIdleShutdownStart like WeakWorkerRef.
+    // We need AllowIdleShutdownStart since every worker thread will
+    // have a ClientManager to support creating its ClientSource.
     workerHolderToken =
-      WorkerHolderToken::Create(workerPrivate, Closing,
+      WorkerHolderToken::Create(workerPrivate, Terminating,
                                 WorkerHolderToken::AllowIdleShutdownStart);
     if (NS_WARN_IF(!workerHolderToken)) {
       Shutdown();
       return;
     }
   }
 
   ClientManagerChild* actor = new ClientManagerChild(workerHolderToken);
--- a/dom/clients/manager/ClientOpPromise.h
+++ b/dom/clients/manager/ClientOpPromise.h
@@ -13,12 +13,14 @@ namespace dom {
 
 class ClientOpResult;
 class ClientState;
 
 typedef MozPromise<ClientOpResult, nsresult, false> ClientOpPromise;
 
 typedef MozPromise<ClientState, nsresult, false> ClientStatePromise;
 
+typedef std::function<void(const ClientOpResult&)> ClientOpCallback;
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // _mozilla_dom_ClientOpPromise_h
--- a/dom/clients/manager/ClientSource.cpp
+++ b/dom/clients/manager/ClientSource.cpp
@@ -8,16 +8,17 @@
 
 #include "ClientManager.h"
 #include "ClientManagerChild.h"
 #include "ClientPrincipalUtils.h"
 #include "ClientSourceChild.h"
 #include "ClientState.h"
 #include "ClientValidation.h"
 #include "mozilla/dom/ClientIPCTypes.h"
+#include "mozilla/dom/DOMMozPromiseRequestHolder.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/dom/MessageEvent.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/Navigator.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerScope.h"
 #include "mozilla/dom/ServiceWorker.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
@@ -631,23 +632,28 @@ ClientSource::Claim(const ClientClaimArg
     SetController(swd);
     ref = ClientOpPromise::CreateAndResolve(NS_OK, __func__);
     return ref.forget();
   }
 
   RefPtr<ClientOpPromise::Private> outerPromise =
     new ClientOpPromise::Private(__func__);
 
+  auto holder =
+    MakeRefPtr<DOMMozPromiseRequestHolder<GenericPromise>>(innerWindow->AsGlobal());
+
   RefPtr<GenericPromise> p = swm->MaybeClaimClient(doc, swd);
   p->Then(mEventTarget, __func__,
-    [outerPromise] (bool aResult) {
+    [outerPromise, holder] (bool aResult) {
+      holder->Complete();
       outerPromise->Resolve(NS_OK, __func__);
-    }, [outerPromise] (nsresult aResult) {
+    }, [outerPromise, holder] (nsresult aResult) {
+      holder->Complete();
       outerPromise->Reject(aResult, __func__);
-    });
+    })->Track(*holder);
 
   ref = outerPromise;
   return ref.forget();
 }
 
 RefPtr<ClientOpPromise>
 ClientSource::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
 {
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -530,18 +530,24 @@ FetchRequest(nsIGlobalObject* aGlobal, c
     RefPtr<WorkerFetchResolver> resolver =
       WorkerFetchResolver::Create(worker, p, signal, observer);
     if (!resolver) {
       NS_WARNING("Could not keep the worker alive.");
       aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
       return nullptr;
     }
 
+    Maybe<ClientInfo> clientInfo(worker->GetClientInfo());
+    if (clientInfo.isNothing()) {
+      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+      return nullptr;
+    }
+
     RefPtr<MainThreadFetchRunnable> run =
-      new MainThreadFetchRunnable(resolver, worker->GetClientInfo(),
+      new MainThreadFetchRunnable(resolver, clientInfo.ref(),
                                   worker->GetController(), r);
     worker->DispatchToMainThread(run.forget());
   }
 
   return p.forget();
 }
 
 void
--- a/dom/smil/moz.build
+++ b/dom/smil/moz.build
@@ -11,16 +11,17 @@ MOCHITEST_MANIFESTS += ['test/mochitest.
 
 EXPORTS += [
     'nsISMILAttr.h',
     'nsISMILType.h',
     'nsSMILAnimationController.h',
     'nsSMILAnimationFunction.h',
     'nsSMILCompositorTable.h',
     'nsSMILCSSProperty.h',
+    'nsSMILCSSValueType.h',
     'nsSMILInstanceTime.h',
     'nsSMILInterval.h',
     'nsSMILKeySpline.h',
     'nsSMILMilestone.h',
     'nsSMILNullType.h',
     'nsSMILRepeatCount.h',
     'nsSMILSetAnimationFunction.h',
     'nsSMILTargetIdentifier.h',
--- a/dom/smil/nsSMILCSSProperty.cpp
+++ b/dom/smil/nsSMILCSSProperty.cpp
@@ -102,32 +102,17 @@ nsSMILCSSProperty::ValueFromString(const
   }
   return NS_OK;
 }
 
 nsresult
 nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
-
-  // Convert nsSMILValue to string
-  nsAutoString valStr;
-  nsSMILCSSValueType::ValueToString(aValue, valStr);
-
-  // Use string value to style the target element
-  nsDOMCSSAttributeDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
-  if (overrideDecl) {
-    nsAutoString oldValStr;
-    overrideDecl->GetPropertyValue(mPropID, oldValStr);
-    if (valStr.Equals(oldValStr)) {
-      return NS_OK;
-    }
-    overrideDecl->SetPropertyValue(mPropID, valStr, nullptr);
-  }
-  return NS_OK;
+  return mElement->GetSMILOverrideStyle()->SetSMILValue(mPropID, aValue);
 }
 
 void
 nsSMILCSSProperty::ClearAnimValue()
 {
   // Put empty string in override style for our property
   nsDOMCSSAttributeDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
   if (overrideDecl) {
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -1905,17 +1905,19 @@ class ChannelGetterRunnable final : publ
 
 public:
   ChannelGetterRunnable(WorkerPrivate* aParentWorker,
                         const nsAString& aScriptURL,
                         WorkerLoadInfo& aLoadInfo)
     : WorkerMainThreadRunnable(aParentWorker,
                                NS_LITERAL_CSTRING("ScriptLoader :: ChannelGetter"))
     , mScriptURL(aScriptURL)
-    , mClientInfo(aParentWorker->GetClientInfo())
+    // ClientInfo should always be present since this should not be called
+    // if parent's status is greater than Running.
+    , mClientInfo(aParentWorker->GetClientInfo().ref())
     , mLoadInfo(aLoadInfo)
     , mResult(NS_ERROR_FAILURE)
   {
     MOZ_ASSERT(aParentWorker);
     aParentWorker->AssertIsOnWorkerThread();
   }
 
   virtual bool
@@ -2241,17 +2243,17 @@ LoadAllScripts(WorkerPrivate* aWorkerPri
   if (!syncLoopTarget) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   Maybe<ClientInfo> clientInfo;
   Maybe<ServiceWorkerDescriptor> controller;
   if (!aIsMainScript) {
-    clientInfo.emplace(aWorkerPrivate->GetClientInfo());
+    clientInfo = aWorkerPrivate->GetClientInfo();
     controller = aWorkerPrivate->GetController();
   }
 
   RefPtr<ScriptLoaderRunnable> loader =
     new ScriptLoaderRunnable(aWorkerPrivate, syncLoopTarget, aLoadInfos,
                              clientInfo, controller,
                              aIsMainScript, aWorkerScriptType, aRv);
 
@@ -2385,17 +2387,17 @@ LoadMainScript(WorkerPrivate* aWorkerPri
   nsTArray<ScriptLoadInfo> loadInfos;
 
   ScriptLoadInfo* info = loadInfos.AppendElement();
   info->mURL = aScriptURL;
   info->mLoadFlags = aWorkerPrivate->GetLoadFlags();
 
   // We are loading the main script, so the worker's Client must be
   // reserved.
-  info->mReservedClientInfo.emplace(aWorkerPrivate->GetClientInfo());
+  info->mReservedClientInfo = aWorkerPrivate->GetClientInfo();
 
   LoadAllScripts(aWorkerPrivate, loadInfos, true, aWorkerScriptType, aRv);
 }
 
 void
 Load(WorkerPrivate* aWorkerPrivate,
      const nsTArray<nsString>& aScriptURLs, WorkerScriptType aWorkerScriptType,
      ErrorResult& aRv)
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3273,22 +3273,24 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
         MOZ_ASSERT(currentStatus == Killing);
 #else
         currentStatus = Killing;
 #endif
       }
 
       // If we're supposed to die then we should exit the loop.
       if (currentStatus == Killing) {
+        // The ClientSource should be cleared in NotifyInternal() when we reach
+        // or pass Terminating.
+        MOZ_DIAGNOSTIC_ASSERT(!mClientSource);
+
         // Flush uncaught rejections immediately, without
         // waiting for a next tick.
         PromiseDebugging::FlushUncaughtRejections();
 
-        mClientSource = nullptr;
-
         ShutdownGCTimers();
 
         DisableMemoryReporter();
 
         {
           MutexAutoLock lock(mMutex);
 
           mStatus = Dead;
@@ -3495,22 +3497,27 @@ WorkerPrivate::EnsurePerformanceStorage(
 {
   AssertIsOnWorkerThread();
 
   if (!mPerformanceStorage) {
     mPerformanceStorage = PerformanceStorageWorker::Create(this);
   }
 }
 
-const ClientInfo&
+Maybe<ClientInfo>
 WorkerPrivate::GetClientInfo() const
 {
   AssertIsOnWorkerThread();
-  MOZ_DIAGNOSTIC_ASSERT(mClientSource);
-  return mClientSource->Info();
+  Maybe<ClientInfo> clientInfo;
+  if (!mClientSource) {
+    MOZ_DIAGNOSTIC_ASSERT(mStatus >= Terminating);
+    return Move(clientInfo);
+  }
+  clientInfo.emplace(mClientSource->Info());
+  return Move(clientInfo);
 }
 
 const ClientState
 WorkerPrivate::GetClientState() const
 {
   AssertIsOnWorkerThread();
   MOZ_DIAGNOSTIC_ASSERT(mClientSource);
   ClientState state;
@@ -3535,16 +3542,22 @@ WorkerPrivate::Control(const ServiceWork
   MOZ_DIAGNOSTIC_ASSERT(Type() != WorkerTypeService);
   mClientSource->SetController(aServiceWorker);
 }
 
 void
 WorkerPrivate::ExecutionReady()
 {
   AssertIsOnWorkerThread();
+  {
+    MutexAutoLock lock(mMutex);
+    if (mStatus >= Terminating) {
+      return;
+    }
+  }
   MOZ_DIAGNOSTIC_ASSERT(mClientSource);
   mClientSource->WorkerExecutionReady(this);
 }
 
 void
 WorkerPrivate::InitializeGCTimers()
 {
   AssertIsOnWorkerThread();
@@ -4509,18 +4522,19 @@ WorkerPrivate::NotifyInternal(WorkerStat
   {
     MutexAutoLock lock(mMutex);
 
     if (mStatus >= aStatus) {
       return true;
     }
 
     if (aStatus >= Terminating) {
+      MutexAutoUnlock unlock(mMutex);
+      mClientSource.reset();
       if (mScope) {
-        MutexAutoUnlock unlock(mMutex);
         mScope->NoteTerminating();
       }
     }
 
     // Make sure the hybrid event target stops dispatching runnables
     // once we reaching the killing state.
     if (aStatus == Killing) {
       // To avoid deadlock we always acquire the event target mutex before the
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -548,17 +548,17 @@ public:
   EnsureClientSource();
 
   void
   EnsurePerformanceStorage();
 
   void
   EnsurePerformanceCounter();
 
-  const ClientInfo&
+  Maybe<ClientInfo>
   GetClientInfo() const;
 
   const ClientState
   GetClientState() const;
 
   const Maybe<ServiceWorkerDescriptor>
   GetController() const;
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -541,19 +541,17 @@ AbstractThread*
 WorkerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
 {
   MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
 }
 
 Maybe<ClientInfo>
 WorkerGlobalScope::GetClientInfo() const
 {
-  Maybe<ClientInfo> info;
-  info.emplace(mWorkerPrivate->GetClientInfo());
-  return Move(info);
+  return mWorkerPrivate->GetClientInfo();
 }
 
 Maybe<ClientState>
 WorkerGlobalScope::GetClientState() const
 {
   Maybe<ClientState> state;
   state.emplace(mWorkerPrivate->GetClientState());
   return Move(state);
--- a/dom/xhr/XMLHttpRequestWorker.cpp
+++ b/dom/xhr/XMLHttpRequestWorker.cpp
@@ -1870,17 +1870,22 @@ XMLHttpRequestWorker::Open(const nsACStr
 
   if (mProxy) {
     MaybeDispatchPrematureAbortEvents(aRv);
     if (aRv.Failed()) {
       return;
     }
   }
   else {
-    mProxy = new Proxy(this, mWorkerPrivate->GetClientInfo(),
+    Maybe<ClientInfo> clientInfo(mWorkerPrivate->GetClientInfo());
+    if (clientInfo.isNothing()) {
+      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+      return;
+    }
+    mProxy = new Proxy(this, clientInfo.ref(),
                        mWorkerPrivate->GetController(), mMozAnon, mMozSystem);
   }
 
   mProxy->mOuterEventStreamId++;
 
   RefPtr<OpenRunnable> runnable =
     new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
                      mBackgroundRequest, mWithCredentials,
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1785,17 +1785,17 @@ gfxPlatform::GetLayerDiagnosticTypes()
   }
   if (gfxPrefs::FlashLayerBorders()) {
     type |= mozilla::layers::DiagnosticTypes::FLASH_BORDERS;
   }
   return type;
 }
 
 BackendPrefsData
-gfxPlatform::GetBackendPrefs()
+gfxPlatform::GetBackendPrefs() const
 {
   BackendPrefsData data;
 
   data.mCanvasBitmask = BackendTypeBit(BackendType::CAIRO);
   data.mContentBitmask = BackendTypeBit(BackendType::CAIRO);
 #ifdef USE_SKIA
   data.mCanvasBitmask |= BackendTypeBit(BackendType::SKIA);
   data.mContentBitmask |= BackendTypeBit(BackendType::SKIA);
@@ -2711,24 +2711,50 @@ gfxPlatform::UsesOffMainThreadCompositin
   }
 
   return result;
 }
 
 bool
 gfxPlatform::UsesTiling() const
 {
-  bool isSkiaPOMTP = XRE_IsContentProcess() &&
-      GetDefaultContentBackend() == BackendType::SKIA &&
-      gfxVars::UseOMTP() &&
-      (gfxPrefs::LayersOMTPPaintWorkers() == -1 ||
+  bool usesSkia = GetDefaultContentBackend() == BackendType::SKIA;
+
+  // We can't just test whether the PaintThread is initialized here because
+  // this function is used when initializing the PaintThread. So instead we
+  // check the conditions that enable OMTP with parallel painting.
+  bool usesPOMTP = XRE_IsContentProcess() &&
+    gfxVars::UseOMTP() &&
+    (gfxPrefs::LayersOMTPPaintWorkers() == -1 ||
       gfxPrefs::LayersOMTPPaintWorkers() > 1);
 
   return gfxPrefs::LayersTilesEnabled() ||
-    (gfxPrefs::LayersTilesEnabledIfSkiaPOMTP() && isSkiaPOMTP);
+    (gfxPrefs::LayersTilesEnabledIfSkiaPOMTP() &&
+      usesSkia &&
+      usesPOMTP);
+}
+
+bool
+gfxPlatform::ContentUsesTiling() const
+{
+  BackendPrefsData data = GetBackendPrefs();
+  BackendType contentBackend = GetContentBackendPref(data.mContentBitmask);
+  if (contentBackend == BackendType::NONE) {
+    contentBackend = data.mContentDefault;
+  }
+
+  bool contentUsesSkia = contentBackend == BackendType::SKIA;
+  bool contentUsesPOMTP = gfxVars::UseOMTP() &&
+    (gfxPrefs::LayersOMTPPaintWorkers() == -1 ||
+      gfxPrefs::LayersOMTPPaintWorkers() > 1);
+
+  return gfxPrefs::LayersTilesEnabled() ||
+    (gfxPrefs::LayersTilesEnabledIfSkiaPOMTP() &&
+      contentUsesSkia &&
+      contentUsesPOMTP);
 }
 
 /***
  * The preference "layout.frame_rate" has 3 meanings depending on the value:
  *
  * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
  *  0 = ASAP mode - used during talos testing.
  *  X = Software vsync at a rate of X times per second.
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -587,19 +587,28 @@ public:
 
     virtual mozilla::gfx::SurfaceFormat Optimal2DFormatForContent(gfxContentType aContent);
 
     virtual gfxImageFormat OptimalFormatForContent(gfxContentType aContent);
 
     virtual gfxImageFormat GetOffscreenFormat()
     { return mozilla::gfx::SurfaceFormat::X8R8G8B8_UINT32; }
 
+    /**
+     * Returns whether the current process should use tiling for layers.
+     */
     virtual bool UsesTiling() const;
 
     /**
+     * Returns whether the content process will use tiling for layers. This is
+     * only used by about:support.
+     */
+    virtual bool ContentUsesTiling() const;
+
+    /**
      * Returns a logger if one is available and logging is enabled
      */
     static mozilla::LogModule* GetLog(eGfxLog aWhichLog);
 
     int GetScreenDepth() const { return mScreenDepth; }
     mozilla::gfx::IntSize GetScreenSize() const { return mScreenSize; }
 
     /**
@@ -752,17 +761,17 @@ protected:
 
     // Returns whether or not layers should be accelerated by default on this platform.
     virtual bool AccelerateLayersByDefault();
 
     // Returns a prioritized list of available compositor backends for acceleration.
     virtual void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends);
 
     // Returns preferences of canvas and content backends.
-    virtual BackendPrefsData GetBackendPrefs();
+    virtual BackendPrefsData GetBackendPrefs() const;
 
     /**
      * Initialise the preferred and fallback canvas backends
      * aBackendBitmask specifies the backends which are acceptable to the caller.
      * The backend used is determined by aBackendBitmask and the order specified
      * by the gfx.canvas.azure.backends pref.
      */
     void InitBackendPrefs(BackendPrefsData&& aPrefsData);
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -97,17 +97,17 @@ gfxPlatformMac::gfxPlatformMac()
 }
 
 gfxPlatformMac::~gfxPlatformMac()
 {
     gfxCoreTextShaper::Shutdown();
 }
 
 BackendPrefsData
-gfxPlatformMac::GetBackendPrefs()
+gfxPlatformMac::GetBackendPrefs() const
 {
   BackendPrefsData data;
 
   data.mCanvasBitmask = BackendTypeBit(BackendType::SKIA);
   data.mContentBitmask = BackendTypeBit(BackendType::SKIA);
   data.mCanvasDefault = BackendType::SKIA;
   data.mContentDefault = BackendType::SKIA;
 
@@ -117,16 +117,22 @@ gfxPlatformMac::GetBackendPrefs()
 bool
 gfxPlatformMac::UsesTiling() const
 {
     // The non-tiling ContentClient requires CrossProcessSemaphore which
     // isn't implemented for OSX.
     return true;
 }
 
+bool
+gfxPlatformMac::ContentUsesTiling() const
+{
+    return UsesTiling();
+}
+
 gfxPlatformFontList*
 gfxPlatformMac::CreatePlatformFontList()
 {
     gfxPlatformFontList* list = new gfxMacPlatformFontList();
     if (NS_SUCCEEDED(list->InitFontList())) {
         return list;
     }
     gfxPlatformFontList::Shutdown();
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -22,16 +22,17 @@ public:
     gfxPlatformMac();
     virtual ~gfxPlatformMac();
 
     static gfxPlatformMac *GetPlatform() {
         return (gfxPlatformMac*) gfxPlatform::GetPlatform();
     }
 
     bool UsesTiling() const override;
+    bool ContentUsesTiling() const override;
 
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenSurface(const IntSize& aSize,
                              gfxImageFormat aFormat) override;
 
     gfxFontGroup*
     CreateFontGroup(const mozilla::FontFamilyList& aFontFamilyList,
                     const gfxFontStyle *aStyle,
@@ -78,17 +79,17 @@ public:
     virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
 
     // lower threshold on font anti-aliasing
     uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
 
 protected:
     bool AccelerateLayersByDefault() override;
 
-    BackendPrefsData GetBackendPrefs() override;
+    BackendPrefsData GetBackendPrefs() const override;
 
     bool CheckVariationFontSupport() override;
 
 private:
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size) override;
 
     // read in the pref value for the lower threshold on font anti-aliasing
     static uint32_t ReadAntiAliasingThreshold();
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -434,17 +434,17 @@ gfxWindowsPlatform::HandleDeviceReset()
 
   InitializeConfig();
   InitializeDevices();
   UpdateANGLEConfig();
   return true;
 }
 
 BackendPrefsData
-gfxWindowsPlatform::GetBackendPrefs()
+gfxWindowsPlatform::GetBackendPrefs() const
 {
   BackendPrefsData data;
 
   data.mCanvasBitmask = BackendTypeBit(BackendType::CAIRO) |
                         BackendTypeBit(BackendType::SKIA);
   data.mContentBitmask = BackendTypeBit(BackendType::CAIRO) |
                          BackendTypeBit(BackendType::SKIA);
   data.mCanvasDefault = BackendType::SKIA;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -228,17 +228,17 @@ protected:
     }
     void GetAcceleratedCompositorBackends(nsTArray<mozilla::layers::LayersBackend>& aBackends) override;
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size) override;
 
     void ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData) override;
     void ImportContentDeviceData(const mozilla::gfx::ContentDeviceData& aData) override;
     void BuildContentDeviceData(mozilla::gfx::ContentDeviceData* aOut) override;
 
-    BackendPrefsData GetBackendPrefs() override;
+    BackendPrefsData GetBackendPrefs() const override;
 
     bool CheckVariationFontSupport() override;
 
 protected:
     RenderMode mRenderMode;
 
 private:
     void Init();
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -1069,30 +1069,18 @@ static const mozilla::EnumSet<ZealMode> 
     ZealMode::YieldBeforeSweepingShapeTrees
 };
 
 void
 GCRuntime::setZeal(uint8_t zeal, uint32_t frequency)
 {
     MOZ_ASSERT(zeal <= unsigned(ZealMode::Limit));
 
-#ifdef ENABLE_WASM_GC
-    // If we run with wasm-gc enabled and there's wasm frames on the stack,
-    // then GCs are suppressed and we should not allow to set the GC zeal,
-    // which presupposes that GC can be run right away.
-    // TODO (bug 1456824) This is temporary and should be removed once proper
-    // GC support is implemented.
-    JSContext* cx = rt->mainContextFromOwnThread();
-    if (cx->options().wasmGc()) {
-        for (FrameIter iter(cx); !iter.done(); ++iter) {
-            if (iter.isWasm())
-                return;
-        }
-    }
-#endif
+    if (temporaryAbortIfWasmGc(rt->mainContextFromOwnThread()))
+        return;
 
     if (verifyPreData)
         VerifyBarriers(rt, PreBarrierVerifier);
 
     if (zeal == 0) {
         if (hasZealMode(ZealMode::GenerationalGC)) {
             evictNursery(JS::gcreason::DEBUG_GC);
             nursery().leaveZealMode();
@@ -8240,16 +8228,23 @@ GCRuntime::clearSelectedForMarking()
 void
 GCRuntime::setDeterministic(bool enabled)
 {
     MOZ_ASSERT(!JS::CurrentThreadIsHeapMajorCollecting());
     deterministicOnly = enabled;
 }
 #endif
 
+#ifdef ENABLE_WASM_GC
+/* static */ bool
+GCRuntime::temporaryAbortIfWasmGc(JSContext* cx) {
+    return cx->options().wasmGc() && cx->suppressGC;
+}
+#endif
+
 #ifdef DEBUG
 
 /* Should only be called manually under gdb */
 void PreventGCDuringInteractiveDebug()
 {
     TlsContext.get()->suppressGC++;
 }
 
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -282,16 +282,26 @@ class GCRuntime
     void setNextScheduled(uint32_t count);
     void verifyPreBarriers();
     void maybeVerifyPreBarriers(bool always);
     bool selectForMarking(JSObject* object);
     void clearSelectedForMarking();
     void setDeterministic(bool enable);
 #endif
 
+#ifdef ENABLE_WASM_GC
+    // If we run with wasm-gc enabled and there's wasm frames on the stack,
+    // then GCs are suppressed and many APIs should not be available.
+    // TODO (bug 1456824) This is temporary and should be removed once proper
+    // GC support is implemented.
+    static bool temporaryAbortIfWasmGc(JSContext* cx);
+#else
+    static bool temporaryAbortIfWasmGc(JSContext* cx) { return false; }
+#endif
+
     uint64_t nextCellUniqueId() {
         MOZ_ASSERT(nextCellUniqueId_ > 0);
         uint64_t uid = ++nextCellUniqueId_;
         return uid;
     }
 
 #ifdef DEBUG
     bool shutdownCollectedEverything() const {
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -174,30 +174,33 @@ NextNode(VerifyNode* node)
 }
 
 void
 gc::GCRuntime::startVerifyPreBarriers()
 {
     if (verifyPreData || isIncrementalGCInProgress())
         return;
 
+    JSContext* cx = rt->mainContextFromOwnThread();
+    if (temporaryAbortIfWasmGc(cx))
+        return;
+
     if (IsIncrementalGCUnsafe(rt) != AbortReason::None ||
-        rt->mainContextFromOwnThread()->keepAtoms ||
+        cx->keepAtoms ||
         rt->hasHelperThreadZones())
     {
         return;
     }
 
     number++;
 
     VerifyPreTracer* trc = js_new<VerifyPreTracer>(rt);
     if (!trc)
         return;
 
-    JSContext* cx = rt->mainContextFromOwnThread();
     AutoPrepareForTracing prep(cx);
 
     {
         AutoLockGC lock(cx->runtime());
         for (auto chunk = allNonEmptyChunks(lock); !chunk.done(); chunk.next())
             chunk->bitmap.clear();
     }
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/gc/block-debugger-findscripts.js
@@ -0,0 +1,29 @@
+if (!wasmGcEnabled()) {
+    quit();
+}
+
+wasmEvalText(`
+    (module
+        (import "global" "func" (result i32))
+        (func (export "func_0") (result i32)
+         call 0 ;; calls the import, which is func #0
+        )
+    )
+`, {
+    global: {
+        func() {
+          var g = newGlobal();
+          var dbg = new Debugger(g);
+          var caught = false;
+          try {
+            dbg.findScripts().filter(isWasm(g, isValidWasmURL, 2));
+          } catch(e) {
+              caught = true;
+              assertEq(/temporarily unavailable/.test(e.toString()), true);
+          }
+          // When this assertion fails, it's time to remove the restriction in
+          // Debugger.findScripts.
+          assertEq(caught, true);
+        }
+    }
+}).exports.func_0();;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/gc/block-verifyprebarriers.js
@@ -0,0 +1,14 @@
+wasmEvalText(`
+    (module
+        (import "global" "func" (result i32))
+        (func (export "func_0") (result i32)
+         call 0
+        )
+    )
+`, {
+    global: {
+        func() {
+            verifyprebarriers();
+        }
+    }
+}).exports.func_0();
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -1281,18 +1281,21 @@ MConstant::valueToBoolean(bool* res) con
         return true;
       case MIRType::Symbol:
         *res = true;
         return true;
       case MIRType::String:
         *res = toString()->length() != 0;
         return true;
       case MIRType::Object:
-        *res = !EmulatesUndefined(&toObject());
-        return true;
+        // We have to call EmulatesUndefined but that reads obj->group->clasp
+        // and so it's racy when the object has a lazy group. The main callers
+        // of this (MTest, MNot) already know how to fold the object case, so
+        // just give up.
+        return false;
       default:
         MOZ_ASSERT(IsMagicType(type()));
         return false;
     }
 }
 
 HashNumber
 MWasmFloatConstant::valueHash() const
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1636,21 +1636,22 @@ class MConstant : public MNullaryInstruc
     static MConstant* NewFloat32(TempAllocator& alloc, double d);
     static MConstant* NewInt64(TempAllocator& alloc, int64_t i);
     static MConstant* NewConstraintlessObject(TempAllocator& alloc, JSObject* v);
     static MConstant* Copy(TempAllocator& alloc, MConstant* src) {
         return new(alloc) MConstant(*src);
     }
 
     // Try to convert this constant to boolean, similar to js::ToBoolean.
-    // Returns false if the type is MIRType::Magic*.
+    // Returns false if the type is MIRType::Magic* or MIRType::Object.
     bool MOZ_MUST_USE valueToBoolean(bool* res) const;
 
     // Like valueToBoolean, but returns the result directly instead of using
-    // an outparam. Should not be used if this constant might be a magic value.
+    // an outparam. Should not be used if this constant might be a magic value
+    // or an object.
     bool valueToBooleanInfallible() const {
         bool res;
         MOZ_ALWAYS_TRUE(valueToBoolean(&res));
         return res;
     }
 
 #ifdef JS_JITSPEW
     void printOpcode(GenericPrinter& out) const override;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4697,16 +4697,21 @@ class MOZ_STACK_CLASS Debugger::ScriptQu
     }
 };
 
 /* static */ bool
 Debugger::findScripts(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER(cx, argc, vp, "findScripts", args, dbg);
 
+    if (gc::GCRuntime::temporaryAbortIfWasmGc(cx)) {
+        JS_ReportErrorASCII(cx, "API temporarily unavailable under wasm gc");
+        return false;
+    }
+
     ScriptQuery query(cx, dbg);
     if (!query.init())
         return false;
 
     if (args.length() >= 1) {
         RootedObject queryObject(cx, NonNullObject(cx, args[0]));
         if (!queryObject || !query.parseQuery(queryObject))
             return false;
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -250,23 +250,23 @@ class ObjectGroup : public gc::TenuredCe
                maybePreliminaryObjectsDontCheckGeneration();
     }
 
     inline UnboxedLayout* maybeUnboxedLayout(const AutoSweepObjectGroup& sweep);
     inline UnboxedLayout& unboxedLayout(const AutoSweepObjectGroup& sweep);
 
     UnboxedLayout* maybeUnboxedLayoutDontCheckGeneration() const {
         if (addendumKind() == Addendum_UnboxedLayout)
-            return reinterpret_cast<UnboxedLayout*>(addendum_);
+            return &unboxedLayoutDontCheckGeneration();
         return nullptr;
     }
 
     UnboxedLayout& unboxedLayoutDontCheckGeneration() const {
         MOZ_ASSERT(addendumKind() == Addendum_UnboxedLayout);
-        return *maybeUnboxedLayoutDontCheckGeneration();
+        return *reinterpret_cast<UnboxedLayout*>(addendum_);
     }
 
     void setUnboxedLayout(UnboxedLayout* layout) {
         setAddendum(Addendum_UnboxedLayout, layout);
     }
 
     ObjectGroup* maybeOriginalUnboxedGroup() const {
         if (addendumKind() == Addendum_OriginalUnboxedGroup)
@@ -277,23 +277,23 @@ class ObjectGroup : public gc::TenuredCe
     void setOriginalUnboxedGroup(ObjectGroup* group) {
         setAddendum(Addendum_OriginalUnboxedGroup, group);
     }
 
     TypeDescr* maybeTypeDescr() {
         // Note: there is no need to sweep when accessing the type descriptor
         // of an object, as it is strongly held and immutable.
         if (addendumKind() == Addendum_TypeDescr)
-            return reinterpret_cast<TypeDescr*>(addendum_);
+            return &typeDescr();
         return nullptr;
     }
 
     TypeDescr& typeDescr() {
         MOZ_ASSERT(addendumKind() == Addendum_TypeDescr);
-        return *maybeTypeDescr();
+        return *reinterpret_cast<TypeDescr*>(addendum_);
     }
 
     void setTypeDescr(TypeDescr* descr) {
         setAddendum(Addendum_TypeDescr, descr);
     }
 
     JSFunction* maybeInterpretedFunction() {
         // Note: as with type descriptors, there is no need to sweep when
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -2401,22 +2401,19 @@ JSStructuredCloneReader::readHeader()
     if (storedScope < JS::StructuredCloneScope::SameProcessSameThread ||
         storedScope > JS::StructuredCloneScope::DifferentProcessForIndexedDB)
     {
         JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA,
                                   "invalid structured clone scope");
         return false;
     }
 
-    if (storedScope == JS::StructuredCloneScope::SameProcessSameThread &&
-        allowedScope == JS::StructuredCloneScope::DifferentProcessForIndexedDB)
-    {
-        // Bug 1434308 - allow stored IndexedDB clones to contain what is
-        // essentially DifferentProcess data, but labeled as
-        // SameProcessSameThread (because that's what old code wrote.)
+    if (allowedScope == JS::StructuredCloneScope::DifferentProcessForIndexedDB) {
+        // Bug 1434308 and bug 1458320 - the scopes stored in old IndexedDB
+        // clones are incorrect. Treat them as if they were DifferentProcess.
         allowedScope = JS::StructuredCloneScope::DifferentProcess;
         return true;
     }
 
     if (storedScope < allowedScope) {
         JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
                                   JSMSG_SC_BAD_SERIALIZED_DATA,
                                   "incompatible structured clone scope");
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -11501,23 +11501,16 @@ nsAdaptorPrintReason(ReflowInput& aReflo
           reflowReasonString = "unknown";
           break;
     }
 
     printf("%s",reflowReasonString);
 }
 
 #endif
-#ifdef DEBUG_LAYOUT
-void
-nsFrame::GetBoxName(nsAutoString& aName)
-{
-  GetFrameName(aName);
-}
-#endif
 
 #ifdef DEBUG
 static void
 GetTagName(nsFrame* aFrame, nsIContent* aContent, int aResultSize,
            char* aResult)
 {
   if (aContent) {
     snprintf(aResult, aResultSize, "%s@%p",
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -674,20 +674,16 @@ protected:
                                       int32_t* aContentOffset,
                                       int32_t* aTarget);
 
   // Fills aCursor with the appropriate information from ui
   static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
                                              nsIFrame::Cursor& aCursor);
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
 
-#ifdef DEBUG_LAYOUT
-  void GetBoxName(nsAutoString& aName) override;
-#endif
-
   nsBoxLayoutMetrics* BoxMetrics() const;
 
   // Fire DOM event. If no aContent argument use frame's mContent.
   void FireDOMEvent(const nsAString& aDOMEventName, nsIContent *aContent = nullptr);
 
 private:
   void BoxReflow(nsBoxLayoutState& aState,
                  nsPresContext*    aPresContext,
--- a/layout/generic/nsFrameStateBits.h
+++ b/layout/generic/nsFrameStateBits.h
@@ -294,19 +294,17 @@ FRAME_STATE_BIT(Generic, 59, NS_FRAME_IS
 
 FRAME_STATE_GROUP(Box, nsBoxFrame)
 
 FRAME_STATE_BIT(Box, 20, NS_STATE_BOX_CHILD_RESERVED)
 FRAME_STATE_BIT(Box, 21, NS_STATE_STACK_NOT_POSITIONED)
 FRAME_STATE_BIT(Box, 22, NS_STATE_IS_HORIZONTAL)
 FRAME_STATE_BIT(Box, 23, NS_STATE_AUTO_STRETCH)
 FRAME_STATE_BIT(Box, 24, NS_STATE_IS_ROOT)
-FRAME_STATE_BIT(Box, 25, NS_STATE_CURRENTLY_IN_DEBUG)
-FRAME_STATE_BIT(Box, 26, NS_STATE_SET_TO_DEBUG)
-FRAME_STATE_BIT(Box, 27, NS_STATE_DEBUG_WAS_SET)
+/* Bits 25, 26, and 27 were used for xul debug flags but are now unused */
 FRAME_STATE_BIT(Box, 28, NS_STATE_MENU_HAS_POPUP_LIST)
 FRAME_STATE_BIT(Box, 29, NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK)
 FRAME_STATE_BIT(Box, 30, NS_STATE_EQUAL_SIZE)
 FRAME_STATE_BIT(Box, 31, NS_STATE_IS_DIRECTION_NORMAL)
 FRAME_STATE_BIT(Box, 60, NS_FRAME_MOUSE_THROUGH_ALWAYS)
 FRAME_STATE_BIT(Box, 61, NS_FRAME_MOUSE_THROUGH_NEVER)
 
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1568,20 +1568,16 @@ nsXULScrollFrame::GetXULBoxAscent(nsBoxL
   ascent += m.top;
 
   return ascent;
 }
 
 nsSize
 nsXULScrollFrame::GetXULPrefSize(nsBoxLayoutState& aState)
 {
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aState);
-#endif
-
   nsSize pref = mHelper.mScrolledFrame->GetXULPrefSize(aState);
 
   ScrollbarStyles styles = GetScrollbarStyles();
 
   // scrolled frames don't have their own margins
 
   if (mHelper.mVScrollbarBox &&
       styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
@@ -1601,20 +1597,16 @@ nsXULScrollFrame::GetXULPrefSize(nsBoxLa
   bool widthSet, heightSet;
   nsIFrame::AddXULPrefSize(this, pref, widthSet, heightSet);
   return pref;
 }
 
 nsSize
 nsXULScrollFrame::GetXULMinSize(nsBoxLayoutState& aState)
 {
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aState);
-#endif
-
   nsSize min = mHelper.mScrolledFrame->GetXULMinSizeForScrollArea(aState);
 
   ScrollbarStyles styles = GetScrollbarStyles();
 
   if (mHelper.mVScrollbarBox &&
       styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
      nsSize vSize = mHelper.mVScrollbarBox->GetXULMinSize(aState);
      AddMargin(mHelper.mVScrollbarBox, vSize);
@@ -1636,20 +1628,16 @@ nsXULScrollFrame::GetXULMinSize(nsBoxLay
   bool widthSet, heightSet;
   nsIFrame::AddXULMinSize(aState, this, min, widthSet, heightSet);
   return min;
 }
 
 nsSize
 nsXULScrollFrame::GetXULMaxSize(nsBoxLayoutState& aState)
 {
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aState);
-#endif
-
   nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
 
   AddBorderAndPadding(maxSize);
   bool widthSet, heightSet;
   nsIFrame::AddXULMaxSize(this, maxSize, widthSet, heightSet);
   return maxSize;
 }
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -3740,23 +3740,16 @@ public:
   virtual Halignment GetXULHAlign() const = 0;
 
   bool IsXULHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
   bool IsXULNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
 
   nsresult XULRedraw(nsBoxLayoutState& aState);
   virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild)=0;
 
-#ifdef DEBUG_LAYOUT
-  virtual nsresult SetXULDebug(nsBoxLayoutState& aState, bool aDebug)=0;
-  virtual nsresult GetXULDebug(bool& aDebug)=0;
-
-  virtual nsresult XULDumpBox(FILE* out)=0;
-#endif
-
   static bool AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
   static bool AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
                             nsSize& aSize, bool& aWidth, bool& aHeightSet);
   static bool AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
   static bool AddXULFlex(nsIFrame* aBox, nscoord& aFlex);
 
   // END OF BOX LAYOUT METHODS
   // The above methods have been migrated from nsIBox and are in the process of
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/MutationEventBinding.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/ServoDeclarationBlock.h"
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIURI.h"
 #include "nsNodeUtils.h"
+#include "nsSMILCSSValueType.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIFrame.h"
 #include "ActiveLayerTracker.h"
 
 using namespace mozilla;
 
 nsDOMCSSAttributeDeclaration::nsDOMCSSAttributeDeclaration(dom::Element* aElement,
                                                            bool aIsSMILOverride)
@@ -175,26 +176,34 @@ nsDOMCSSAttributeDeclaration::GetServoCS
 {
   return {
     mElement->GetURLDataForStyleAttr(aSubjectPrincipal),
     mElement->OwnerDoc()->GetCompatibilityMode(),
     mElement->OwnerDoc()->CSSLoader(),
   };
 }
 
-css::Rule*
-nsDOMCSSAttributeDeclaration::GetParentRule()
+nsresult
+nsDOMCSSAttributeDeclaration::SetSMILValue(const nsCSSPropertyID aPropID,
+                                           const nsSMILValue& aValue)
 {
-  return nullptr;
-}
+  MOZ_ASSERT(mIsSMILOverride);
 
-/* virtual */ nsINode*
-nsDOMCSSAttributeDeclaration::GetParentObject()
-{
-  return mElement;
+  // Convert nsSMILValue to string.
+  //
+  // FIXME(emilio): This roundtrip should go away.
+  nsAutoString valStr;
+  nsSMILCSSValueType::ValueToString(aValue, valStr);
+
+  nsAutoString oldValStr;
+  GetPropertyValue(aPropID, oldValStr);
+  if (valStr.Equals(oldValStr)) {
+    return NS_OK;
+  }
+  return SetPropertyValue(aPropID, valStr, nullptr);
 }
 
 nsresult
 nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
                                                const nsAString& aValue,
                                                nsIPrincipal* aSubjectPrincipal)
 {
   // Scripted modifications to style.opacity or style.transform
--- a/layout/style/nsDOMCSSAttrDeclaration.h
+++ b/layout/style/nsDOMCSSAttrDeclaration.h
@@ -9,16 +9,17 @@
 #ifndef nsDOMCSSAttributeDeclaration_h
 #define nsDOMCSSAttributeDeclaration_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/DocGroup.h"
 #include "nsDOMCSSDeclaration.h"
 
 
+class nsSMILValue;
 namespace mozilla {
 namespace dom {
 class DomGroup;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration
@@ -33,19 +34,27 @@ public:
 
   // If GetCSSDeclaration returns non-null, then the decl it returns
   // is owned by our current style rule.
   virtual mozilla::DeclarationBlock* GetCSSDeclaration(Operation aOperation) override;
   virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
                                         nsIPrincipal* aSubjectPrincipal) override;
   nsDOMCSSDeclaration::ServoCSSParsingEnvironment
   GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
-  mozilla::css::Rule* GetParentRule() override;
+  mozilla::css::Rule* GetParentRule() override
+  {
+    return nullptr;
+  }
 
-  virtual nsINode* GetParentObject() override;
+  nsINode* GetParentObject() override
+  {
+    return mElement;
+  }
+
+  nsresult SetSMILValue(const nsCSSPropertyID aPropID, const nsSMILValue&);
 
   nsresult SetPropertyValue(const nsCSSPropertyID aPropID,
                             const nsAString& aValue,
                             nsIPrincipal* aSubjectPrincipal) override;
 
 protected:
   ~nsDOMCSSAttributeDeclaration();
 
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -18,19 +18,17 @@
 #include "nsIURI.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "nsContentUtils.h"
 #include "nsQueryObject.h"
 #include "mozilla/layers/ScrollLinkedEffectDetector.h"
 
 using namespace mozilla;
 
-nsDOMCSSDeclaration::~nsDOMCSSDeclaration()
-{
-}
+nsDOMCSSDeclaration::~nsDOMCSSDeclaration() = default;
 
 /* virtual */ JSObject*
 nsDOMCSSDeclaration::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return dom::CSS2PropertiesBinding::Wrap(aCx, this, aGivenProto);
 }
 
 NS_IMPL_QUERY_INTERFACE(nsDOMCSSDeclaration,
@@ -265,43 +263,42 @@ nsDOMCSSDeclaration::GetServoCSSParsingE
 
   return {
     sheet->URLData(),
     eCompatibility_FullStandards,
     nullptr,
   };
 }
 
-template<typename GeckoFunc, typename ServoFunc>
+template<typename Func>
 nsresult
 nsDOMCSSDeclaration::ModifyDeclaration(nsIPrincipal* aSubjectPrincipal,
-                                       GeckoFunc aGeckoFunc,
-                                       ServoFunc aServoFunc)
+                                       Func aFunc)
 {
   DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
   if (!olddecl) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
 
   bool changed;
-  ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment(
-      aSubjectPrincipal);
+  ServoCSSParsingEnvironment servoEnv =
+    GetServoCSSParsingEnvironment(aSubjectPrincipal);
   if (!servoEnv.mUrlExtraData) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  changed = aServoFunc(decl->AsServo(), servoEnv);
+  changed = aFunc(decl->AsServo(), servoEnv);
 
   if (!changed) {
     // Parsing failed -- but we don't throw an exception for that.
     return NS_OK;
   }
 
   return SetCSSDeclaration(decl);
 }
@@ -309,19 +306,16 @@ nsDOMCSSDeclaration::ModifyDeclaration(n
 nsresult
 nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSPropertyID aPropID,
                                         const nsAString& aPropValue,
                                         bool aIsImportant,
                                         nsIPrincipal* aSubjectPrincipal)
 {
   return ModifyDeclaration(
     aSubjectPrincipal,
-    [&](css::Declaration* decl, CSSParsingEnvironment& env, bool* changed) {
-      MOZ_CRASH("old style system disabled");
-    },
     [&](ServoDeclarationBlock* decl, ServoCSSParsingEnvironment& env) {
       NS_ConvertUTF16toUTF8 value(aPropValue);
       return Servo_DeclarationBlock_SetPropertyById(
         decl->Raw(), aPropID, &value, aIsImportant, env.mUrlExtraData,
         ParsingMode::Default, env.mCompatMode, env.mLoader);
     });
 }
 
@@ -329,19 +323,16 @@ nsresult
 nsDOMCSSDeclaration::ParseCustomPropertyValue(const nsAString& aPropertyName,
                                               const nsAString& aPropValue,
                                               bool aIsImportant,
                                               nsIPrincipal* aSubjectPrincipal)
 {
   MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
   return ModifyDeclaration(
     aSubjectPrincipal,
-    [&](css::Declaration* decl, CSSParsingEnvironment& env, bool* changed) {
-      MOZ_CRASH("old style system disabled");
-    },
     [&](ServoDeclarationBlock* decl, ServoCSSParsingEnvironment& env) {
       NS_ConvertUTF16toUTF8 property(aPropertyName);
       NS_ConvertUTF16toUTF8 value(aPropValue);
       return Servo_DeclarationBlock_SetProperty(
         decl->Raw(), &property, &value, aIsImportant, env.mUrlExtraData,
         ParsingMode::Default, env.mCompatMode, env.mLoader);
     });
 }
--- a/layout/style/nsDOMCSSDeclaration.h
+++ b/layout/style/nsDOMCSSDeclaration.h
@@ -223,14 +223,14 @@ protected:
 
   nsresult RemovePropertyInternal(nsCSSPropertyID aPropID);
   nsresult RemovePropertyInternal(const nsAString& aProperty);
 
 protected:
   virtual ~nsDOMCSSDeclaration();
 
 private:
-  template<typename GeckoFunc, typename ServoFunc>
+  template<typename ServoFunc>
   inline nsresult ModifyDeclaration(nsIPrincipal* aSubjectPrincipal,
-                                    GeckoFunc aGeckoFunc, ServoFunc aServoFunc);
+                                    ServoFunc aServoFunc);
 };
 
 #endif // nsDOMCSSDeclaration_h___
--- a/layout/xul/nsBox.cpp
+++ b/layout/xul/nsBox.cpp
@@ -20,118 +20,19 @@
 #include "nsBoxLayout.h"
 #include "FrameLayerBuilder.h"
 #include "mozilla/dom/Attr.h"
 #include "mozilla/dom/Element.h"
 #include <algorithm>
 
 using namespace mozilla;
 
-#ifdef DEBUG_LAYOUT
-int32_t gIndent = 0;
-#endif
-
-#ifdef DEBUG_LAYOUT
-void
-nsBoxAddIndents()
-{
-    for(int32_t i=0; i < gIndent; i++)
-    {
-        printf(" ");
-    }
-}
-#endif
-
-#ifdef DEBUG_LAYOUT
-void
-nsBox::AppendAttribute(const nsAutoString& aAttribute, const nsAutoString& aValue, nsAutoString& aResult)
-{
-   aResult.Append(aAttribute);
-   aResult.AppendLiteral("='");
-   aResult.Append(aValue);
-   aResult.AppendLiteral("' ");
-}
-
-void
-nsBox::ListBox(nsAutoString& aResult)
-{
-    nsAutoString name;
-    GetBoxName(name);
-
-    char addr[100];
-    sprintf(addr, "[@%p] ", static_cast<void*>(this));
-
-    aResult.AppendASCII(addr);
-    aResult.Append(name);
-    aResult.Append(' ');
-
-    nsIContent* content = GetContent();
-
-    // add on all the set attributes
-    if (content && content->IsElement()) {
-      RefPtr<nsDOMAttributeMap> namedMap = content->AsElement()->Attributes();
-
-      uint32_t length = namedMap->Length();
-
-      RefPtr<dom::Attr> attribute;
-      for (uint32_t i = 0; i < length; ++i)
-      {
-        attribute = namedMap->Item(i);
-        attribute->GetName(name);
-        nsAutoString value;
-        attribute->GetValue(value);
-        AppendAttribute(name, value, aResult);
-      }
-    }
-}
-
-nsresult
-nsBox::XULDumpBox(FILE* aFile)
-{
-  nsAutoString s;
-  ListBox(s);
-  fprintf(aFile, "%s", NS_LossyConvertUTF16toASCII(s).get());
-  return NS_OK;
-}
-
-void
-nsBox::PropagateDebug(nsBoxLayoutState& aState)
-{
-  // propagate debug information
-  if (mState & NS_STATE_DEBUG_WAS_SET) {
-    if (mState & NS_STATE_SET_TO_DEBUG)
-      SetXULDebug(aState, true);
-    else
-      SetXULDebug(aState, false);
-  } else if (mState & NS_STATE_IS_ROOT) {
-    SetXULDebug(aState, gDebug);
-  }
-}
-#endif
-
-#ifdef DEBUG_LAYOUT
-void
-nsBox::GetBoxName(nsAutoString& aName)
-{
-  aName.AssignLiteral("Box");
-}
-#endif
-
 nsresult
 nsBox::BeginXULLayout(nsBoxLayoutState& aState)
 {
-#ifdef DEBUG_LAYOUT
-
-  nsBoxAddIndents();
-  printf("XULLayout: ");
-  XULDumpBox(stdout);
-  printf("\n");
-  gIndent++;
-#endif
-
   // mark ourselves as dirty so no child under us
   // can post an incremental layout.
   // XXXldb Is this still needed?
   AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
 
   if (GetStateBits() & NS_FRAME_IS_DIRTY)
   {
     // If the parent is dirty, all the children are dirty (ReflowInput
@@ -142,49 +43,38 @@ nsBox::BeginXULLayout(nsBoxLayoutState& 
   }
 
   // Another copy-over from ReflowInput.
   // Since we are in reflow, we don't need to store these properties anymore.
   DeleteProperty(UsedBorderProperty());
   DeleteProperty(UsedPaddingProperty());
   DeleteProperty(UsedMarginProperty());
 
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aState);
-#endif
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBox::DoXULLayout(nsBoxLayoutState& aState)
 {
   return NS_OK;
 }
 
 nsresult
 nsBox::EndXULLayout(nsBoxLayoutState& aState)
 {
-
-  #ifdef DEBUG_LAYOUT
-      --gIndent;
-  #endif
-
   return SyncLayout(aState);
 }
 
 bool nsBox::gGotTheme = false;
 nsITheme* nsBox::gTheme = nullptr;
 
 nsBox::nsBox(ClassID aID)
   : nsIFrame(aID)
 {
   MOZ_COUNT_CTOR(nsBox);
-  //mX = 0;
-  //mY = 0;
   if (!gGotTheme) {
     gGotTheme = true;
     CallGetService("@mozilla.org/chrome/chrome-native-theme;1", &gTheme);
   }
 }
 
 nsBox::~nsBox()
 {
@@ -218,26 +108,22 @@ nsIFrame::GetXULClientRect(nsRect& aClie
   aClientRect.Deflate(borderPadding);
 
   if (aClientRect.width < 0)
      aClientRect.width = 0;
 
   if (aClientRect.height < 0)
      aClientRect.height = 0;
 
- // NS_ASSERTION(aClientRect.width >=0 && aClientRect.height >= 0, "Content Size < 0");
-
   return NS_OK;
 }
 
 void
 nsBox::SetXULBounds(nsBoxLayoutState& aState, const nsRect& aRect, bool aRemoveOverflowAreas)
 {
-    NS_BOX_ASSERTION(this, aRect.width >=0 && aRect.height >= 0, "SetXULBounds Size < 0");
-
     nsRect rect(mRect);
 
     uint32_t flags = GetXULLayoutFlags();
 
     uint32_t stateFlags = aState.LayoutFlags();
 
     flags |= stateFlags;
 
@@ -254,29 +140,16 @@ nsBox::SetXULBounds(nsBoxLayoutState& aS
     }
 
     if (!(flags & NS_FRAME_NO_MOVE_VIEW))
     {
       nsContainerFrame::PositionFrameView(this);
       if ((rect.x != aRect.x) || (rect.y != aRect.y))
         nsContainerFrame::PositionChildViews(this);
     }
-
-
-   /*
-    // only if the origin changed
-    if ((rect.x != aRect.x) || (rect.y != aRect.y))  {
-      if (frame->HasView()) {
-        nsContainerFrame::PositionFrameView(presContext, frame,
-                                            frame->GetView());
-      } else {
-        nsContainerFrame::PositionChildViews(presContext, frame);
-      }
-    }
-    */
 }
 
 nsresult
 nsIFrame::GetXULBorderAndPadding(nsMargin& aBorderAndPadding)
 {
   aBorderAndPadding.SizeTo(0, 0, 0, 0);
   nsresult rv = GetXULBorder(aBorderAndPadding);
   if (NS_FAILED(rv))
@@ -928,53 +801,8 @@ nsBox::GetNextXULBox(const nsIFrame* aFr
 
 /*static*/ nsIFrame*
 nsBox::GetParentXULBox(const nsIFrame* aFrame)
 {
   return aFrame->GetParent() &&
     aFrame->GetParent()->IsXULBoxFrame() ? aFrame->GetParent() : nullptr;
 }
 
-#ifdef DEBUG_LAYOUT
-nsresult
-nsBox::SetXULDebug(nsBoxLayoutState& aState, bool aDebug)
-{
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-nsBox::GetDebugBoxAt( const nsPoint& aPoint,
-                      nsIFrame**     aBox)
-{
-  nsRect thisRect(nsPoint(0,0), GetSize());
-  if (!thisRect.Contains(aPoint))
-    return NS_ERROR_FAILURE;
-
-  nsIFrame* child = nsBox::GetChildXULBox(this);
-  nsIFrame* hit = nullptr;
-
-  *aBox = nullptr;
-  while (nullptr != child) {
-    nsresult rv = child->GetDebugBoxAt(aPoint - child->GetOffsetTo(this), &hit);
-
-    if (NS_SUCCEEDED(rv) && hit) {
-      *aBox = hit;
-    }
-    child = GetNextXULBox(child);
-  }
-
-  // found a child
-  if (*aBox) {
-    return NS_OK;
-  }
-
-  return NS_ERROR_FAILURE;
-}
-
-
-nsresult
-nsBox::GetXULDebug(bool& aDebug)
-{
-  aDebug = false;
-  return NS_OK;
-}
-
-#endif
--- a/layout/xul/nsBox.h
+++ b/layout/xul/nsBox.h
@@ -37,31 +37,21 @@ public:
   virtual nsresult GetXULPadding(nsMargin& aBorderAndPadding) override;
   virtual nsresult GetXULMargin(nsMargin& aMargin) override;
 
   virtual Valignment GetXULVAlign() const override { return vAlign_Top; }
   virtual Halignment GetXULHAlign() const override { return hAlign_Left; }
 
   virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild) override;
 
-#ifdef DEBUG_LAYOUT
-  NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIFrame** aBox) override;
-  virtual nsresult GetXULDebug(bool& aDebug) override;
-  virtual nsresult SetXULDebug(nsBoxLayoutState& aState, bool aDebug) override;
-
-  virtual nsresult XULDumpBox(FILE* out) override;
-  void PropagateDebug(nsBoxLayoutState& aState);
-#endif
-
   nsBox(ClassID aID);
   virtual ~nsBox();
 
   /**
-   * Returns true if this box clips its children, e.g., if this box is an sc
-rollbox.
+   * Returns true if this box clips its children, e.g., if this box is an scrollbox.
   */
   virtual bool DoesClipChildren();
   virtual bool ComputesOwnOverflowArea() = 0;
 
   nsresult SyncLayout(nsBoxLayoutState& aBoxLayoutState);
 
   bool DoesNeedRecalc(const nsSize& aSize);
   bool DoesNeedRecalc(nscoord aCoord);
@@ -79,50 +69,24 @@ rollbox.
   static nscoord BoundsCheck(nscoord aMinSize, nscoord aPrefSize, nscoord aMaxSize);
 
   static nsIFrame* GetChildXULBox(const nsIFrame* aFrame);
   static nsIFrame* GetNextXULBox(const nsIFrame* aFrame);
   static nsIFrame* GetParentXULBox(const nsIFrame* aFrame);
 
 protected:
 
-#ifdef DEBUG_LAYOUT
-  virtual void AppendAttribute(const nsAutoString& aAttribute, const nsAutoString& aValue, nsAutoString& aResult);
-
-  virtual void ListBox(nsAutoString& aResult);
-#endif
-
   nsresult BeginXULLayout(nsBoxLayoutState& aState);
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState);
   nsresult EndXULLayout(nsBoxLayoutState& aState);
 
-#ifdef DEBUG_LAYOUT
-  virtual void GetBoxName(nsAutoString& aName);
-  void PropagateDebug(nsBoxLayoutState& aState);
-#endif
-
   static bool gGotTheme;
   static nsITheme* gTheme;
 
   enum eMouseThrough {
     unset,
     never,
     always
   };
-
-private:
-
-  //nscoord mX;
-  //nscoord mY;
 };
 
-#ifdef DEBUG_LAYOUT
-#define NS_BOX_ASSERTION(box,expr,str) \
-  if (!(expr)) { \
-       box->XULDumpBox(stdout); \
-       NS_DebugBreak(NSDebugAssertion, str, #expr, __FILE__, __LINE__); \
-  }
-#else
-#define NS_BOX_ASSERTION(box,expr,str) {}
-#endif
-
 #endif
 
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -71,33 +71,16 @@
 #include "nsIURI.h"
 
 #include "mozilla/TouchEvents.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
-//define DEBUG_REDRAW
-
-#define DEBUG_SPRING_SIZE 8
-#define DEBUG_BORDER_SIZE 2
-#define COIL_SIZE 8
-
-//#define TEST_SANITY
-
-#ifdef DEBUG_rods
-//#define DO_NOISY_REFLOW
-#endif
-
-#ifdef DEBUG_LAYOUT
-bool nsBoxFrame::gDebug = false;
-nsIFrame* nsBoxFrame::mDebugChild = nullptr;
-#endif
-
 nsIFrame*
 NS_NewBoxFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle, bool aIsRoot, nsBoxLayout* aLayoutManager)
 {
   return new (aPresShell) nsBoxFrame(aStyle, nsBoxFrame::kClassID,
                                      aIsRoot, aLayoutManager);
 }
 
 nsIFrame*
@@ -181,23 +164,16 @@ nsBoxFrame::Init(nsIContent*       aCont
   if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER) {
     AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
   }
 
   MarkIntrinsicISizesDirty();
 
   CacheAttributes();
 
-#ifdef DEBUG_LAYOUT
-    // if we are root and this
-  if (mState & NS_STATE_IS_ROOT) {
-    GetDebugPref();
-  }
-#endif
-
   UpdateMouseThrough();
 
   // register access key
   RegUnregAccessKey(true);
 }
 
 void nsBoxFrame::UpdateMouseThrough()
 {
@@ -252,53 +228,18 @@ nsBoxFrame::CacheAttributes()
         RemoveStateBits(NS_STATE_EQUAL_SIZE);
 
   bool autostretch = !!(mState & NS_STATE_AUTO_STRETCH);
   GetInitialAutoStretch(autostretch);
   if (autostretch)
         AddStateBits(NS_STATE_AUTO_STRETCH);
      else
         RemoveStateBits(NS_STATE_AUTO_STRETCH);
-
-
-#ifdef DEBUG_LAYOUT
-  bool debug = mState & NS_STATE_SET_TO_DEBUG;
-  bool debugSet = GetInitialDebug(debug);
-  if (debugSet) {
-        AddStateBits(NS_STATE_DEBUG_WAS_SET);
-        if (debug)
-            AddStateBits(NS_STATE_SET_TO_DEBUG);
-        else
-            RemoveStateBits(NS_STATE_SET_TO_DEBUG);
-  } else {
-        RemoveStateBits(NS_STATE_DEBUG_WAS_SET);
-  }
-#endif
 }
 
-#ifdef DEBUG_LAYOUT
-bool
-nsBoxFrame::GetInitialDebug(bool& aDebug)
-{
-  if (!GetContent() || !GetContent()->IsElement())
-    return false;
-
-  static Element::AttrValuesArray strings[] =
-    {&nsGkAtoms::_false, &nsGkAtoms::_true, nullptr};
-  int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None,
-      nsGkAtoms::debug, strings, eCaseMatters);
-  if (index >= 0) {
-    aDebug = index == 1;
-    return true;
-  }
-
-  return false;
-}
-#endif
-
 bool
 nsBoxFrame::GetInitialHAlignment(nsBoxFrame::Halignment& aHalign)
 {
   if (!GetContent() || !GetContent()->IsElement())
     return false;
 
   Element* element = GetContent()->AsElement();
   // XXXdwh Everything inside this if statement is deprecated code.
@@ -767,20 +708,16 @@ nsBoxFrame::GetXULPrefSize(nsBoxLayoutSt
 
   nsSize size(0,0);
   DISPLAY_PREF_SIZE(this, size);
   if (!DoesNeedRecalc(mPrefSize)) {
     size = mPrefSize;
     return size;
   }
 
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aBoxLayoutState);
-#endif
-
   if (IsXULCollapsed())
     return size;
 
   // if the size was not completely redefined in CSS then ask our children
   bool widthSet, heightSet;
   if (!nsIFrame::AddXULPrefSize(this, size, widthSet, heightSet))
   {
     if (mLayoutManager) {
@@ -803,20 +740,16 @@ nsBoxFrame::GetXULPrefSize(nsBoxLayoutSt
 }
 
 nscoord
 nsBoxFrame::GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState)
 {
   if (!DoesNeedRecalc(mAscent))
      return mAscent;
 
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aBoxLayoutState);
-#endif
-
   if (IsXULCollapsed())
     return 0;
 
   if (mLayoutManager)
     mAscent = mLayoutManager->GetAscent(this, aBoxLayoutState);
   else
     mAscent = nsBox::GetXULBoxAscent(aBoxLayoutState);
 
@@ -831,20 +764,16 @@ nsBoxFrame::GetXULMinSize(nsBoxLayoutSta
 
   nsSize size(0,0);
   DISPLAY_MIN_SIZE(this, size);
   if (!DoesNeedRecalc(mMinSize)) {
     size = mMinSize;
     return size;
   }
 
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aBoxLayoutState);
-#endif
-
   if (IsXULCollapsed())
     return size;
 
   // if the size was not completely redefined in CSS then ask our children
   bool widthSet, heightSet;
   if (!nsIFrame::AddXULMinSize(aBoxLayoutState, this, size, widthSet, heightSet))
   {
     if (mLayoutManager) {
@@ -872,20 +801,16 @@ nsBoxFrame::GetXULMaxSize(nsBoxLayoutSta
 
   nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
   DISPLAY_MAX_SIZE(this, size);
   if (!DoesNeedRecalc(mMaxSize)) {
     size = mMaxSize;
     return size;
   }
 
-#ifdef DEBUG_LAYOUT
-  PropagateDebug(aBoxLayoutState);
-#endif
-
   if (IsXULCollapsed())
     return size;
 
   // if the size was not completely redefined in CSS then ask our children
   bool widthSet, heightSet;
   if (!nsIFrame::AddXULMaxSize(this, size, widthSet, heightSet))
   {
     if (mLayoutManager) {
@@ -977,42 +902,16 @@ nsBoxFrame::DestroyFrom(nsIFrame* aDestr
   RegUnregAccessKey(false);
 
   // clean up the container box's layout manager and child boxes
   SetXULLayoutManager(nullptr);
 
   nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
 }
 
-#ifdef DEBUG_LAYOUT
-nsresult
-nsBoxFrame::SetXULDebug(nsBoxLayoutState& aState, bool aDebug)
-{
-  // see if our state matches the given debug state
-  bool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
-  bool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
-
-  // if it doesn't then tell each child below us the new debug state
-  if (debugChanged)
-  {
-     if (aDebug) {
-         AddStateBits(NS_STATE_CURRENTLY_IN_DEBUG);
-     } else {
-         RemoveStateBits(NS_STATE_CURRENTLY_IN_DEBUG);
-     }
-
-     SetDebugOnChildList(aState, mFirstChild, aDebug);
-
-    MarkIntrinsicISizesDirty();
-  }
-
-  return NS_OK;
-}
-#endif
-
 /* virtual */ void
 nsBoxFrame::MarkIntrinsicISizesDirty()
 {
   SizeNeedsRecalc(mPrefSize);
   SizeNeedsRecalc(mMinSize);
   SizeNeedsRecalc(mMaxSize);
   CoordNeedsRecalc(mFlex);
   CoordNeedsRecalc(mAscent);
@@ -1070,22 +969,16 @@ nsBoxFrame::InsertFrames(ChildListID    
      mLayoutManager->ChildrenInserted(this, state, aPrevFrame, newFrames);
 
    // Make sure to check box order _after_ notifying the layout
    // manager; otherwise the slice we give the layout manager will
    // just be bogus.  If the layout manager cares about the order, we
    // just lose.
    CheckBoxOrder();
 
-#ifdef DEBUG_LAYOUT
-   // if we are in debug make sure our children are in debug as well.
-   if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
-       SetDebugOnChildList(state, mFrames.FirstChild(), true);
-#endif
-
    PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                                  NS_FRAME_HAS_DIRTY_CHILDREN);
 }
 
 
 void
 nsBoxFrame::AppendFrames(ChildListID     aListID,
                          nsFrameList&    aFrameList)
@@ -1101,22 +994,16 @@ nsBoxFrame::AppendFrames(ChildListID    
      mLayoutManager->ChildrenAppended(this, state, newFrames);
 
    // Make sure to check box order _after_ notifying the layout
    // manager; otherwise the slice we give the layout manager will
    // just be bogus.  If the layout manager cares about the order, we
    // just lose.
    CheckBoxOrder();
 
-#ifdef DEBUG_LAYOUT
-   // if we are in debug make sure our children are in debug as well.
-   if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
-       SetDebugOnChildList(state, mFrames.FirstChild(), true);
-#endif
-
    // XXXbz why is this NS_FRAME_FIRST_REFLOW check here?
    if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
      PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                                    NS_FRAME_HAS_DIRTY_CHILDREN);
    }
 }
 
 /* virtual */ nsContainerFrame*
@@ -1169,19 +1056,16 @@ nsBoxFrame::AttributeChanged(int32_t aNa
       aAttribute == nsGkAtoms::dir          ||
       aAttribute == nsGkAtoms::mousethrough ||
       aAttribute == nsGkAtoms::equalsize) {
 
     if (aAttribute == nsGkAtoms::align  ||
         aAttribute == nsGkAtoms::valign ||
         aAttribute == nsGkAtoms::orient  ||
         aAttribute == nsGkAtoms::pack    ||
-#ifdef DEBUG_LAYOUT
-        aAttribute == nsGkAtoms::debug   ||
-#endif
         aAttribute == nsGkAtoms::dir) {
 
       mValign = nsBoxFrame::vAlign_Top;
       mHalign = nsBoxFrame::hAlign_Left;
 
       bool orient = true;
       GetInitialOrientation(orient);
       if (orient)
@@ -1201,31 +1085,16 @@ nsBoxFrame::AttributeChanged(int32_t aNa
 
       bool equalSize = false;
       GetInitialEqualSize(equalSize);
       if (equalSize)
         AddStateBits(NS_STATE_EQUAL_SIZE);
       else
         RemoveStateBits(NS_STATE_EQUAL_SIZE);
 
-#ifdef DEBUG_LAYOUT
-      bool debug = mState & NS_STATE_SET_TO_DEBUG;
-      bool debugSet = GetInitialDebug(debug);
-      if (debugSet) {
-        AddStateBits(NS_STATE_DEBUG_WAS_SET);
-
-        if (debug)
-          AddStateBits(NS_STATE_SET_TO_DEBUG);
-        else
-          RemoveStateBits(NS_STATE_SET_TO_DEBUG);
-      } else {
-        RemoveStateBits(NS_STATE_DEBUG_WAS_SET);
-      }
-#endif
-
       bool autostretch = !!(mState & NS_STATE_AUTO_STRETCH);
       GetInitialAutoStretch(autostretch);
       if (autostretch)
         AddStateBits(NS_STATE_AUTO_STRETCH);
       else
         RemoveStateBits(NS_STATE_AUTO_STRETCH);
     }
     else if (aAttribute == nsGkAtoms::left ||
@@ -1269,63 +1138,16 @@ nsBoxFrame::AttributeChanged(int32_t aNa
     // nsTreeBodyFrame's layout reads this from its parent (this frame).
     PresShell()->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
                                   NS_FRAME_IS_DIRTY);
   }
 
   return rv;
 }
 
-#ifdef DEBUG_LAYOUT
-void
-nsBoxFrame::GetDebugPref()
-{
-  gDebug = Preferences::GetBool("xul.debug.box");
-}
-
-class nsDisplayXULDebug : public nsDisplayItem {
-public:
-  nsDisplayXULDebug(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
-    nsDisplayItem(aBuilder, aFrame) {
-    MOZ_COUNT_CTOR(nsDisplayXULDebug);
-  }
-#ifdef NS_BUILD_REFCNT_LOGGING
-  virtual ~nsDisplayXULDebug() {
-    MOZ_COUNT_DTOR(nsDisplayXULDebug);
-  }
-#endif
-
-  virtual void HitTest(nsDisplayListBuilder* aBuilder, nsRect aRect,
-                       HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
-    nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
-    static_cast<nsBoxFrame*>(mFrame)->
-      DisplayDebugInfoFor(this, rectCenter - ToReferenceFrame());
-    aOutFrames->AppendElement(this);
-  }
-  virtual void Paint(nsDisplayListBuilder* aBuilder
-                     gfxContext* aCtx);
-  NS_DISPLAY_DECL_NAME("XULDebug", TYPE_XUL_DEBUG)
-};
-
-void
-nsDisplayXULDebug::Paint(nsDisplayListBuilder* aBuilder,
-                         gfxContext* aCtx)
-{
-  static_cast<nsBoxFrame*>(mFrame)->
-    PaintXULDebugOverlay(*aCtx->GetDrawTarget(), ToReferenceFrame());
-}
-
-static void
-PaintXULDebugBackground(nsIFrame* aFrame, DrawTarget* aDrawTarget,
-                        const nsRect& aDirtyRect, nsPoint aPt)
-{
-  static_cast<nsBoxFrame*>(aFrame)->PaintXULDebugBackground(aDrawTarget, aPt);
-}
-#endif
-
 void
 nsBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                              const nsDisplayListSet& aLists)
 {
   bool forceLayer = false;
 
   if (GetContent()->IsXULElement()) {
     // forcelayer is only supported on XUL elements with box layout
@@ -1342,26 +1164,16 @@ nsBoxFrame::BuildDisplayList(nsDisplayLi
     }
   }
 
   nsDisplayListCollection tempLists(aBuilder);
   const nsDisplayListSet& destination = forceLayer ? tempLists : aLists;
 
   DisplayBorderBackgroundOutline(aBuilder, destination);
 
-#ifdef DEBUG_LAYOUT
-  if (mState & NS_STATE_CURRENTLY_IN_DEBUG) {
-    destination.BorderBackground()->AppendToTop(
-      MakeDisplayItem<nsDisplayGeneric>(aBuilder, this, PaintXULDebugBackground,
-                       "XULDebugBackground"));
-    destination.Outlines()->AppendToTop(
-      MakeDisplayItem<nsDisplayXULDebug>(aBuilder, this));
-  }
-#endif
-
   Maybe<nsDisplayListBuilder::AutoContainerASRTracker> contASRTracker;
   if (forceLayer) {
     contASRTracker.emplace(aBuilder);
   }
 
   BuildDisplayListForChildren(aBuilder, destination);
 
   // see if we have to draw a selection frame around this container
@@ -1402,486 +1214,24 @@ nsBoxFrame::BuildDisplayListForChildren(
   nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
   // The children should be in the right order
   while (kid) {
     BuildDisplayListForChild(aBuilder, kid, set);
     kid = kid->GetNextSibling();
   }
 }
 
-// REVIEW: PaintChildren did a few things none of which are a big deal
-// anymore:
-// * Paint some debugging rects for this frame.
-// This is done by nsDisplayXULDebugBackground, which goes in the
-// BorderBackground() layer so it isn't clipped by OVERFLOW_CLIP.
-// * Apply OVERFLOW_CLIP to the children.
-// This is now in nsFrame::BuildDisplayListForStackingContext/Child.
-// * Actually paint the children.
-// Moved to BuildDisplayList.
-// * Paint per-kid debug information.
-// This is done by nsDisplayXULDebug, which is in the Outlines()
-// layer so it goes on top. This means it is not clipped by OVERFLOW_CLIP,
-// whereas it did used to respect OVERFLOW_CLIP, but too bad.
-#ifdef DEBUG_LAYOUT
-void
-nsBoxFrame::PaintXULDebugBackground(DrawTarget* aDrawTarget, nsPoint aPt)
-{
-  nsMargin border;
-  GetXULBorder(border);
-
-  nsMargin debugBorder;
-  nsMargin debugMargin;
-  nsMargin debugPadding;
-
-  bool isHorizontal = IsXULHorizontal();
-
-  GetDebugBorder(debugBorder);
-  PixelMarginToTwips(debugBorder);
-
-  GetDebugMargin(debugMargin);
-  PixelMarginToTwips(debugMargin);
-
-  GetDebugPadding(debugPadding);
-  PixelMarginToTwips(debugPadding);
-
-  nsRect inner(mRect);
-  inner.MoveTo(aPt);
-  inner.Deflate(debugMargin);
-  inner.Deflate(border);
-  //nsRect borderRect(inner);
-
-  int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
-
-  ColorPattern color(ToDeviceColor(isHorizontal ? Color(0.f, 0.f, 1.f, 1.f) :
-                                                  Color(1.f, 0.f, 0.f, 1.f)));
-
-  //left
-  nsRect r(inner);
-  r.width = debugBorder.left;
-  aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
-
-  // top
-  r = inner;
-  r.height = debugBorder.top;
-  aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
-
-  //right
-  r = inner;
-  r.x = r.x + r.width - debugBorder.right;
-  r.width = debugBorder.right;
-  aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
-
-  //bottom
-  r = inner;
-  r.y = r.y + r.height - debugBorder.bottom;
-  r.height = debugBorder.bottom;
-  aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), color);
-
-  // If we have dirty children or we are dirty place a green border around us.
-  if (NS_SUBTREE_DIRTY(this)) {
-    nsRect dirty(inner);
-    ColorPattern green(ToDeviceColor(Color(0.f, 1.f, 0.f, 1.f)));
-    aDrawTarget->StrokeRect(NSRectToRect(dirty, appUnitsPerDevPixel), green);
-  }
-}
-
-void
-nsBoxFrame::PaintXULDebugOverlay(DrawTarget& aDrawTarget, nsPoint aPt)
-{
-  nsMargin border;
-  GetXULBorder(border);
-
-  nsMargin debugMargin;
-  GetDebugMargin(debugMargin);
-  PixelMarginToTwips(debugMargin);
-
-  nsRect inner(mRect);
-  inner.MoveTo(aPt);
-  inner.Deflate(debugMargin);
-  inner.Deflate(border);
-
-  nscoord onePixel = GetPresContext()->IntScaledPixelsToTwips(1);
-
-  kid = nsBox::GetChildXULBox(this);
-  while (nullptr != kid) {
-    bool isHorizontal = IsXULHorizontal();
-
-    nscoord x, y, borderSize, spacerSize;
-
-    nsRect cr(kid->mRect);
-    nsMargin margin;
-    kid->GetXULMargin(margin);
-    cr.Inflate(margin);
-
-    if (isHorizontal)
-    {
-        cr.y = inner.y;
-        x = cr.x;
-        y = cr.y + onePixel;
-        spacerSize = debugBorder.top - onePixel*4;
-    } else {
-        cr.x = inner.x;
-        x = cr.y;
-        y = cr.x + onePixel;
-        spacerSize = debugBorder.left - onePixel*4;
-    }
-
-    nscoord flex = kid->GetXULFlex();
-
-    if (!kid->IsXULCollapsed()) {
-      if (isHorizontal)
-          borderSize = cr.width;
-      else
-          borderSize = cr.height;
-
-      DrawSpacer(GetPresContext(), aDrawTarget, isHorizontal, flex, x, y, borderSize, spacerSize);
-    }
-
-    kid = GetNextXULBox(kid);
-  }
-}
-#endif
-
-#ifdef DEBUG_LAYOUT
-void
-nsBoxFrame::GetBoxName(nsAutoString& aName)
-{
-   GetFrameName(aName);
-}
-#endif
-
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsBoxFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Box"), aResult);
 }
 #endif
 
-#ifdef DEBUG_LAYOUT
-nsresult
-nsBoxFrame::GetXULDebug(bool& aDebug)
-{
-  aDebug = (mState & NS_STATE_CURRENTLY_IN_DEBUG);
-  return NS_OK;
-}
-#endif
-
-// REVIEW: nsBoxFrame::GetFrameForPoint is a problem because of 'mousethrough'
-// attribute support. Here's how it works:
-// * For each child frame F, we determine the target frame T(F) by recursively
-// invoking GetFrameForPoint on the child
-// * Let F' be the last child frame such that T(F') doesn't have mousethrough.
-// If F' exists, return T(F')
-// * Otherwise let F'' be the first child frame such that T(F'') is non-null.
-// If F'' exists, return T(F'')
-// * Otherwise return this frame, if this frame contains the point
-// * Otherwise return null
-// It's not clear how this should work for more complex z-ordering situations.
-// The basic principle seems to be that if a frame F has a descendant
-// 'mousethrough' frame that includes the target position, then F
-// will not receive events (unless it overrides GetFrameForPoint).
-// A 'mousethrough' frame will only receive an event if, after applying that rule,
-// all eligible frames are 'mousethrough'; the bottom-most inner-most 'mousethrough'
-// frame is then chosen (the first eligible frame reached in a
-// traversal of the frame tree --- pre/post is irrelevant since ancestors
-// of the mousethrough frames can't be eligible).
-// IMHO this is very bogus and adds a great deal of complexity for something
-// that is very rarely used. So I'm redefining 'mousethrough' to the following:
-// a frame with mousethrough is transparent to mouse events. This is compatible
-// with the way 'mousethrough' is used in Seamonkey's navigator.xul and
-// Firefox's browser.xul. The only other place it's used is in the 'expander'
-// XBL binding, which in our tree is only used by Thunderbird SMIME Advanced
-// Preferences, and I can't figure out what that does, so I'll have to test it.
-// If it's broken I'll probably just change the binding to use it more sensibly.
-// This new behaviour is implemented in nsDisplayList::HitTest.
-// REVIEW: This debug-box stuff is annoying. I'm just going to put debug boxes
-// in the outline layer and avoid GetDebugBoxAt.
-
-// REVIEW: GetCursor had debug-only event dumping code. I have replaced it
-// with instrumentation in nsDisplayXULDebug.
-
-#ifdef DEBUG_LAYOUT
-void
-nsBoxFrame::DrawLine(DrawTarget& aDrawTarget, bool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2)
-{
-    nsPoint p1(x1, y1);
-    nsPoint p2(x2, y2);
-    if (!aHorizontal) {
-      Swap(p1.x, p1.y);
-      Swap(p2.x, p2.y);
-    }
-    ColorPattern white(ToDeviceColor(Color(1.f, 1.f, 1.f, 1.f)));
-    StrokeLineWithSnapping(p1, p2, PresContext()->AppUnitsPerDevPixel(),
-                           aDrawTarget, color);
-}
-
-void
-nsBoxFrame::FillRect(DrawTarget& aDrawTarget, bool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height)
-{
-    Rect rect = NSRectToSnappedRect(aHorizontal ? nsRect(x, y, width, height) :
-                                                  nsRect(y, x, height, width),
-                                    PresContext()->AppUnitsPerDevPixel(),
-                                    aDrawTarget);
-    ColorPattern white(ToDeviceColor(Color(1.f, 1.f, 1.f, 1.f)));
-    aDrawTarget.FillRect(rect, white);
-}
-
-void
-nsBoxFrame::DrawSpacer(nsPresContext* aPresContext, DrawTarget& aDrawTarget,
-                       bool aHorizontal, int32_t flex, nscoord x, nscoord y,
-                       nscoord size, nscoord spacerSize)
-{
-         nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
-
-     // if we do draw the coils
-        int distance = 0;
-        int center = 0;
-        int offset = 0;
-        int coilSize = COIL_SIZE*onePixel;
-        int halfSpacer = spacerSize/2;
-
-        distance = size;
-        center = y + halfSpacer;
-        offset = x;
-
-        int coils = distance/coilSize;
-
-        int halfCoilSize = coilSize/2;
-
-        if (flex == 0) {
-            DrawLine(aDrawTarget, aHorizontal, x,y + spacerSize/2, x + size, y + spacerSize/2);
-        } else {
-            for (int i=0; i < coils; i++)
-            {
-                   DrawLine(aDrawTarget, aHorizontal, offset, center+halfSpacer, offset+halfCoilSize, center-halfSpacer);
-                   DrawLine(aDrawTarget, aHorizontal, offset+halfCoilSize, center-halfSpacer, offset+coilSize, center+halfSpacer);
-
-                   offset += coilSize;
-            }
-        }
-
-        FillRect(aDrawTarget, aHorizontal, x + size - spacerSize/2, y, spacerSize/2, spacerSize);
-        FillRect(aDrawTarget, aHorizontal, x, y, spacerSize/2, spacerSize);
-}
-
-void
-nsBoxFrame::GetDebugBorder(nsMargin& aInset)
-{
-    aInset.SizeTo(2,2,2,2);
-
-    if (IsXULHorizontal())
-       aInset.top = 10;
-    else
-       aInset.left = 10;
-}
-
-void
-nsBoxFrame::GetDebugMargin(nsMargin& aInset)
-{
-    aInset.SizeTo(2,2,2,2);
-}
-
-void
-nsBoxFrame::GetDebugPadding(nsMargin& aPadding)
-{
-    aPadding.SizeTo(2,2,2,2);
-}
-
-void
-nsBoxFrame::PixelMarginToTwips(nsMargin& aMarginPixels)
-{
-  nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
-  aMarginPixels.left   *= onePixel;
-  aMarginPixels.right  *= onePixel;
-  aMarginPixels.top    *= onePixel;
-  aMarginPixels.bottom *= onePixel;
-}
-
-void
-nsBoxFrame::GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* ch)
-{
-    float p2t = aPresContext->ScaledPixelsToTwips();
-
-    char width[100];
-    char height[100];
-
-    if (a.width == NS_INTRINSICSIZE)
-        sprintf(width,"%s","INF");
-    else
-        sprintf(width,"%d", nscoord(a.width/*/p2t*/));
-
-    if (a.height == NS_INTRINSICSIZE)
-        sprintf(height,"%s","INF");
-    else
-        sprintf(height,"%d", nscoord(a.height/*/p2t*/));
-
-
-    sprintf(ch, "(%s%s, %s%s)", width, (b.width != NS_INTRINSICSIZE ? "[SET]" : ""),
-                    height, (b.height != NS_INTRINSICSIZE ? "[SET]" : ""));
-
-}
-
-void
-nsBoxFrame::GetValue(nsPresContext* aPresContext, int32_t a, int32_t b, char* ch)
-{
-    if (a == NS_INTRINSICSIZE)
-      sprintf(ch, "%d[SET]", b);
-    else
-      sprintf(ch, "%d", a);
-}
-
-nsresult
-nsBoxFrame::DisplayDebugInfoFor(nsIFrame*  aBox,
-                                nsPoint& aPoint)
-{
-    nsBoxLayoutState state(GetPresContext());
-
-    nscoord x = aPoint.x;
-    nscoord y = aPoint.y;
-
-    // get the area inside our border but not our debug margins.
-    nsRect insideBorder(aBox->mRect);
-    insideBorder.MoveTo(0,0):
-    nsMargin border(0,0,0,0);
-    aBox->GetXULBorderAndPadding(border);
-    insideBorder.Deflate(border);
-
-    bool isHorizontal = IsXULHorizontal();
-
-    if (!insideBorder.Contains(nsPoint(x,y)))
-        return NS_ERROR_FAILURE;
-
-    //printf("%%%%%% inside box %%%%%%%\n");
-
-    int count = 0;
-    nsIFrame* child = nsBox::GetChildXULBox(aBox);
-
-    nsMargin m;
-    nsMargin m2;
-    GetDebugBorder(m);
-    PixelMarginToTwips(m);
-
-    GetDebugMargin(m2);
-    PixelMarginToTwips(m2);
-
-    m += m2;
-
-    if ((isHorizontal && y < insideBorder.y + m.top) ||
-        (!isHorizontal && x < insideBorder.x + m.left)) {
-        //printf("**** inside debug border *******\n");
-        while (child)
-        {
-            const nsRect& r = child->mRect;
-
-            // if we are not in the child. But in the spacer above the child.
-            if ((isHorizontal && x >= r.x && x < r.x + r.width) ||
-                (!isHorizontal && y >= r.y && y < r.y + r.height)) {
-                aCursor = NS_STYLE_CURSOR_POINTER;
-                   // found it but we already showed it.
-                    if (mDebugChild == child)
-                        return NS_OK;
-
-                    if (aBox->GetContent()) {
-                      printf("---------------\n");
-                      XULDumpBox(stdout);
-                      printf("\n");
-                    }
-
-                    if (child->GetContent()) {
-                        printf("child #%d: ", count);
-                        child->XULDumpBox(stdout);
-                        printf("\n");
-                    }
-
-                    mDebugChild = child;
-
-                    nsSize prefSizeCSS(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
-                    nsSize minSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
-                    nsSize maxSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
-                    nscoord flexCSS = NS_INTRINSICSIZE;
-
-                    bool widthSet, heightSet;
-                    nsIFrame::AddXULPrefSize(child, prefSizeCSS, widthSet, heightSet);
-                    nsIFrame::AddXULMinSize (state, child, minSizeCSS, widthSet, heightSet);
-                    nsIFrame::AddXULMaxSize (child, maxSizeCSS, widthSet, heightSet);
-                    nsIFrame::AddXULFlex    (child, flexCSS);
-
-                    nsSize prefSize = child->GetXULPrefSize(state);
-                    nsSize minSize = child->GetXULMinSize(state);
-                    nsSize maxSize = child->GetXULMaxSize(state);
-                    nscoord flexSize = child->GetXULFlex();
-                    nscoord ascentSize = child->GetXULBoxAscent(state);
-
-                    char min[100];
-                    char pref[100];
-                    char max[100];
-                    char calc[100];
-                    char flex[100];
-                    char ascent[100];
-
-                    nsSize actualSize;
-                    GetFrameSizeWithMargin(child, actualSize);
-                    nsSize actualSizeCSS (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
-
-                    GetValue(aPresContext, minSize,  minSizeCSS, min);
-                    GetValue(aPresContext, prefSize, prefSizeCSS, pref);
-                    GetValue(aPresContext, maxSize,  maxSizeCSS, max);
-                    GetValue(aPresContext, actualSize, actualSizeCSS, calc);
-                    GetValue(aPresContext, flexSize,  flexCSS, flex);
-                    GetValue(aPresContext, ascentSize,  NS_INTRINSICSIZE, ascent);
-
-
-                    printf("min%s, pref%s, max%s, actual%s, flex=%s, ascent=%s\n\n",
-                        min,
-                        pref,
-                        max,
-                        calc,
-                        flex,
-                        ascent
-                    );
-
-                    return NS_OK;
-            }
-
-          child = GetNextXULBox(child);
-          count++;
-        }
-    } else {
-    }
-
-    mDebugChild = nullptr;
-
-    return NS_OK;
-}
-
-void
-nsBoxFrame::SetDebugOnChildList(nsBoxLayoutState& aState, nsIFrame* aChild, bool aDebug)
-{
-    nsIFrame* child = nsBox::GetChildXULBox(this);
-     while (child)
-     {
-        child->SetXULDebug(aState, aDebug);
-        child = GetNextXULBox(child);
-     }
-}
-
-nsresult
-nsBoxFrame::GetFrameSizeWithMargin(nsIFrame* aBox, nsSize& aSize)
-{
-  nsRect rect(aBox->GetRect());
-  nsMargin margin(0,0,0,0);
-  aBox->GetXULMargin(margin);
-  rect.Inflate(margin);
-  aSize.width = rect.width;
-  aSize.height = rect.height;
-  return NS_OK;
-}
-#endif
-
 // If you make changes to this function, check its counterparts
 // in nsTextBoxFrame and nsXULLabelFrame
 void
 nsBoxFrame::RegUnregAccessKey(bool aDoReg)
 {
   MOZ_ASSERT(mContent);
 
   // only support accesskeys for the following elements
--- a/layout/xul/nsBoxFrame.h
+++ b/layout/xul/nsBoxFrame.h
@@ -61,20 +61,16 @@ public:
 
   virtual nsresult XULRelayoutChildAtOrdinal(nsIFrame* aChild) override;
 
   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
   virtual nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) override;
   virtual nscoord GetXULFlex() override;
   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
-#ifdef DEBUG_LAYOUT
-  virtual nsresult SetXULDebug(nsBoxLayoutState& aBoxLayoutState, bool aDebug) override;
-  virtual nsresult GetXULDebug(bool& aDebug) override;
-#endif
   virtual Valignment GetXULVAlign() const override { return mValign; }
   virtual Halignment GetXULHAlign() const override { return mHalign; }
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
 
   virtual bool ComputesOwnOverflowArea() override { return false; }
 
   // ----- child and sibling operations ---
 
@@ -141,22 +137,16 @@ public:
   // virtual so nsStackFrame, nsButtonBoxFrame, nsSliderFrame and nsMenuFrame
   // can override it
   virtual void BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
                                            const nsDisplayListSet& aLists);
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
-#ifdef DEBUG_LAYOUT
-    virtual void SetDebugOnChildList(nsBoxLayoutState& aState, nsIFrame* aChild, bool aDebug);
-    nsresult DisplayDebugInfoFor(nsIFrame*  aBox,
-                                 nsPoint& aPoint);
-#endif
-
   static nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIFrame* aBox, const nsRect& aRect);
 
   /**
    * Utility method to redirect events on descendants to this frame.
    * Supports 'allowevents' attribute on descendant elements to allow those
    * elements and their descendants to receive events.
    */
   void WrapListsInRedirector(nsDisplayListBuilder*   aBuilder,
@@ -177,24 +167,16 @@ public:
 private:
   explicit nsBoxFrame(ComputedStyle* aStyle)
     : nsBoxFrame(aStyle, kClassID, false, nullptr) {}
 protected:
   nsBoxFrame(ComputedStyle* aStyle, ClassID aID, bool aIsRoot = false,
              nsBoxLayout* aLayoutManager = nullptr);
   virtual ~nsBoxFrame();
 
-#ifdef DEBUG_LAYOUT
-    virtual void GetBoxName(nsAutoString& aName) override;
-    void PaintXULDebugBackground(gfxContext& aRenderingContext,
-                                 nsPoint aPt);
-    void PaintXULDebugOverlay(DrawTarget& aRenderingContext,
-                              nsPoint aPt);
-#endif
-
     virtual bool GetInitialEqualSize(bool& aEqualSize);
     virtual void GetInitialOrientation(bool& aIsHorizontal);
     virtual void GetInitialDirection(bool& aIsNormal);
     virtual bool GetInitialHAlignment(Halignment& aHalign);
     virtual bool GetInitialVAlignment(Valignment& aValign);
     virtual bool GetInitialAutoStretch(bool& aStretch);
 
     virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
@@ -217,44 +199,20 @@ protected:
 
 protected:
     void RegUnregAccessKey(bool aDoReg);
 
   void CheckBoxOrder();
 
 private:
 
-#ifdef DEBUG_LAYOUT
-    nsresult SetXULDebug(nsPresContext* aPresContext, bool aDebug);
-    bool GetInitialDebug(bool& aDebug);
-    void GetDebugPref();
-
-    void GetDebugBorder(nsMargin& aInset);
-    void GetDebugPadding(nsMargin& aInset);
-    void GetDebugMargin(nsMargin& aInset);
-
-    nsresult GetFrameSizeWithMargin(nsIFrame* aBox, nsSize& aSize);
-
-    void PixelMarginToTwips(nsMargin& aMarginPixels);
-
-    void GetValue(nsPresContext* aPresContext, const nsSize& a, const nsSize& b, char* value);
-    void GetValue(nsPresContext* aPresContext, int32_t a, int32_t b, char* value);
-    void DrawSpacer(nsPresContext* aPresContext, DrawTarget& aDrawTarget, bool aHorizontal, int32_t flex, nscoord x, nscoord y, nscoord size, nscoord spacerSize);
-    void DrawLine(DrawTarget& aDrawTarget,  bool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2);
-    void FillRect(DrawTarget& aDrawTarget,  bool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height);
-#endif
     virtual void UpdateMouseThrough();
 
     void CacheAttributes();
 
     // instance variables.
     Halignment mHalign;
     Valignment mValign;
 
-#ifdef DEBUG_LAYOUT
-    static bool gDebug;
-    static nsIFrame* mDebugChild;
-#endif
-
 }; // class nsBoxFrame
 
 #endif
 
--- a/layout/xul/nsLeafBoxFrame.cpp
+++ b/layout/xul/nsLeafBoxFrame.cpp
@@ -36,25 +36,16 @@ using namespace mozilla;
 nsIFrame*
 NS_NewLeafBoxFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle)
 {
   return new (aPresShell) nsLeafBoxFrame(aStyle);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsLeafBoxFrame)
 
-#ifdef DEBUG_LAYOUT
-void
-nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
-{
-   GetFrameName(aName);
-}
-#endif
-
-
 /**
  * Initialize us. This is a good time to get the alignment of the box
  */
 void
 nsLeafBoxFrame::Init(nsIContent*       aContent,
                      nsContainerFrame* aParent,
                      nsIFrame*         aPrevInFlow)
 {
--- a/layout/xul/nsLeafBoxFrame.h
+++ b/layout/xul/nsLeafBoxFrame.h
@@ -71,20 +71,16 @@ public:
                                     int32_t aModType) override;
 
   virtual bool ComputesOwnOverflowArea() override { return false; }
 
 protected:
 
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aState) override;
 
-#ifdef DEBUG_LAYOUT
-  virtual void GetBoxName(nsAutoString& aName) override;
-#endif
-
   virtual nscoord GetIntrinsicISize() override;
 
   explicit nsLeafBoxFrame(ComputedStyle* aStyle, ClassID aID = kClassID)
     : nsLeafFrame(aStyle, aID)
   {}
 
 private:
 
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -764,53 +764,16 @@ nsMenuFrame::DoXULLayout(nsBoxLayoutStat
   if (popupFrame) {
     bool sizeToPopup = IsSizedToPopup(mContent, false);
     popupFrame->LayoutPopup(aState, this, GetAnchor()->GetPrimaryFrame(), sizeToPopup);
   }
 
   return rv;
 }
 
-#ifdef DEBUG_LAYOUT
-nsresult
-nsMenuFrame::SetXULDebug(nsBoxLayoutState& aState, bool aDebug)
-{
-  // see if our state matches the given debug state
-  bool debugSet = mState & NS_STATE_CURRENTLY_IN_DEBUG;
-  bool debugChanged = (!aDebug && debugSet) || (aDebug && !debugSet);
-
-  // if it doesn't then tell each child below us the new debug state
-  if (debugChanged)
-  {
-      nsBoxFrame::SetXULDebug(aState, aDebug);
-      nsMenuPopupFrame* popupFrame = GetPopup();
-      if (popupFrame)
-        SetXULDebug(aState, popupFrame, aDebug);
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsMenuFrame::SetXULDebug(nsBoxLayoutState& aState, nsIFrame* aList, bool aDebug)
-{
-      if (!aList)
-          return NS_OK;
-
-      while (aList) {
-        if (aList->IsXULBoxFrame())
-          aList->SetXULDebug(aState, aDebug);
-
-        aList = aList->GetNextSibling();
-      }
-
-      return NS_OK;
-}
-#endif
-
 //
 // Enter
 //
 // Called when the user hits the <Enter>/<Return> keys or presses the
 // shortcut key. If this is a leaf item, the item's action will be executed.
 // In either case, do nothing if the item is disabled.
 //
 nsMenuFrame*
@@ -1329,21 +1292,16 @@ nsMenuFrame::RemoveFrame(ChildListID    
 void
 nsMenuFrame::InsertFrames(ChildListID     aListID,
                           nsIFrame*       aPrevFrame,
                           nsFrameList&    aFrameList)
 {
   if (!HasPopup() && (aListID == kPrincipalList || aListID == kPopupList)) {
     SetPopupFrame(aFrameList);
     if (HasPopup()) {
-#ifdef DEBUG_LAYOUT
-      nsBoxLayoutState state(PresContext());
-      SetXULDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG);
-#endif
-
       PresShell()->
         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                          NS_FRAME_HAS_DIRTY_CHILDREN);
     }
   }
 
   if (aFrameList.IsEmpty())
     return;
@@ -1357,21 +1315,16 @@ nsMenuFrame::InsertFrames(ChildListID   
 
 void
 nsMenuFrame::AppendFrames(ChildListID     aListID,
                           nsFrameList&    aFrameList)
 {
   if (!HasPopup() && (aListID == kPrincipalList || aListID == kPopupList)) {
     SetPopupFrame(aFrameList);
     if (HasPopup()) {
-
-#ifdef DEBUG_LAYOUT
-      nsBoxLayoutState state(PresContext());
-      SetXULDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG);
-#endif
       PresShell()->
         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                          NS_FRAME_HAS_DIRTY_CHILDREN);
     }
   }
 
   if (aFrameList.IsEmpty())
     return;
--- a/layout/xul/nsMenuFrame.h
+++ b/layout/xul/nsMenuFrame.h
@@ -94,20 +94,16 @@ public:
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
-#ifdef DEBUG_LAYOUT
-  virtual nsresult SetXULDebug(nsBoxLayoutState& aState, bool aDebug) override;
-#endif
-
   // The following methods are all overridden so that the menupopup
   // can be stored in a separate list, so that it doesn't impact reflow of the
   // actual menu item at all.
   virtual const nsFrameList& GetChildList(ChildListID aList) const override;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
   virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
 
   // Overridden to prevent events from going to children of the menu.
@@ -269,19 +265,16 @@ protected:
   bool ShouldBlink();
   void StartBlinking(mozilla::WidgetGUIEvent* aEvent, bool aFlipChecked);
   void StopBlinking();
   void CreateMenuCommandEvent(mozilla::WidgetGUIEvent* aEvent,
                               bool aFlipChecked);
   void PassMenuCommandEventToPopupManager();
 
 protected:
-#ifdef DEBUG_LAYOUT
-  nsresult SetXULDebug(nsBoxLayoutState& aState, nsIFrame* aList, bool aDebug);
-#endif
   nsresult Notify(nsITimer* aTimer);
 
   bool mIsMenu; // Whether or not we can even have children or not.
   bool mChecked;              // are we checked?
   bool mIgnoreAccelTextChange; // temporarily set while determining the accelerator key
   bool mReflowCallbackPosted;
   nsMenuType mType;
 
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -485,25 +485,16 @@ nsSliderFrame::DoXULLayout(nsBoxLayoutSt
 
   if (!thumbBox) {
     SyncLayout(aState);
     return NS_OK;
   }
 
   EnsureOrient();
 
-#ifdef DEBUG_LAYOUT
-  if (mState & NS_STATE_DEBUG_WAS_SET) {
-      if (mState & NS_STATE_SET_TO_DEBUG)
-          SetXULDebug(aState, true);
-      else
-          SetXULDebug(aState, false);
-  }
-#endif
-
   // get the content area inside our borders
   nsRect clientRect;
   GetXULClientRect(clientRect);
 
   // get the scrollbar
   nsIFrame* scrollbarBox = GetScrollbar();
   nsCOMPtr<nsIContent> scrollbar = GetContentOfBox(scrollbarBox);
 
--- a/layout/xul/nsSprocketLayout.cpp
+++ b/layout/xul/nsSprocketLayout.cpp
@@ -20,23 +20,16 @@
 #include "nsContainerFrame.h"
 #include "nsBoxFrame.h"
 #include "StackArena.h"
 #include "mozilla/Likely.h"
 #include <algorithm>
 
 nsBoxLayout* nsSprocketLayout::gInstance = nullptr;
 
-//#define DEBUG_GROW
-
-#define DEBUG_SPRING_SIZE 8
-#define DEBUG_BORDER_SIZE 2
-#define COIL_SIZE 8
-
-
 nsresult
 NS_NewSprocketLayout(nsCOMPtr<nsBoxLayout>& aNewLayout)
 {
   if (!nsSprocketLayout::gInstance) {
     nsSprocketLayout::gInstance = new nsSprocketLayout();
     NS_IF_ADDREF(nsSprocketLayout::gInstance);
   }
   // we have not instance variables so just return our static one.
@@ -485,17 +478,16 @@ nsSprocketLayout::XULLayout(nsIFrame* aB
         child->XULLayout(aState);
 
       // If the child was a block or inline (e.g., HTML) it may have changed its rect *during* layout.
       // We have to check for this.
       nsRect newChildRect(child->GetRect());
 
       if (!newChildRect.IsEqualInterior(childRect)) {
 #ifdef DEBUG_GROW
-        child->XULDumpBox(stdout);
         printf(" GREW from (%d,%d) -> (%d,%d)\n", childRect.width, childRect.height, newChildRect.width, newChildRect.height);
 #endif
         newChildRect.Inflate(margin);
         childRect.Inflate(margin);
 
         // The child changed size during layout.  The ChildResized method handles this
         // scenario.
         ChildResized(aBox,
@@ -650,19 +642,16 @@ nsSprocketLayout::PopulateBoxSizes(nsIFr
   // used for the equal size flag
   nscoord biggestPrefWidth = 0;
   nscoord biggestMinWidth = 0;
   nscoord smallestMaxWidth = NS_INTRINSICSIZE;
 
   nsFrameState frameState = nsFrameState(0);
   GetFrameState(aBox, frameState);
 
-  //if (frameState & NS_STATE_CURRENTLY_IN_DEBUG)
-  //   printf("In debug\n");
-
   aMinSize = 0;
   aMaxSize = NS_INTRINSICSIZE;
 
   bool isHorizontal;
 
   if (IsXULHorizontal(aBox))
      isHorizontal = true;
   else
--- a/mozglue/misc/Mutex_posix.cpp
+++ b/mozglue/misc/Mutex_posix.cpp
@@ -1,34 +1,73 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Assertions.h"
 
+#include <algorithm>
 #include <errno.h>
 #include <pthread.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #include "mozilla/PlatformMutex.h"
 #include "MutexPlatformData_posix.h"
 
+#define REPORT_PTHREADS_ERROR(result, msg)      \
+  {                                             \
+    errno = result;                             \
+    perror(msg);                                \
+    MOZ_CRASH(msg);                             \
+  }
+
 #define TRY_CALL_PTHREADS(call, msg)            \
   {                                             \
     int result = (call);                        \
     if (result != 0) {                          \
-      errno = result;                           \
-      perror(msg);                              \
-      MOZ_CRASH(msg);                           \
+      REPORT_PTHREADS_ERROR(result, msg);       \
     }                                           \
   }
 
+#ifdef XP_DARWIN
+
+// CPU count. Read concurrently from multiple threads. Written once during the
+// first mutex initialization; re-initialization is safe hence relaxed ordering
+// is OK.
+static mozilla::Atomic<uint32_t, mozilla::MemoryOrdering::Relaxed> sCPUCount(0);
+
+static void
+EnsureCPUCount()
+{
+  if (sCPUCount) {
+    return;
+  }
+
+  // _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are common, but not
+  // standard.
+#if defined(_SC_NPROCESSORS_CONF)
+  long n = sysconf(_SC_NPROCESSORS_CONF);
+  sCPUCount = (n > 0) ? uint32_t(n) : 1;
+#elif defined(_SC_NPROCESSORS_ONLN)
+  long n = sysconf(_SC_NPROCESSORS_ONLN);
+  sCPUCount = (n > 0) ? uint32_t(n) : 1;
+#else
+  sCPUCount = 1;
+#endif
+}
+
+#endif // XP_DARWIN
+
 mozilla::detail::MutexImpl::MutexImpl()
+#ifdef XP_DARWIN
+  : averageSpins(0)
+#endif
 {
   pthread_mutexattr_t* attrp = nullptr;
 
   // Linux with glibc and FreeBSD support adaptive mutexes that spin
   // for a short number of tries before sleeping.  NSPR's locks did
   // this, too, and it seems like a reasonable thing to do.
 #if (defined(__linux__) && defined(__GLIBC__)) || defined(__FreeBSD__)
 #define ADAPTIVE_MUTEX_SUPPORTED
@@ -55,29 +94,90 @@ mozilla::detail::MutexImpl::MutexImpl()
 
   TRY_CALL_PTHREADS(pthread_mutex_init(&platformData()->ptMutex, attrp),
                     "mozilla::detail::MutexImpl::MutexImpl: pthread_mutex_init failed");
 
 #if defined(ATTR_REQUIRED)
   TRY_CALL_PTHREADS(pthread_mutexattr_destroy(&attr),
                     "mozilla::detail::MutexImpl::MutexImpl: pthread_mutexattr_destroy failed");
 #endif
+
+#ifdef XP_DARWIN
+  EnsureCPUCount();
+#endif
 }
 
 mozilla::detail::MutexImpl::~MutexImpl()
 {
   TRY_CALL_PTHREADS(pthread_mutex_destroy(&platformData()->ptMutex),
                     "mozilla::detail::MutexImpl::~MutexImpl: pthread_mutex_destroy failed");
 }
 
+inline void
+mozilla::detail::MutexImpl::mutexLock()
+{
+  TRY_CALL_PTHREADS(pthread_mutex_lock(&platformData()->ptMutex),
+                    "mozilla::detail::MutexImpl::mutexLock: pthread_mutex_lock failed");
+}
+
+#ifdef XP_DARWIN
+inline bool
+mozilla::detail::MutexImpl::mutexTryLock()
+{
+  int result = pthread_mutex_trylock(&platformData()->ptMutex);
+  if (result == 0) {
+    return true;
+  }
+
+  if (result == EBUSY) {
+    return false;
+  }
+
+  REPORT_PTHREADS_ERROR(result,
+                        "mozilla::detail::MutexImpl::mutexTryLock: pthread_mutex_trylock failed");
+}
+#endif
+
 void
 mozilla::detail::MutexImpl::lock()
 {
-  TRY_CALL_PTHREADS(pthread_mutex_lock(&platformData()->ptMutex),
-                    "mozilla::detail::MutexImpl::lock: pthread_mutex_lock failed");
+#ifndef XP_DARWIN
+  mutexLock();
+#else
+  // Mutex performance on OSX can be very poor if there's a lot of contention as
+  // this causes excessive context switching. On Linux/FreeBSD we use the
+  // adaptive mutex type (PTHREAD_MUTEX_ADAPTIVE_NP) to address this, but this
+  // isn't available on OSX. The code below is a reimplementation of this
+  // feature.
+
+  MOZ_ASSERT(sCPUCount);
+  if (sCPUCount == 1) {
+    mutexLock();
+    return;
+  }
+
+  if (!mutexTryLock()) {
+    const int32_t SpinLimit = 100;
+
+    int32_t count = 0;
+    int32_t maxSpins = std::min(SpinLimit, 2 * averageSpins + 10);
+    do {
+      if (count >= maxSpins) {
+        mutexLock();
+        break;
+      }
+      asm("pause"); // Hint to the processor that we're spinning.
+      count++;
+    } while (!mutexTryLock());
+
+    // Update moving average.
+    averageSpins += (count - averageSpins) / 8;
+    MOZ_ASSERT(averageSpins >= 0 && averageSpins <= SpinLimit);
+  }
+#endif // XP_DARWIN
 }
 
 void
 mozilla::detail::MutexImpl::unlock()
 {
   TRY_CALL_PTHREADS(pthread_mutex_unlock(&platformData()->ptMutex),
                     "mozilla::detail::MutexImpl::unlock: pthread_mutex_unlock failed");
 }
--- a/mozglue/misc/PlatformMutex.h
+++ b/mozglue/misc/PlatformMutex.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_PlatformMutex_h
 #define mozilla_PlatformMutex_h
 
+#include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Move.h"
 
 #if !defined(XP_WIN)
 # include <pthread.h>
 #endif
 
 namespace mozilla {
@@ -37,23 +38,34 @@ protected:
   MFBT_API void unlock();
 
 private:
   MutexImpl(const MutexImpl&) = delete;
   void operator=(const MutexImpl&) = delete;
   MutexImpl(MutexImpl&&) = delete;
   void operator=(MutexImpl&&) = delete;
 
+  void mutexLock();
+#ifdef XP_DARWIN
+  bool mutexTryLock();
+#endif
+
   PlatformData* platformData();
 
 #if !defined(XP_WIN)
   void* platformData_[sizeof(pthread_mutex_t) / sizeof(void*)];
   static_assert(sizeof(pthread_mutex_t) / sizeof(void*) != 0 &&
                 sizeof(pthread_mutex_t) % sizeof(void*) == 0,
                 "pthread_mutex_t must have pointer alignment");
+#ifdef XP_DARWIN
+  // Moving average of the number of spins it takes to acquire the mutex if we
+  // have to wait. May be accessed by multiple threads concurrently. Getting the
+  // latest value is not essential hence relaxed memory ordering is sufficient.
+  mozilla::Atomic<int32_t, mozilla::MemoryOrdering::Relaxed> averageSpins;
+#endif
 #else
   void* platformData_[6];
 #endif
 
   friend class mozilla::detail::ConditionVariableImpl;
 };
 
 } // namespace detail
new file mode 100644
--- /dev/null
+++ b/taskcluster/ci/beetmover-release-source-checksums/kind.yml
@@ -0,0 +1,17 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+loader: taskgraph.loader.single_dep:loader
+
+transforms:
+   - taskgraph.transforms.name_sanity:transforms
+   - taskgraph.transforms.beetmover_source_checksums:transforms
+   - taskgraph.transforms.release_notifications:transforms
+   - taskgraph.transforms.task:transforms
+
+kind-dependencies:
+   - release-source-checksums-signing
+
+job-template:
+   shipping-phase: promote
--- a/taskcluster/ci/config.yml
+++ b/taskcluster/ci/config.yml
@@ -33,18 +33,20 @@ treeherder:
         'X': 'Xpcshell tests'
         'X-e10s': 'Xpcshell tests with e10s'
         'L10n': 'Localised Repacks'
         'L10n-Rpk': 'Localized Repackaged Repacks'
         'BM-L10n': 'Beetmover for locales'
         'BMR-L10n': 'Beetmover repackages for locales'
         'c-Up': 'Balrog submission of complete updates'
         'cs': 'Checksum signing'
+        'css': 'Checksum signing for source'
         'rs': 'Repackage signing'
-        'BMcs': 'Beetmover checksums,'
+        'BMcs': 'Beetmover checksums'
+        'BMcss': 'Beetmover checksums for source'
         'Aries': 'Aries Device Image'
         'Deb7': 'Packages for Debian 7'
         'Deb9': 'Packages for Debian 9'
         'Nexus 5-L': 'Nexus 5-L Device Image'
         'I': 'Docker Image Builds'
         'TL': 'Toolchain builds for Linux 64-bits'
         'TM': 'Toolchain builds for OSX'
         'TMW': 'Toolchain builds for Windows MinGW'
--- a/taskcluster/ci/post-beetmover-checksums-dummy/kind.yml
+++ b/taskcluster/ci/post-beetmover-checksums-dummy/kind.yml
@@ -6,16 +6,17 @@ loader: taskgraph.loader.transform:loade
 
 transforms:
    - taskgraph.transforms.reverse_chunk_deps:transforms
    - taskgraph.transforms.release_notifications:transforms
    - taskgraph.transforms.task:transforms
 
 kind-dependencies:
    - beetmover-checksums
+   - beetmover-release-source-checksums
 
 jobs:
    firefox-promote:
       name: post-beetmover-checksums-dummy
       description: Dummy task to deal with max_dependencies
       run-on-projects: []
       shipping-phase: promote
       shipping-product: firefox
--- a/taskcluster/ci/release-generate-checksums/kind.yml
+++ b/taskcluster/ci/release-generate-checksums/kind.yml
@@ -50,55 +50,55 @@ job-defaults:
       symbol: Rel(GenChcks)
       kind: test
       tier: 1
 
 jobs:
    firefox:
       shipping-product: firefox
       attributes:
-         build_platform: linux64
+         build_platform: firefox-release
          build_type: opt
       run:
          extra-config:
             by-project:
                mozilla-(release|beta):
                   stage_product: "firefox"
                   bucket_name: "net-mozaws-prod-delivery-firefox"
                default:
                   stage_product: "firefox"
                   bucket_name: "net-mozaws-stage-delivery-firefox"
       treeherder:
-         platform: linux64/opt
+         platform: firefox-release/opt
 
    fennec:
       shipping-product: fennec
       attributes:
-         build_platform: android-nightly
+         build_platform: fennec-release
          build_type: opt
       run:
          extra-config:
             by-project:
                mozilla-(release|beta):
                   stage_product: "mobile"
                   bucket_name: "net-mozaws-prod-delivery-archive"
                default:
                   stage_product: "mobile"
                   bucket_name: "net-mozaws-stage-delivery-archive"
       treeherder:
-         platform: Android/opt
+         platform: fennec-release/opt
 
    devedition:
       shipping-product: devedition
       attributes:
-         build_platform: linux64-devedition
+         build_platform: devedition-release
          build_type: opt
       run:
          extra-config:
             by-project:
                mozilla-beta:
                   stage_product: "devedition"
                   bucket_name: "net-mozaws-prod-delivery-archive"
                default:
                   stage_product: "devedition"
                   bucket_name: "net-mozaws-stage-delivery-archive"
       treeherder:
-         platform: linux64-devedition/opt
+         platform: devedition-release/opt
new file mode 100644
--- /dev/null
+++ b/taskcluster/ci/release-source-checksums-signing/kind.yml
@@ -0,0 +1,17 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+loader: taskgraph.loader.single_dep:loader
+
+transforms:
+   - taskgraph.transforms.name_sanity:transforms
+   - taskgraph.transforms.source_checksums_signing:transforms
+   - taskgraph.transforms.release_notifications:transforms
+   - taskgraph.transforms.task:transforms
+
+kind-dependencies:
+   - beetmover-source
+
+job-template:
+   shipping-phase: promote
--- a/taskcluster/ci/release-source-signing/kind.yml
+++ b/taskcluster/ci/release-source-signing/kind.yml
@@ -1,13 +1,13 @@
 # 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/.
 
-loader: taskgraph.loader.build_signing:loader
+loader: taskgraph.loader.single_dep:loader
 
 transforms:
    - taskgraph.transforms.name_sanity:transforms
    - taskgraph.transforms.build_signing:transforms
    - taskgraph.transforms.signing:transforms
    - taskgraph.transforms.release_notifications:transforms
    - taskgraph.transforms.task:transforms
 
--- a/taskcluster/ci/release-source/kind.yml
+++ b/taskcluster/ci/release-source/kind.yml
@@ -1,46 +1,62 @@
 # 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/.
 
 loader: taskgraph.loader.transform:loader
 
 kind-dependencies:
-   - toolchain
+    - toolchain
 
 transforms:
-   - taskgraph.transforms.build:transforms
-   - taskgraph.transforms.build_attrs:transforms
-   - taskgraph.transforms.build_lints:transforms
-   - taskgraph.transforms.use_toolchains:transforms
-   - taskgraph.transforms.release_notifications:transforms
-   - taskgraph.transforms.job:transforms
-   - taskgraph.transforms.task:transforms
+    - taskgraph.transforms.build:transforms
+    - taskgraph.transforms.build_attrs:transforms
+    - taskgraph.transforms.build_lints:transforms
+    - taskgraph.transforms.use_toolchains:transforms
+    - taskgraph.transforms.release_notifications:transforms
+    - taskgraph.transforms.job:transforms
+    - taskgraph.transforms.task:transforms
 
-jobs-from:
-   - source.yml
 
 job-defaults:
-   shipping-phase: promote
-   treeherder:
-      symbol: Src
-   worker-type: aws-provisioner-v1/gecko-{level}-b-linux
-   worker:
-      max-run-time: 3600
-      env:
-         TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/linux64/releng.manifest"
-         PKG_SRCPACK_BASENAME: source
-   run:
-      using: mozharness
-      actions: [package-source]
-      script: "mozharness/scripts/fx_desktop_build.py"
-      config:
-         - builds/releng_sub_linux_configs/64_source.py
-      options: []
-      tooltool-downloads: public
-      need-xvfb: false
-   run-on-projects: []
-   toolchains:
-      - linux64-clang
-      - linux64-gcc
-      - linux64-rust
-      - linux64-sccache
+    shipping-phase: promote
+    treeherder:
+        symbol: Src
+    worker-type: aws-provisioner-v1/gecko-{level}-b-linux
+    worker:
+        max-run-time: 3600
+        env:
+            TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/linux64/releng.manifest"
+            PKG_SRCPACK_BASENAME: source
+    run:
+        using: mozharness
+        actions: [package-source]
+        script: "mozharness/scripts/fx_desktop_build.py"
+        config:
+            - builds/releng_sub_linux_configs/64_source.py
+        options: []
+        tooltool-downloads: public
+        need-xvfb: false
+    run-on-projects: []
+    # The build_attrs transform defaults to setting a `skip-unlles-schedules'
+    # optimization based on the task label. The tasks here don't have corresponding
+    # schedules defined in mozbuild.
+    optimization: {}
+
+jobs:
+    firefox-source/opt:
+        description: "Firefox source builder"
+        treeherder:
+            platform: firefox-release/opt
+        shipping-product: firefox
+
+    fennec-source/opt:
+        description: "Fennec source builder"
+        treeherder:
+            platform: fennec-release/opt
+        shipping-product: fennec
+
+    devedition-source/opt:
+        description: "Devedition source builder"
+        treeherder:
+            platform: devedition-release/opt
+        shipping-product: devedition
deleted file mode 100644
--- a/taskcluster/ci/release-source/source.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-linux64-source/opt:
-    description: "Firefox source builder"
-    treeherder:
-        platform: linux64/opt
-    shipping-product: firefox
-
-linux64-fennec-source/opt:
-    description: "Fennec source builder"
-    treeherder:
-        platform: android-api-16/opt
-    shipping-product: fennec
-
-linux64-devedition-source/opt:
-    description: "Devedition source builder"
-    treeherder:
-        platform: linux64-devedition-source/opt
-    shipping-product: devedition
--- a/taskcluster/docs/kinds.rst
+++ b/taskcluster/docs/kinds.rst
@@ -200,22 +200,34 @@ beetmover-source
 Beetmover-source publishes release source. This is part of release promotion.
 
 checksums-signing
 -----------------
 Checksums-signing take as input the checksums file generated by beetmover tasks
 and sign it via the signing scriptworkers. Returns the same file signed and
 additional detached signature.
 
+release-source-checksums-signing
+-------------------------------
+release-source-checksums-signing take as input the checksums file generated by
+source-related beetmover task and sign it via the signing scriptworkers.
+Returns the same file signed and additional detached signature.
+
 beetmover-checksums
 -------------------
 Beetmover, takes specific artifact checksums and pushes it to a location outside
 of Taskcluster's task artifacts (archive.mozilla.org as one place) and in the
 process determines the final location and "pretty" names it (version product name)
 
+beetmover-release-source-checksums
+---------------------------------
+Beetmover, takes source specific artifact checksums and pushes it to a location outside
+of Taskcluster's task artifacts (archive.mozilla.org as one place) and in the
+process determines the final location and "pretty" names it (version product name)
+
 google-play-strings
 -------------------
 Download strings to display on Google Play from https://l10n.mozilla-community.org/stores_l10n/.
 Artifact is then used by push-apk.
 
 push-apk
 --------
 PushApk publishes Android packages onto Google Play Store. Jobs of this kind take
--- a/taskcluster/taskgraph/transforms/beetmover.py
+++ b/taskcluster/taskgraph/transforms/beetmover.py
@@ -139,22 +139,16 @@ UPSTREAM_ARTIFACT_UNSIGNED_PATHS = {
     'linux64-asan-reporter-nightly':
         # ASan reporter builds don't generate the regular crashreporter symbol
         # packages, so we shouldn't try to beetmove them
         filter(lambda a: a != 'target.crashreporter-symbols.zip',
                _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
                     "host/bin/mar",
                     "host/bin/mbsdiff",
                 ]),
-    'linux64-source': [
-    ],
-    'linux64-devedition-source': [
-    ],
-    'linux64-fennec-source': [
-    ],
     'android-x86-nightly': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'android-aarch64-nightly': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'android-api-16-nightly': _MOBILE_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US,
     'macosx64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
         "host/bin/mar",
         "host/bin/mbsdiff",
     ],
     'macosx64-devedition-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US + [
@@ -212,28 +206,16 @@ UPSTREAM_ARTIFACT_SIGNED_PATHS = {
     'linux-devedition-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US + [
         "target.tar.bz2",
         "target.tar.bz2.asc",
     ],
     'linux64-asan-reporter-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US + [
         "target.tar.bz2",
         "target.tar.bz2.asc",
     ],
-    'linux64-source': [
-        "source.tar.xz",
-        "source.tar.xz.asc",
-    ],
-    'linux64-devedition-source': [
-        "source.tar.xz",
-        "source.tar.xz.asc",
-    ],
-    'linux64-fennec-source': [
-        "source.tar.xz",
-        "source.tar.xz.asc",
-    ],
     'android-x86-nightly': ["en-US/target.apk"],
     'android-aarch64-nightly': ["en-US/target.apk"],
     'android-api-16-nightly': ["en-US/target.apk"],
     'macosx64-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US + [
         "target.dmg",
         "target.dmg.asc",
     ],
     'macosx64-devedition-nightly': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_EN_US + [
@@ -289,16 +271,24 @@ UPSTREAM_ARTIFACT_SIGNED_PATHS = {
     'win64-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_L10N + [
         "target.zip",
     ],
     'win64-devedition-nightly-l10n': _DESKTOP_UPSTREAM_ARTIFACTS_SIGNED_L10N + [
         "target.zip",
     ],
 
 }
+# Until bug 1331141 is fixed, if you are adding any new artifacts here that
+# need to be transfered to S3, please be aware you also need to follow-up
+# with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+# See example in bug 1348286
+UPSTREAM_SOURCE_ARTIFACTS = [
+    "source.tar.xz",
+    "source.tar.xz.asc",
+]
 
 # Voluptuous uses marker objects as dictionary *keys*, but they are not
 # comparable, so we cast all of the keys back to regular strings
 task_description_schema = {str(k): v for k, v in task_description_schema.schema.iteritems()}
 
 transforms = TransformSequence()
 
 # shortcut for a string where task references are allowed
@@ -401,16 +391,27 @@ def generate_upstream_artifacts(job, sig
     build_mapping = UPSTREAM_ARTIFACT_UNSIGNED_PATHS
     signing_mapping = UPSTREAM_ARTIFACT_SIGNED_PATHS
 
     artifact_prefix = get_artifact_prefix(job)
     if locale:
         artifact_prefix = '{}/{}'.format(artifact_prefix, locale)
         platform = "{}-l10n".format(platform)
 
+    if platform.endswith("-source"):
+        return [
+            {
+                "taskId": {"task-reference": signing_task_ref},
+                "taskType": "signing",
+                "paths": ["{}/{}".format(artifact_prefix, p)
+                          for p in UPSTREAM_SOURCE_ARTIFACTS],
+                "locale": locale or "en-US",
+            }
+        ]
+
     upstream_artifacts = []
 
     # Some platforms (like android-api-16-nightly-l10n) may not depend on any unsigned artifact
     if build_mapping[platform]:
         upstream_artifacts.append({
             "taskId": {"task-reference": build_task_ref},
             "taskType": "build",
             "paths": ["{}/{}".format(artifact_prefix, p)
@@ -445,21 +446,18 @@ def generate_upstream_artifacts(job, sig
 
     return upstream_artifacts
 
 
 def craft_release_properties(config, job):
     params = config.params
     build_platform = job['attributes']['build_platform']
     build_platform = build_platform.replace('-nightly', '')
-    if 'fennec-source' in build_platform:
-        # XXX This case is hardcoded to match the current implementation in beetmover
-        build_platform = 'android-api-16'
-    else:
-        build_platform = build_platform.replace('-source', '')
+    if build_platform.endswith("-source"):
+        build_platform = build_platform.replace('-source', '-release')
 
     # XXX This should be explicitly set via build attributes or something
     if 'android' in job['label'] or 'fennec' in job['label']:
         app_name = 'Fennec'
     elif config.graph_config['trust-domain'] == 'comm':
         app_name = 'Thunderbird'
     else:
         # XXX Even DevEdition is called Firefox
new file mode 100644
--- /dev/null
+++ b/taskcluster/taskgraph/transforms/beetmover_source_checksums.py
@@ -0,0 +1,166 @@
+# 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/.
+"""
+Transform beetmover-release-source-checksums task into an actual task description.
+"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+from taskgraph.transforms.base import TransformSequence
+from taskgraph.transforms.beetmover import craft_release_properties
+from taskgraph.util.attributes import copy_attributes_from_dependent_job
+from taskgraph.util.schema import validate_schema, Schema
+from taskgraph.util.scriptworker import (get_beetmover_bucket_scope,
+                                         get_beetmover_action_scope,
+                                         get_worker_type_for_scope)
+from taskgraph.transforms.task import task_description_schema
+from voluptuous import Any, Required, Optional
+
+# Voluptuous uses marker objects as dictionary *keys*, but they are not
+# comparable, so we cast all of the keys back to regular strings
+task_description_schema = {str(k): v for k, v in task_description_schema.schema.iteritems()}
+
+transforms = TransformSequence()
+
+taskref_or_string = Any(
+    basestring,
+    {Required('task-reference'): basestring})
+
+beetmover_checksums_description_schema = Schema({
+    Required('dependent-task'): object,
+    Required('depname', default='build'): basestring,
+    Optional('label'): basestring,
+    Optional('treeherder'): task_description_schema['treeherder'],
+    Optional('locale'): basestring,
+    Optional('shipping-phase'): task_description_schema['shipping-phase'],
+    Optional('shipping-product'): task_description_schema['shipping-product'],
+})
+
+
+@transforms.add
+def validate(config, jobs):
+    for job in jobs:
+        label = job.get('dependent-task', object).__dict__.get('label', '?no-label?')
+        validate_schema(
+            beetmover_checksums_description_schema, job,
+            "In checksums-signing ({!r} kind) task for {!r}:".format(config.kind, label))
+        yield job
+
+
+@transforms.add
+def make_beetmover_checksums_description(config, jobs):
+    for job in jobs:
+        dep_job = job['dependent-task']
+        attributes = dep_job.attributes
+
+        treeherder = job.get('treeherder', {})
+        treeherder.setdefault('symbol', 'BMcss(N)')
+        dep_th_platform = dep_job.task.get('extra', {}).get(
+            'treeherder', {}).get('machine', {}).get('platform', '')
+        treeherder.setdefault('platform',
+                              "{}/opt".format(dep_th_platform))
+        treeherder.setdefault('tier', 1)
+        treeherder.setdefault('kind', 'build')
+
+        label = job['label']
+        build_platform = attributes.get('build_platform')
+
+        description = "Beetmover submission of checksums for source file"
+
+        extra = {}
+        if build_platform.startswith("android"):
+            extra['product'] = 'fennec'
+        elif 'devedition' in build_platform:
+            extra['product'] = 'devedition'
+        else:
+            extra['product'] = 'firefox'
+
+        dependent_kind = str(dep_job.kind)
+        dependencies = {dependent_kind: dep_job.label}
+        for k, v in dep_job.dependencies.items():
+            if k.startswith('beetmover'):
+                dependencies[k] = v
+
+        attributes = copy_attributes_from_dependent_job(dep_job)
+
+        bucket_scope = get_beetmover_bucket_scope(config)
+        action_scope = get_beetmover_action_scope(config)
+
+        task = {
+            'label': label,
+            'description': description,
+            'worker-type': get_worker_type_for_scope(config, bucket_scope),
+            'scopes': [bucket_scope, action_scope],
+            'dependencies': dependencies,
+            'attributes': attributes,
+            'run-on-projects': dep_job.attributes.get('run_on_projects'),
+            'treeherder': treeherder,
+            'extra': extra,
+        }
+
+        if 'shipping-phase' in job:
+            task['shipping-phase'] = job['shipping-phase']
+
+        if 'shipping-product' in job:
+            task['shipping-product'] = job['shipping-product']
+
+        yield task
+
+
+def generate_upstream_artifacts(refs, platform, locale=None):
+    # Until bug 1331141 is fixed, if you are adding any new artifacts here that
+    # need to be transfered to S3, please be aware you also need to follow-up
+    # with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
+    # See example in bug 1348286
+    common_paths = [
+        "public/target-source.checksums",
+        "public/target-source.checksums.asc",
+    ]
+
+    upstream_artifacts = [{
+        "taskId": {"task-reference": refs["signing"]},
+        "taskType": "signing",
+        "paths": common_paths,
+        "locale": locale or "en-US",
+    }]
+
+    return upstream_artifacts
+
+
+@transforms.add
+def make_beetmover_checksums_worker(config, jobs):
+    for job in jobs:
+        valid_beetmover_job = (len(job["dependencies"]) == 2)
+        if not valid_beetmover_job:
+            raise NotImplementedError("Beetmover checksums must have two dependencies.")
+
+        locale = job["attributes"].get("locale")
+        platform = job["attributes"]["build_platform"]
+
+        refs = {
+            "beetmover": None,
+            "signing": None,
+        }
+        for dependency in job["dependencies"].keys():
+            if dependency.startswith("beetmover"):
+                refs['beetmover'] = "<{}>".format(dependency)
+            else:
+                refs['signing'] = "<{}>".format(dependency)
+        if None in refs.values():
+            raise NotImplementedError(
+                "Beetmover checksums must have a beetmover and signing dependency!")
+
+        worker = {
+            'implementation': 'beetmover',
+            'release-properties': craft_release_properties(config, job),
+            'upstream-artifacts': generate_upstream_artifacts(
+                refs, platform, locale
+            ),
+        }
+
+        if locale:
+            worker["locale"] = locale
+        job["worker"] = worker
+
+        yield job
new file mode 100644
--- /dev/null
+++ b/taskcluster/taskgraph/transforms/source_checksums_signing.py
@@ -0,0 +1,99 @@
+# 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/.
+"""
+Transform the checksums signing task into an actual task description.
+"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+from taskgraph.transforms.base import TransformSequence
+from taskgraph.util.attributes import copy_attributes_from_dependent_job
+from taskgraph.util.schema import validate_schema, Schema
+from taskgraph.util.scriptworker import (
+    get_signing_cert_scope,
+    get_worker_type_for_scope,
+)
+from taskgraph.transforms.task import task_description_schema
+from voluptuous import Any, Required, Optional
+
+# Voluptuous uses marker objects as dictionary *keys*, but they are not
+# comparable, so we cast all of the keys back to regular strings
+task_description_schema = {str(k): v for k, v in task_description_schema.schema.iteritems()}
+
+transforms = TransformSequence()
+
+taskref_or_string = Any(
+    basestring,
+    {Required('task-reference'): basestring})
+
+checksums_signing_description_schema = Schema({
+    Required('dependent-task'): object,
+    Required('depname', default='beetmover'): basestring,
+    Optional('label'): basestring,
+    Optional('treeherder'): task_description_schema['treeherder'],
+    Optional('shipping-product'): task_description_schema['shipping-product'],
+    Optional('shipping-phase'): task_description_schema['shipping-phase'],
+})
+
+
+@transforms.add
+def validate(config, jobs):
+    for job in jobs:
+        label = job.get('dependent-task', object).__dict__.get('label', '?no-label?')
+        validate_schema(
+            checksums_signing_description_schema, job,
+            "In checksums-signing ({!r} kind) task for {!r}:".format(config.kind, label))
+        yield job
+
+
+@transforms.add
+def make_checksums_signing_description(config, jobs):
+    for job in jobs:
+        dep_job = job['dependent-task']
+        attributes = dep_job.attributes
+
+        treeherder = job.get('treeherder', {})
+        treeherder.setdefault('symbol', 'css(N)')
+        dep_th_platform = dep_job.task.get('extra', {}).get(
+            'treeherder', {}).get('machine', {}).get('platform', '')
+        treeherder.setdefault('platform',
+                              "{}/opt".format(dep_th_platform))
+        treeherder.setdefault('tier', 1)
+        treeherder.setdefault('kind', 'build')
+
+        label = job['label']
+        description = "Signing of release-source checksums file"
+        dependencies = {"beetmover": dep_job.label}
+
+        attributes = copy_attributes_from_dependent_job(dep_job)
+
+        upstream_artifacts = [{
+            "taskId": {"task-reference": "<beetmover>"},
+            "taskType": "beetmover",
+            "paths": [
+                "public/target-source.checksums",
+            ],
+            "formats": ["gpg"]
+        }]
+
+        signing_cert_scope = get_signing_cert_scope(config)
+
+        task = {
+            'label': label,
+            'description': description,
+            'worker-type': get_worker_type_for_scope(config, signing_cert_scope),
+            'worker': {'implementation': 'scriptworker-signing',
+                       'upstream-artifacts': upstream_artifacts,
+                       'max-run-time': 3600},
+            'scopes': [
+                signing_cert_scope,
+                "project:releng:signing:format:gpg"
+            ],
+            'dependencies': dependencies,
+            'attributes': attributes,
+            'run-on-projects': dep_job.attributes.get('run_on_projects'),
+            'treeherder': treeherder,
+        }
+
+        yield task
--- a/taskcluster/taskgraph/util/scriptworker.py
+++ b/taskcluster/taskgraph/util/scriptworker.py
@@ -440,17 +440,17 @@ def get_release_config(config):
     release_config['next_version'] = str(config.params['next_version'])
     release_config['build_number'] = config.params['build_number']
     return release_config
 
 
 def get_signing_cert_scope_per_platform(build_platform, is_nightly, config):
     if 'devedition' in build_platform:
         return get_devedition_signing_cert_scope(config)
-    elif is_nightly or build_platform in ('linux64-source', 'linux64-fennec-source'):
+    elif is_nightly or build_platform in ('firefox-source', 'fennec-source'):
         return get_signing_cert_scope(config)
     else:
         return add_scope_prefix(config, 'signing:cert:dep-signing')
 
 
 def get_worker_type_for_scope(config, scope):
     """Get the scriptworker type that will accept the given scope.
 
--- a/testing/talos/talos/tests/devtools/addon/content/tests/head.js
+++ b/testing/talos/talos/tests/devtools/addon/content/tests/head.js
@@ -44,17 +44,17 @@ exports.testSetup = function(url) {
   return damp.testSetup(url);
 };
 
 exports.testTeardown = function() {
   return damp.testTeardown();
 };
 
 exports.logTestResult = function(name, value) {
-  damp._results.push(name, value);
+  damp._results.push({ name, value });
 };
 
 function getBrowserWindow() {
   return Services.wm.getMostRecentWindow("navigator:browser");
 }
 exports.getBrowserWindow = getBrowserWindow;
 
 function getActiveTab() {
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/CSS2/backgrounds/background-root-010.xht.ini
@@ -0,0 +1,3 @@
+[background-root-010.xht]
+  disabled:
+    if webrender: bug 1453935
--- a/testing/web-platform/meta/css/CSS2/backgrounds/background-root-016.xht.ini
+++ b/testing/web-platform/meta/css/CSS2/backgrounds/background-root-016.xht.ini
@@ -1,4 +1,3 @@
 [background-root-016.xht]
-  expected:
-    if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-    if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
+  disabled:
+    if webrender: bug 1453935
--- a/toolkit/content/aboutSupport.js
+++ b/toolkit/content/aboutSupport.js
@@ -445,16 +445,17 @@ var snapshotFormatters = {
     addRowFromKey("features", "webgl2WSIInfo");
     addRowFromKey("features", "webgl2Renderer");
     addRowFromKey("features", "webgl2Version");
     addRowFromKey("features", "webgl2DriverExtensions");
     addRowFromKey("features", "webgl2Extensions");
     addRowFromKey("features", "supportsHardwareH264", "hardwareH264");
     addRowFromKey("features", "direct2DEnabled", "#Direct2D");
     addRowFromKey("features", "usesTiling");
+    addRowFromKey("features", "contentUsesTiling");
     addRowFromKey("features", "offMainThreadPaintEnabled");
     addRowFromKey("features", "offMainThreadPaintWorkerCount");
 
     if ("directWriteEnabled" in data) {
       let message = data.directWriteEnabled;
       if ("directWriteVersion" in data)
         message += " (" + data.directWriteVersion + ")";
       addRow("features", "#DirectWrite", message);
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -1243,17 +1243,17 @@
             // autoscrolling on. So instead we do the same math as Gecko.
             const scaleFactor = 60 / Math.round(60 / screen.defaultCSSScaleFactor);
             let minX = left.value / scaleFactor + 0.5 * POPUP_SIZE;
             let maxX = (left.value + width.value) / scaleFactor - 0.5 * POPUP_SIZE;
             let minY = top.value / scaleFactor + 0.5 * POPUP_SIZE;
             let maxY = (top.value + height.value) / scaleFactor - 0.5 * POPUP_SIZE;
             let popupX = Math.max(minX, Math.min(maxX, screenX));
             let popupY = Math.max(minY, Math.min(maxY, screenY));
-            this._autoScrollPopup.openPopup(null, "after_start", popupX, popupY);
+            this._autoScrollPopup.openPopupAtScreen(popupX, popupY);
             this._ignoreMouseEvents = true;
             this._scrolling = true;
             this._startX = screenX;
             this._startY = screenY;
 
             window.addEventListener("mousemove", this, true);
             window.addEventListener("mousedown", this, true);
             window.addEventListener("mouseup", this, true);
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
@@ -96,16 +96,17 @@ unknownFailure = Blocklisted; failure co
 d3d11layersCrashGuard = D3D11 Compositor
 d3d11videoCrashGuard = D3D11 Video Decoder
 d3d9videoCrashGuard = D3D9 Video Decoder
 glcontextCrashGuard = OpenGL
 resetOnNextRestart = Reset on Next Restart
 gpuProcessKillButton = Terminate GPU Process
 gpuDeviceResetButton = Trigger Device Reset
 usesTiling = Uses Tiling
+contentUsesTiling = Uses Tiling (Content)
 offMainThreadPaintEnabled = Off Main Thread Painting Enabled
 offMainThreadPaintWorkerCount = Off Main Thread Painting Worker Count
 
 audioBackend = Audio Backend
 maxAudioChannels = Max Channels
 channelLayout = Preferred Channel Layout
 sampleRate = Preferred Sample Rate
 
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -419,16 +419,17 @@ var dataProviders = {
       adapterDriverDate2: "driverDate2",
       isGPU2Active: null,
 
       D2DEnabled: "direct2DEnabled",
       DWriteEnabled: "directWriteEnabled",
       DWriteVersion: "directWriteVersion",
       cleartypeParameters: "clearTypeParameters",
       UsesTiling: "usesTiling",
+      ContentUsesTiling: "contentUsesTiling",
       OffMainThreadPaintEnabled: "offMainThreadPaintEnabled",
       OffMainThreadPaintWorkerCount: "offMainThreadPaintWorkerCount",
     };
 
     for (let prop in gfxInfoProps) {
       try {
         data[gfxInfoProps[prop] || prop] = gfxInfo[prop];
       } catch (e) {}
--- a/toolkit/modules/tests/browser/browser_Troubleshoot.js
+++ b/toolkit/modules/tests/browser/browser_Troubleshoot.js
@@ -343,16 +343,19 @@ const SNAPSHOT_SCHEMA = {
           type: "boolean",
         },
         directWriteVersion: {
           type: "string",
         },
         usesTiling: {
           type: "boolean",
         },
+        contentUsesTiling: {
+          type: "boolean",
+        },
         offMainThreadPaintEnabled: {
           type: "boolean",
         },
         offMainThreadPaintWorkerCount: {
           type: "number",
         },
         clearTypeParameters: {
           type: "string",
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -1476,16 +1476,23 @@ GfxInfoBase::GetWebRenderEnabled(bool* a
 NS_IMETHODIMP
 GfxInfoBase::GetUsesTiling(bool* aUsesTiling)
 {
   *aUsesTiling = gfxPlatform::GetPlatform()->UsesTiling();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+GfxInfoBase::GetContentUsesTiling(bool* aUsesTiling)
+{
+  *aUsesTiling = gfxPlatform::GetPlatform()->ContentUsesTiling();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 GfxInfoBase::GetOffMainThreadPaintEnabled(bool* aOffMainThreadPaintEnabled)
 {
   *aOffMainThreadPaintEnabled = gfxConfig::IsEnabled(Feature::OMTP);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GfxInfoBase::GetOffMainThreadPaintWorkerCount(int32_t* aOffMainThreadPaintWorkerCount)
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -57,16 +57,17 @@ public:
   NS_IMETHOD GetFeatures(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetFeatureLog(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetActiveCrashGuards(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetContentBackend(nsAString & aContentBackend) override;
   NS_IMETHOD GetUsingGPUProcess(bool *aOutValue) override;
   NS_IMETHOD GetWebRenderEnabled(bool* aWebRenderEnabled) override;
   NS_IMETHOD GetIsHeadless(bool* aIsHeadless) override;
   NS_IMETHOD GetUsesTiling(bool* aUsesTiling) override;
+  NS_IMETHOD GetContentUsesTiling(bool* aUsesTiling) override;
   NS_IMETHOD GetOffMainThreadPaintEnabled(bool* aOffMainThreadPaintEnabled) override;
   NS_IMETHOD GetOffMainThreadPaintWorkerCount(int32_t* aOffMainThreadPaintWorkerCount) override;
 
   // Initialization function. If you override this, you must call this class's
   // version of Init first.
   // We need Init to be called separately from the constructor so we can
   // register as an observer after all derived classes have been constructed
   // and we know we have a non-zero refcount.
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -21,16 +21,17 @@ interface nsIGfxInfo : nsISupports
 
   /*
    * These are valid across all platforms.
    */
   readonly attribute DOMString ContentBackend;
   readonly attribute boolean WebRenderEnabled;
   readonly attribute boolean isHeadless;
   readonly attribute boolean UsesTiling;
+  readonly attribute boolean ContentUsesTiling;
   readonly attribute boolean OffMainThreadPaintEnabled;
   readonly attribute long OffMainThreadPaintWorkerCount;
 
   // XXX: Switch to a list of devices, rather than explicitly numbering them.
 
   /**
    * The name of the display adapter.
    */