merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 04 May 2017 10:57:00 +0200
changeset 572570 33b92d9c40562dab3d7b602368c75619f1d793f7
parent 572569 a8d597ee6dd58306e62e55a07c4ab20958726d6a (current diff)
parent 572528 06d436f9330d2e8c7a7d1066f560c8a872c9eb57 (diff)
child 572571 1367360a33986fdaea705c7b3a5aa849644387a2
child 572585 81b32ddbbb381a45ecb0628178eb0764b3814eee
child 572592 b1caa3efc832560853e40d0fbc4206f3ba439e2a
child 572640 a161bb4fc758f91f1f53e3376a89178fcfc5a25f
child 572661 06c3b1698f13035a81cb87c285d8995400a175b5
child 572670 47ac7c6fe179b5f5b71c5aac0f91c8252439b430
child 572677 f015a0fb76a986dc2adc9c0f1cb67a02bf9058f3
child 572678 030c595473212cc88de5d83183762e0cd08e4787
child 572679 7208a840a89f17f45afe8faad7a11f34e9eb5457
child 572692 dbb98905c98fded4038999f8285154e10e75fcc7
child 572696 95d6c02b9e2bcb7526315c88792add47f0599964
child 572699 096d499ae1c8678a9c45e406a4c1d99e46c40773
child 572703 1572c3db391507643d2bafac32d968eeb31171a3
child 572707 7b7e8eabaa79e91cc9da3214dd6d9e9a5a72b68b
child 572709 cf3c543a24ddf04e542886d0c73f391cc11ea080
child 572718 d3b488ac423bd50913e14ea5340c98387ece9523
child 572721 4e95bcd00a771618029415f04a2b3c817605f70f
child 572727 63d18d750efda0c99d2bce225bfc8c658f6da77c
child 572739 bf9e8a51d33159be252cbd3369a817304780b7e5
child 572747 c9f8cc626a37d84022ad87729face700e677ca72
child 572756 6b3d6e99ba5dfdc4e03a7ad05015e27be6d89743
child 572773 32f28b578374e77ff021fac2176dd4d3ea45837a
child 572850 c302f0b4f1854f4a9f9d69c5abd6c5bfe55e61ba
child 572853 f034e73516d951655371ab665aaa26255d55d47e
child 572855 9ee83839ae983bae41a9a66d62bd61e26d617335
child 572857 295bb72bd3734565cfe29e9010d590d19f7b9130
child 572891 4a51154ed216a5e93338d1f75521b104488b5491
child 572893 2c1d6a5d31d60242e8d71087eb6b91570f60e3c8
child 572894 e31790a28f785b38b7a0f0b8065a16ee9a766075
child 572896 b87247da7565ef6cd0435877362c44f007bc50f4
child 572915 8c41b5ca1639ec5418ded616ba66d4327988affb
child 573056 38f2765e94df6b7750b442586bb0fa97c64d9b49
child 573104 01424585603f033bead0b84198f48fe79800a442
child 573260 d7ff0ee807feaabcfb106b35b3e5e0a8aa48c5c8
child 573396 4f23e49e40d2ae609a60d6773a72ab56f008d1df
child 573925 5632c98a00e5eab3f747814dd903cbe8a69c66bf
push id57112
push userbmo:jacheng@mozilla.com
push dateThu, 04 May 2017 09:50:00 +0000
reviewersmerge
milestone55.0a1
merge mozilla-inbound to mozilla-central a=merge
browser/base/content/test/sync/accounts_testRemoteCommands.html
browser/base/content/test/sync/browser_fxa_web_channel.html
browser/base/content/test/sync/content_aboutAccounts.js
js/src/jsclist.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7566,17 +7566,17 @@ nsDocShell::OnRedirectStateChange(nsICha
       nsCOMPtr<nsIScriptSecurityManager> secMan =
         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
 
       if (secMan) {
         nsCOMPtr<nsIPrincipal> principal;
         secMan->GetDocShellCodebasePrincipal(newURI, this,
                                              getter_AddRefs(principal));
         appCacheChannel->SetChooseApplicationCache(
-          NS_ShouldCheckAppCache(principal, UsePrivateBrowsing()));
+          NS_ShouldCheckAppCache(principal));
       }
     }
   }
 
   if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
       mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
     mLoadType = LOAD_NORMAL_REPLACE;
     SetHistoryEntry(&mLSHE, nullptr);
@@ -11155,17 +11155,17 @@ nsDocShell::DoURILoad(nsIURI* aURI,
       nsCOMPtr<nsIScriptSecurityManager> secMan =
         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
 
       if (secMan) {
         nsCOMPtr<nsIPrincipal> principal;
         secMan->GetDocShellCodebasePrincipal(aURI, this,
                                              getter_AddRefs(principal));
         appCacheChannel->SetChooseApplicationCache(
-          NS_ShouldCheckAppCache(principal, UsePrivateBrowsing()));
+          NS_ShouldCheckAppCache(principal));
       }
     }
   }
 
   // Make sure to give the caller a channel if we managed to create one
   // This is important for correct error page/session history interaction
   if (aRequest) {
     NS_ADDREF(*aRequest = channel);
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3205,17 +3205,16 @@ Element*
 Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
 {
   nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aResult);
   if (!selectorList) {
     // Either we failed (and aResult already has the exception), or this
     // is a pseudo-element-only selector that matches nothing.
     return nullptr;
   }
-  OwnerDoc()->FlushPendingLinkUpdates();
   TreeMatchContext matchingContext(false,
                                    nsRuleWalker::eRelevantLinkUnvisited,
                                    OwnerDoc(),
                                    TreeMatchContext::eNeverMatchVisited);
   matchingContext.SetHasSpecifiedScope();
   matchingContext.AddScopeElement(this);
   for (nsINode* node = this; node; node = node->GetParentNode()) {
     if (node->IsElement() &&
@@ -3233,17 +3232,16 @@ Element::Matches(const nsAString& aSelec
 {
   nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aError);
   if (!selectorList) {
     // Either we failed (and aError already has the exception), or this
     // is a pseudo-element-only selector that matches nothing.
     return false;
   }
 
-  OwnerDoc()->FlushPendingLinkUpdates();
   TreeMatchContext matchingContext(false,
                                    nsRuleWalker::eRelevantLinkUnvisited,
                                    OwnerDoc(),
                                    TreeMatchContext::eNeverMatchVisited);
   matchingContext.SetHasSpecifiedScope();
   matchingContext.AddScopeElement(this);
   return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
                                                  selectorList);
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6764,16 +6764,44 @@ nsContentUtils::WidgetForDocument(const 
         }
       }
     }
   }
 
   return nullptr;
 }
 
