Bug 1452889: Handle appending multiple items to a listbox correctly. r=bz

What happened in bug 1446368 is the following: We append two items to an empty
listbox.

We can't construct lazily because this is XUL, so that goes through
IssueSingleInsertNotifications for each of the items.

When we insert the first one we call LazilyStyleNewChildRange _only on the first
sibling_, yet the listbox code tries to construct frames for the next sibling
too from CreateRows. The next sibling is unstyled, so we panic.

Instead of handling it in ContentRangeInserted but not ContentAppended, just do
it in the listbox-specific code instead, which looks slightly cleaner (though we
can't assert we're constructing async).

This should fix the case where the listbox is display: none or what not which,
combined with the patch in bug 1303605, supersede the backed out patch in
bug 1429088, which was backed out because listboxes suck.

MozReview-Commit-ID: D7UQ41S6Ras
This commit is contained in:
Emilio Cobos Álvarez
2018-04-10 11:15:39 +02:00
parent 4cc18aa344
commit 3119c8490b

View File

@@ -7073,19 +7073,18 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
return;
}
if (aInsertionKind == InsertionKind::Async &&
MaybeConstructLazily(CONTENTAPPEND, aFirstNewContent)) {
LazilyStyleNewChildRange(aFirstNewContent, nullptr);
return;
}
// We couldn't construct lazily. Make Servo eagerly traverse the new content
// if needed (when aInsertionKind == InsertionKind::Sync, we know that the
// styles are up-to-date already).
if (aInsertionKind == InsertionKind::Async) {
if (MaybeConstructLazily(CONTENTAPPEND, aFirstNewContent)) {
LazilyStyleNewChildRange(aFirstNewContent, nullptr);
return;
}
// We couldn't construct lazily. Make Servo eagerly traverse the new content
// if needed (when aInsertionKind == InsertionKind::Sync, we know that the
// styles are up-to-date already).
StyleNewChildRange(aFirstNewContent, nullptr);
}
LAYOUT_PHASE_TEMP_EXIT();
if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
LAYOUT_PHASE_TEMP_REENTER();
@@ -7423,14 +7422,6 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
}
#endif
auto styleNewChildRangeEagerly =
[this, aInsertionKind, aStartChild, aEndChild]() {
// When aInsertionKind == InsertionKind::Sync, we know that the
// styles are up-to-date already.
if (aInsertionKind == InsertionKind::Async) {
StyleNewChildRange(aStartChild, aEndChild);
}
};
bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
NS_ASSERTION(isSingleInsert ||
@@ -7441,8 +7432,6 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
#ifdef MOZ_XUL
if (aStartChild->GetParent() && IsXULListBox(aStartChild->GetParent())) {
// For XUL list box, we need to style the new children eagerly.
styleNewChildRangeEagerly();
if (isSingleInsert) {
// The insert case in NotifyListBoxBody doesn't use "old next sibling".
if (NotifyListBoxBody(mPresShell->GetPresContext(),
@@ -7528,16 +7517,17 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
return;
}
if (aInsertionKind == InsertionKind::Async &&
MaybeConstructLazily(CONTENTINSERT, aStartChild)) {
LazilyStyleNewChildRange(aStartChild, aEndChild);
return;
if (aInsertionKind == InsertionKind::Async) {
if (MaybeConstructLazily(CONTENTINSERT, aStartChild)) {
LazilyStyleNewChildRange(aStartChild, aEndChild);
return;
}
// We couldn't construct lazily. Make Servo eagerly traverse the new content
// if needed (when aInsertionKind == InsertionKind::Sync, we know that the
// styles are up-to-date already).
StyleNewChildRange(aStartChild, aEndChild);
}
// We couldn't construct lazily. Make Servo eagerly traverse the new content
// if needed.
styleNewChildRangeEagerly();
bool isAppend, isRangeInsertSafe;
nsIFrame* prevSibling = GetInsertionPrevSibling(&insertion, aStartChild,
&isAppend, &isRangeInsertSafe);
@@ -11118,6 +11108,10 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame,
GetFloatContainingBlock(aParentFrame),
do_AddRef(mTempFrameTreeState));
if (aChild->IsElement() && !aChild->AsElement()->HasServoData()) {
mPresShell->StyleSet()->StyleNewSubtree(aChild->AsElement());
}
RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aChild);
// Pre-check for display "none" - only if we find that, do we create