Back out bugs 1519918, 1524246 and 1523181 from beta. a=lizzard
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 08 Feb 2019 13:09:00 +0200
changeset 512961 bfdf856d1c9a2d717f33bddf1dabad8776167805
parent 512960 546e05b0e3d22b9957fff74c7c5a0f0c8617494f
child 512962 e235f01aae95976bfcf777893c3eba188431699d
push id10659
push usernbeleuzu@mozilla.com
push dateSat, 09 Feb 2019 03:19:25 +0000
treeherdermozilla-beta@bfdf856d1c9a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslizzard
bugs1519918, 1524246, 1523181
milestone66.0
Back out bugs 1519918, 1524246 and 1523181 from beta. a=lizzard
dom/base/Document.cpp
dom/base/Document.h
dom/canvas/CanvasRenderingContext2D.cpp
layout/base/PresShell.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/FontFaceSet.cpp
layout/style/GeckoBindings.cpp
layout/style/ServoStyleSet.cpp
layout/style/nsFontFaceLoader.cpp
layout/style/nsFontFaceLoader.h
uriloader/base/nsDocLoader.cpp
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -1243,16 +1243,17 @@ Document::Document(const char* aContentT
       mHasUnsafeInlineCSP(false),
       mBFCacheDisallowed(false),
       mHasHadDefaultView(false),
       mStyleSheetChangeEventsEnabled(false),
       mIsSrcdocDocument(false),
       mDidDocumentOpen(false),
       mHasDisplayDocument(false),
       mFontFaceSetDirty(true),
+      mGetUserFontSetCalled(false),
       mDidFireDOMContentLoaded(true),
       mHasScrollLinkedEffect(false),
       mFrameRequestCallbacksScheduled(false),
       mIsTopLevelContentDocument(false),
       mIsContentDocument(false),
       mDidCallBeginLoad(false),
       mAllowPaymentRequest(false),
       mEncodingMenuDisabled(false),
@@ -11596,25 +11597,57 @@ nsAutoSyncOperation::~nsAutoSyncOperatio
     doc->SetIsInSyncOperation(false);
   }
   CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
   if (ccjs) {
     ccjs->SetMicroTaskLevel(mMicroTaskLevel);
   }
 }
 
