Bug 657353 part 2. Switch content state updates away from calling Begin/EndUpdate. r=sicking
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 31 May 2011 17:38:25 -0400
changeset 70393 acd4a2d5d3d1348255f92a2b0e069639a54104aa
parent 70392 d47a10acc66dc96d378a2a47f1d551fa201f5394
child 70394 1c52f2d68d3949465ab6db0750ab624d6fa403a0
push idunknown
push userunknown
push dateunknown
reviewerssicking
bugs657353
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 657353 part 2. Switch content state updates away from calling Begin/EndUpdate. r=sicking
content/base/public/nsIDocument.h
content/base/public/nsIDocumentObserver.h
content/base/src/Link.cpp
content/base/src/nsContentSink.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/base/src/nsImageLoadingContent.cpp
content/base/src/nsObjectLoadingContent.cpp
content/events/src/nsEventStateManager.cpp
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsHTMLButtonElement.cpp
content/html/content/src/nsHTMLFormElement.cpp
content/html/content/src/nsHTMLInputElement.cpp
content/html/content/src/nsHTMLOptionElement.cpp
content/html/content/src/nsHTMLOutputElement.cpp
content/html/content/src/nsHTMLSelectElement.cpp
content/html/content/src/nsHTMLTextAreaElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/mathml/content/src/nsMathMLElement.cpp
content/xtf/src/nsXTFElementWrapper.cpp
content/xul/content/src/nsXULElement.cpp
dom/base/nsFocusManager.cpp
dom/base/nsGlobalWindow.cpp
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -751,17 +751,18 @@ public:
   virtual void EndUpdate(nsUpdateType aUpdateType) = 0;
   virtual void BeginLoad() = 0;
   virtual void EndLoad() = 0;
 
   enum ReadyState { READYSTATE_UNINITIALIZED = 0, READYSTATE_LOADING = 1, READYSTATE_INTERACTIVE = 3, READYSTATE_COMPLETE = 4};
   virtual void SetReadyStateInternal(ReadyState rs) = 0;
   virtual ReadyState GetReadyStateEnum() = 0;
 
-  // notify that a content node changed state
+  // notify that a content node changed state.  This must happen under
+  // a scriptblocker but NOT within a begin/end update.
   virtual void ContentStateChanged(nsIContent* aContent,
                                    nsEventStates aStateMask) = 0;
 
   // Notify that a document state has changed.
   // This should only be called by callers whose state is also reflected in the
   // implementation of nsDocument::GetDocumentState.
   virtual void DocumentStatesChanged(nsEventStates aStateMask) = 0;
 
--- a/content/base/public/nsIDocumentObserver.h
+++ b/content/base/public/nsIDocumentObserver.h
@@ -51,18 +51,17 @@ class nsIDocument;
 #define NS_IDOCUMENT_OBSERVER_IID \
 { 0x900bc4bc, 0x8b6c, 0x4cba, \
  { 0x82, 0xfa, 0x56, 0x8a, 0x80, 0xff, 0xfd, 0x3e } }
 
 typedef PRUint32 nsUpdateType;
 
 #define UPDATE_CONTENT_MODEL 0x00000001
 #define UPDATE_STYLE         0x00000002
