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
Родитель 10167dbcac
Коммит fb4762b5e6
4 изменённых файлов: 50 добавлений и 15 удалений

Просмотреть файл

@ -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>

Просмотреть файл

@ -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

Просмотреть файл

@ -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);

Просмотреть файл

@ -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
{