-gfxUserFontSet* Document::GetUserFontSet() {
+gfxUserFontSet* Document::GetUserFontSet(bool aFlushUserFontSet) {
+  // We want to initialize the user font set lazily the first time the
+  // user asks for it, rather than building it too early and forcing
+  // rule cascade creation.  Thus we try to enforce the invariant that
+  // we *never* build the user font set until the first call to
+  // GetUserFontSet.  However, once it's been requested, we can't wait
+  // for somebody to call GetUserFontSet in order to rebuild it (see
+  // comments below in MarkUserFontSetDirty for why).
+#ifdef DEBUG
+  bool userFontSetGottenBefore = mGetUserFontSetCalled;
+#endif
+  // Set mGetUserFontSetCalled up front, so that FlushUserFontSet will actually
+  // flush.
+  mGetUserFontSetCalled = true;
+  if (mFontFaceSetDirty && aFlushUserFontSet) {
+    // If this assertion fails, and there have actually been changes to
+    // @font-face rules, then we will call StyleChangeReflow in
+    // FlushUserFontSet.  If we're in the middle of reflow,
+    // that's a bad thing to do, and the caller was responsible for
+    // flushing first.  If we're not (e.g., in frame construction), it's
+    // ok.
+    NS_ASSERTION(!userFontSetGottenBefore || !GetShell() ||
+                     !GetShell()->IsReflowLocked(),
+                 "FlushUserFontSet should have been called first");
+    FlushUserFontSet();
+  }
+
   if (!mFontFaceSet) {
     return nullptr;
   }
 
   return mFontFaceSet->GetUserFontSet();
 }
 
 void Document::FlushUserFontSet() {
+  if (!mGetUserFontSetCalled) {
+    return;  // No one cares about this font set yet, but we want to be careful
+             // to not unset our mFontFaceSetDirty bit, so when someone really
+             // does we'll create it.
+  }
+
   if (!mFontFaceSetDirty) {
     return;
   }
 
   mFontFaceSetDirty = false;
 
   if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
     nsTArray<nsFontFaceRuleContainer> rules;
@@ -11641,30 +11674,32 @@ void Document::FlushUserFontSet() {
       if (nsPresContext* presContext = shell->GetPresContext()) {
         presContext->UserFontSetUpdated();
       }
     }
   }
 }
 
 void Document::MarkUserFontSetDirty() {
-  if (mFontFaceSetDirty) {
-    return;
-  }
+  if (!mGetUserFontSetCalled) {
+    // We want to lazily build the user font set the first time it's
+    // requested (so we don't force creation of rule cascades too
+    // early), so don't do anything now.
+    return;
+  }
+
   mFontFaceSetDirty = true;
-  if (nsIPresShell* shell = GetShell()) {
-    shell->EnsureStyleFlush();
-  }
 }
 
 FontFaceSet* Document::Fonts() {
   if (!mFontFaceSet) {
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
     mFontFaceSet = new FontFaceSet(window, this);
-    FlushUserFontSet();
+    GetUserFontSet();  // this will cause the user font set to be
+                       // created/updated
   }
   return mFontFaceSet;
 }
 
 void Document::ReportHasScrollLinkedEffect() {
   if (mHasScrollLinkedEffect) {
     // We already did this once for this document, don't do it again.
     return;
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3260,17 +3260,17 @@ class Document : public nsINode,
 
     nsWeakPtr weakNode = do_GetWeakReference(node);
 
     if (weakNode) {
       mBlockedTrackingNodes.AppendElement(weakNode);
     }
   }
 
-  gfxUserFontSet* GetUserFontSet();
+  gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
   void FlushUserFontSet();
   void MarkUserFontSetDirty();
   mozilla::dom::FontFaceSet* GetFonts() { return mFontFaceSet; }
 
   // FontFaceSource
   mozilla::dom::FontFaceSet* Fonts();
 
   bool DidFireDOMContentLoaded() const { return mDidFireDOMContentLoaded; }
@@ -3986,16 +3986,19 @@ class Document : public nsINode,
   // be a resource document.  Normally this is the same as !!mDisplayDocument,
   // but mDisplayDocument is cleared during Unlink.  mHasDisplayDocument is
   // valid in the document's destructor.
   bool mHasDisplayDocument : 1;
 
   // Is the current mFontFaceSet valid?
   bool mFontFaceSetDirty : 1;
 
+  // Has GetUserFontSet() been called?
+  bool mGetUserFontSetCalled : 1;
+
   // True if we have fired the DOMContentLoaded event, or don't plan to fire one
   // (e.g. we're not being parsed at all).
   bool mDidFireDOMContentLoaded : 1;
 
   // True if ReportHasScrollLinkedEffect() has been called.
   bool mHasScrollLinkedEffect : 1;
 
   // True if we have frame request callbacks scheduled with the refresh driver.
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -3481,18 +3481,16 @@ bool CanvasRenderingContext2D::SetFontIn
   // device pixels, to avoid being affected by page zoom. nsFontMetrics will
   // convert nsFont size in app units to device pixels for the font group, so
   // here we first apply to the size the equivalent of a conversion from device
   // pixels to CSS pixels, to adjust for the difference in expectations from
   // other nsFontMetrics clients.
   resizedFont.size =
       (fontStyle->mSize * c->AppUnitsPerDevPixel()) / AppUnitsPerCSSPixel();
 
-  c->Document()->FlushUserFontSet();
-
   nsFontMetrics::Params params;
   params.language = fontStyle->mLanguage;
   params.explicitLanguage = fontStyle->mExplicitLanguage;
   params.userFontSet = c->GetUserFontSet();
   params.textPerf = c->GetTextPerfMetrics();
   RefPtr<nsFontMetrics> metrics =
       c->DeviceContext()->GetMetricsFor(resizedFont, params);
 
@@ -4023,17 +4021,16 @@ nsresult CanvasRenderingContext2D::DrawO
 
   MOZ_ASSERT(!presShell->IsDestroying(),
              "GetCurrentFontStyle() should have returned null if the presshell "
              "is being destroyed");
 
   nsPresContext* presContext = presShell->GetPresContext();
 
   // ensure user font set is up to date
-  presContext->Document()->FlushUserFontSet();
   currentFontStyle->SetUserFontSet(presContext->GetUserFontSet());
 
   if (currentFontStyle->GetStyle()->size == 0.0F) {
     if (aWidth) {
       *aWidth = 0;
     }
     return NS_OK;
   }
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1166,17 +1166,19 @@ void PresShell::Destroy() {
   gfxTextPerfMetrics* tp;
   if (mPresContext && (tp = mPresContext->GetTextPerfMetrics())) {
     tp->Accumulate();
     if (tp->cumulative.numChars > 0) {
       LogTextPerfStats(tp, this, tp->cumulative, 0.0, eLog_totals, nullptr);
     }
   }
   if (mPresContext) {
-    if (gfxUserFontSet* fs = mPresContext->GetUserFontSet()) {
+    const bool mayFlushUserFontSet = false;
+    gfxUserFontSet* fs = mPresContext->GetUserFontSet(mayFlushUserFontSet);
+    if (fs) {
       uint32_t fontCount;
       uint64_t fontSize;
       fs->GetLoadStatistics(fontCount, fontSize);
       Telemetry::Accumulate(Telemetry::WEBFONT_PER_PAGE, fontCount);
       Telemetry::Accumulate(Telemetry::WEBFONT_SIZE_PER_PAGE,
                             uint32_t(fontSize / 1024));
     } else {
       Telemetry::Accumulate(Telemetry::WEBFONT_PER_PAGE, 0);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -9564,27 +9564,30 @@ static nsRect ComputeHTMLReferenceRect(n
   return StaticPrefs::layout_css_control_characters_visible()
              ? NS_STYLE_CONTROL_CHARACTER_VISIBILITY_VISIBLE
              : NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN;
 }
 
 /* static */
 already_AddRefed<nsFontMetrics> nsLayoutUtils::GetMetricsFor(
     nsPresContext* aPresContext, bool aIsVertical,
-    const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet) {
+    const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet,
+    FlushUserFontSet aFlushUserFontSet) {
   nsFont font = aStyleFont->mFont;
   font.size = aFontSize;
   gfxFont::Orientation orientation =
       aIsVertical ? gfxFont::eVertical : gfxFont::eHorizontal;
   nsFontMetrics::Params params;
   params.language = aStyleFont->mLanguage;
   params.explicitLanguage = aStyleFont->mExplicitLanguage;
   params.orientation = orientation;
-  params.userFontSet =
-      aUseUserFontSet ? aPresContext->GetUserFontSet() : nullptr;
+  params.userFontSet = aUseUserFontSet
+                           ? aPresContext->GetUserFontSet(aFlushUserFontSet ==
+                                                          FlushUserFontSet::Yes)
+                           : nullptr;
   params.textPerf = aPresContext->GetTextPerfMetrics();
   return aPresContext->DeviceContext()->GetMetricsFor(font, params);
 }
 
 /* static */ void nsLayoutUtils::FixupNoneGeneric(
     nsFont* aFont, const nsPresContext* aPresContext, uint8_t aGenericFontID,
     const nsFont* aDefaultVariableFont) {
   bool useDocumentFonts =
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2940,21 +2940,25 @@ class nsLayoutUtils {
 
   static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
                                           nsIFrame* aFrame);
 
   // Return the default value to be used for -moz-control-character-visibility,
   // from preferences.
   static uint8_t ControlCharVisibilityDefault();
 
-  // Callers are responsible to ensure the user-font-set is up-to-date if
-  // aUseUserFontSet is true.
+  enum class FlushUserFontSet {
+    Yes,
+    No,
+  };
+
   static already_AddRefed<nsFontMetrics> GetMetricsFor(
       nsPresContext* aPresContext, bool aIsVertical,
-      const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet);
+      const nsStyleFont* aStyleFont, nscoord aFontSize, bool aUseUserFontSet,
+      FlushUserFontSet aFlushUserFontSet);
 
   /**
    * Appropriately add the correct font if we are using DocumentFonts or
    * overriding for XUL
    */
   static void FixupNoneGeneric(nsFont* aFont, const nsPresContext* aPresContext,
                                uint8_t aGenericFontID,
                                const nsFont* aDefaultVariableFont);
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1856,18 +1856,18 @@ bool nsPresContext::HasAuthorSpecifiedRu
   if (pseudoType == CSSPseudoElementType::InheritingAnonBox ||
       pseudoType == CSSPseudoElementType::NonInheritingAnonBox) {
     return false;
   }
   return Servo_HasAuthorSpecifiedRules(computedStyle, elem, pseudoType,
                                        aRuleTypeMask, UseDocumentColors());
 }
 
-gfxUserFontSet* nsPresContext::GetUserFontSet() {
-  return mDocument->GetUserFontSet();
+gfxUserFontSet* nsPresContext::GetUserFontSet(bool aFlushUserFontSet) {
+  return mDocument->GetUserFontSet(aFlushUserFontSet);
 }
 
 void nsPresContext::UserFontSetUpdated(gfxUserFontEntry* aUpdatedFont) {
   if (!mShell) return;
 
   // Note: this method is called without a font when rules in the userfont set
   // are updated, which may occur during reflow as a result of the lazy
   // initialization of the userfont set. It would be better to avoid a full
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -896,17 +896,17 @@ class nsPresContext : public nsISupports
   }
 
   // This method should be used instead of directly accessing mPaintFlashing,
   // as that value may be out of date when mPaintFlashingInitialized is false.
   bool GetPaintFlashing() const;
 
   bool SuppressingResizeReflow() const { return mSuppressResizeReflow; }
 
-  gfxUserFontSet* GetUserFontSet();
+  gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
 
   // Should be called whenever the set of fonts available in the user
   // font set changes (e.g., because a new font loads, or because the
   // user font set is changed and fonts become unavailable).
   void UserFontSetUpdated(gfxUserFontEntry* aUpdatedFont = nullptr);
 
   gfxMissingFontRecorder* MissingFontRecorder() { return mMissingFonts.get(); }
 
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -167,38 +167,35 @@ FontFaceSet::FontFaceSet(nsPIDOMWindowIn
 }
 
 FontFaceSet::~FontFaceSet() {
   // Assert that we don't drop any FontFaceSet objects during a Servo traversal,
   // since PostTraversalTask objects can hold raw pointers to FontFaceSets.
   MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal());
 
   Disconnect();
+  for (auto it = mLoaders.Iter(); !it.Done(); it.Next()) {
+    it.Get()->GetKey()->Cancel();
+  }
 }
 
 JSObject* FontFaceSet::WrapObject(JSContext* aContext,
                                   JS::Handle<JSObject*> aGivenProto) {
   return FontFaceSet_Binding::Wrap(aContext, this, aGivenProto);
 }
 
 void FontFaceSet::Disconnect() {
   RemoveDOMContentLoadedListener();
 
   if (mDocument && mDocument->CSSLoader()) {
     // We're null checking CSSLoader() since FontFaceSet::Disconnect() might be
     // being called during unlink, at which time the loader amy already have
     // been unlinked from the document.
     mDocument->CSSLoader()->RemoveObserver(this);
   }
-
-  for (auto it = mLoaders.Iter(); !it.Done(); it.Next()) {
-    it.Get()->GetKey()->Cancel();
-  }
-
-  mLoaders.Clear();
 }
 
 void FontFaceSet::RemoveDOMContentLoadedListener() {
   if (mDocument) {
     mDocument->RemoveSystemEventListener(NS_LITERAL_STRING("DOMContentLoaded"),
                                          this, false);
   }
 }
@@ -579,17 +576,16 @@ nsresult FontFaceSet::StartLoad(gfxUserF
       principal ? principal->get() : nullptr,
       nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS, nsIContentPolicy::TYPE_FONT,
       nullptr,  // PerformanceStorage
       loadGroup);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RefPtr<nsFontFaceLoader> fontLoader = new nsFontFaceLoader(
       aUserFontEntry, aFontFaceSrc->mURI->get(), this, channel);
-  mLoaders.PutEntry(fontLoader);
 
   if (LOG_ENABLED()) {
     LOG(
         ("userfonts (%p) download start - font uri: (%s) "
          "referrer uri: (%s)\n",
          fontLoader.get(), aFontFaceSrc->mURI->GetSpecOrDefault().get(),
          aFontFaceSrc->mReferrer
              ? aFontFaceSrc->mReferrer->GetSpecOrDefault().get()
@@ -637,16 +633,17 @@ nsresult FontFaceSet::StartLoad(gfxUserF
       nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, loadGroup);
 
   rv = channel->AsyncOpen2(streamLoader);
   if (NS_FAILED(rv)) {
     fontLoader->DropChannel();  // explicitly need to break ref cycle
   }
 
   if (NS_SUCCEEDED(rv)) {
+    mLoaders.PutEntry(fontLoader);
     fontLoader->StartedLoading(streamLoader);
     // let the font entry remember the loader, in case we need to cancel it
     aUserFontEntry->SetLoader(fontLoader);
   }
 
   return rv;
 }
 
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -2053,17 +2053,18 @@ GeckoFontMetrics Gecko_GetFontMetrics(Ra
   // to be performed immediately after the traversal is finished.  This
   // works well for starting downloadable font loads, since we don't have
   // those fonts available to get metrics for anyway.  Platform fonts and
   // ArrayBuffer-backed FontFace objects are handled synchronously.
 
   nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
   presContext->SetUsesExChUnits(true);
   RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetMetricsFor(
-      presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet);
+      presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet,
+      nsLayoutUtils::FlushUserFontSet::No);
 
   ret.mXSize = fm->XHeight();
   gfxFloat zeroWidth = fm->GetThebesFontGroup()
                            ->GetFirstValidFont()
                            ->GetMetrics(fm->Orientation())
                            .zeroOrAveCharWidth;
   ret.mChSize = NS_round(aPresContext->AppUnitsPerDevPixel() * zeroWidth);
   return ret;
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -346,17 +346,19 @@ void ServoStyleSet::SetAuthorStyleDisabl
   // to rebuild stylist for this change. But we have bug around this, and we
   // may want to rethink how things should work. See bug 1437785.
   SetStylistStyleSheetsDirty();
 }
 
 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleFor(
     Element* aElement, LazyComputeBehavior aMayCompute) {
   if (aMayCompute == LazyComputeBehavior::Allow) {
-    return ResolveStyleLazily(aElement, CSSPseudoElementType::NotPseudo);
+    PreTraverseSync();
+    return ResolveStyleLazilyInternal(aElement,
+                                      CSSPseudoElementType::NotPseudo);
   }
 
   return ResolveServoStyle(*aElement);
 }
 
 const ServoElementSnapshotTable& ServoStyleSet::Snapshots() {
   MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
   return GetPresContext()->RestyleManager()->Snapshots();
@@ -371,22 +373,16 @@ void ServoStyleSet::ResolveMappedAttrDec
 }
 
 void ServoStyleSet::PreTraverseSync() {
   // Get the Document's root element to ensure that the cache is valid before
   // calling into the (potentially-parallel) Servo traversal, where a cache hit
   // is necessary to avoid a data race when updating the cache.
   mozilla::Unused << mDocument->GetRootElement();
 
-  // FIXME(emilio): This shouldn't be needed in theory, the call to the same
-  // function in PresShell should do the work, but as it turns out we
-  // ProcessPendingRestyles() twice, and runnables from frames just constructed
-  // can end up doing editing stuff, which adds stylesheets etc...
-  mDocument->FlushUserFontSet();
-
   ResolveMappedAttrDeclarationBlocks();
 
   nsMediaFeatures::InitSystemMetrics();
 
   LookAndFeel::NativeInit();
 
   mDocument->CacheAllKnownLangPrefs();
 
@@ -535,16 +531,17 @@ already_AddRefed<ComputedStyle> ServoSty
   MOZ_ASSERT(computedValues);
   return computedValues.forget();
 }
 
 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleLazily(
     Element* aElement, CSSPseudoElementType aPseudoType,
     StyleRuleInclusion aRuleInclusion) {
   PreTraverseSync();
+
   return ResolveStyleLazilyInternal(aElement, aPseudoType, aRuleInclusion);
 }
 
 already_AddRefed<ComputedStyle>
 ServoStyleSet::ResolveInheritingAnonymousBoxStyle(
     nsAtom* aPseudoTag, ComputedStyle* aParentContext) {
   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
              !nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -96,17 +96,17 @@ void nsFontFaceLoader::StartedLoading(ns
 }
 
 /* static */ void nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer,
                                                       void* aClosure) {
   nsFontFaceLoader* loader = static_cast<nsFontFaceLoader*>(aClosure);
 
   MOZ_DIAGNOSTIC_ASSERT(!loader->mInLoadTimerCallback);
   MOZ_DIAGNOSTIC_ASSERT(!loader->mInStreamComplete);
-  AutoRestore<bool> scope { loader->mInLoadTimerCallback };
+  AutoRestore<bool> scope{loader->mInLoadTimerCallback};
   loader->mInLoadTimerCallback = true;
 
   if (!loader->mFontFaceSet) {
     // We've been canceled
     return;
   }
 
   gfxUserFontEntry* ufe = loader->mUserFontEntry.get();
@@ -196,21 +196,19 @@ NS_IMETHODIMP
 nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
                                    nsISupports* aContext, nsresult aStatus,
                                    uint32_t aStringLen,
                                    const uint8_t* aString) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(!mInLoadTimerCallback);
   MOZ_DIAGNOSTIC_ASSERT(!mInStreamComplete);
 
-  AutoRestore<bool> scope { mInStreamComplete };
+  AutoRestore<bool> scope{mInStreamComplete};
   mInStreamComplete = true;
 
-  DropChannel();
-
   if (!mFontFaceSet) {
     // We've been canceled
     return aStatus;
   }
 
   TimeStamp doneTime = TimeStamp::Now();
   TimeDuration downloadTime = doneTime - mStartTime;
   uint32_t downloadTimeMS = uint32_t(downloadTime.ToMilliseconds());
@@ -308,34 +306,31 @@ nsFontFaceLoader::OnStartRequest(nsIRequ
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFontFaceLoader::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
                                 nsresult aStatusCode) {
   MOZ_ASSERT(NS_IsMainThread());
-  DropChannel();
   return NS_OK;
 }
 
 void nsFontFaceLoader::Cancel() {
   MOZ_DIAGNOSTIC_ASSERT(!mInLoadTimerCallback);
   MOZ_DIAGNOSTIC_ASSERT(!mInStreamComplete);
   MOZ_DIAGNOSTIC_ASSERT(mFontFaceSet);
 
   mUserFontEntry->LoadCanceled();
-  mUserFontEntry = nullptr;
   mFontFaceSet = nullptr;
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nullptr;
   }
-  nsCOMPtr<nsIChannel> channel = mChannel.forget();
-  channel->Cancel(NS_BINDING_ABORTED);
+  mChannel->Cancel(NS_BINDING_ABORTED);
 }
 
 StyleFontDisplay nsFontFaceLoader::GetFontDisplay() {
   if (!StaticPrefs::layout_css_font_display_enabled()) {
     return StyleFontDisplay::Auto;
   }
   return mUserFontEntry->GetFontDisplay();
 }
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -50,18 +50,17 @@ class nsFontFaceLoader final : public ns
   virtual ~nsFontFaceLoader();
 
   // helper method for determining the font-display value
   mozilla::StyleFontDisplay GetFontDisplay();
 
  private:
   RefPtr<gfxUserFontEntry> mUserFontEntry;
   nsCOMPtr<nsIURI> mFontURI;
-  // Cleared in FontFaceSet::~FontFaceSet, and on cancelation and such too.
-  mozilla::dom::FontFaceSet* MOZ_NON_OWNING_REF mFontFaceSet;
+  RefPtr<mozilla::dom::FontFaceSet> mFontFaceSet;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsITimer> mLoadTimer;
   mozilla::TimeStamp mStartTime;
   nsIStreamLoader* mStreamLoader;
   bool mInStreamComplete = false;
   bool mInLoadTimerCallback = false;
 };
 
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -634,18 +634,18 @@ void nsDocLoader::DocLoaderIsEmpty(bool 
       nsCOMPtr<mozilla::dom::Document> doc =
           do_GetInterface(GetAsSupports(this));
       if (doc) {
         // We start loads from style resolution, so we need to flush out style
         // no matter what.  If we have user fonts, we also need to flush layout,
         // since the reflow is what starts font loads.
         mozilla::FlushType flushType = mozilla::FlushType::Style;
         // Be safe in case this presshell is in teardown now
-        doc->FlushUserFontSet();
-        if (doc->GetUserFontSet()) {
+        nsPresContext* presContext = doc->GetPresContext();
+        if (presContext && presContext->GetUserFontSet()) {
           flushType = mozilla::FlushType::Layout;
         }
         mDontFlushLayout = mIsFlushingLayout = true;
         doc->FlushPendingNotifications(flushType);
         mDontFlushLayout = mIsFlushingLayout = false;
       }
     }