Bug 933044 - Push style scopes even if we would skip pushing ancestors when there is no ancestor filter. r=bz

This commit is contained in:
Cameron McCormack 2013-11-17 17:51:04 +11:00
parent ce3e819cab
commit 6a434aebfc
3 changed files with 102 additions and 57 deletions

View File

@ -2516,11 +2516,11 @@ ElementRestyler::RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint)
!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
UndisplayedNode* undisplayed =
frameConstructor->GetAllUndisplayedContentIn(undisplayedParent);
for (TreeMatchContext::AutoAncestorPusher
pushAncestor(undisplayed, mTreeMatchContext,
undisplayedParent ? undisplayedParent->AsElement()
: nullptr);
undisplayed; undisplayed = undisplayed->mNext) {
TreeMatchContext::AutoAncestorPusher pusher(mTreeMatchContext);
if (undisplayed) {
pusher.PushAncestorAndStyleScope(undisplayedParent);
}
for (; undisplayed; undisplayed = undisplayed->mNext) {
NS_ASSERTION(undisplayedParent ||
undisplayed->mContent ==
mPresContext->Document()->GetRootElement(),
@ -2533,11 +2533,10 @@ ElementRestyler::RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint)
// 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->IsActiveChildrenElement();
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint,
mTreeMatchContext,
parent && parent->IsElement() ? parent->AsElement() : nullptr);
TreeMatchContext::AutoAncestorPusher insertionPointPusher(mTreeMatchContext);
if (parent && parent->IsActiveChildrenElement()) {
insertionPointPusher.PushAncestorAndStyleScope(parent);
}
nsRestyleHint thisChildHint = aChildRestyleHint;
RestyleTracker::RestyleData undisplayedRestyleData;
@ -2685,12 +2684,11 @@ ElementRestyler::RestyleContentChildren(nsIFrame* aParent,
nsRestyleHint aChildRestyleHint)
{
nsIFrame::ChildListIterator lists(aParent);
for (TreeMatchContext::AutoAncestorPusher
pushAncestor(!lists.IsDone(),
mTreeMatchContext,
mContent && mContent->IsElement()
? mContent->AsElement() : nullptr);
!lists.IsDone(); lists.Next()) {
TreeMatchContext::AutoAncestorPusher ancestorPusher(mTreeMatchContext);
if (!lists.IsDone()) {
ancestorPusher.PushAncestorAndStyleScope(mContent);
}
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
@ -2706,10 +2704,10 @@ ElementRestyler::RestyleContentChildren(nsIFrame* aParent,
// 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->IsActiveChildrenElement();
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint, mTreeMatchContext,
parent && parent->IsElement() ? parent->AsElement() : nullptr);
TreeMatchContext::AutoAncestorPusher insertionPointPusher(mTreeMatchContext);
if (parent && parent->IsActiveChildrenElement()) {
insertionPointPusher.PushAncestorAndStyleScope(parent);
}
// only do frames that are in flow
if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder

View File

@ -2358,8 +2358,8 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
return nullptr;
}
TreeMatchContext::AutoAncestorPusher
ancestorPusher(true, state.mTreeMatchContext, aDocElement);
TreeMatchContext::AutoAncestorPusher ancestorPusher(state.mTreeMatchContext);
ancestorPusher.PushAncestorAndStyleScope(aDocElement);
// Make sure to start any background image loads for the root element now.
styleContext->StartBackgroundImageLoads();
@ -3552,12 +3552,15 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
// 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->IsActiveChildrenElement();
TreeMatchContext::AutoAncestorPusher
insertionPointPusher(pushInsertionPoint,
aState.mTreeMatchContext,
parent && parent->IsElement() ? parent->AsElement() : nullptr);
insertionPointPusher(aState.mTreeMatchContext);
if (parent && parent->IsActiveChildrenElement()) {
if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
insertionPointPusher.PushAncestorAndStyleScope(parent);
} else {
insertionPointPusher.PushStyleScope(parent);
}
}
// Push the content as a style ancestor now, so we don't have to do
// it in our various full-constructor functions. In particular,
@ -3568,9 +3571,12 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
// pushing of the content instead of having to do it in multiple
// places.
TreeMatchContext::AutoAncestorPusher
ancestorPusher(aState.mTreeMatchContext.mAncestorFilter.HasFilter(),
aState.mTreeMatchContext,
content->IsElement() ? content->AsElement() : nullptr);
ancestorPusher(aState.mTreeMatchContext);
if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
ancestorPusher.PushAncestorAndStyleScope(content);
} else {
ancestorPusher.PushStyleScope(content);
}
nsIFrame* newFrame;
nsIFrame* primaryFrame;
@ -3792,10 +3798,12 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
aPendingBinding);
TreeMatchContext::AutoAncestorPusher
ancestorPusher(aState.mTreeMatchContext.mAncestorFilter.HasFilter(),
aState.mTreeMatchContext,
aParent->AsElement());
TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
ancestorPusher.PushAncestorAndStyleScope(aParent->AsElement());
} else {
ancestorPusher.PushStyleScope(aParent->AsElement());
}
nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
NS_ASSERTION(creator,
@ -9313,11 +9321,14 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
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());
TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
if (parent != aContent) {
if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
ancestorPusher.PushAncestorAndStyleScope(parent->AsElement());
} else {
ancestorPusher.PushStyleScope(parent->AsElement());
}
}
// Frame construction item construction should not post
// restyles, so removing restyle flags here is safe.
@ -10566,10 +10577,12 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
nsStyleContext* const parentStyleContext = aParentItem.mStyleContext;
nsIContent* const parentContent = aParentItem.mContent;
TreeMatchContext::AutoAncestorPusher
ancestorPusher(aState.mTreeMatchContext.mAncestorFilter.HasFilter(),
aState.mTreeMatchContext,
parentContent->AsElement());
TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
ancestorPusher.PushAncestorAndStyleScope(parentContent->AsElement());
} else {
ancestorPusher.PushStyleScope(parentContent->AsElement());
}
if (!aItemIsWithinSVGText) {
// Probe for generated content before
@ -10605,11 +10618,14 @@ nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
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());
TreeMatchContext::AutoAncestorPusher insertionPointPusher(aState.mTreeMatchContext);
if (contentParent != parentContent) {
if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
insertionPointPusher.PushAncestorAndStyleScope(contentParent->AsElement());
} else {
insertionPointPusher.PushStyleScope(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,

View File

@ -238,29 +238,60 @@ struct MOZ_STACK_CLASS TreeMatchContext {
/* Helper class for maintaining the ancestor state */
class MOZ_STACK_CLASS AutoAncestorPusher {
public:
AutoAncestorPusher(bool aDoPush,
TreeMatchContext &aTreeMatchContext,
mozilla::dom::Element *aElement
AutoAncestorPusher(TreeMatchContext& aTreeMatchContext
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mPushed(aDoPush && aElement),
mTreeMatchContext(aTreeMatchContext),
mElement(aElement)
: mPushedAncestor(false)
, mPushedStyleScope(false)
, mTreeMatchContext(aTreeMatchContext)
, mElement(nullptr)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (mPushed) {
}
void PushAncestorAndStyleScope(mozilla::dom::Element* aElement) {
MOZ_ASSERT(!mElement);
if (aElement) {
mElement = aElement;
mPushedAncestor = true;
mPushedStyleScope = true;
mTreeMatchContext.mAncestorFilter.PushAncestor(aElement);
mTreeMatchContext.PushStyleScope(aElement);
}
}
void PushAncestorAndStyleScope(nsIContent* aContent) {
if (aContent && aContent->IsElement()) {
PushAncestorAndStyleScope(aContent->AsElement());
}
}
void PushStyleScope(mozilla::dom::Element* aElement) {
MOZ_ASSERT(!mElement);
if (aElement) {
mElement = aElement;
mPushedStyleScope = true;
mTreeMatchContext.PushStyleScope(aElement);
}
}
void PushStyleScope(nsIContent* aContent) {
if (aContent && aContent->IsElement()) {
PushStyleScope(aContent->AsElement());
}
}
~AutoAncestorPusher() {
if (mPushed) {
if (mPushedAncestor) {
mTreeMatchContext.mAncestorFilter.PopAncestor();
}
if (mPushedStyleScope) {
mTreeMatchContext.PopStyleScope(mElement);
}
}
private:
bool mPushed;
bool mPushedAncestor;
bool mPushedStyleScope;
TreeMatchContext& mTreeMatchContext;
mozilla::dom::Element* mElement;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER