зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d9a71807ae
Коммит
7f47643f52
|
@ -269,14 +269,20 @@ nsContentSink::StyleSheetLoaded(nsICSSStyleSheet* aSheet,
|
|||
NS_ASSERTION(mPendingSheetCount > 0, "How'd that happen?");
|
||||
--mPendingSheetCount;
|
||||
|
||||
if (mPendingSheetCount == 0 && 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.
|
||||
StartLayout(PR_FALSE);
|
||||
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.
|
||||
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
|
||||
|
||||
FlushTags();
|
||||
if (WaitForPendingSheets()) {
|
||||
mDeferredFlushTags = PR_TRUE;
|
||||
} else {
|
||||
FlushTags();
|
||||
|
||||
// Now try and scroll to the reference
|
||||
// XXX Should we scroll unconditionally for history loads??
|
||||
TryToScrollToRef();
|
||||
}
|
||||
|
||||
// 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,7 +280,9 @@ 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)) {
|
||||
content->DoneCreatingElement();
|
||||
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++;
|
||||
}
|
||||
|
||||
MaybeStartLayout(PR_FALSE);
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче