Bug 1355351: Clean up pseudo-element props. r=heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 19 Apr 2017 10:27:33 +0200
changeset 568272 4349d76b8236458508f3a173be7df31a176a4e8c
parent 568271 aa1b1b7f851eba2ba42d5f57f6aec6523534fc03
child 568273 64474e0dddf1caf6c5c04a93065e4ffff5e12c7b
push id55809
push userbmo:emilio+bugs@crisal.io
push dateTue, 25 Apr 2017 22:14:00 +0000
reviewersheycam
bugs1355351
milestone55.0a1
Bug 1355351: Clean up pseudo-element props. r=heycam MozReview-Commit-ID: JZAhEN3chPs
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsLayoutUtils.cpp
layout/generic/nsIFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -6140,16 +6140,19 @@ nsCSSFrameConstructor::AddFrameConstruct
 }
 
 static void
 AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIContent* aContent)
 {
   NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aOwnerFrame),
                "property should only be set on first continuation/ib-sibling");
 
+  // FIXME(emilio): Remove this property, and use the frame of the generated
+  // content itself to tear the content down? It should be quite simpler.
+
   FrameProperties props = aOwnerFrame->Properties();
   nsIFrame::ContentArray* value = props.Get(nsIFrame::GenConProperty());
   if (!value) {
     value = new nsIFrame::ContentArray;
     props.Set(nsIFrame::GenConProperty(), value);
   }
   value->AppendElement(aContent);
 }
