Bug 1321284 - Part 1: Make StyleChildrenIterator skip NAC generated by root element primary frame ancestors. r=bholley
MozReview-Commit-ID: HICYWQgkE77
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -378,17 +378,20 @@ AllChildrenIterator::Seek(nsIContent* aC
void
AllChildrenIterator::AppendNativeAnonymousChildren()
{
AppendNativeAnonymousChildrenFromFrame(mOriginalContent->GetPrimaryFrame());
// The root scroll frame is not the primary frame of the root element.
// Detect and handle this case.
- if (mOriginalContent == mOriginalContent->OwnerDoc()->GetRootElement()) {
+ //
+ // XXXheycam This probably needs to find the nsCanvasFrame's NAC too.
+ if (!(mFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
+ mOriginalContent == mOriginalContent->OwnerDoc()->GetRootElement()) {
nsIPresShell* presShell = mOriginalContent->OwnerDoc()->GetShell();
nsIFrame* scrollFrame = presShell ? presShell->GetRootScrollFrame() : nullptr;
if (scrollFrame) {
AppendNativeAnonymousChildrenFromFrame(scrollFrame);
}
}
}
@@ -580,22 +583,16 @@ StyleChildrenIterator::IsNeeded(const El
}
// If the node has native anonymous content, return true.
nsIAnonymousContentCreator* ac = do_QueryFrame(aElement->GetPrimaryFrame());
if (ac) {
return true;
}
- // The root element has a scroll frame that is not the primary frame, so we
- // need to do special checking for that case.
- if (aElement == aElement->OwnerDoc()->GetRootElement()) {
- return true;
- }
-
return false;
}
nsIContent*
StyleChildrenIterator::GetNextChild()
{
while (nsIContent* child = AllChildrenIterator::GetNextChild()) {
--- a/dom/base/ChildIterator.h
+++ b/dom/base/ChildIterator.h
@@ -251,28 +251,32 @@ private:
// there's no easy way to do that.
nsMutationGuard mMutationGuard;
#endif
};
/**
* StyleChildrenIterator traverses the children of the element from the
* perspective of the style system, particularly the children we need to traverse
- * during restyle. This is identical to AllChildrenIterator with eAllChildren,
- * _except_ that we detect and skip any native anonymous children that are used
- * to implement pseudo-elements (since the style system needs to cascade those
- * using different algorithms).
+ * during restyle. This is identical to AllChildrenIterator with
+ * (eAllChildren | eSkipDocumentLevelNativeAnonymousContent), _except_ that we
+ * detect and skip any native anonymous children that are used to implement
+ * pseudo-elements (since the style system needs to cascade those using
+ * different algorithms).
*
* Note: it assumes that no mutation of the DOM or frame tree takes place during
* iteration, and will break horribly if that is not true.
*/
-class StyleChildrenIterator : private AllChildrenIterator {
+class StyleChildrenIterator : private AllChildrenIterator
+{
public:
explicit StyleChildrenIterator(const nsIContent* aContent)
- : AllChildrenIterator(aContent, nsIContent::eAllChildren)
+ : AllChildrenIterator(aContent,
+ nsIContent::eAllChildren |
+ nsIContent::eSkipDocumentLevelNativeAnonymousContent)
{
MOZ_COUNT_CTOR(StyleChildrenIterator);
}
~StyleChildrenIterator() { MOZ_COUNT_DTOR(StyleChildrenIterator); }
nsIContent* GetNextChild();
// Returns true if we cannot find all the children we need to style by
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -140,17 +140,24 @@ public:
* 4. :after generated node
*/
eAllButXBL = 1,
/**
* Skip native anonymous content created for placeholder of HTML input,
* used in conjunction with eAllChildren or eAllButXBL.
*/
- eSkipPlaceholderContent = 2
+ eSkipPlaceholderContent = 2,
+
+ /**
+ * Skip native anonymous content created by ancestor frames of the root
+ * element's primary frame, such as scrollbar elements created by the root
+ * scroll frame.
+ */
+ eSkipDocumentLevelNativeAnonymousContent = 4,
};
/**
* Return either the XBL explicit children of the node or the XBL flattened
* tree children of the node, depending on the filter, as well as
* native anonymous children.
*
* @note calling this method with eAllButXBL will return children that are
--- a/layout/generic/nsIAnonymousContentCreator.h
+++ b/layout/generic/nsIAnonymousContentCreator.h
@@ -61,17 +61,19 @@ public:
* that.
*/
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements)=0;
/**
* Appends "native" anonymous children created by CreateAnonymousContent()
* to the given content list depending on the filter.
*
- * @see nsIContent::GetChildren for set of values used for filter.
+ * @see nsIContent::GetChildren for set of values used for filter. Currently,
+ * eSkipPlaceholderContent is the only flag that any implementation of
+ * this method heeds.
*/
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) = 0;
/**
* Implementations can override this method to create special frames for the
* anonymous content returned from CreateAnonymousContent.
* By default this method returns nullptr, which means the default frame