mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
Make the 'noappend' selector optimizations only restyle later siblings, which is what they need to do. (Bug 534804) r=bzbarsky
This commit is contained in:
parent
76df418748
commit
86bba93f79
@ -139,18 +139,19 @@ enum {
|
||||
NODE_HAS_EDGE_CHILD_SELECTOR = 0x00008000U,
|
||||
|
||||
// A child of the node has a selector such that any insertion or
|
||||
// removal of children requires restyling the parent (but append is
|
||||
// OK). Additionally (in this manner it is stronger than
|
||||
// NODE_HAS_SLOW_SELECTOR), if a child's style changes in any way
|
||||
// (e.g., the child changes to or from matching :empty due to a
|
||||
// grandchild changes), the node must also be restyled.
|
||||
NODE_HAS_SLOW_SELECTOR_NOAPPEND
|
||||
// removal of children requires restyling later siblings of that
|
||||
// element. Additionally (in this manner it is stronger than
|
||||
// NODE_HAS_SLOW_SELECTOR), if a child's style changes due to any
|
||||
// other content tree changes (e.g., the child changes to or from
|
||||
// matching :empty due to a grandchild insertion or removal), the
|
||||
// child's later siblings must also be restyled.
|
||||
NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS
|
||||
= 0x00010000U,
|
||||
|
||||
NODE_ALL_SELECTOR_FLAGS = NODE_HAS_EMPTY_SELECTOR |
|
||||
NODE_HAS_SLOW_SELECTOR |
|
||||
NODE_HAS_EDGE_CHILD_SELECTOR |
|
||||
NODE_HAS_SLOW_SELECTOR_NOAPPEND,
|
||||
NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS,
|
||||
|
||||
NODE_MAY_HAVE_CONTENT_EDITABLE_ATTR
|
||||
= 0x00020000U,
|
||||
|
@ -11320,16 +11320,16 @@ nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame)
|
||||
void
|
||||
nsCSSFrameConstructor::RestyleForEmptyChange(Element* aContainer)
|
||||
{
|
||||
Element* toRestyle = aContainer;
|
||||
// In some cases (:empty + E, :empty ~ E), a change if the content of
|
||||
// an element requires restyling its grandparent, because it changes
|
||||
// its parent's :empty state.
|
||||
nsRestyleHint hint = eRestyle_Self;
|
||||
nsIContent* grandparent = aContainer->GetParent();
|
||||
if (grandparent &&
|
||||
(grandparent->GetFlags() & NODE_HAS_SLOW_SELECTOR_NOAPPEND)) {
|
||||
toRestyle = grandparent->AsElement();
|
||||
(grandparent->GetFlags() & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS)) {
|
||||
hint = nsRestyleHint(hint | eRestyle_LaterSiblings);
|
||||
}
|
||||
PostRestyleEvent(toRestyle, eRestyle_Self, NS_STYLE_HINT_NONE);
|
||||
PostRestyleEvent(aContainer, hint, NS_STYLE_HINT_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -11347,7 +11347,7 @@ nsCSSFrameConstructor::RestyleForAppend(Element* aContainer,
|
||||
#endif
|
||||
PRUint32 selectorFlags =
|
||||
aContainer->GetFlags() & (NODE_ALL_SELECTOR_FLAGS &
|
||||
~NODE_HAS_SLOW_SELECTOR_NOAPPEND);
|
||||
~NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
|
||||
if (selectorFlags == 0)
|
||||
return;
|
||||
|
||||
@ -11391,6 +11391,25 @@ nsCSSFrameConstructor::RestyleForAppend(Element* aContainer,
|
||||
}
|
||||
}
|
||||
|
||||
// Needed since we can't use PostRestyleEvent on non-elements (with
|
||||
// eRestyle_LaterSiblings or nsRestyleHint(eRestyle_Self |
|
||||
// eRestyle_LaterSiblings) as appropriate).
|
||||
static void
|
||||
RestyleSiblingsStartingWith(nsCSSFrameConstructor *aFrameConstructor,
|
||||
nsIContent *aStartingSibling /* may be null */)
|
||||
{
|
||||
for (nsIContent *sibling = aStartingSibling; sibling;
|
||||
sibling = sibling->GetNextSibling()) {
|
||||
if (sibling->IsElement()) {
|
||||
aFrameConstructor->
|
||||
PostRestyleEvent(sibling->AsElement(),
|
||||
nsRestyleHint(eRestyle_Self | eRestyle_LaterSiblings),
|
||||
NS_STYLE_HINT_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restyling for a ContentInserted or CharacterDataChanged notification.
|
||||
// This could be used for ContentRemoved as well if we got the
|
||||
// notification before the removal happened (and sometimes
|
||||
@ -11431,13 +11450,17 @@ nsCSSFrameConstructor::RestyleForInsertOrChange(Element* aContainer,
|
||||
}
|
||||
}
|
||||
|
||||
if (selectorFlags & (NODE_HAS_SLOW_SELECTOR |
|
||||
NODE_HAS_SLOW_SELECTOR_NOAPPEND)) {
|
||||
if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
|
||||
PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE);
|
||||
// Restyling the container is the most we can do here, so we're done.
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
|
||||
// Restyle all later siblings.
|
||||
RestyleSiblingsStartingWith(this, aChild->GetNextSibling());
|
||||
}
|
||||
|
||||
if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
|
||||
// restyle the previously-first element child if it is after this node
|
||||
PRBool passedChild = PR_FALSE;
|
||||
@ -11509,13 +11532,17 @@ nsCSSFrameConstructor::RestyleForRemove(Element* aContainer,
|
||||
}
|
||||
}
|
||||
|
||||
if (selectorFlags & (NODE_HAS_SLOW_SELECTOR |
|
||||
NODE_HAS_SLOW_SELECTOR_NOAPPEND)) {
|
||||
if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
|
||||
PostRestyleEvent(aContainer, eRestyle_Self, NS_STYLE_HINT_NONE);
|
||||
// Restyling the container is the most we can do here, so we're done.
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
|
||||
// Restyle all later siblings.
|
||||
RestyleSiblingsStartingWith(this, aFollowingSibling);
|
||||
}
|
||||
|
||||
if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
|
||||
// restyle the now-first element child if it was after aOldChild
|
||||
PRBool reachedFollowingSibling = PR_FALSE;
|
||||
|
@ -1444,7 +1444,7 @@ nthChildGenericMatches(RuleProcessorData& data,
|
||||
if (isFromEnd)
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
|
||||
else
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
|
||||
}
|
||||
|
||||
const PRInt32 index = data.GetNthIndex(isOfType, isFromEnd, PR_FALSE);
|
||||
@ -1481,7 +1481,7 @@ edgeOfTypeMatches(RuleProcessorData& data, TreeMatchContext& aTreeMatchContext,
|
||||
if (checkLast)
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
|
||||
else
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
|
||||
}
|
||||
|
||||
return (!checkFirst ||
|
||||
@ -2124,7 +2124,7 @@ static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
|
||||
nsIContent* parent = prevdata->mParentContent;
|
||||
if (parent) {
|
||||
if (aTreeMatchContext.mForStyling)
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
|
||||
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
|
||||
|
||||
PRInt32 index = parent->IndexOf(prevdata->mElement);
|
||||
while (0 <= --index) {
|
||||
|
Loading…
Reference in New Issue
Block a user