+nsIWidget*
+nsContentUtils::WidgetForContent(const nsIContent* aContent)
+{
+  nsIFrame* frame = aContent->GetPrimaryFrame();
+  if (frame) {
+    frame = nsLayoutUtils::GetDisplayRootFrame(frame);
+
+    nsView* view = frame->GetView();
+    if (view) {
+      return view->GetWidget();
+    }
+  }
+
+  return nullptr;
+}
+
+already_AddRefed<LayerManager>
+nsContentUtils::LayerManagerForContent(const nsIContent *aContent)
+{
+  nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
+  if (widget) {
+    RefPtr<LayerManager> manager = widget->GetLayerManager();
+    return manager.forget();
+  }
+
+  return nullptr;
+}
+
 static already_AddRefed<LayerManager>
 LayerManagerForDocumentInternal(const nsIDocument *aDoc, bool aRequirePersistent)
 {
   nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
   if (widget) {
     RefPtr<LayerManager> manager =
       widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT :
                               nsIWidget::LAYER_MANAGER_CURRENT);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2021,33 +2021,57 @@ public:
    * might not be this document's actual presentation.
    */
   static nsIPresShell* FindPresShellForDocument(const nsIDocument* aDoc);
 
   /**
    * Returns the widget for this document if there is one. Looks at all ancestor
    * documents to try to find a widget, so for example this can still find a
    * widget for documents in display:none frames that have no presentation.
+   *
+   * You should probably use WidgetForContent() instead of this, unless you have
+   * a good reason to do otherwise.
    */
   static nsIWidget* WidgetForDocument(const nsIDocument* aDoc);
 
   /**
+   * Returns the appropriate widget for this element, if there is one. Unlike
+   * WidgetForDocument(), this returns the correct widget for content in popups.
+   *
+   * You should probably use this instead of WidgetForDocument().
+   */
+  static nsIWidget* WidgetForContent(const nsIContent* aContent);
+
+  /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager.
    *
+   * You should probably use LayerManagerForContent() instead of this, unless
+   * you have a good reason to do otherwise.
+   *
    * @param aDoc the document for which to return a layer manager.
    * @param aAllowRetaining an outparam that states whether the returned
    * layer manager should be used for retained layers
    */
   static already_AddRefed<mozilla::layers::LayerManager>
   LayerManagerForDocument(const nsIDocument *aDoc);
 
   /**
+   * Returns a layer manager to use for the given content. Unlike
+   * LayerManagerForDocument(), this returns the correct layer manager for
+   * content in popups.
+   *
+   * You should probably use this instead of LayerManagerForDocument().
+   */
+  static already_AddRefed<mozilla::layers::LayerManager>
+  LayerManagerForContent(const nsIContent *aContent);
+
+  /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager. In addition to the normal layer manager lookup this will
    * specifically request a persistent layer manager. This means that the layer
    * manager is expected to remain the layer manager for the document in the
    * forseeable future. This function should be used carefully as it may change
    * the document's layer manager.
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -52,16 +52,17 @@
 #include "nsISHistory.h"
 #include "NullPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsGlobalWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsView.h"
+#include "nsBaseWidget.h"
 #include "GroupedSHistory.h"
 #include "PartialSHistory.h"
 
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 
 #include "nsGkAtoms.h"
@@ -1244,19 +1245,28 @@ nsFrameLoader::ShowRemoteFrame(const Scr
   // cross-process layers; need to figure out what behavior we really
   // want here.  For now, hack.
   if (!mRemoteBrowserShown) {
     if (!mOwnerContent ||
         !mOwnerContent->GetComposedDoc()) {
       return false;
     }
 
-    RefPtr<layers::LayerManager> layerManager =
-      nsContentUtils::LayerManagerForDocument(mOwnerContent->GetComposedDoc());
-    if (!layerManager) {
+    // We never want to host remote frameloaders in simple popups, like menus.
+    nsIWidget* widget = nsContentUtils::WidgetForContent(mOwnerContent);
+    if (!widget || static_cast<nsBaseWidget*>(widget)->IsSmallPopup()) {
+      return false;
+    }
+
+    RenderFrameParent* rfp = GetCurrentRenderFrame();
+    if (!rfp) {
+      return false;
+    }
+
+    if (!rfp->AttachLayerManager()) {
       // This is just not going to work.
       return false;
     }
 
     nsPIDOMWindowOuter* win = mOwnerContent->OwnerDoc()->GetWindow();
     bool parentIsActive = false;
     if (win) {
       nsCOMPtr<nsPIWindowRoot> windowRoot =
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2459,18 +2459,30 @@ public:
 
   virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) = 0;
 
   virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
 
   // Add aLink to the set of links that need their status resolved.
   void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);
 
-  // Update state on links in mLinksToUpdate.  This function must
-  // be called prior to selector matching.
+  // Update state on links in mLinksToUpdate.  This function must be called
+  // prior to selector matching that needs to differentiate between :link and
+  // :visited.  In particular, it does _not_ need to be called before doing any
+  // selector matching that uses TreeMatchContext::eNeverMatchVisited.  The only
+  // reason we haven't moved all calls to this function entirely inside the
+  // TreeMatchContext constructor is to not call it all the time during various
+  // style system and frame construction operations (though it would likely be a
+  // no-op for all but the first call).
+  //
+  // XXXbz Does this really need to be called before selector matching?  All it
+  // will do is ensure all the links involved are registered to observe history,
+  // which won't synchronously change their state to :visited anyway!  So
+  // calling this won't affect selector matching done immediately afterward, as
+  // far as I can tell.
   void FlushPendingLinkUpdates();
 
   void FlushPendingLinkUpdatesFromRunnable();
 
 #define DEPRECATED_OPERATION(_op) e##_op,
   enum DeprecatedOperations {
 #include "nsDeprecatedOperationList.h"
     eDeprecatedOperationCount
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -2801,17 +2801,16 @@ template<bool onlyFirstMatch, class Coll
 MOZ_ALWAYS_INLINE static void
 FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
                      ErrorResult& aRv)
 {
   nsIDocument* doc = aRoot->OwnerDoc();
 
   TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
                                    doc, TreeMatchContext::eNeverMatchVisited);
-  doc->FlushPendingLinkUpdates();
   AddScopeElements(matchingContext, aRoot);
 
   // Fast-path selectors involving IDs.  We can only do this if aRoot
   // is in the document and the document is not in quirks mode, since
   // ID selectors are case-insensitive in quirks mode.  Also, only do
   // this if aSelectorList only has one selector, because otherwise
   // ordering the elements correctly is a pain.
   NS_ASSERTION(aRoot->IsElement() || aRoot->IsNodeOfType(nsINode::eDOCUMENT) ||
--- a/dom/html/HTMLContentElement.cpp
+++ b/dom/html/HTMLContentElement.cpp
@@ -290,17 +290,16 @@ HTMLContentElement::Match(nsIContent* aC
 
   if (mSelectorList) {
     nsIDocument* doc = OwnerDoc();
     ShadowRoot* containingShadow = GetContainingShadow();
     nsIContent* host = containingShadow->GetHost();
 
     TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
                                      doc, TreeMatchContext::eNeverMatchVisited);
-    doc->FlushPendingLinkUpdates();
     matchingContext.SetHasSpecifiedScope();
     matchingContext.AddScopeElement(host->AsElement());
 
     if (!aContent->IsElement()) {
       return false;
     }
 
     return nsCSSRuleProcessor::SelectorListMatches(aContent->AsElement(),
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2288,39 +2288,39 @@ TabParent::RecvIsParentWindowMainWidgetV
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabParent::RecvGetDPI(float* aValue)
 {
   TryCacheDPIAndScale();
 
-  MOZ_ASSERT(mDPI > 0,
+  MOZ_ASSERT(mDPI > 0 || mFrameElement,
              "Must not ask for DPI before OwnerElement is received!");
   *aValue = mDPI;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabParent::RecvGetDefaultScale(double* aValue)
 {
   TryCacheDPIAndScale();
 
-  MOZ_ASSERT(mDefaultScale.scale > 0,
+  MOZ_ASSERT(mDefaultScale.scale > 0 || mFrameElement,
              "Must not ask for scale before OwnerElement is received!");
   *aValue = mDefaultScale.scale;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabParent::RecvGetWidgetRounding(int32_t* aValue)
 {
   TryCacheDPIAndScale();
 
-  MOZ_ASSERT(mRounding > 0,
+  MOZ_ASSERT(mRounding > 0 || mFrameElement,
              "Must not ask for rounding before OwnerElement is received!");
   *aValue = mRounding;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabParent::RecvGetMaxTouchPoints(uint32_t* aTouchPoints)
 {
@@ -2576,17 +2576,17 @@ TabParent::TryCacheDPIAndScale()
 }
 
 already_AddRefed<nsIWidget>
 TabParent::GetWidget() const
 {
   if (!mFrameElement) {
     return nullptr;
   }
-  nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc());
+  nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForContent(mFrameElement);
   return widget.forget();
 }
 
 void
 TabParent::ApzAwareEventRoutingToChild(ScrollableLayerGuid* aOutTargetGuid,
                                        uint64_t* aOutInputBlockId,
                                        nsEventStatus* aOutApzResponse)
 {
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -1003,19 +1003,19 @@ gfxFontconfigFontFamily::FindStyleVariat
 }
 
 void
 gfxFontconfigFontFamily::AddFontPattern(FcPattern* aFontPattern)
 {
     NS_ASSERTION(!mHasStyles,
                  "font patterns must not be added to already enumerated families");
 
-    FcBool scalable;
-    if (FcPatternGetBool(aFontPattern, FC_SCALABLE, 0, &scalable) != FcResultMatch ||
-        !scalable) {
+    FcBool outline;
+    if (FcPatternGetBool(aFontPattern, FC_OUTLINE, 0, &outline) != FcResultMatch ||
+        !outline) {
         mHasNonScalableFaces = true;
     }
 
     nsCountedRef<FcPattern> pattern(aFontPattern);
     mFontPatterns.AppendElement(pattern);
 }
 
 static const double kRejectDistance = 10000.0;
deleted file mode 100644
--- a/js/src/jsclist.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=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/. */
-
-#ifndef jsclist_h
-#define jsclist_h
-
-#include "jstypes.h"
-
-/*
-** Circular linked list
-*/
-typedef struct JSCListStr {
-    struct JSCListStr* next;
-    struct JSCListStr* prev;
-} JSCList;
-
-/*
-** Insert element "_e" into the list, before "_l".
-*/
-#define JS_INSERT_BEFORE(_e,_l)  \
-    JS_BEGIN_MACRO               \
-        (_e)->next = (_l);       \
-        (_e)->prev = (_l)->prev; \
-        (_l)->prev->next = (_e); \
-        (_l)->prev = (_e);       \
-    JS_END_MACRO
-
-/*
-** Insert element "_e" into the list, after "_l".
-*/
-#define JS_INSERT_AFTER(_e,_l)   \
-    JS_BEGIN_MACRO               \
-        (_e)->next = (_l)->next; \
-        (_e)->prev = (_l);       \
-        (_l)->next->prev = (_e); \
-        (_l)->next = (_e);       \
-    JS_END_MACRO
-
-/*
-** Return the element following element "_e"
-*/
-#define JS_NEXT_LINK(_e)         \
-        ((_e)->next)
-/*
-** Return the element preceding element "_e"
-*/
-#define JS_PREV_LINK(_e)         \
-        ((_e)->prev)
-
-/*
-** Append an element "_e" to the end of the list "_l"
-*/
-#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
-
-/*
-** Insert an element "_e" at the head of the list "_l"
-*/
-#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
-
-/* Return the head/tail of the list */
-#define JS_LIST_HEAD(_l) (_l)->next
-#define JS_LIST_TAIL(_l) (_l)->prev
-
-/*
-** Remove the element "_e" from it's circular list.
-*/
-#define JS_REMOVE_LINK(_e)             \
-    JS_BEGIN_MACRO                     \
-        (_e)->prev->next = (_e)->next; \
-        (_e)->next->prev = (_e)->prev; \
-    JS_END_MACRO
-
-/*
-** Remove the element "_e" from it's circular list. Also initializes the
-** linkage.
-*/
-#define JS_REMOVE_AND_INIT_LINK(_e)    \
-    JS_BEGIN_MACRO                     \
-        (_e)->prev->next = (_e)->next; \
-        (_e)->next->prev = (_e)->prev; \
-        (_e)->next = (_e);             \
-        (_e)->prev = (_e);             \
-    JS_END_MACRO
-
-/*
-** Return non-zero if the given circular list "_l" is empty, zero if the
-** circular list is not empty
-*/
-#define JS_CLIST_IS_EMPTY(_l) \
-    bool((_l)->next == (_l))
-
-/*
-** Initialize a circular list
-*/
-#define JS_INIT_CLIST(_l)  \
-    JS_BEGIN_MACRO         \
-        (_l)->next = (_l); \
-        (_l)->prev = (_l); \
-    JS_END_MACRO
-
-#define JS_INIT_STATIC_CLIST(_l) \
-    {(_l), (_l)}
-
-#endif /* jsclist_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -76,17 +76,16 @@ if CONFIG['HAVE_DTRACE']:
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 EXPORTS += [
     '!js-config.h',
     'js.msg',
     'jsalloc.h',
     'jsapi.h',
     'jsbytecode.h',
-    'jsclist.h',
     'jscpucfg.h',
     'jsfriendapi.h',
     'jsprf.h',
     'jsprototypes.h',
     'jspubtd.h',
     'jstypes.h',
     'jsversion.h',
     'jswrapper.h',
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -519,17 +519,16 @@ RequireGlobalObject(JSContext* cx, Handl
 }
 
 
 /*** Breakpoints *********************************************************************************/
 
 BreakpointSite::BreakpointSite(Type type)
   : type_(type), enabledCount(0)
 {
-    JS_INIT_CLIST(&breakpoints);
 }
 
 void
 BreakpointSite::inc(FreeOp* fop)
 {
     enabledCount++;
     if (enabledCount == 1)
         recompile(fop);
@@ -542,79 +541,66 @@ BreakpointSite::dec(FreeOp* fop)
     enabledCount--;
     if (enabledCount == 0)
         recompile(fop);
 }
 
 bool
 BreakpointSite::isEmpty() const
 {
-    return JS_CLIST_IS_EMPTY(&breakpoints);
+    return breakpoints.isEmpty();
 }
 
 Breakpoint*
 BreakpointSite::firstBreakpoint() const
 {
-    if (JS_CLIST_IS_EMPTY(&breakpoints))
+    if (isEmpty())
         return nullptr;
-    return Breakpoint::fromSiteLinks(JS_NEXT_LINK(&breakpoints));
+    return &(*breakpoints.begin());
 }
 
 bool
-BreakpointSite::hasBreakpoint(Breakpoint* bp)
-{
-    for (Breakpoint* p = firstBreakpoint(); p; p = p->nextInSite())
+BreakpointSite::hasBreakpoint(Breakpoint* toFind)
+{
+    const BreakpointList::Iterator bp(toFind);
+    for (auto p = breakpoints.begin(); p; p++)
         if (p == bp)
             return true;
     return false;
 }
 
 Breakpoint::Breakpoint(Debugger* debugger, BreakpointSite* site, JSObject* handler)
     : debugger(debugger), site(site), handler(handler)
 {
     MOZ_ASSERT(handler->compartment() == debugger->object->compartment());
-    JS_APPEND_LINK(&debuggerLinks, &debugger->breakpoints);
-    JS_APPEND_LINK(&siteLinks, &site->breakpoints);
-}
-
-Breakpoint*
-Breakpoint::fromDebuggerLinks(JSCList* links)
-{
-    return (Breakpoint*) ((unsigned char*) links - offsetof(Breakpoint, debuggerLinks));
-}
-
-Breakpoint*
-Breakpoint::fromSiteLinks(JSCList* links)
-{
-    return (Breakpoint*) ((unsigned char*) links - offsetof(Breakpoint, siteLinks));
+    debugger->breakpoints.pushBack(this);
+    site->breakpoints.pushBack(this);
 }
 
 void
 Breakpoint::destroy(FreeOp* fop)
 {
     if (debugger->enabled)
         site->dec(fop);
-    JS_REMOVE_LINK(&debuggerLinks);
-    JS_REMOVE_LINK(&siteLinks);
+    debugger->breakpoints.remove(this);
+    site->breakpoints.remove(this);
     site->destroyIfEmpty(fop);
     fop->delete_(this);
 }
 
 Breakpoint*
 Breakpoint::nextInDebugger()
 {
-    JSCList* link = JS_NEXT_LINK(&debuggerLinks);
-    return (link == &debugger->breakpoints) ? nullptr : fromDebuggerLinks(link);
+    return debuggerLink.mNext;
 }
 
 Breakpoint*
 Breakpoint::nextInSite()
 {
-    JSCList* link = JS_NEXT_LINK(&siteLinks);
-    return (link == &site->breakpoints) ? nullptr : fromSiteLinks(link);
+    return siteLink.mNext;
 }
 
 JSBreakpointSite::JSBreakpointSite(JSScript* script, jsbytecode* pc)
   : BreakpointSite(Type::JS),
     script(script),
     pc(pc)
 {
     MOZ_ASSERT(!script->hasBreakpointsAt(pc));
@@ -679,19 +665,16 @@ Debugger::Debugger(JSContext* cx, Native
     traceLoggerLastDrainedSize(0),
     traceLoggerLastDrainedIteration(0),
 #endif
     traceLoggerScriptedCallsLastDrainedSize(0),
     traceLoggerScriptedCallsLastDrainedIteration(0)
 {
     assertSameCompartment(cx, dbg);
 
-    JS_INIT_CLIST(&breakpoints);
-    JS_INIT_CLIST(&onNewGlobalObjectWatchersLink);
-
 #ifdef JS_TRACE_LOGGING
     TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
     if (logger) {
 #ifdef NIGHTLY_BUILD
         logger->getIterationAndSize(&traceLoggerLastDrainedIteration, &traceLoggerLastDrainedSize);
 #endif
         logger->getIterationAndSize(&traceLoggerScriptedCallsLastDrainedIteration,
                                     &traceLoggerScriptedCallsLastDrainedSize);
@@ -700,25 +683,25 @@ Debugger::Debugger(JSContext* cx, Native
 }
 
 Debugger::~Debugger()
 {
     MOZ_ASSERT_IF(debuggees.initialized(), debuggees.empty());
     allocationsLog.clear();
 
     /*
-     * Since the inactive state for this link is a singleton cycle, it's always
-     * safe to apply JS_REMOVE_LINK to it, regardless of whether we're in the list or not.
-     *
      * We don't have to worry about locking here since Debugger is not
      * background finalized.
      */
-    JS_REMOVE_LINK(&onNewGlobalObjectWatchersLink);
-
     JSContext* cx = TlsContext.get();
+    if (onNewGlobalObjectWatchersLink.mPrev ||
+        onNewGlobalObjectWatchersLink.mNext ||
+        cx->runtime()->onNewGlobalObjectWatchers().begin() == JSRuntime::WatchersList::Iterator(this))
+        cx->runtime()->onNewGlobalObjectWatchers().remove(this);
+
     cx->runtime()->endSingleThreadedExecution(cx);
 }
 
 bool
 Debugger::init(JSContext* cx)
 {
     if (!debuggees.init() ||
         !debuggeeZones.init() ||
@@ -2173,33 +2156,29 @@ Debugger::fireNewGlobalObject(JSContext*
                              : handleUncaughtException(ac, vp);
     MOZ_ASSERT(!cx->isExceptionPending());
     return status;
 }
 
 void
 Debugger::slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global)
 {
-    MOZ_ASSERT(!JS_CLIST_IS_EMPTY(&cx->runtime()->onNewGlobalObjectWatchers()));
+    MOZ_ASSERT(!cx->runtime()->onNewGlobalObjectWatchers().isEmpty());
     if (global->compartment()->creationOptions().invisibleToDebugger())
         return;
 
     /*
      * Make a copy of the runtime's onNewGlobalObjectWatchers before running the
      * handlers. Since one Debugger's handler can disable another's, the list
      * can be mutated while we're walking it.
      */
     AutoObjectVector watchers(cx);
-    for (JSCList* link = JS_LIST_HEAD(&cx->runtime()->onNewGlobalObjectWatchers());
-         link != &cx->runtime()->onNewGlobalObjectWatchers();
-         link = JS_NEXT_LINK(link))
-    {
-        Debugger* dbg = fromOnNewGlobalObjectWatchersLink(link);
-        MOZ_ASSERT(dbg->observesNewGlobalObject());
-        JSObject* obj = dbg->object;
+    for (auto& dbg : cx->runtime()->onNewGlobalObjectWatchers()) {
+        MOZ_ASSERT(dbg.observesNewGlobalObject());
+        JSObject* obj = dbg.object;
         JS::ExposeObjectToActiveJS(obj);
         if (!watchers.append(obj)) {
             if (cx->isExceptionPending())
                 cx->clearPendingException();
             return;
         }
     }
 
@@ -3370,24 +3349,19 @@ Debugger::setEnabled(JSContext* cx, unsi
         }
 
         /*
          * Add or remove ourselves from the runtime's list of Debuggers
          * that care about new globals.
          */
         if (dbg->getHook(OnNewGlobalObject)) {
             if (!wasEnabled) {
-                /* If we were not enabled, the link should be a singleton list. */
-                MOZ_ASSERT(JS_CLIST_IS_EMPTY(&dbg->onNewGlobalObjectWatchersLink));
-                JS_APPEND_LINK(&dbg->onNewGlobalObjectWatchersLink,
-                               &cx->runtime()->onNewGlobalObjectWatchers());
+                cx->runtime()->onNewGlobalObjectWatchers().pushBack(dbg);
             } else {
-                /* If we were enabled, the link should be inserted in the list. */
-                MOZ_ASSERT(!JS_CLIST_IS_EMPTY(&dbg->onNewGlobalObjectWatchersLink));
-                JS_REMOVE_AND_INIT_LINK(&dbg->onNewGlobalObjectWatchersLink);
+                cx->runtime()->onNewGlobalObjectWatchers().remove(dbg);
             }
         }
 
         // Ensure the compartment is observable if we are re-enabling a
         // Debugger with hooks that observe all execution.
         if (!dbg->updateObservesAllExecutionOnDebuggees(cx, dbg->observesAllExecution()))
             return false;
 
@@ -3537,24 +3511,19 @@ Debugger::setOnNewGlobalObject(JSContext
 
     /*
      * Add or remove ourselves from the runtime's list of Debuggers that
      * care about new globals.
      */
     if (dbg->enabled) {
         JSObject* newHook = dbg->getHook(OnNewGlobalObject);
         if (!oldHook && newHook) {
-            /* If we didn't have a hook, the link should be a singleton list. */
-            MOZ_ASSERT(JS_CLIST_IS_EMPTY(&dbg->onNewGlobalObjectWatchersLink));
-            JS_APPEND_LINK(&dbg->onNewGlobalObjectWatchersLink,
-                           &cx->runtime()->onNewGlobalObjectWatchers());
+            cx->runtime()->onNewGlobalObjectWatchers().pushBack(dbg);
         } else if (oldHook && !newHook) {
-            /* If we did have a hook, the link should be inserted in the list. */
-            MOZ_ASSERT(!JS_CLIST_IS_EMPTY(&dbg->onNewGlobalObjectWatchersLink));
-            JS_REMOVE_AND_INIT_LINK(&dbg->onNewGlobalObjectWatchersLink);
+            cx->runtime()->onNewGlobalObjectWatchers().remove(dbg);
         }
     }
 
     return true;
 }
 
 /* static */ bool
 Debugger::getUncaughtExceptionHook(JSContext* cx, unsigned argc, Value* vp)
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -2,23 +2,23 @@
  * vim: set ts=8 sts=4 et sw=4 tw=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/. */
 
 #ifndef vm_Debugger_h
 #define vm_Debugger_h
 
+#include "mozilla/DoublyLinkedList.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/Range.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Vector.h"
 
-#include "jsclist.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsweakmap.h"
 #include "jswrapper.h"
 
 #include "builtin/Promise.h"
 #include "ds/TraceableFifo.h"
 #include "gc/Barrier.h"
@@ -254,16 +254,17 @@ typedef mozilla::Variant<ScriptSourceObj
 // Either a AbstractFramePtr, for ordinary JS, or a wasm::DebugFrame,
 // for synthesized frame of a wasm code.
 typedef mozilla::Variant<AbstractFramePtr, wasm::DebugFrame*> DebuggerFrameReferent;
 
 class Debugger : private mozilla::LinkedListElement<Debugger>
 {
     friend class Breakpoint;
     friend class DebuggerMemory;
+    friend struct JSRuntime::GlobalObjectWatchersSiblingAccess<Debugger>;
     friend class SavedStacks;
     friend class ScriptedOnStepHandler;
     friend class ScriptedOnPopHandler;
     friend class mozilla::LinkedListElement<Debugger>;
     friend class mozilla::LinkedList<Debugger>;
     friend bool (::JS_DefineDebuggerObject)(JSContext* cx, JS::HandleObject obj);
     friend bool (::JS::dbg::IsDebugger)(JSObject&);
     friend bool (::JS::dbg::GetDebuggeeGlobals)(JSContext*, JSObject&, AutoObjectVector&);
@@ -381,17 +382,37 @@ class Debugger : private mozilla::Linked
     JS::ZoneSet debuggeeZones; /* Set of zones that we have debuggees in. */
     js::GCPtrObject uncaughtExceptionHook; /* Strong reference. */
     bool enabled;
     bool allowUnobservedAsmJS;
 
     // Whether to enable code coverage on the Debuggee.
     bool collectCoverageInfo;
 
-    JSCList breakpoints;                /* Circular list of all js::Breakpoints in this debugger */
+    template<typename T>
+    struct DebuggerSiblingAccess {
+      static T* GetNext(T* elm) {
+        return elm->debuggerLink.mNext;
+      }
+      static void SetNext(T* elm, T* next) {
+        elm->debuggerLink.mNext = next;
+      }
+      static T* GetPrev(T* elm) {
+        return elm->debuggerLink.mPrev;
+      }
+      static void SetPrev(T* elm, T* prev) {
+        elm->debuggerLink.mPrev = prev;
+      }
+    };
+
+    // List of all js::Breakpoints in this debugger.
+    using BreakpointList =
+        mozilla::DoublyLinkedList<js::Breakpoint,
+                                  DebuggerSiblingAccess<js::Breakpoint>>;
+    BreakpointList breakpoints;
 
     // The set of GC numbers for which one or more of this Debugger's observed
     // debuggees participated in.
     using GCNumberSet = HashSet<uint64_t, DefaultHasher<uint64_t>, RuntimeAllocPolicy>;
     GCNumberSet observedGCs;
 
     using AllocationsLog = js::TraceableFifo<AllocationsLogEntry>;
 
@@ -441,21 +462,20 @@ class Debugger : private mozilla::Linked
     /*
      * Add or remove allocations tracking for all debuggees.
      */
     MOZ_MUST_USE bool addAllocationsTrackingForAllDebuggees(JSContext* cx);
     void removeAllocationsTrackingForAllDebuggees();
 
     /*
      * If this Debugger is enabled, and has a onNewGlobalObject handler, then
-     * this link is inserted into the circular list headed by
-     * JSRuntime::onNewGlobalObjectWatchers. Otherwise, this is set to a
-     * singleton cycle.
+     * this link is inserted into the list headed by
+     * JSRuntime::onNewGlobalObjectWatchers.
      */
-    JSCList onNewGlobalObjectWatchersLink;
+    mozilla::DoublyLinkedListElement<Debugger> onNewGlobalObjectWatchersLink;
 
     /*
      * Map from stack frames that are currently on the stack to Debugger.Frame
      * instances.
      *
      * The keys are always live stack frames. We drop them from this map as
      * soon as they leave the stack (see slowPathOnLeaveFrame) and in
      * removeDebuggee.
@@ -785,18 +805,16 @@ class Debugger : private mozilla::Linked
                                              const FrameIter* maybeIter,
                                              MutableHandleValue vp);
     MOZ_MUST_USE bool getScriptFrameWithIter(JSContext* cx, AbstractFramePtr frame,
                                              const FrameIter* maybeIter,
                                              MutableHandleDebuggerFrame result);
 
     inline Breakpoint* firstBreakpoint() const;
 
-    static inline Debugger* fromOnNewGlobalObjectWatchersLink(JSCList* link);
-
     static MOZ_MUST_USE bool replaceFrameGuts(JSContext* cx, AbstractFramePtr from,
                                               AbstractFramePtr to,
                                               ScriptFrameIter& iter);
 
   public:
     Debugger(JSContext* cx, NativeObject* dbg);
     ~Debugger();
 
@@ -1558,17 +1576,37 @@ class BreakpointSite {
     friend class Debugger;
 
   public:
     enum class Type { JS, Wasm };
 
   private:
     Type type_;
 
-    JSCList breakpoints;  /* cyclic list of all js::Breakpoints at this instruction */
+    template<typename T>
+    struct SiteSiblingAccess {
+      static T* GetNext(T* elm) {
+        return elm->siteLink.mNext;
+      }
+      static void SetNext(T* elm, T* next) {
+        elm->siteLink.mNext = next;
+      }
+      static T* GetPrev(T* elm) {
+        return elm->siteLink.mPrev;
+      }
+      static void SetPrev(T* elm, T* prev) {
+        elm->siteLink.mPrev = prev;
+      }
+    };
+
+    // List of all js::Breakpoints at this instruction.
+    using BreakpointList =
+        mozilla::DoublyLinkedList<js::Breakpoint,
+                                  SiteSiblingAccess<js::Breakpoint>>;
+    BreakpointList breakpoints;
     size_t enabledCount;  /* number of breakpoints in the list that are enabled */
 
   protected:
     virtual void recompile(FreeOp* fop) = 0;
     bool isEmpty() const;
     inline bool isEnabled() const { return enabledCount > 0; }
 
   public:
@@ -1602,29 +1640,32 @@ class BreakpointSite {
  * Nothing else causes a breakpoint to be retained, so if its script or
  * debugger is collected, the breakpoint is destroyed during GC sweep phase,
  * even if the debugger compartment isn't being GC'd. This is implemented in
  * Zone::sweepBreakpoints.
  */
 class Breakpoint {
     friend struct ::JSCompartment;
     friend class Debugger;
+    friend class BreakpointSite;
 
   public:
     Debugger * const debugger;
     BreakpointSite * const site;
   private:
     /* |handler| is marked unconditionally during minor GC. */
     js::PreBarrieredObject handler;
-    JSCList debuggerLinks;
-    JSCList siteLinks;
+
+    /**
+     * Link elements for each list this breakpoint can be in.
+     */
+    mozilla::DoublyLinkedListElement<Breakpoint> debuggerLink;
+    mozilla::DoublyLinkedListElement<Breakpoint> siteLink;
 
   public:
-    static Breakpoint* fromDebuggerLinks(JSCList* links);
-    static Breakpoint* fromSiteLinks(JSCList* links);
     Breakpoint(Debugger* debugger, BreakpointSite* site, JSObject* handler);
     void destroy(FreeOp* fop);
     Breakpoint* nextInDebugger();
     Breakpoint* nextInSite();
     const PreBarrieredObject& getHandler() const { return handler; }
     PreBarrieredObject& getHandlerRef() { return handler; }
 
     inline WasmBreakpoint* asWasm();
@@ -1692,25 +1733,19 @@ Breakpoint::asWasm()
     MOZ_ASSERT(site && site->type() == BreakpointSite::Type::Wasm);
     return static_cast<WasmBreakpoint*>(this);
 }
 
 
 Breakpoint*
 Debugger::firstBreakpoint() const
 {
-    if (JS_CLIST_IS_EMPTY(&breakpoints))
+    if (breakpoints.isEmpty())
         return nullptr;
-    return Breakpoint::fromDebuggerLinks(JS_NEXT_LINK(&breakpoints));
-}
-
-/* static */ Debugger*
-Debugger::fromOnNewGlobalObjectWatchersLink(JSCList* link) {
-    char* p = reinterpret_cast<char*>(link);
-    return reinterpret_cast<Debugger*>(p - offsetof(Debugger, onNewGlobalObjectWatchersLink));
+    return &(*breakpoints.begin());
 }
 
 const js::GCPtrNativeObject&
 Debugger::toJSObject() const
 {
     MOZ_ASSERT(object);
     return object;
 }
@@ -1761,17 +1796,17 @@ Debugger::onNewScript(JSContext* cx, Han
 
 /* static */ void
 Debugger::onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global)
 {
     MOZ_ASSERT(!global->compartment()->firedOnNewGlobalObject);
 #ifdef DEBUG
     global->compartment()->firedOnNewGlobalObject = true;
 #endif
-    if (!JS_CLIST_IS_EMPTY(&cx->runtime()->onNewGlobalObjectWatchers()))
+    if (!cx->runtime()->onNewGlobalObjectWatchers().isEmpty())
         Debugger::slowPathOnNewGlobalObject(cx, global);
 }
 
 /* static */ bool
 Debugger::onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame, mozilla::TimeStamp when)
 {
     GlobalObject::DebuggerVector* dbgs = cx->global()->getDebuggers();
     if (!dbgs || dbgs->empty())
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -172,17 +172,16 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     lastAnimationTime(0),
     performanceMonitoring_(thisFromCtor()),
     stackFormat_(parentRuntime ? js::StackFormat::Default
                                : js::StackFormat::SpiderMonkey)
 {
     liveRuntimesCount++;
 
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
-    JS_INIT_CLIST(&onNewGlobalObjectWatchers());
 
     PodZero(&asmJSCacheOps);
     lcovOutput().init();
 }
 
 JSRuntime::~JSRuntime()
 {
     MOZ_ASSERT(!initialized_);
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -4,27 +4,27 @@
  * 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 vm_Runtime_h
 #define vm_Runtime_h
 
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/DoublyLinkedList.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/ThreadLocal.h"
 #include "mozilla/Vector.h"
 
 #include <setjmp.h>
 
 #include "jsatom.h"
-#include "jsclist.h"
 #include "jsscript.h"
 
 #ifdef XP_DARWIN
 # include "wasm/WasmSignalHandlers.h"
 #endif
 #include "builtin/AtomicsObject.h"
 #include "builtin/Intl.h"
 #include "builtin/Promise.h"
@@ -555,24 +555,44 @@ struct JSRuntime : public js::MallocProv
     // List of non-ephemeron weak containers to sweep during beginSweepingSweepGroup.
     js::ActiveThreadData<mozilla::LinkedList<JS::WeakCache<void*>>> weakCaches_;
   public:
     mozilla::LinkedList<JS::WeakCache<void*>>& weakCaches() { return weakCaches_.ref(); }
     void registerWeakCache(JS::WeakCache<void*>* cachep) {
         weakCaches().insertBack(cachep);
     }
 
+    template <typename T>
+    struct GlobalObjectWatchersSiblingAccess {
+      static T* GetNext(T* elm) {
+        return elm->onNewGlobalObjectWatchersLink.mNext;
+      }
+      static void SetNext(T* elm, T* next) {
+        elm->onNewGlobalObjectWatchersLink.mNext = next;
+      }
+      static T* GetPrev(T* elm) {
+        return elm->onNewGlobalObjectWatchersLink.mPrev;
+      }
+      static void SetPrev(T* elm, T* prev) {
+        elm->onNewGlobalObjectWatchersLink.mPrev = prev;
+      }
+    };
+
+    using WatchersList =
+        mozilla::DoublyLinkedList<js::Debugger,
+                                  GlobalObjectWatchersSiblingAccess<js::Debugger>>;
   private:
     /*
-     * Head of circular list of all enabled Debuggers that have
-     * onNewGlobalObject handler methods established.
+     * List of all enabled Debuggers that have onNewGlobalObject handler
+     * methods established.
      */
-    js::ActiveThreadData<JSCList> onNewGlobalObjectWatchers_;
+    js::ActiveThreadData<WatchersList> onNewGlobalObjectWatchers_;
+
   public:
-    JSCList& onNewGlobalObjectWatchers() { return onNewGlobalObjectWatchers_.ref(); }
+    WatchersList& onNewGlobalObjectWatchers() { return onNewGlobalObjectWatchers_.ref(); }
 
   private:
     /*
      * Lock taken when using per-runtime or per-zone data that could otherwise
      * be accessed simultaneously by multiple threads.
      *
      * Locking this only occurs if there is actually a thread other than the
      * active thread which could access such data.
--- a/layout/inspector/inDOMUtils.cpp
+++ b/layout/inspector/inDOMUtils.cpp
@@ -508,18 +508,18 @@ inDOMUtils::SelectorMatchesElement(nsIDO
     }
 
     // We have a matching pseudo element, now remove it so we can compare
     // directly against |element| when proceeding into SelectorListMatches.
     // It's OK to do this - we just cloned sel and nothing else is using it.
     sel->RemoveRightmostSelector();
   }
 
-  element->OwnerDoc()->FlushPendingLinkUpdates();
-  // XXXbz what exactly should we do with visited state here?
+  // XXXbz what exactly should we do with visited state here?  If we ever start
+  // caring about it, remember to do FlushPendingLinkUpdates().
   TreeMatchContext matchingContext(false,
                                    nsRuleWalker::eRelevantLinkUnvisited,
                                    element->OwnerDoc(),
                                    TreeMatchContext::eNeverMatchVisited);
   *aMatches = nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
                                                       sel);
   return NS_OK;
 }
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -141,16 +141,17 @@ RenderFrameParent::IsInitted()
 {
   return mInitted;
 }
 
 void
 RenderFrameParent::Destroy()
 {
   mFrameLoaderDestroyed = true;
+  mLayerManager = nullptr;
 }
 
 already_AddRefed<Layer>
 RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
                               nsIFrame* aFrame,
                               LayerManager* aManager,
                               const nsIntRect& aVisibleRect,
                               nsDisplayItem* aItem,
@@ -201,42 +202,60 @@ RenderFrameParent::BuildLayer(nsDisplayL
   // Remote content can't be repainted by us, so we multiply down
   // the resolution that our container expects onto our container.
   m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0);
   layer->SetBaseTransform(m);
 
   return layer.forget();
 }
 
+LayerManager*
+RenderFrameParent::AttachLayerManager()
+{
+  RefPtr<LayerManager> lm;
+
+  if (mFrameLoader) {
+    nsIContent* content = mFrameLoader->GetOwnerContent();
+    if (content) {
+      lm = nsContentUtils::LayerManagerForContent(content);
+    }
+  }
+
+  // Perhaps the document containing this frame currently has no presentation?
+  if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) {
+    mLayersConnected = lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId);
+    FrameLayerBuilder::InvalidateAllLayers(lm);
+  }
+
+  mLayerManager = lm.forget();
+  return mLayerManager;
+}
+
 void
 RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
 {
   MOZ_ASSERT(!mFrameLoader || mFrameLoader->GetOwnerContent() == aContent,
              "Don't build new map if owner is same!");
 
-  RefPtr<LayerManager> lm = mFrameLoader ? GetFrom(mFrameLoader) : nullptr;
-  // Perhaps the document containing this frame currently has no presentation?
-  if (lm && lm->GetCompositorBridgeChild()) {
-    mLayersConnected = lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId);
-    FrameLayerBuilder::InvalidateAllLayers(lm);
-  }
+  Unused << AttachLayerManager();
 }
 
 void
 RenderFrameParent::ActorDestroy(ActorDestroyReason why)
 {
   if (mLayersId != 0) {
     if (XRE_IsParentProcess()) {
       GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, OtherPid());
     } else if (XRE_IsContentProcess()) {
       ContentChild::GetSingleton()->SendDeallocateLayerTreeId(mLayersId);
     }
   }
 
   mFrameLoader = nullptr;
+  mLayerManager = nullptr;
 }
 
 mozilla::ipc::IPCResult
 RenderFrameParent::RecvNotifyCompositorTransaction()
 {
   TriggerRepaint();
   return IPC_OK();
 }
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -85,16 +85,18 @@ public:
   inline uint64_t GetLayersId() const { return mLayersId; }
   inline bool IsLayersConnected() const { return mLayersConnected; }
   inline CompositorOptions GetCompositorOptions() const { return mCompositorOptions; }
 
   void TakeFocusForClickFromTap();
 
   void EnsureLayersConnected(CompositorOptions* aCompositorOptions);
 
+  LayerManager* AttachLayerManager();
+
 protected:
   void ActorDestroy(ActorDestroyReason why) override;
 
   virtual mozilla::ipc::IPCResult RecvNotifyCompositorTransaction() override;
 
 private:
   void TriggerRepaint();
   void DispatchEventForPanZoomController(const InputEvent& aEvent);
@@ -109,16 +111,17 @@ private:
   bool mLayersConnected;
   // The compositor options for this layers id. This is only meaningful if
   // the compositor actually knows about this layers id (i.e. when mLayersConnected
   // is true).
   CompositorOptions mCompositorOptions;
 
   RefPtr<nsFrameLoader> mFrameLoader;
   RefPtr<ContainerLayer> mContainer;
+  RefPtr<LayerManager> mLayerManager;
 
   // True after Destroy() has been called, which is triggered
   // originally by nsFrameLoader::Destroy().  After this point, we can
   // no longer safely ask the frame loader to find its nearest layer
   // manager, because it may have been disconnected from the DOM.
   // It's still OK to *tell* the frame loader that we've painted after
   // it's destroyed; it'll just ignore us, and we won't be able to
   // find an nsIFrame to invalidate.  See ShadowLayersUpdated().
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -753,18 +753,16 @@ void
 nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
 {
   nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
   if (!document) {
     ClearStyleContext();
     return;
   }
 
-  document->FlushPendingLinkUpdates();
-
   // Flush _before_ getting the presshell, since that could create a new
   // presshell.  Also note that we want to flush the style on the document
   // we're computing style in, not on the document mContent is in -- the two
   // may be different.
   document->FlushPendingNotifications(
     aNeedsLayoutFlush ? FlushType::Layout : FlushType::Style);
 #ifdef DEBUG
   mFlushedPendingReflows = aNeedsLayoutFlush;
--- a/layout/style/nsRuleProcessorData.h
+++ b/layout/style/nsRuleProcessorData.h
@@ -365,16 +365,23 @@ struct MOZ_STACK_CLASS TreeMatchContext 
   // (e.g. for children of elements that have a mandatory frame-type for which
   // we ignore "display:flex/grid").
   bool mSkippingParentDisplayBasedStyleFixup;
 
   // Whether this TreeMatchContext is being used with an nsCSSRuleProcessor
   // for an HTML5 scoped style sheet.
   bool mForScopedStyle;
 
+  // An enum that communicates the consumer's intensions for this
+  // TreeMatchContext in terms of :visited handling.  eNeverMatchVisited means
+  // that this TreeMatchContext's VisitedHandlingType will always be
+  // eRelevantLinkUnvisited (in other words, this value will be passed to the
+  // constructor and ResetForVisitedMatching() will never be called).
+  // eMatchVisitedDefault doesn't communicate any information about the current
+  // or future VisitedHandlingType of this TreeMatchContext.
   enum MatchVisited {
     eNeverMatchVisited,
     eMatchVisitedDefault
   };
 
   // List of ancestor elements that define a style scope (due to having a
   // <style scoped> child).
   AutoTArray<mozilla::dom::Element*, 1> mStyleScopes;
@@ -399,16 +406,19 @@ struct MOZ_STACK_CLASS TreeMatchContext 
     , mForScopedStyle(false)
     , mCurrentStyleScope(nullptr)
   {
     if (aMatchVisited != eNeverMatchVisited) {
       nsILoadContext* loadContext = mDocument->GetLoadContext();
       if (loadContext) {
         mUsingPrivateBrowsing = loadContext->UsePrivateBrowsing();
       }
+    } else {
+      MOZ_ASSERT(aVisitedHandling == nsRuleWalker::eRelevantLinkUnvisited,
+                 "You promised you'd never try to match :visited!");
     }
   }
 
   enum ForFrameConstructionTag { ForFrameConstruction };
 
   TreeMatchContext(nsIDocument* aDocument, ForFrameConstructionTag)
     : TreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited, aDocument)
   {}
--- a/mfbt/DoublyLinkedList.h
+++ b/mfbt/DoublyLinkedList.h
@@ -7,16 +7,18 @@
 /** A doubly-linked list with flexible next/prev naming. */
 
 #ifndef mozilla_DoublyLinkedList_h
 #define mozilla_DoublyLinkedList_h
 
 #include <algorithm>
 #include <iterator>
 
+#include "mozilla/Assertions.h"
+
 /**
  * Where mozilla::LinkedList strives for ease of use above all other
  * considerations, mozilla::DoublyLinkedList strives for flexibility. The
  * following are things that can be done with mozilla::DoublyLinkedList that
  * cannot be done with mozilla::LinkedList:
  *
  *   * Arbitrary next/prev placement and naming. With the tools provided here,
  *     the next and previous pointers can be at the end of the structure, in a
--- a/mozglue/misc/StackWalk.cpp
+++ b/mozglue/misc/StackWalk.cpp
@@ -291,16 +291,34 @@ static LdrUnloadDll_func stub_LdrUnloadD
 static NTSTATUS NTAPI
 patched_LdrUnloadDll(HMODULE module)
 {
   // Prevent the stack walker from suspending this thread when LdrUnloadDll
   // holds the RtlLookupFunctionEntry lock.
   AutoSuppressStackWalking suppress;
   return stub_LdrUnloadDll(module);
 }
+
+// These pointers are disguised as PVOID to avoid pulling in obscure headers
+typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
+  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
+  PVOID ThunkAddress, ULONG Flags);
+static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
+
+static PVOID WINAPI patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
+  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
+  PVOID ThunkAddress, ULONG Flags)
+{
+  // Prevent the stack walker from suspending this thread when
+  // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
+  AutoSuppressStackWalking suppress;
+  return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
+                                       FailureDllHook, FailureSystemHook,
+                                       ThunkAddress, Flags);
+}
 #endif // STACKWALK_HAS_DLL_INTERCEPTOR
 #endif // _M_AMD64
 
 // Routine to print an error message to standard error.
 static void
 PrintError(const char* aPrefix)
 {
   LPSTR lpMsgBuf;
@@ -383,16 +401,19 @@ EnsureWalkThreadReady()
   stackWalkThread = nullptr;
   readyEvent = nullptr;
 
 #if defined(_M_AMD64) && defined(STACKWALK_HAS_DLL_INTERCEPTOR)
   NtDllInterceptor.Init("ntdll.dll");
   NtDllInterceptor.AddHook("LdrUnloadDll",
                            reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
                            (void**)&stub_LdrUnloadDll);
+  NtDllInterceptor.AddHook("LdrResolveDelayLoadedAPI",
+                           reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
+                           (void**)&stub_LdrResolveDelayLoadedAPI);
 #endif
 
   InitializeDbgHelpCriticalSection();
 
   return walkThreadReady = true;
 }
 
 static void
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -1560,39 +1560,45 @@ NS_LoadPersistentPropertiesFromURISpec(n
 
     properties.swap(*outResult);
     return NS_OK;
 }
 
 bool
 NS_UsePrivateBrowsing(nsIChannel *channel)
 {
-    bool isPrivate = false;
-    nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(channel);
-    if (pbChannel && NS_SUCCEEDED(pbChannel->GetIsChannelPrivate(&isPrivate))) {
-        return isPrivate;
-    }
-
-    // Some channels may not implement nsIPrivateBrowsingChannel
-    nsCOMPtr<nsILoadContext> loadContext;
-    NS_QueryNotificationCallbacks(channel, loadContext);
-    return loadContext && loadContext->UsePrivateBrowsing();
+    OriginAttributes attrs;
+    bool result = NS_GetOriginAttributes(channel, attrs);
+    NS_ENSURE_TRUE(result, result);
+    return attrs.mPrivateBrowsingId > 0;
 }
 
 bool
 NS_GetOriginAttributes(nsIChannel *aChannel,
                        mozilla::OriginAttributes &aAttributes)
 {
     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
     if (!loadInfo) {
         return false;
     }
 
     loadInfo->GetOriginAttributes(&aAttributes);
-    aAttributes.SyncAttributesWithPrivateBrowsing(NS_UsePrivateBrowsing(aChannel));
+
+    bool isPrivate = false;
+    nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(aChannel);
+    if (pbChannel) {
+        nsresult rv = pbChannel->GetIsChannelPrivate(&isPrivate);
+        NS_ENSURE_SUCCESS(rv, false);
+    } else {
+        // Some channels may not implement nsIPrivateBrowsingChannel
+        nsCOMPtr<nsILoadContext> loadContext;
+        NS_QueryNotificationCallbacks(aChannel, loadContext);
+        isPrivate = loadContext && loadContext->UsePrivateBrowsing();
+    }
+    aAttributes.SyncAttributesWithPrivateBrowsing(isPrivate);
     return true;
 }
 
 bool
 NS_HasBeenCrossOrigin(nsIChannel* aChannel, bool aReport)
 {
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   MOZ_RELEASE_ASSERT(loadInfo, "Origin tracking only works for channels created with a loadinfo");
@@ -1645,52 +1651,32 @@ NS_HasBeenCrossOrigin(nsIChannel* aChann
   if (aboutBlankInherits && NS_IsAboutBlank(uri)) {
     return false;
   }
 
   return NS_FAILED(loadingPrincipal->CheckMayLoad(uri, aReport, dataInherits));
 }
 
 bool
-NS_ShouldCheckAppCache(nsIURI *aURI, bool usePrivateBrowsing)
+NS_ShouldCheckAppCache(nsIPrincipal *aPrincipal)
 {
-    if (usePrivateBrowsing) {
+    uint32_t privateBrowsingId = 0;
+    nsresult rv = aPrincipal->GetPrivateBrowsingId(&privateBrowsingId);
+    if (NS_SUCCEEDED(rv) && (privateBrowsingId > 0)) {
         return false;
     }
 
     nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
         do_GetService("@mozilla.org/offlinecacheupdate-service;1");
     if (!offlineService) {
         return false;
     }
 
     bool allowed;
-    nsresult rv = offlineService->OfflineAppAllowedForURI(aURI,
-                                                          nullptr,
-                                                          &allowed);
-    return NS_SUCCEEDED(rv) && allowed;
-}
-
-bool
-NS_ShouldCheckAppCache(nsIPrincipal *aPrincipal, bool usePrivateBrowsing)
-{
-    if (usePrivateBrowsing) {
-        return false;
-    }
-
-    nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
-        do_GetService("@mozilla.org/offlinecacheupdate-service;1");
-    if (!offlineService) {
-        return false;
-    }
-
-    bool allowed;
-    nsresult rv = offlineService->OfflineAppAllowed(aPrincipal,
-                                                    nullptr,
-                                                    &allowed);
+    rv = offlineService->OfflineAppAllowed(aPrincipal, nullptr, &allowed);
     return NS_SUCCEEDED(rv) && allowed;
 }
 
 void
 NS_WrapAuthPrompt(nsIAuthPrompt   *aAuthPrompt,
                   nsIAuthPrompt2 **aAuthPrompt2)
 {
     nsCOMPtr<nsIAuthPromptAdapterFactory> factory =
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -654,21 +654,19 @@ bool NS_HasBeenCrossOrigin(nsIChannel* a
 #define NECKO_SAFEBROWSING_FIRST_PARTY_DOMAIN \
   "safebrowsing.86868755-6b82-4842-b301-72671a0db32e.mozilla"
 
 // Unique first-party domain for separating about uri.
 #define ABOUT_URI_FIRST_PARTY_DOMAIN \
   "about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla"
 
 /**
- * Determines whether appcache should be checked for a given URI.
+ * Determines whether appcache should be checked for a given principal.
  */
-bool NS_ShouldCheckAppCache(nsIURI *aURI, bool usePrivateBrowsing);
-
-bool NS_ShouldCheckAppCache(nsIPrincipal *aPrincipal, bool usePrivateBrowsing);
+bool NS_ShouldCheckAppCache(nsIPrincipal *aPrincipal);
 
 /**
  * Wraps an nsIAuthPrompt so that it can be used as an nsIAuthPrompt2. This
  * method is provided mainly for use by other methods in this file.
  *
  * *aAuthPrompt2 should be set to null before calling this function.
  */
 void NS_WrapAuthPrompt(nsIAuthPrompt *aAuthPrompt,
--- a/netwerk/cookie/CookieServiceParent.cpp
+++ b/netwerk/cookie/CookieServiceParent.cpp
@@ -22,18 +22,17 @@ using mozilla::OriginAttributes;
 using mozilla::dom::PContentParent;
 using mozilla::net::NeckoParent;
 
 namespace {
 
 // Ignore failures from this function, as they only affect whether we do or
 // don't show a dialog box in private browsing mode if the user sets a pref.
 void
-CreateDummyChannel(nsIURI* aHostURI, OriginAttributes& aAttrs, bool aIsPrivate,
-                   nsIChannel** aChannel)
+CreateDummyChannel(nsIURI* aHostURI, OriginAttributes& aAttrs, nsIChannel** aChannel)
 {
   nsCOMPtr<nsIPrincipal> principal =
     BasePrincipal::CreateCodebasePrincipal(aHostURI, aAttrs);
   if (!principal) {
     return;
   }
 
   nsCOMPtr<nsIURI> dummyURI;
@@ -48,17 +47,17 @@ CreateDummyChannel(nsIURI* aHostURI, Ori
   NS_NewChannel(getter_AddRefs(dummyChannel), dummyURI, principal,
                 nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
                 nsIContentPolicy::TYPE_INVALID);
   nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(dummyChannel);
   if (!pbChannel) {
     return;
   }
 
-  pbChannel->SetPrivate(aIsPrivate);
+  pbChannel->SetPrivate(aAttrs.mPrivateBrowsingId > 0);
   dummyChannel.forget(aChannel);
   return;
 }
 
 }
 
 namespace mozilla {
 namespace net {
@@ -96,19 +95,17 @@ CookieServiceParent::RecvGetCookieString
     return IPC_OK();
 
   // Deserialize URI. Having a host URI is mandatory and should always be
   // provided by the child; thus we consider failure fatal.
   nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
   if (!hostURI)
     return IPC_FAIL_NO_REASON(this);
 
-  bool isPrivate = aAttrs.mPrivateBrowsingId > 0;
-  mCookieService->GetCookieStringInternal(hostURI, aIsForeign, false, aAttrs,
-                                          isPrivate, *aResult);
+  mCookieService->GetCookieStringInternal(hostURI, aIsForeign, false, aAttrs, *aResult);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
                                          const bool& aIsForeign,
                                          const nsCString& aCookieString,
                                          const nsCString& aServerTime,
@@ -118,32 +115,30 @@ CookieServiceParent::RecvSetCookieString
     return IPC_OK();
 
   // Deserialize URI. Having a host URI is mandatory and should always be
   // provided by the child; thus we consider failure fatal.
   nsCOMPtr<nsIURI> hostURI = DeserializeURI(aHost);
   if (!hostURI)
     return IPC_FAIL_NO_REASON(this);
 
-  bool isPrivate = aAttrs.mPrivateBrowsingId > 0;
-
   // This is a gross hack. We've already computed everything we need to know
   // for whether to set this cookie or not, but we need to communicate all of
   // this information through to nsICookiePermission, which indirectly
   // computes the information from the channel. We only care about the
   // aIsPrivate argument as nsCookieService::SetCookieStringInternal deals
   // with aIsForeign before we have to worry about nsCookiePermission trying
   // to use the channel to inspect it.
   nsCOMPtr<nsIChannel> dummyChannel;
   CreateDummyChannel(hostURI, const_cast<OriginAttributes&>(aAttrs),
-                     isPrivate, getter_AddRefs(dummyChannel));
+                     getter_AddRefs(dummyChannel));
 
   // NB: dummyChannel could be null if something failed in CreateDummyChannel.
   nsDependentCString cookieString(aCookieString, 0);
   mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
                                           aServerTime, false, aAttrs,
-                                          isPrivate, dummyChannel);
+                                          dummyChannel);
   return IPC_OK();
 }
 
 } // namespace net
 } // namespace mozilla
 
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -2006,21 +2006,18 @@ nsCookieService::GetCookieStringCommon(n
   mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
   // Get originAttributes.
   OriginAttributes attrs;
   if (aChannel) {
     NS_GetOriginAttributes(aChannel, attrs);
   }
 
-  bool isPrivate = aChannel && NS_UsePrivateBrowsing(aChannel);
-
   nsAutoCString result;
-  GetCookieStringInternal(aHostURI, isForeign, aHttpBound, attrs,
-                          isPrivate, result);
+  GetCookieStringInternal(aHostURI, isForeign, aHttpBound, attrs, result);
   *aCookie = result.IsEmpty() ? nullptr : ToNewCString(result);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieString(nsIURI     *aHostURI,
                                  nsIPrompt  *aPrompt,
                                  const char *aCookieHeader,
@@ -2079,45 +2076,41 @@ nsCookieService::SetCookieStringCommon(n
   mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
 
   // Get originAttributes.
   OriginAttributes attrs;
   if (aChannel) {
     NS_GetOriginAttributes(aChannel, attrs);
   }
 
-  bool isPrivate = aChannel && NS_UsePrivateBrowsing(aChannel);
-
   nsDependentCString cookieString(aCookieHeader);
   nsDependentCString serverTime(aServerTime ? aServerTime : "");
   SetCookieStringInternal(aHostURI, isForeign, cookieString,
-                          serverTime, aFromHttp, attrs,
-                          isPrivate, aChannel);
+                          serverTime, aFromHttp, attrs, aChannel);
   return NS_OK;
 }
 
 void
 nsCookieService::SetCookieStringInternal(nsIURI                 *aHostURI,
                                          bool                    aIsForeign,
                                          nsDependentCString     &aCookieHeader,
                                          const nsCString        &aServerTime,
                                          bool                    aFromHttp,
                                          const OriginAttributes &aOriginAttrs,
-                                         bool                    aIsPrivate,
                                          nsIChannel             *aChannel)
 {
   NS_ASSERTION(aHostURI, "null host!");
 
   if (!mDBState) {
     NS_WARNING("No DBState! Profile already closed?");
     return;
   }
 
   AutoRestore<DBState*> savePrevDBState(mDBState);
-  mDBState = aIsPrivate ? mPrivateDBState : mDefaultDBState;
+  mDBState = (aOriginAttrs.mPrivateBrowsingId > 0) ? mPrivateDBState : mDefaultDBState;
 
   // get the base domain for the host URI.
   // e.g. for "www.bbc.co.uk", this would be "bbc.co.uk".
   // file:// URI's (i.e. with an empty host) are allowed, but any other
   // scheme must have a non-empty host. A trailing dot in the host
   // is acceptable.
   bool requireHostMatch;
   nsAutoCString baseDomain;
@@ -3203,28 +3196,27 @@ PathMatches(nsCookie* aCookie, const nsA
   return true;
 }
 
 void
 nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
                                          bool aIsForeign,
                                          bool aHttpBound,
                                          const OriginAttributes& aOriginAttrs,
-                                         bool aIsPrivate,
                                          nsCString &aCookieString)
 {
   NS_ASSERTION(aHostURI, "null host!");
 
   if (!mDBState) {
     NS_WARNING("No DBState! Profile already closed?");
     return;
   }
 
   AutoRestore<DBState*> savePrevDBState(mDBState);
-  mDBState = aIsPrivate ? mPrivateDBState : mDefaultDBState;
+  mDBState = (aOriginAttrs.mPrivateBrowsingId > 0) ? mPrivateDBState : mDefaultDBState;
 
   // get the base domain, host, and path from the URI.
   // e.g. for "www.bbc.co.uk", the base domain would be "bbc.co.uk".
   // file:// URI's (i.e. with an empty host) are allowed, but any other
   // scheme must have a non-empty host. A trailing dot in the host
   // is acceptable.
   bool requireHostMatch;
   nsAutoCString baseDomain, hostFromURI, pathFromURI;
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -289,19 +289,19 @@ class nsCookieService final : public nsI
     void                          AsyncReadComplete();
     void                          CancelAsyncRead(bool aPurgeReadSet);
     void                          EnsureReadDomain(const nsCookieKey &aKey);
     void                          EnsureReadComplete();
     nsresult                      NormalizeHost(nsCString &aHost);
     nsresult                      GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
     nsresult                      GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
     nsresult                      GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
-    void                          GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, bool aIsPrivate, nsCString &aCookie);
+    void                          GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsCString &aCookie);
     nsresult                      SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
-    void                          SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const OriginAttributes &aOriginAttrs, bool aIsPrivate, nsIChannel* aChannel);
+    void                          SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const OriginAttributes &aOriginAttrs, nsIChannel* aChannel);
     bool                          SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel);
     void                          AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
     void                          RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = nullptr);
     void                          AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
     void                          UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
     static bool                   GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
     static bool                   ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
     bool                          RequireThirdPartyCheck();
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -585,17 +585,17 @@ HttpChannelParent::DoAsyncOpen(  const U
       NS_GetOriginAttributes(mChannel, attrs);
 
       nsCOMPtr<nsIPrincipal> principal =
         BasePrincipal::CreateCodebasePrincipal(uri, attrs);
 
       bool chooseAppCache = false;
       // This works because we've already called SetNotificationCallbacks and
       // done mPBOverride logic by this point.
-      chooseAppCache = NS_ShouldCheckAppCache(principal, NS_UsePrivateBrowsing(mChannel));
+      chooseAppCache = NS_ShouldCheckAppCache(principal);
 
       appCacheChan->SetChooseApplicationCache(chooseAppCache);
     }
   }
 
   mChannel->SetRequestContextID(aRequestContextID);
 
   mSuspendAfterSynthesizeResponse = aSuspendAfterSynthesizeResponse;
--- a/toolkit/xre/test/win/TestDllInterceptor.cpp
+++ b/toolkit/xre/test/win/TestDllInterceptor.cpp
@@ -238,16 +238,28 @@ bool TestNtQueryFullAttributesFile(void*
 
 bool TestLdrUnloadDll(void* aFunc)
 {
   typedef NTSTATUS (NTAPI *LdrUnloadDllType)(HMODULE);
   auto patchedLdrUnloadDll = reinterpret_cast<LdrUnloadDllType>(aFunc);
   return patchedLdrUnloadDll(0) != 0;
 }
 
+bool TestLdrResolveDelayLoadedAPI(void* aFunc)
+{
+  // These pointers are disguised as PVOID to avoid pulling in obscure headers
+  typedef PVOID (WINAPI *LdrResolveDelayLoadedAPIType)(PVOID, PVOID, PVOID,
+                                                       PVOID, PVOID, ULONG);
+  auto patchedLdrResolveDelayLoadedAPI =
+    reinterpret_cast<LdrResolveDelayLoadedAPIType>(aFunc);
+  // No idea how to call this API. Flags==99 is just an arbitrary number that
+  // doesn't crash when the other params are null.
+  return patchedLdrResolveDelayLoadedAPI(0, 0, 0, 0, 0, 99) == 0;
+}
+
 bool TestSetUnhandledExceptionFilter(void* aFunc)
 {
   auto patchedSetUnhandledExceptionFilter =
     reinterpret_cast<decltype(&SetUnhandledExceptionFilter)>(aFunc);
   // Retrieve the current filter as we set the new filter to null, then restore the current filter.
   LPTOP_LEVEL_EXCEPTION_FILTER current = patchedSetUnhandledExceptionFilter(0);
   patchedSetUnhandledExceptionFilter(current);
   return true;
@@ -466,16 +478,17 @@ int main()
       TestHook(TestImmGetCompositionStringW, "imm32.dll", "ImmGetCompositionStringW") &&
       TestHook(TestImmSetCandidateWindow, "imm32.dll", "ImmSetCandidateWindow") &&
       TestHook(TestImmNotifyIME, "imm32.dll", "ImmNotifyIME") &&
       TestHook(TestGetSaveFileNameW, "comdlg32.dll", "GetSaveFileNameW") &&
       TestHook(TestGetOpenFileNameW, "comdlg32.dll", "GetOpenFileNameW") &&
 #ifdef _M_X64
       TestHook(TestGetKeyState, "user32.dll", "GetKeyState") &&    // see Bug 1316415
       TestHook(TestLdrUnloadDll, "ntdll.dll", "LdrUnloadDll") &&
+      TestHook(TestLdrResolveDelayLoadedAPI, "ntdll.dll", "LdrResolveDelayLoadedAPI") &&
 #endif
       MaybeTestHook(ShouldTestTipTsf(), TestProcessCaretEvents, "tiptsf.dll", "ProcessCaretEvents") &&
 #ifdef _M_IX86
       TestHook(TestSendMessageTimeoutW, "user32.dll", "SendMessageTimeoutW") &&
 #endif
       TestDetour("ntdll.dll", "LdrLoadDll")) {
     printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
     return 0;
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -917,17 +917,19 @@ nsBaseWidget::ComputeShouldAccelerate()
   return gfx::gfxConfig::IsEnabled(gfx::Feature::HW_COMPOSITING) &&
          WidgetTypeSupportsAcceleration();
 }
 
 bool
 nsBaseWidget::UseAPZ()
 {
   return (gfxPlatform::AsyncPanZoomEnabled() &&
-          (WindowType() == eWindowType_toplevel || WindowType() == eWindowType_child));
+          (WindowType() == eWindowType_toplevel ||
+           WindowType() == eWindowType_child ||
+           (WindowType() == eWindowType_popup && !IsSmallPopup())));
 }
 
 void nsBaseWidget::CreateCompositor()
 {
   LayoutDeviceIntRect rect = GetBounds();
   CreateCompositor(rect.width, rect.height);
 }