-#define UPDATE_CONTENT_STATE 0x00000004
-#define UPDATE_ALL (UPDATE_CONTENT_MODEL | UPDATE_STYLE | UPDATE_CONTENT_STATE)
+#define UPDATE_ALL (UPDATE_CONTENT_MODEL | UPDATE_STYLE)
 
 // Document observer interface
 class nsIDocumentObserver : public nsIMutationObserver
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_OBSERVER_IID)
 
   /**
--- a/content/base/src/Link.cpp
+++ b/content/base/src/Link.cpp
@@ -96,17 +96,17 @@ Link::SetLinkState(nsLinkState aState)
   // Notify the document that our visited state has changed.
   nsIContent *content = Content();
   nsIDocument *doc = content->GetCurrentDoc();
   NS_ASSERTION(doc, "Registered but we have no document?!");
   nsEventStates newLinkState = LinkState();
   NS_ASSERTION(newLinkState == NS_EVENT_STATE_VISITED ||
                newLinkState == NS_EVENT_STATE_UNVISITED,
                "Unexpected state obtained from LinkState()!");
-  mozAutoDocUpdate update(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
   doc->ContentStateChanged(content, oldLinkState ^ newLinkState);
 }
 
 nsEventStates
 Link::LinkState() const
 {
   // We are a constant method, but we are just lazily doing things and have to
   // track that state.  Cast away that constness!
@@ -485,17 +485,17 @@ Link::ResetLinkState(bool aNotify)
 
   // If aNotify is true, notify both of the visited-related states.  We have
   // to do that, because we might be racing with a response from history and
   // hence need to make sure that we get restyled whether we were visited or
   // not before.  In particular, we need to make sure that our LinkState() is
   // called so that we'll start a new history query as needed.
   if (aNotify && doc) {
     nsEventStates changedState = NS_EVENT_STATE_VISITED ^ NS_EVENT_STATE_UNVISITED;
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, aNotify);
+    nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(content, changedState);
   }
 }
 
 void
 Link::UnregisterFromHistory()
 {
   // If we are not registered, we have nothing to do.
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1475,46 +1475,30 @@ nsContentSink::BeginUpdate(nsIDocument *
   }
 
   // If we're in a script and we didn't do the notification,
   // something else in the script processing caused the
   // notification to occur. Since this could result in frame
   // creation, make sure we've flushed everything before we
   // continue.
 
-  // 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.
-  NS_ASSERTION(aUpdateType && (aUpdateType & UPDATE_ALL) == aUpdateType,
-               "Weird update type bitmask");
-  if (aUpdateType != UPDATE_CONTENT_STATE && !mInNotification++) {
+  if (!mInNotification++) {
     FlushTags();
   }
 }
 
 void
 nsContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
 {
   // If we're in a script and we didn't do the notification,
   // 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.  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) {
+  // this update leaves us not inside a notification.
+  if (!--mInNotification) {
     UpdateChildCounts();
   }
 }
 
 void
 nsContentSink::DidBuildModelImpl(PRBool aTerminated)
 {
   if (mDocument && !aTerminated) {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -4198,16 +4198,18 @@ nsDocument::EndLoad()
   } else {
     DispatchContentLoadedEvents();
   }
 }
 
 void
 nsDocument::ContentStateChanged(nsIContent* aContent, nsEventStates aStateMask)
 {
+  NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
+                  "Someone forgot a scriptblocker");
   NS_DOCUMENT_NOTIFY_OBSERVERS(ContentStateChanged,
                                (this, aContent, aStateMask));
 }
 
 void
 nsDocument::DocumentStatesChanged(nsEventStates aStateMask)
 {
   // Invalidate our cached state.
@@ -7577,17 +7579,17 @@ nsDocument::RefreshLinkHrefs()
 {
   // Get a list of all links we know about.  We will reset them, which will
   // remove them from the document, so we need a copy of what is in the
   // hashtable.
   LinkArray linksToNotify(mStyledLinks.Count());
   (void)mStyledLinks.EnumerateEntries(EnumerateStyledLinks, &linksToNotify);
 
   // Reset all of our styled links.
-  MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
   for (LinkArray::size_type i = 0; i < linksToNotify.Length(); i++) {
     linksToNotify[i]->ResetLinkState(true);
   }
 }
 
 NS_IMETHODIMP
 nsDocument::GetScriptTypeID(PRUint32 *aScriptType)
 {
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -4678,17 +4678,16 @@ nsGenericElement::SetAttrAndNotify(PRInt
         binding->AttributeChanged(aName, aNamespaceID, PR_FALSE, aNotify);
       }
     }
   }
 
   if (aNotify) {
     stateMask ^= IntrinsicState();
     if (document && !stateMask.IsEmpty()) {
-      MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
       document->ContentStateChanged(this, stateMask);
     }
     nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
   }
 
   if (aNamespaceID == kNameSpaceID_XMLEvents && 
       aName == nsGkAtoms::event && mNodeInfo->GetDocument()) {
     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
@@ -4923,17 +4922,16 @@ nsGenericElement::UnsetAttr(PRInt32 aNam
         binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
       }
     }
   }
 
   if (aNotify) {
     stateMask ^= IntrinsicState();
     if (document && !stateMask.IsEmpty()) {
-      MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, aNotify);
       document->ContentStateChanged(this, stateMask);
     }
     nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
                                   nsIDOMMutationEvent::REMOVAL);
   }
 
   rv = AfterSetAttr(aNameSpaceID, aName, nsnull, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -858,17 +858,17 @@ protected:
   {
     return NS_OK;
   }
 
   /**
    * Hook that is called by nsGenericElement::SetAttr to allow subclasses to
    * deal with attribute sets.  This will only be called after we have called
    * SetAndTakeAttr and AttributeChanged (that is, after we have actually set
-   * the attr).
+   * the attr).  It will always be called under a scriptblocker.
    *
    * @param aNamespaceID the namespace of the attr being set
    * @param aName the localname of the attribute being set
    * @param aValue the value it's being set to.  If null, the attr is being
    *        removed.
    * @param aNotify Whether we plan to notify document observers.
    */
   // Note that this is inlined so that when subclasses call it it gets
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -819,17 +819,17 @@ nsImageLoadingContent::UpdateImageState(
   }
 
   if (aNotify) {
     nsIDocument* doc = thisContent->GetCurrentDoc();
     if (doc) {
       NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
       nsEventStates changedBits = oldState ^ ImageState();
       if (!changedBits.IsEmpty()) {
-        mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+        nsAutoScriptBlocker scriptBlocker;
         doc->ContentStateChanged(thisContent, changedBits);
       }
     }
   }
 }
 
 void
 nsImageLoadingContent::CancelImageRequests(PRBool aNotify)
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1657,17 +1657,17 @@ nsObjectLoadingContent::NotifyStateChang
   nsEventStates newState = ObjectState();
 
   if (newState != aOldState) {
     // This will trigger frame construction
     NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
     nsEventStates changedBits = aOldState ^ newState;
 
     {
-      mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(thisContent, changedBits);
     }
     if (aSync) {
       // Make sure that frames are actually constructed, and do it after
       // EndUpdate was called.
       doc->FlushPendingNotifications(Flush_Frames);
     }
   } else if (aOldType != mType) {
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -4408,17 +4408,17 @@ nsEventStateManager::SetContentState(nsI
     // anyway if notifyContent1 is null.
     notifyContent1 = notifyContent2;
     notifyContent2 = nsnull;
   }
 
   if (notifyContent1 && mPresContext) {
     EnsureDocument(mPresContext);
     if (mDocument) {
-      MOZ_AUTO_DOC_UPDATE(mDocument, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
 
       if (notifyAncestors) {
         nsCOMPtr<nsIContent> commonAncestor =
           FindCommonAncestor(notifyContent1, notifyContent2);
         NotifyAncestors(mDocument, notifyContent1, commonAncestor, aState);
         if (notifyContent2) {
           NotifyAncestors(mDocument, notifyContent2, commonAncestor, aState);
         }
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2638,17 +2638,17 @@ nsGenericHTMLFormElement::BeforeSetAttr(
 
       mForm->RemoveElement(this, false);
 
       // Removing the element from the form can make it not be the default
       // control anymore.  Go ahead and notify on that change, though we might
       // end up readding and becoming the default control again in
       // AfterSetAttr.
       if (doc && aNotify) {
-        MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+        nsAutoScriptBlocker scriptBlocker;
         doc->ContentStateChanged(this, NS_EVENT_STATE_DEFAULT);
       }
     }
 
     if (aName == nsGkAtoms::form) {
       // If @form isn't set or set to the empty string, there were no observer
       // so we don't have to remove it.
       if (nsContentUtils::HasNonEmptyAttr(this, kNameSpaceID_None,
@@ -2696,17 +2696,16 @@ nsGenericHTMLFormElement::AfterSetAttr(P
 
       mForm->AddElement(this, false, aNotify);
 
       // Adding the element to the form can make it be the default control .
       // Go ahead and notify on that change.
       // Note: no need to notify on CanBeDisabled(), since type attr
       // changes can't affect that.
       if (doc && aNotify) {
-        MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
         doc->ContentStateChanged(this, NS_EVENT_STATE_DEFAULT);
       }
     }
 
     if (aName == nsGkAtoms::form) {
       // We need a new form id observer.
       nsIDocument* doc = GetCurrentDoc();
       if (doc) {
@@ -3013,17 +3012,17 @@ nsGenericHTMLFormElement::FieldSetDisabl
   if (!aNotify) {
     return;
   }
 
   aStates |= NS_EVENT_STATE_DISABLED | NS_EVENT_STATE_ENABLED;
 
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, aStates);
   }
 }
 
 //----------------------------------------------------------------------
 
 nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement()
 {
@@ -3580,12 +3579,12 @@ nsGenericHTMLElement::ChangeEditableStat
   }
 
   if (document->HasFlag(NODE_IS_EDITABLE)) {
     document = nsnull;
   }
 
   // MakeContentDescendantsEditable is going to call ContentStateChanged for
   // this element and all descendants if editable state has changed.
-  // We have to create a document update batch now so it's created once.
-  MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
+  // We might as well wrap it all in one script blocker.
+  nsAutoScriptBlocker scriptBlocker;
   MakeContentDescendantsEditable(this, document);
 }
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -575,17 +575,16 @@ nsHTMLButtonElement::AfterSetAttr(PRInt3
       }
 
       states |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
     }
 
     if (aNotify && !states.IsEmpty()) {
       nsIDocument* doc = GetCurrentDoc();
       if (doc) {
-        MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
         doc->ContentStateChanged(this, states);
       }
     }
   }
 
   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
                                                 aValue, aNotify);
 }
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -379,18 +379,16 @@ nsresult
 nsHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify)
 {
   if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
     // Update all form elements states because they might be [no longer]
     // affected by :-moz-ui-valid or :-moz-ui-invalid.
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
-
       for (PRUint32 i = 0, length = mControls->mElements.Length();
            i < length; ++i) {
         doc->ContentStateChanged(mControls->mElements[i],
                                  NS_EVENT_STATE_MOZ_UI_VALID |
                                  NS_EVENT_STATE_MOZ_UI_INVALID);
       }
 
       for (PRUint32 i = 0, length = mControls->mNotInElements.Length();
@@ -504,17 +502,17 @@ static void
 CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsGenericHTMLFormElement*> aArray
 #ifdef DEBUG
                , nsIDOMHTMLFormElement* aThisForm
 #endif
                )
 {
   // Prepare document update batch.
   nsIDocument* doc = aArray.IsEmpty() ? nsnull : aArray[0]->GetCurrentDoc();
-  MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
 
   // Walk backwards so that if we remove elements we can just keep iterating
   PRUint32 length = aArray.Length();
   for (PRUint32 i = length; i > 0; --i) {
     nsGenericHTMLFormElement* node = aArray[i-1];
 
     // Now if MAYBE_ORPHAN_FORM_ELEMENT is not set, that would mean that the
     // node is in fact a descendant of the form and hence should stay in the
@@ -1229,17 +1227,17 @@ nsHTMLFormElement::AddElement(nsGenericH
     // Notify that the state of the previous default submit element has changed
     // if the element which is the default submit element has changed.  The new
     // default submit element is responsible for its own ContentStateChanged
     // call.
     if (aNotify && oldDefaultSubmit &&
         oldDefaultSubmit != mDefaultSubmitElement) {
       nsIDocument* document = GetCurrentDoc();
       if (document) {
-        MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
+        nsAutoScriptBlocker scriptBlocker;
         nsCOMPtr<nsIContent> oldElement(do_QueryInterface(oldDefaultSubmit));
         document->ContentStateChanged(oldElement, NS_EVENT_STATE_DEFAULT);
       }
     }
   }
 
   // If the element is subject to constraint validaton and is invalid, we need
   // to update our internal counter.
@@ -1367,17 +1365,17 @@ nsHTMLFormElement::HandleDefaultSubmitRe
   NS_POSTCONDITION(mDefaultSubmitElement == mFirstSubmitInElements ||
                    mDefaultSubmitElement == mFirstSubmitNotInElements,
                    "What happened here?");
 
   // Notify about change if needed.
   if (mDefaultSubmitElement) {
     nsIDocument* document = GetCurrentDoc();
     if (document) {
-      MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       document->ContentStateChanged(mDefaultSubmitElement,
                                     NS_EVENT_STATE_DEFAULT);
     }
   }
 }
 
 nsresult
 nsHTMLFormElement::RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
@@ -1747,17 +1745,17 @@ nsHTMLFormElement::CheckValidFormSubmiss
         nsIDocument* doc = GetCurrentDoc();
         if (doc) {
           /*
            * We are going to call ContentStateChanged assuming elements want to
            * be notified because we can't know.
            * Submissions shouldn't happen during parsing so it _should_ be safe.
            */
 
-          MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+          nsAutoScriptBlocker scriptBlocker;
 
           for (PRUint32 i = 0, length = mControls->mElements.Length();
                i < length; ++i) {
             // Input elements can trigger a form submission and we want to
             // update the style in that case.
             if (mControls->mElements[i]->IsHTML(nsGkAtoms::input) &&
                 nsContentUtils::IsFocusedContent(mControls->mElements[i])) {
               static_cast<nsHTMLInputElement*>(mControls->mElements[i])
@@ -1832,17 +1830,17 @@ nsHTMLFormElement::UpdateValidity(PRBool
 
   /*
    * We are going to call ContentStateChanged assuming submit controls want to
    * be notified because we can't know.
    * UpdateValidity shouldn't be called so much during parsing so it _should_
    * be safe.
    */
 
-  MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
 
   // Inform submit controls that the form validity has changed.
   for (PRUint32 i = 0, length = mControls->mElements.Length();
        i < length; ++i) {
     if (mControls->mElements[i]->IsSubmitControl()) {
       doc->ContentStateChanged(mControls->mElements[i],
                                NS_EVENT_STATE_MOZ_SUBMITINVALID);
     }
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -949,17 +949,16 @@ nsHTMLInputElement::AfterSetAttr(PRInt32
       if (aName == nsGkAtoms::type) {
         UpdateEditableState();
       } else if (IsSingleLineTextControl(PR_FALSE) && aName == nsGkAtoms::readonly) {
         UpdateEditableState();
         states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
       }
 
       if (doc && !states.IsEmpty()) {
-        MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
         doc->ContentStateChanged(this, states);
       }
     }
   }
 
   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
                                                 aValue, aNotify);
 }
@@ -1022,17 +1021,17 @@ nsHTMLInputElement::SetIndeterminateInte
     nsIFrame* frame = GetPrimaryFrame();
     if (frame)
       frame->InvalidateFrameSubtree();
   }
 
   // Notify the document so it can update :indeterminate pseudoclass rules
   nsIDocument* document = GetCurrentDoc();
   if (document) {
-    mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     document->ContentStateChanged(this, NS_EVENT_STATE_INDETERMINATE);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::SetIndeterminate(PRBool aValue)
@@ -1439,17 +1438,17 @@ nsHTMLInputElement::SetValueInternal(con
       SetValueChanged(PR_TRUE);
     }
     mInputData.mState->SetValue(value, aUserInput);
 
     if (PlaceholderApplies() &&
         HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
       nsIDocument* doc = GetCurrentDoc();
       if (doc) {
-        mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+        nsAutoScriptBlocker scriptBlocker;
         doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_PLACEHOLDER);
       }
     }
 
     return NS_OK;
   }
 
   // If the value of a hidden input was changed, we mark it changed so that we
@@ -1478,17 +1477,17 @@ nsHTMLInputElement::SetValueChanged(PRBo
     if (!IsSingleLineTextControl(PR_FALSE)) {
       FreeData();
     }
   }
 
   if (valueChangedBefore != aValueChanged) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_UI_VALID |
                                      NS_EVENT_STATE_MOZ_UI_INVALID);
     }
   }
 
   return NS_OK;
 }
 
