Bug 1389790: Ensure we always have an up-to-date style context even if we have no frame. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sat, 12 Aug 2017 22:17:44 +0200
changeset 645447 4a684759eef5dbd064fe6277d3dc7da4ea08c000
parent 645446 06a92f01da236f510473723ce3d2e69ddfed7205
child 725902 039ccebfd8b1023961c64ac6de9bc2de4c3c2aea
push id73753
push userbmo:emilio+bugs@crisal.io
push dateSat, 12 Aug 2017 22:07:14 +0000
reviewersheycam
bugs1389790
milestone57.0a1
Bug 1389790: Ensure we always have an up-to-date style context even if we have no frame. r?heycam I'm still not quite sure how may we end up restyling a text node under there, but all my attempts to build a test-case have failed. Anyway this is the right thing to do. MozReview-Commit-ID: FitqSKhNt2n
layout/base/ServoRestyleManager.cpp
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -786,44 +786,48 @@ ServoRestyleManager::ProcessPostTraversa
     thisFrameRestyleState.emplace(*styleFrame, aRestyleState, changeHint, type);
   }
 
   // We can't really assume as used changes from display: contents elements (or
   // other elements without frames).
   ServoRestyleState& childrenRestyleState =
     thisFrameRestyleState ? *thisFrameRestyleState : aRestyleState;
 
-  RefPtr<ServoStyleContext> newContext = nullptr;
+  RefPtr<ServoStyleContext> upToDateContext =
+    (wasRestyled || !oldStyleContext)
+      ? aRestyleState.StyleSet().ResolveServoStyle(aElement)
+      : oldStyleContext;
+
+  MOZ_ASSERT(upToDateContext);
+
   if (wasRestyled && oldStyleContext) {
     MOZ_ASSERT(styleFrame || displayContentsStyle);
-    newContext =
-      aRestyleState.StyleSet().ResolveServoStyle(aElement);
-    MOZ_ASSERT(oldStyleContext->ComputedData() != newContext->ComputedData());
+    MOZ_ASSERT(oldStyleContext->ComputedData() != upToDateContext->ComputedData());
 
-    newContext->ResolveSameStructsAs(oldStyleContext);
+    upToDateContext->ResolveSameStructsAs(oldStyleContext);
 
     // We want to walk all the continuations here, even the ones with different
     // styles.  In practice, the only reason we get continuations with different
     // styles here is ::first-line (::first-letter never affects element
     // styles).  But in that case, newContext is the right context for the
     // _later_ continuations anyway (the ones not affected by ::first-line), not
     // the earlier ones, so there is no point stopping right at the point when
     // we'd actually be setting the right style context.
     //
     // This does mean that we may be setting the wrong style context on our
     // initial continuations; ::first-line fixes that up after the fact.
     for (nsIFrame* f = styleFrame; f; f = f->GetNextContinuation()) {
       MOZ_ASSERT_IF(f != styleFrame, !f->GetAdditionalStyleContext(0));
-      f->SetStyleContext(newContext);
+      f->SetStyleContext(upToDateContext);
     }
 
     if (MOZ_UNLIKELY(displayContentsStyle)) {
       MOZ_ASSERT(!styleFrame);
       PresContext()->FrameConstructor()->
-        ChangeRegisteredDisplayContentsStyleFor(aElement, newContext);
+        ChangeRegisteredDisplayContentsStyleFor(aElement, upToDateContext);
     }
 
     if (styleFrame) {
       UpdateAdditionalStyleContexts(styleFrame, aRestyleState);
       styleFrame->UpdateStyleOfOwnedAnonBoxes(childrenRestyleState);
     }
 
     if (!aElement->GetParent()) {
@@ -851,19 +855,16 @@ ServoRestyleManager::ProcessPostTraversa
 
   const bool traverseElementChildren =
     NeedsToTraverseElementChildren(*aElement);
   const bool descendantsNeedFrames =
     aElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
   const bool traverseTextChildren = wasRestyled || descendantsNeedFrames;
   bool recreatedAnyContext = wasRestyled;
   if (traverseElementChildren || traverseTextChildren) {
-    ServoStyleContext* upToDateContext =
-      wasRestyled ? newContext : oldStyleContext;
-
     StyleChildrenIterator it(aElement);
     TextPostTraversalState textState(*upToDateContext,
                                      displayContentsStyle && wasRestyled,
                                      childrenRestyleState);
     for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
       if (traverseElementChildren && n->IsElement()) {
         recreatedAnyContext |= ProcessPostTraversal(n->AsElement(),
                                                     upToDateContext,