Bug 1461749: Fix slow path for finding the next sibling frame for appending in presence of Shadow DOM. r=mats

In this case we have a shadow hoot with display: contents, with no children.
Those children wouldn't be flattened tree children of the shadow host.

Instead of using the last light dom child and seek to it, use
FlattenedChildIterator's reverse iteration.

MozReview-Commit-ID: 18XL5Ong7ww

--HG--
extra : rebase_source : 2d34bd5b1fdd509a069ffa5052a7b7b3302be24c
This commit is contained in:
Emilio Cobos Álvarez 2018-05-23 18:20:33 +02:00
parent 10167dbcac
commit fb4762b5e6
4 changed files with 50 additions and 15 deletions

View File

@ -0,0 +1,19 @@
<style>
:last-of-type {
display: contents;
}
</style>
<script>
function start() {
o1 = document.createElement('footer')
o2 = document.createElement('t')
document.documentElement.appendChild(o1)
document.documentElement.appendChild(o2)
o3 = o1.attachShadow({
mode: "open"
})
o2.getClientRects()
o3.innerHTML = ">"
}
window.addEventListener('load', start)
</script>

View File

@ -534,3 +534,4 @@ load 1453196.html
pref(dom.webcomponents.shadowdom.enabled,true) load 1414303.html
load 1461812.html
load 1462412.html
pref(dom.webcomponents.shadowdom.enabled,true) load 1461749.html

View File

@ -7050,6 +7050,26 @@ nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild,
}
}
nsIFrame*
nsCSSFrameConstructor::FindNextSiblingForAppend(const InsertionPoint& aInsertion)
{
auto SlowPath = [&]() -> nsIFrame* {
FlattenedChildIterator iter(aInsertion.mContainer,
/* aStartAtBeginning = */ false);
iter.GetPreviousChild(); // Prime the iterator.
StyleDisplay unused = UNSET_DISPLAY;
return FindNextSibling(iter, unused);
};
if (!IsDisplayContents(aInsertion.mContainer) &&
!nsLayoutUtils::GetAfterFrame(aInsertion.mContainer)) {
MOZ_ASSERT(!SlowPath());
return nullptr;
}
return SlowPath();
}
void
nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
InsertionKind aInsertionKind)
@ -7144,17 +7164,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
MOZ_ASSERT(!parentFrame->IsFieldSetFrame() && !parentFrame->IsDetailsFrame(),
"Parent frame should not be fieldset or details!");
// Deal with possible :after generated content on the parent, or display:
// contents.
nsIFrame* nextSibling = nullptr;
if (IsDisplayContents(insertion.mContainer) ||
nsLayoutUtils::GetAfterFrame(insertion.mContainer)) {
FlattenedChildIterator iter(insertion.mContainer);
iter.Seek(insertion.mContainer->GetLastChild());
StyleDisplay unused = UNSET_DISPLAY;
nextSibling = FindNextSibling(iter, unused);
}
nsIFrame* nextSibling = FindNextSiblingForAppend(insertion);
if (nextSibling) {
parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
} else {
@ -7183,10 +7193,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
//
// FIXME(emilio): This kinda sucks! :(
if (nextSibling && !wf) {
FlattenedChildIterator iter(insertion.mContainer);
iter.Seek(insertion.mContainer->GetLastChild());
StyleDisplay unused = UNSET_DISPLAY;
nextSibling = FindNextSibling(iter, unused);
nextSibling = FindNextSiblingForAppend(insertion);
if (nextSibling) {
parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
containingBlock = GetFloatContainingBlock(parentFrame);

View File

@ -2038,6 +2038,14 @@ private:
void CheckForFirstLineInsertion(nsIFrame* aParentFrame,
nsFrameItems& aFrameItems);
/**
* Find the next frame for appending to a given insertion point.
*
* We're appending, so this is almost always null, except for a few edge
* cases.
*/
nsIFrame* FindNextSiblingForAppend(const InsertionPoint&);
// The direction in which we should look for siblings.
enum class SiblingDirection
{