@@ -1527,17 +1526,17 @@ nsHTMLInputElement::SetCheckedChangedInt
 
   SET_BOOLBIT(mBitField, BF_CHECKED_CHANGED, aCheckedChanged);
 
   // This method can't be called when we are not authorized to notify
   // so we do not need a aNotify parameter.
   if (checkedChangedBefore != aCheckedChanged) {
     nsIDocument* document = GetCurrentDoc();
     if (document) {
-      mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       document->ContentStateChanged(this,
                                     NS_EVENT_STATE_MOZ_UI_VALID |
                                     NS_EVENT_STATE_MOZ_UI_INVALID);
     }
   }
 }
 
 NS_IMETHODIMP
@@ -1730,17 +1729,17 @@ nsHTMLInputElement::SetCheckedInternal(P
     }
   }
 
   // Notify the document that the CSS :checked pseudoclass for this element
   // has changed state.
   if (aNotify) {
     nsIDocument* document = GetCurrentDoc();
     if (document) {
-      mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, aNotify);
+      nsAutoScriptBlocker scriptBlocker;
       document->ContentStateChanged(this, NS_EVENT_STATE_CHECKED);
     }
   }
 
   UpdateAllValidityStates(aNotify);
 }
 
 NS_IMETHODIMP
@@ -2074,17 +2073,17 @@ nsHTMLInputElement::PostHandleEvent(nsEv
         HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
         // TODO: checking if the value is empty could be a good idea but we do not
       // have a simple way to do that, see bug 585100
       states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
     }
 
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, states);
     }
   }
 
   // ignore the activate event fired by the "Browse..." button
   // (file input controls fire their own) (bug 500885)
   if (mType == NS_FORM_INPUT_FILE) {
     nsCOMPtr<nsIContent> maybeButton =
@@ -3652,17 +3651,17 @@ nsHTMLInputElement::DoesPatternApply() c
 
 NS_IMETHODIMP
 nsHTMLInputElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
                                    NS_EVENT_STATE_VALID |
                                    NS_EVENT_STATE_MOZ_UI_INVALID |
                                    NS_EVENT_STATE_MOZ_UI_VALID);
   }
 
   return NS_OK;
 }
@@ -3869,17 +3868,17 @@ nsHTMLInputElement::UpdateAllValiditySta
   UpdateTooLongValidityState();
   UpdateValueMissingValidityState();
   UpdateTypeMismatchValidityState();
   UpdatePatternMismatchValidityState();
 
   if (validBefore != IsValid() && aNotify) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this,
                                NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
                                NS_EVENT_STATE_MOZ_UI_VALID |
                                NS_EVENT_STATE_MOZ_UI_INVALID);
     }
   }
 }
 
@@ -4172,17 +4171,17 @@ nsHTMLInputElement::OnValueChanged(PRBoo
 
   // :-moz-placeholder pseudo-class may change when the value changes.
   // However, we don't want to waste cycles if the state doesn't apply.
   if (aNotify && PlaceholderApplies()
       && HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)
       && !nsContentUtils::IsFocusedContent((nsIContent*)(this))) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_PLACEHOLDER);
     }
   }
 }
 
 void
 nsHTMLInputElement::FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify)
 {
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -169,17 +169,17 @@ nsHTMLOptionElement::SetSelectedInternal
   mSelectedChanged = PR_TRUE;
   mIsSelected = aValue;
 
   // When mIsInSetDefaultSelected is true, the notification will be handled by
   // SetAttr/UnsetAttr.
   if (aNotify && !mIsInSetDefaultSelected) {
     nsIDocument* document = GetCurrentDoc();
     if (document) {
-      mozAutoDocUpdate upd(document, UPDATE_CONTENT_STATE, aNotify);
+      nsAutoScriptBlocker scriptBlocker;
       document->ContentStateChanged(this, NS_EVENT_STATE_CHECKED);
     }
   }
 }
 
 NS_IMETHODIMP 
 nsHTMLOptionElement::GetSelected(PRBool* aValue)
 {
--- a/content/html/content/src/nsHTMLOutputElement.cpp
+++ b/content/html/content/src/nsHTMLOutputElement.cpp
@@ -154,17 +154,17 @@ NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_S
 
 NS_IMETHODIMP
 nsHTMLOutputElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
                                    NS_EVENT_STATE_VALID |
                                    NS_EVENT_STATE_MOZ_UI_INVALID |
                                    NS_EVENT_STATE_MOZ_UI_VALID);
   }
 
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -200,17 +200,17 @@ NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_S
 
 NS_IMETHODIMP
 nsHTMLSelectElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
                                    NS_EVENT_STATE_VALID |
                                    NS_EVENT_STATE_MOZ_UI_INVALID |
                                    NS_EVENT_STATE_MOZ_UI_VALID);
   }
 
   return NS_OK;
 }
@@ -353,17 +353,17 @@ nsHTMLSelectElement::RemoveOptionsFromLi
     if (!CheckSelectSomething(aNotify) && mSelectedIndex == -1) {
       // Update the validity state in case of we've just removed the last
       // option.
       UpdateValueMissingValidityState();
 
       if (aNotify) {
         nsIDocument* doc = GetCurrentDoc();
         if (doc) {
-          MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+          nsAutoScriptBlocker scriptBlocker;
           doc->ContentStateChanged(this, NS_EVENT_STATE_VALID |
                                          NS_EVENT_STATE_INVALID |
                                          NS_EVENT_STATE_MOZ_UI_INVALID |
                                          NS_EVENT_STATE_MOZ_UI_VALID);
         }
       }
     }
   }
@@ -886,17 +886,17 @@ nsHTMLSelectElement::OnOptionSelected(ns
   if (aSelectFrame) {
     aSelectFrame->OnOptionSelected(aIndex, aSelected);
   }
 
   UpdateValueMissingValidityState();
   if (aNotify) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, NS_EVENT_STATE_VALID |
                                      NS_EVENT_STATE_INVALID |
                                      NS_EVENT_STATE_MOZ_UI_INVALID |
                                      NS_EVENT_STATE_MOZ_UI_VALID);
     }
   }
 }
 
@@ -1319,17 +1319,17 @@ nsHTMLSelectElement::SelectSomething(PRB
     if (NS_FAILED(rv) || !disabled) {
       rv = SetSelectedIndexInternal(i, aNotify);
       NS_ENSURE_SUCCESS(rv, PR_FALSE);
 
       UpdateValueMissingValidityState();
       if (aNotify) {
         nsIDocument* doc = GetCurrentDoc();
         if (doc) {
-          MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+          nsAutoScriptBlocker scriptBlocker;
           doc->ContentStateChanged(this, NS_EVENT_STATE_VALID |
                                          NS_EVENT_STATE_INVALID |
                                          NS_EVENT_STATE_MOZ_UI_INVALID |
                                          NS_EVENT_STATE_MOZ_UI_VALID);
         }
       }
 
       return PR_TRUE;
@@ -1385,17 +1385,17 @@ nsHTMLSelectElement::AfterSetAttr(PRInt3
       states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
                 NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
     }
   }
 
   if (aNotify && !states.IsEmpty()) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, states);
     }
   }
 
   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
                                                 aValue, aNotify);
 }
 
@@ -1561,17 +1561,17 @@ nsHTMLSelectElement::PostHandleEvent(nsE
     // We don't have to update NS_EVENT_STATE_MOZ_UI_INVALID nor
     // NS_EVENT_STATE_MOZ_UI_VALID given that the states should not change.
   } else if (aVisitor.mEvent->message == NS_BLUR_CONTENT) {
     mCanShowInvalidUI = PR_TRUE;
     mCanShowValidUI = PR_TRUE;
 
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_UI_VALID |
                                      NS_EVENT_STATE_MOZ_UI_INVALID);
     }
   }
 
   return nsGenericHTMLFormElement::PostHandleEvent(aVisitor);
 }
 
@@ -2295,15 +2295,15 @@ nsHTMLSelectElement::SetSelectionChanged
   }
 
   PRBool previousSelectionChangedValue = mSelectionHasChanged;
   mSelectionHasChanged = aValue;
 
   if (aNotify && mSelectionHasChanged != previousSelectionChangedValue) {
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_UI_INVALID |
                                      NS_EVENT_STATE_MOZ_UI_VALID);
     }
   }
 }
 
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -591,17 +591,17 @@ nsHTMLTextAreaElement::SetValueChanged(P
                            NS_EVENT_STATE_MOZ_UI_INVALID;
 
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
       states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
     }
 
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, states);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -769,17 +769,17 @@ nsHTMLTextAreaElement::PostHandleEvent(n
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
       // TODO: checking if the value is empty could be a good idea but we do not
       // have a simple way to do that, see bug 585100
       states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
     }
 
     nsIDocument* doc = GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(this, states);
     }
   }
 
   // Reset the flag for other content besides this text field
   aVisitor.mEvent->flags |= (aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH)
     ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
 
@@ -1219,17 +1219,16 @@ nsHTMLTextAreaElement::AfterSetAttr(PRIn
       nsIDocument* doc = GetCurrentDoc();
 
       if (aName == nsGkAtoms::readonly) {
         UpdateEditableState();
         states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
       }
 
       if (doc && !states.IsEmpty()) {
-        MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
         doc->ContentStateChanged(this, states);
       }
     }
   }
 
   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                                 aNotify);
 }
@@ -1267,17 +1266,17 @@ nsHTMLTextAreaElement::IsValueEmpty() co
 
 NS_IMETHODIMP
 nsHTMLTextAreaElement::SetCustomValidity(const nsAString& aError)
 {
   nsIConstraintValidation::SetCustomValidity(aError);
 
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
-    MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
                                    NS_EVENT_STATE_VALID |
                                    NS_EVENT_STATE_MOZ_UI_INVALID |
                                    NS_EVENT_STATE_MOZ_UI_VALID);
   }
 
   return NS_OK;
 }
@@ -1498,17 +1497,17 @@ nsHTMLTextAreaElement::OnValueChanged(PR
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)
         && !nsContentUtils::IsFocusedContent((nsIContent*)(this))) {
       states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
     }
 
     if (!states.IsEmpty()) {
       nsIDocument* doc = GetCurrentDoc();
       if (doc) {
-        MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+        nsAutoScriptBlocker scriptBlocker;
         doc->ContentStateChanged(this, states);
       }
     }
   }
 }
 
 void
 nsHTMLTextAreaElement::FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify)
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2980,17 +2980,17 @@ nsHTMLDocument::EditingStateChanged()
       editSession->TearDownEditorOnWindow(window);
       mEditingState = eOff;
 
       return rv;
     }
   }
 
   if (updateState) {
-    mozAutoDocUpdate upd(this, UPDATE_CONTENT_STATE, PR_TRUE);
+    nsAutoScriptBlocker scriptBlocker;
     NotifyEditableStateChange(this, this, !designMode);
   }
 
   // Resync the editor's spellcheck state.
   if (spellRecheckAll) {
     nsCOMPtr<nsISelectionController> selcon;
     nsresult rv = editor->GetSelectionController(getter_AddRefs(selcon));
     NS_ENSURE_SUCCESS(rv, rv); 
--- a/content/mathml/content/src/nsMathMLElement.cpp
+++ b/content/mathml/content/src/nsMathMLElement.cpp
@@ -462,11 +462,11 @@ nsMathMLElement::SetIncrementScriptLevel
   mIncrementScriptLevel = aIncrementScriptLevel;
 
   NS_ASSERTION(aNotify, "We always notify!");
 
   nsIDocument* doc = GetCurrentDoc();
   if (!doc)
     return;
 
-  mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
   doc->ContentStateChanged(this, NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL);
 }
--- a/content/xtf/src/nsXTFElementWrapper.cpp
+++ b/content/xtf/src/nsXTFElementWrapper.cpp
@@ -909,17 +909,17 @@ nsXTFElementWrapper::SetIntrinsicState(n
   if (!doc || bits.IsEmpty())
     return NS_OK;
 
   NS_WARN_IF_FALSE(!newStates.HasAllStates(NS_EVENT_STATE_MOZ_READONLY |
                                            NS_EVENT_STATE_MOZ_READWRITE),
                    "Both READONLY and READWRITE are being set.  Yikes!!!");
 
   mIntrinsicState = newStates;
-  mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
   doc->ContentStateChanged(this, bits);
 
   return NS_OK;
 }
 
 nsIAtom *
 nsXTFElementWrapper::GetClassAttributeName() const
 {
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1465,17 +1465,16 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
         if (binding)
             binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
 
     }
 
     if (aNotify) {
         stateMask ^= IntrinsicState();
         if (doc && !stateMask.IsEmpty()) {
-            MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, aNotify);
             doc->ContentStateChanged(this, stateMask);
         }
         nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
                                       nsIDOMMutationEvent::REMOVAL);
     }
 
     if (hasMutationListeners) {
         nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED);
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -883,17 +883,17 @@ nsFocusManager::WindowShown(nsIDOMWindow
 
   return NS_OK;
 }
 
 static void
 NotifyFocusStateChange(nsIContent* aContent, nsPIDOMWindow* aWindow)
 {
   nsIDocument *doc = aContent->GetCurrentDoc();
-  MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  nsAutoScriptBlocker scriptBlocker;
   nsEventStates eventState = NS_EVENT_STATE_FOCUS;
   if (aWindow->ShouldShowFocusRing()) {
     eventState |= NS_EVENT_STATE_FOCUSRING;
   }
   doc->ContentStateChanged(aContent, eventState);
 }
 
 NS_IMETHODIMP
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7653,17 +7653,17 @@ nsGlobalWindow::SetKeyboardIndicators(UI
         childWindow->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings);
       }
     }
   }
 
   if (mHasFocus && mFocusedNode) { // send content state notifications
     nsIDocument *doc = mFocusedNode->GetCurrentDoc();
     if (doc) {
-      MOZ_AUTO_DOC_UPDATE(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+      nsAutoScriptBlocker scriptBlocker;
       doc->ContentStateChanged(mFocusedNode, NS_EVENT_STATE_FOCUSRING);
     }
   }
 }
 
 void
 nsGlobalWindow::GetKeyboardIndicators(PRBool* aShowAccelerators,
                                       PRBool* aShowFocusRings)