Bug 1299348 - Remove StylingStarted(). r=emilio

StylingStarted is a kind of nebulous and not-very-useful concept. The concept
that _is_ useful is whether the presshell has been initialized or not, but the
root element may not exist at that point.

So we need to make sure we that we can trigger the initial document style in both
presshell initialized _and_ ContentInserted, which has the nice effect of handling
root element reinsertions.

We also take the opportunity to make StyleDocument assert the existence of a root
element, and align the responsibility for clearing the dirty descendant bits between
document and non-document nodes.
This commit is contained in:
Bobby Holley 2016-08-30 18:06:47 -07:00
Родитель 77b5bc12c3
Коммит ff780d017f
4 изменённых файлов: 39 добавлений и 43 удалений

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

@ -280,17 +280,21 @@ ServoRestyleManager::ProcessPendingRestyles()
{
MOZ_ASSERT(PresContext()->Document(), "No document? Pshaw!");
MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");
if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
// PresShell::FlushPendingNotifications doesn't early-return in the case
// where the PreShell hasn't yet been initialized (and therefore we haven't
// yet done the initial style traversal of the DOM tree). We should arguably
// fix up the callers and assert against this case, but we just detect and
// handle it for now.
return;
}
if (!HasPendingRestyles()) {
return;
}
ServoStyleSet* styleSet = StyleSet();
if (!styleSet->StylingStarted()) {
// If something caused us to restyle, and we haven't started styling yet,
// do nothing. Everything is dirty, and we'll style it all later.
return;
}
nsIDocument* doc = PresContext()->Document();
Element* root = doc->GetRootElement();
if (root) {
@ -331,7 +335,7 @@ ServoRestyleManager::ProcessPendingRestyles()
}
MOZ_ASSERT(!doc->IsDirtyForServo());
MOZ_ASSERT(!doc->HasDirtyDescendantsForServo());
doc->UnsetHasDirtyDescendantsForServo();
mModifiedElements.Clear();
@ -354,6 +358,20 @@ ServoRestyleManager::RestyleForInsertOrChange(nsINode* aContainer,
void
ServoRestyleManager::ContentInserted(nsINode* aContainer, nsIContent* aChild)
{
if (aContainer == aContainer->OwnerDoc()) {
// If we're getting this notification for the insertion of a root element,
// that means either:
// (a) We initialized the PresShell before the root element existed, or
// (b) The root element was removed and it or another root is being
// inserted.
//
// Either way the whole tree is dirty, so we should style the document.
MOZ_ASSERT(aChild == aChild->OwnerDoc()->GetRootElement());
MOZ_ASSERT(aChild->IsDirtyForServo());
StyleSet()->StyleDocument(/* aLeaveDirtyBits = */ false);
return;
}
if (!aContainer->ServoData().get()) {
// This can happen with display:none. Bug 1297249 tracks more investigation
// and assertions here.

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

@ -1682,8 +1682,15 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
if (mStyleSet->IsServo()) {
mStyleSet->AsServo()->StartStyling(GetPresContext());
if (mStyleSet->IsServo() && mDocument->GetRootElement()) {
// If we have the root element already, go ahead style it along with any
// descendants.
//
// Some things, like nsDocumentViewer::GetPageMode, recreate the PresShell
// while keeping the content tree alive (see bug 1292280) - so we
// unconditionally mark the root as dirty.
mDocument->GetRootElement()->SetIsDirtyForServo();
mStyleSet->AsServo()->StyleDocument(/* aLeaveDirtyBits = */ false);
}
// Get the root frame from the frame manager

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

@ -22,7 +22,6 @@ ServoStyleSet::ServoStyleSet()
: mPresContext(nullptr)
, mRawSet(Servo_StyleSet_Init())
, mBatching(0)
, mStylingStarted(false)
{
}
@ -73,24 +72,6 @@ ServoStyleSet::EndUpdate()
return NS_OK;
}
void
ServoStyleSet::StartStyling(nsPresContext* aPresContext)
{
MOZ_ASSERT(!mStylingStarted);
// Some things, like nsDocumentViewer::GetPageMode, recreate the presShell,
// while keeping the content tree alive. See bug 1292280.
//
// That's why we need to force a restyle.
nsIContent* root = mPresContext->Document()->GetRootElement();
if (root) {
root->SetIsDirtyForServo();
}
StyleDocument(/* aLeaveDirtyBits = */ false);
mStylingStarted = true;
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext)
@ -484,21 +465,16 @@ ClearDirtyBits(nsIContent* aContent)
void
ServoStyleSet::StyleDocument(bool aLeaveDirtyBits)
{
// Unconditionally clear the flag on the document so that HasPendingRestyles
// returns false.
nsIDocument* doc = mPresContext->Document();
doc->UnsetHasDirtyDescendantsForServo();
// Grab the root.
nsIContent* root = mPresContext->Document()->GetRootElement();
if (!root) {
return;
}
nsIDocument* doc = mPresContext->Document();
nsIContent* root = doc->GetRootElement();
MOZ_ASSERT(root);
// Restyle the document, clearing the dirty bits if requested.
Servo_RestyleSubtree(root, mRawSet.get());
if (!aLeaveDirtyBits) {
ClearDirtyBits(root);
doc->UnsetHasDirtyDescendantsForServo();
}
}

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

@ -55,8 +55,6 @@ public:
void BeginUpdate();
nsresult EndUpdate();
void StartStyling(nsPresContext* aPresContext);
already_AddRefed<nsStyleContext>
ResolveStyleFor(dom::Element* aElement,
nsStyleContext* aParentContext);
@ -128,7 +126,7 @@ public:
/**
* Performs a Servo traversal to compute style for all dirty nodes in the
* document.
* document. The root element must be non-null.
*
* If aLeaveDirtyBits is true, the dirty/dirty-descendant bits are not
* cleared.
@ -155,8 +153,6 @@ public:
*/
void StyleNewChildren(nsIContent* aParent);
bool StylingStarted() const { return mStylingStarted; }
private:
already_AddRefed<nsStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
nsStyleContext* aParentContext,
@ -173,7 +169,6 @@ private:
EnumeratedArray<SheetType, SheetType::Count,
nsTArray<RefPtr<ServoStyleSheet>>> mSheets;
int32_t mBatching;
bool mStylingStarted;
};
} // namespace mozilla