diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp
index 73e03958aff..72b0aef05ff 100644
--- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp
+++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp
@@ -3977,10 +3977,20 @@ HTMLContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
// notification to occur. Since this could result in frame
// creation, make sure we've flushed everything before we
// continue.
- // Also increment mInNotification to make sure we don't flush again
- // until the end of this update, even if nested updates or
+
+ // Note that UPDATE_CONTENT_STATE notifications never cause
+ // synchronous frame construction, so we never have to worry about
+ // them here. The code that handles the async event these
+ // notifications post will flush us out if it needs to.
+
+ // Also, if this is not an UPDATE_CONTENT_STATE notification,
+ // increment mInNotification to make sure we don't flush again until
+ // the end of this update, even if nested updates or
// FlushPendingNotifications calls happen during it.
- if (!mInNotification++ && mCurrentContext) {
+ NS_ASSERTION(aUpdateType && (aUpdateType & UPDATE_ALL) == aUpdateType,
+ "Weird update type bitmask");
+ if (aUpdateType != UPDATE_CONTENT_STATE && !mInNotification++ &&
+ mCurrentContext) {
mCurrentContext->FlushTags(PR_TRUE);
}
}
@@ -3992,8 +4002,13 @@ HTMLContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
// something else in the script processing caused the
// notification to occur. Update our notion of how much
// has been flushed to include any new content if ending
- // this update leaves us not inside a notification.
- if (!--mInNotification) {
+ // this update leaves us not inside a notification. Note that we
+ // exclude UPDATE_CONTENT_STATE notifications here, since those
+ // never affect the frame model directly while inside the
+ // notification.
+ NS_ASSERTION(aUpdateType && (aUpdateType & UPDATE_ALL) == aUpdateType,
+ "Weird update type bitmask");
+ if (aUpdateType != UPDATE_CONTENT_STATE && !--mInNotification) {
UpdateAllContexts();
}
}
diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp
index 404abfa09d5..0bb9b2ee80b 100644
--- a/mozilla/layout/base/nsCSSFrameConstructor.cpp
+++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp
@@ -10425,16 +10425,19 @@ nsCSSFrameConstructor::DoContentStateChanged(nsIContent* aContent,
NS_ASSERTION(styleSet, "couldn't get style set");
if (aContent) {
- nsChangeHint hint;
- if (aStateMask & (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
- NS_EVENT_STATE_SUPPRESSED)) {
- // Any change to a content state that affects which frames we
- // construct must lead to a frame reconstruct here
- hint = nsChangeHint_ReconstructFrame;
- } else {
- hint = NS_STYLE_HINT_NONE;
- nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent);
- if (primaryFrame) {
+ nsChangeHint hint = NS_STYLE_HINT_NONE;
+ // Any change to a content state that affects which frames we construct
+ // must lead to a frame reconstruct here if we already have a frame.
+ // Note that we never decide through non-CSS means to not create frames
+ // based on content states, so if we already don't have a frame we don't
+ // need to force a reframe -- if it's needed, the HasStateDependentStyle
+ // call will handle things.
+ nsIFrame* primaryFrame = mPresShell->GetPrimaryFrameFor(aContent);
+ if (primaryFrame) {
+ if (aStateMask & (NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED |
+ NS_EVENT_STATE_SUPPRESSED)) {
+ hint = nsChangeHint_ReconstructFrame;
+ } else {
PRUint8 app = primaryFrame->GetStyleDisplay()->mAppearance;
if (app) {
nsITheme *theme = presContext->GetTheme();
@@ -13253,7 +13256,16 @@ void nsCSSFrameConstructor::RestyleEvent::HandleEvent() {
NS_ASSERTION(viewManager, "Must have view manager for update");
viewManager->BeginUpdateViewBatch();
+ // Force flushing of any pending content notifications that might have queued
+ // up while our event was pending. That will ensure that we don't construct
+ // frames for content right now that's still waiting to be notified on,
+ constructor->mPresShell->GetDocument()->
+ FlushPendingNotifications(Flush_ContentAndNotify);
+
+ // Make sure that any restyles that happen from now on will go into
+ // a new event.
constructor->mRestyleEventQueue = nsnull;
+
constructor->ProcessPendingRestyles();
viewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
}