Bug 1439395: Avoid leaving an stale restyle root if there's no servo data on it. r=bholley

If a single element is inserted in the document, from the lazy frame
construction path we mark it as the restyle root.

It has no restyle data, and we weren't calling ClearServoData when its parent
was being removed from ClearServoDataFromSubtree, thus leaving the stale restyle
root.

MozReview-Commit-ID: GY812b8tDk0

--HG--
extra : rebase_source : e6d1035e7d3a72b931aa53ac8dcbf7db58982479
This commit is contained in:
Emilio Cobos Álvarez 2018-02-26 18:50:19 +01:00
parent f3fc2e4852
commit ac779f9004
4 changed files with 25 additions and 15 deletions

View File

@ -1928,11 +1928,13 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
}
if (HasServoData()) {
MOZ_ASSERT(document);
MOZ_ASSERT(IsInAnonymousSubtree());
MOZ_ASSERT(document && document->IsStyledByServo());
}
if (document && document->IsStyledByServo()) {
ClearServoData(document);
} else if (document && document->GetServoRestyleRoot() == this) {
document->ClearServoRestyleRoot();
}
if (aNullParent) {
@ -4386,7 +4388,11 @@ Element::ClearServoData(nsIDocument* aDoc) {
MOZ_ASSERT(IsStyledByServo());
MOZ_ASSERT(aDoc);
#ifdef MOZ_STYLO
Servo_Element_ClearData(this);
if (HasServoData()) {
Servo_Element_ClearData(this);
} else {
UnsetFlags(kAllServoDescendantBits | NODE_NEEDS_FRAME);
}
// Since this element is losing its servo data, nothing under it may have
// servo data either, so we can forget restyles rooted at this element. This
// is necessary for correctness, since we invoke ClearServoData in various

View File

@ -1272,14 +1272,18 @@ FragmentOrElement::SetTextContentInternal(const nsAString& aTextContent,
void
FragmentOrElement::DestroyContent()
{
nsIDocument* document = OwnerDoc();
// Drop any servo data. We do this before the RemovedFromDocument call below
// so that it doesn't need to try to keep the style state sane when shuffling
// around the flattened tree.
if (IsElement() && AsElement()->HasServoData()) {
//
// TODO(emilio): I suspect this can be asserted against instead, with a bit of
// effort to avoid calling nsDocument::Destroy with a shell...
if (IsElement() && document->IsStyledByServo()) {
AsElement()->ClearServoData();
}
nsIDocument *document = OwnerDoc();
document->BindingManager()->RemovedFromDocument(this, document,
nsBindingManager::eRunDtor);
document->ClearBoxObjectFor(this);

View File

@ -436,21 +436,19 @@ ServoRestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
/* static */ void
ServoRestyleManager::ClearServoDataFromSubtree(Element* aElement, IncludeRoot aIncludeRoot)
{
if (!aElement->HasServoData()) {
MOZ_ASSERT(!aElement->HasDirtyDescendantsForServo());
MOZ_ASSERT(!aElement->HasAnimationOnlyDirtyDescendantsForServo());
return;
}
StyleChildrenIterator it(aElement);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (n->IsElement()) {
ClearServoDataFromSubtree(n->AsElement(), IncludeRoot::Yes);
if (aElement->HasServoData()) {
StyleChildrenIterator it(aElement);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (n->IsElement()) {
ClearServoDataFromSubtree(n->AsElement(), IncludeRoot::Yes);
}
}
}
if (MOZ_LIKELY(aIncludeRoot == IncludeRoot::Yes)) {
aElement->ClearServoData();
MOZ_ASSERT(!aElement->HasAnyOfFlags(Element::kAllServoDescendantBits | NODE_NEEDS_FRAME));
MOZ_ASSERT(aElement != aElement->OwnerDoc()->GetServoRestyleRoot());
}
}

View File

@ -897,6 +897,8 @@ nsPresContext::Init(nsDeviceContext* aDeviceContext)
// lazily drop the servo data. We don't do this eagerly during layout teardown
// because that would incur an extra whole-tree traversal that's unnecessary
// most of the time.
//
// FIXME(emilio): I'm pretty sure this doesn't happen after bug 1414999.
if (mDocument->IsStyledByServo()) {
Element* root = mDocument->GetRootElement();
if (root && root->HasServoData()) {