Bug 653881 - Push <xbl:children> in ancestor filter. r=bz,dbaron

--HG--
extra : rebase_source : 9aafffadd2451ca7274e99d7e07d0d71ea52ca02
This commit is contained in:
William Chen 2013-05-30 17:39:08 -07:00
parent a3a6516091
commit 1f6764a664
3 changed files with 66 additions and 19 deletions

View File

@ -3513,6 +3513,19 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
const nsStyleDisplay* display = styleContext->StyleDisplay();
nsIContent* const content = aItem.mContent;
// Get the parent of the content and check if it is a XBL children element.
// Push the children element as an ancestor here because it does
// not have a frame and would not otherwise be pushed as an ancestor. It is
// necessary to do so in order to correctly handle style resolution on
// descendants.
nsIContent* parent = content->GetParent();
bool pushInsertionPoint = aState.mTreeMatchContext.mAncestorFilter.HasFilter() &&
parent && parent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL);
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint,
aState.mTreeMatchContext,
parent && parent->IsElement() ? parent->AsElement() : nullptr);
// Push the content as a style ancestor now, so we don't have to do
// it in our various full-constructor functions. In particular,
// since a number of full-constructor functions don't actually call
@ -9945,6 +9958,20 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
FlattenedChildIterator iter(aContent);
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
// Get the parent of the content and check if it is a XBL children element
// (if the content is a children element then parent != aContent because the
// FlattenedChildIterator will transitively iterate through <xbl:children>
// for default content). Push the children element as an ancestor here because
// it does not have a frame and would not otherwise be pushed as an ancestor.
nsIContent* parent = child->GetParent();
MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children.");
MOZ_ASSERT(parent->IsElement());
bool pushInsertionPoint = parent != aContent &&
aState.mTreeMatchContext.mAncestorFilter.HasFilter();
TreeMatchContext::AutoAncestorPusher
ancestorPusher(pushInsertionPoint, aState.mTreeMatchContext,
parent->AsElement());
// Frame construction item construction should not post
// restyles, so removing restyle flags here is safe.
if (child->IsElement()) {
@ -11204,6 +11231,20 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
FlattenedChildIterator iter(parentContent);
for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
// Get the parent of the content and check if it is a XBL children element
// (if the content is a children element then contentParent != parentContent because the
// FlattenedChildIterator will transitively iterate through <xbl:children>
// for default content). Push the children element as an ancestor here because
// it does not have a frame and would not otherwise be pushed as an ancestor.
nsIContent* contentParent = content->GetParent();
MOZ_ASSERT(contentParent, "Parent must be non-null because we are iterating children.");
MOZ_ASSERT(contentParent->IsElement());
bool pushInsertionPoint = contentParent != parentContent &&
aState.mTreeMatchContext.mAncestorFilter.HasFilter();
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint, aState.mTreeMatchContext,
contentParent->AsElement());
// Manually check for comments/PIs, since we don't have a frame to pass to
// AddFrameConstructionItems. We know our parent is a non-replaced inline,
// so there is no need to do the NeedFrameFor check.

View File

@ -1369,6 +1369,18 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
NS_ASSERTION(!undisplayed->mStyle->GetPseudo(),
"Shouldn't have random pseudo style contexts in the "
"undisplayed map");
// Get the parent of the undisplayed content and check if it is a XBL
// children element. Push the children element as an ancestor here because it does
// not have a frame and would not otherwise be pushed as an ancestor.
nsIContent* parent = undisplayed->mContent->GetParent();
bool pushInsertionPoint = parent &&
parent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL);
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint,
aTreeMatchContext,
parent && parent->IsElement() ? parent->AsElement() : nullptr);
nsRestyleHint thisChildHint = childRestyleHint;
RestyleTracker::RestyleData undisplayedRestyleData;
if (aRestyleTracker.GetRestyleData(undisplayed->mContent->AsElement(),
@ -1524,6 +1536,19 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
// Get the parent of the child frame's content and check if it is a XBL
// children element. Push the children element as an ancestor here because it does
// not have a frame and would not otherwise be pushed as an ancestor.
// Check if the frame has a content because |child| may be a nsPageFrame that does
// not have a content.
nsIContent* parent = child->GetContent() ? child->GetContent()->GetParent() : nullptr;
bool pushInsertionPoint = parent &&
parent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL);
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint, aTreeMatchContext,
parent && parent->IsElement() ? parent->AsElement() : nullptr);
// only do frames that are in flow
if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
// get out of flow frame and recur there

View File

@ -3395,14 +3395,6 @@ TreeMatchContext::InitAncestors(Element *aElement)
break;
}
if (parent->AsElement()->NodeInfo()->Equals(nsGkAtoms::children,
kNameSpaceID_XBL)) {
parent = parent->GetParentNode();
if (!parent->IsElement()) {
break;
}
}
cur = parent->AsElement();
} while (true);
@ -3471,17 +3463,6 @@ AncestorFilter::AssertHasAllAncestors(Element *aElement) const
{
nsINode* cur = aElement->GetParentNode();
while (cur && cur->IsElement()) {
// We build our ancestor tree from the top-down. However, because
// <xbl:children> elements don't have frames and don't directly
// participate in the style tree, they never get pushed as ancestors.
// Skip them on the way up as we do on the way down (see also
// mozilla::dom::ExplicitChildIterator).
if (cur->AsElement()->NodeInfo()->Equals(nsGkAtoms::children,
kNameSpaceID_XBL)) {
cur = cur->GetParentNode();
continue;
}
MOZ_ASSERT(mElements.Contains(cur));
cur = cur->GetParentNode();
}