@@ -6401,17 +6404,17 @@ AdjustAppendParentForAfterContent(nsFram
                                   nsIContent* aChild,
                                   nsIFrame** aAfterFrame)
 {
   // If the parent frame has any pseudo-elements or aContainer is a
   // display:contents node then we need to walk through the child
   // frames to find the first one that is either a ::after frame for an
   // ancestor of aChild or a frame that is for a node later in the
   // document than aChild and return that in aAfterFrame.
-  if (aParentFrame->GetGenConPseudos() ||
+  if (aParentFrame->Properties().Get(nsIFrame::GenConProperty()) ||
       nsLayoutUtils::HasPseudoStyle(aContainer, aParentFrame->StyleContext(),
                                     CSSPseudoElementType::after,
                                     aParentFrame->PresContext()) ||
       aFrameManager->GetDisplayContentsStyleFor(aContainer)) {
     nsIFrame* afterFrame = nullptr;
     nsContainerFrame* parent =
       static_cast<nsContainerFrame*>(aParentFrame->LastContinuation());
     bool done = false;
@@ -8534,35 +8537,33 @@ nsCSSFrameConstructor::ContentRemoved(ns
   if (!childFrame || childFrame->GetContent() != aChild) {
     // XXXbz the GetContent() != aChild check is needed due to bug 135040.
     // Remove it once that's fixed.
     ClearUndisplayedContentIn(aChild, aContainer);
   }
   MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
              "display:contents nodes shouldn't have a frame");
   if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
-    nsIFrame* ancestorFrame = nullptr;
     nsIContent* ancestor = aContainer;
-    for (; ancestor; ancestor = ancestor->GetParent()) {
-      ancestorFrame = ancestor->GetPrimaryFrame();
-      if (ancestorFrame) {
-        break;
-      }
-    }
-    if (ancestorFrame) {
-      nsTArray<nsIContent*>* generated = ancestorFrame->GetGenConPseudos();
-      if (generated) {
-        *aDidReconstruct = true;
-        LAYOUT_PHASE_TEMP_EXIT();
-        // XXXmats Can we recreate frames only for the ::after/::before content?
-        // XXX Perhaps even only those that belong to the aChild sub-tree?
-        RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor);
-        LAYOUT_PHASE_TEMP_REENTER();
-        return;
-      }
+    while (!ancestor->GetPrimaryFrame()) {
+      // FIXME(emilio): Should this use the flattened tree parent instead?
+      ancestor = ancestor->GetParent();
+      MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
+    }
+
+    nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
+    if (ancestorFrame->Properties().Get(nsIFrame::GenConProperty())) {
+      *aDidReconstruct = true;
+      LAYOUT_PHASE_TEMP_EXIT();
+
+      // XXXmats Can we recreate frames only for the ::after/::before content?
+      // XXX Perhaps even only those that belong to the aChild sub-tree?
+      RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor);
+      LAYOUT_PHASE_TEMP_REENTER();
+      return;
     }
 
     FlattenedChildIterator iter(aChild);
     for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
       if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) {
         LAYOUT_PHASE_TEMP_EXIT();
         ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct, aDestroyedFramesFor);
         LAYOUT_PHASE_TEMP_REENTER();
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1584,90 +1584,34 @@ nsLayoutUtils::GetChildListNameFor(nsIFr
 
   return id;
 }
 
 /*static*/ nsIFrame*
 nsLayoutUtils::GetBeforeFrameForContent(nsIFrame* aFrame,
                                         const nsIContent* aContent)
 {
-  // We need to call GetGenConPseudos() on the first continuation/ib-split.
-  // Find it, for symmetry with GetAfterFrameForContent.
-  nsContainerFrame* genConParentFrame =
-    FirstContinuationOrIBSplitSibling(aFrame)->GetContentInsertionFrame();
-  if (!genConParentFrame) {
-    return nullptr;
-  }
-  nsTArray<nsIContent*>* prop = genConParentFrame->GetGenConPseudos();
-  if (prop) {
-    const nsTArray<nsIContent*>& pseudos(*prop);
-    for (uint32_t i = 0; i < pseudos.Length(); ++i) {
-      if (pseudos[i]->GetParent() == aContent &&
-          pseudos[i]->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) {
-        return pseudos[i]->GetPrimaryFrame();
-      }
-    }
-  }
-  // If the first child frame is a pseudo-frame, then try that.
-  // Note that the frame we create for the generated content is also a
-  // pseudo-frame and so don't drill down in that case.
-  nsIFrame* childFrame = genConParentFrame->PrincipalChildList().FirstChild();
-  if (childFrame &&
-      childFrame->IsPseudoFrame(aContent) &&
-      !childFrame->IsGeneratedContentFrame()) {
-    return GetBeforeFrameForContent(childFrame, aContent);
-  }
-  return nullptr;
+  auto* pseudo =
+    static_cast<Element*>(aContent->GetProperty(nsGkAtoms::beforePseudoProperty));
+  return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
 }
 
 /*static*/ nsIFrame*
 nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame)
 {
   return GetBeforeFrameForContent(aFrame, aFrame->GetContent());
 }
 
 /*static*/ nsIFrame*
 nsLayoutUtils::GetAfterFrameForContent(nsIFrame* aFrame,
                                        const nsIContent* aContent)
 {
-  // We need to call GetGenConPseudos() on the first continuation,
-  // but callers are likely to pass the last.
-  nsContainerFrame* genConParentFrame =
-    FirstContinuationOrIBSplitSibling(aFrame)->GetContentInsertionFrame();
-  if (!genConParentFrame) {
-    return nullptr;
-  }
-  nsTArray<nsIContent*>* prop = genConParentFrame->GetGenConPseudos();
-  if (prop) {
-    const nsTArray<nsIContent*>& pseudos(*prop);
-    for (uint32_t i = 0; i < pseudos.Length(); ++i) {
-      if (pseudos[i]->GetParent() == aContent &&
-          pseudos[i]->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) {
-        return pseudos[i]->GetPrimaryFrame();
-      }
-    }
-  }
-  // If the last child frame is a pseudo-frame, then try that.
-  // Note that the frame we create for the generated content is also a
-  // pseudo-frame and so don't drill down in that case.
-  genConParentFrame = aFrame->GetContentInsertionFrame();
-  if (!genConParentFrame) {
-    return nullptr;
-  }
-  nsIFrame* lastParentContinuation =
-    LastContinuationWithChild(static_cast<nsContainerFrame*>(
-      LastContinuationOrIBSplitSibling(genConParentFrame)));
-  nsIFrame* childFrame =
-    lastParentContinuation->GetChildList(nsIFrame::kPrincipalList).LastChild();
-  if (childFrame &&
-      childFrame->IsPseudoFrame(aContent) &&
-      !childFrame->IsGeneratedContentFrame()) {
-    return GetAfterFrameForContent(childFrame->FirstContinuation(), aContent);
-  }
-  return nullptr;
+  auto* pseudo =
+    static_cast<Element*>(aContent->GetProperty(nsGkAtoms::afterPseudoProperty));
+  return pseudo ? pseudo->GetPrimaryFrame() : nullptr;
 }
 
 /*static*/ nsIFrame*
 nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame)
 {
   return GetAfterFrameForContent(aFrame, aFrame->GetContent());
 }
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1175,20 +1175,16 @@ public:
     return GetBidiData().baseLevel;
   }
 
   nsBidiLevel GetEmbeddingLevel()
   {
     return GetBidiData().embeddingLevel;
   }
 
-  nsTArray<nsIContent*>* GetGenConPseudos() {
-    return Properties().Get(GenConProperty());
-  }
-
   /**
    * Return the distance between the border edge of the frame and the
    * margin edge of the frame.  Like GetRect(), returns the dimensions
    * as of the most recent reflow.
    *
    * This doesn't include any margin collapsing that may have occurred.
    *
    * It also treats 'auto' margins as zero, and treats any margins that