Don't start layout for XML just because the root has been opened. And don't

start layout until <html:head> closes if <html:head> gets opened.  For XHTML
documents, this should prevent flashes of unstyled content.

Also, don't flush tags unless forced to if a sheet is pending.

Bug 380028, r+sr=sicking
This commit is contained in:
bzbarsky@mit.edu 2007-07-10 20:42:11 -07:00
Родитель d9a71807ae
Коммит 7f47643f52
5 изменённых файлов: 61 добавлений и 20 удалений

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

@ -269,14 +269,20 @@ nsContentSink::StyleSheetLoaded(nsICSSStyleSheet* aSheet,
NS_ASSERTION(mPendingSheetCount > 0, "How'd that happen?");
--mPendingSheetCount;
if (mPendingSheetCount == 0 && mDeferredLayoutStart) {
if (mPendingSheetCount == 0 &&
(mDeferredLayoutStart || mDeferredFlushTags)) {
if (mDeferredFlushTags) {
FlushTags();
}
if (mDeferredLayoutStart) {
// We might not have really started layout, since this sheet was still
// loading. Do it now. Probably doesn't matter whether we do this
// before or after we unblock scripts, but before feels saner. Note that
// if mDeferredLayoutStart is true, that means any subclass StartLayout()
// stuff that needs to happen has already happened, so we don't need to
// worry about it.
// before or after we unblock scripts, but before feels saner. Note
// that if mDeferredLayoutStart is true, that means any subclass
// StartLayout() stuff that needs to happen has already happened, so we
// don't need to worry about it.
StartLayout(PR_FALSE);
}
// Go ahead and try to scroll to our ref if we have one
TryToScrollToRef();
@ -1019,7 +1025,7 @@ nsContentSink::StartLayout(PRBool aIgnorePendingSheets)
mDeferredLayoutStart = PR_TRUE;
if (!aIgnorePendingSheets && mPendingSheetCount > 0) {
if (!aIgnorePendingSheets && WaitForPendingSheets()) {
// Bail out; we'll start layout when the sheets load
return;
}
@ -1172,11 +1178,16 @@ nsContentSink::Notify(nsITimer *timer)
}
#endif
if (WaitForPendingSheets()) {
mDeferredFlushTags = PR_TRUE;
} else {
FlushTags();
// Now try and scroll to the reference
// XXX Should we scroll unconditionally for history loads??
TryToScrollToRef();
}
mNotificationTimer = nsnull;
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::Notify()\n"));
MOZ_TIMER_STOP(mWatch);
@ -1191,6 +1202,11 @@ nsContentSink::IsTimeToNotify()
return PR_FALSE;
}
if (WaitForPendingSheets()) {
mDeferredFlushTags = PR_TRUE;
return PR_FALSE;
}
PRTime now = PR_Now();
PRInt64 interval, diff;
@ -1213,7 +1229,9 @@ nsContentSink::WillInterruptImpl()
SINK_TRACE(gContentSinkLogModuleInfo, SINK_TRACE_CALLS,
("nsContentSink::WillInterrupt: this=%p", this));
#ifndef SINK_NO_INCREMENTAL
if (mNotifyOnTimer && mLayoutStarted) {
if (WaitForPendingSheets()) {
mDeferredFlushTags = PR_TRUE;
} else if (mNotifyOnTimer && mLayoutStarted) {
if (mBackoffCount && !mInMonolithicContainer) {
PRInt64 now = PR_Now();
PRInt64 interval = GetNotificationInterval();

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

@ -211,6 +211,10 @@ protected:
void TryToScrollToRef();
// Later on we might want to make this more involved somehow
// (e.g. stop waiting after some timeout or whatnot).
PRBool WaitForPendingSheets() { return mPendingSheetCount > 0; }
private:
// People shouldn't be allocating this class directly. All subclasses should
// be allocated using a zeroing operator new.
@ -276,6 +280,8 @@ protected:
PRUint8 mHaveOfflineResources : 1;
// true if offline-resource links should be saved to the offline cache
PRUint8 mSaveOfflineResources : 1;
// If true, we deferred notifications until sheets load
PRUint8 mDeferredFlushTags : 1;
// -- Can interrupt parsing members --
PRUint32 mDelayTimerStart;

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

@ -1340,6 +1340,7 @@ SinkContext::AddText(const nsAString& aText)
nsresult
SinkContext::FlushTags()
{
mSink->mDeferredFlushTags = PR_FALSE;
PRBool oldBeganUpdate = mSink->mBeganUpdate;
PRUint32 oldUpdates = mSink->mUpdatesInNotification;

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

@ -1066,17 +1066,24 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
// Some HTML nodes need DoneCreatingElement() called to initialize
// properly (eg form state restoration).
if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML &&
(nodeInfo->NameAtom() == nsGkAtoms::input ||
nodeInfo->NameAtom() == nsGkAtoms::button)) {
if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML) {
if (nodeInfo->NameAtom() == nsGkAtoms::input ||
nodeInfo->NameAtom() == nsGkAtoms::button) {
content->DoneCreatingElement();
} else if (nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) {
mCurrentHead = content;
}
}
if (IsMonolithicContainer(nodeInfo)) {
mInMonolithicContainer++;
}
if (content != mDocElement && !mCurrentHead) {
// This isn't the root and we're not inside an XHTML <head>.
// Might need to start layout
MaybeStartLayout(PR_FALSE);
}
return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() :
result;
@ -1122,10 +1129,17 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName,
result = CloseElement(content);
if (mCurrentHead == content) {
mCurrentHead = nsnull;
}
if (mDocElement == content) {
// XXXbz for roots that don't want to be appended on open, we
// probably need to deal here.... (and stop appending them on open).
mState = eXMLContentSinkState_InEpilog;
// We might have had no occasion to start layout yet. Do so now.
MaybeStartLayout(PR_FALSE);
}
PRInt32 stackLen = mContentStack.Length();
@ -1591,6 +1605,7 @@ nsXMLContentSink::FlushPendingNotifications(mozFlushType aType)
nsresult
nsXMLContentSink::FlushTags()
{
mDeferredFlushTags = PR_FALSE;
PRBool oldBeganUpdate = mBeganUpdate;
PRUint32 oldUpdates = mUpdatesInNotification;

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

@ -183,6 +183,7 @@ protected:
PRBool aInterruptable);
nsIContent* mDocElement;
nsCOMPtr<nsIContent> mCurrentHead; // When set, we're in an XHTML <haed>
PRUnichar* mText;
XMLContentSinkState mState;