Bug 578696 part 9. Stop holding strong refs when calling ContentAppended. r=sicking
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 21 Jul 2010 11:33:32 -0400
changeset 48014 1c424f1f465e1433b6f003e4a02336be25c96657
parent 48013 b397d9d1b6c15cade1a9abb54436efa2e46a401f
child 48015 cccefcd4cedabb59e28475d5497c4a333f4c48a2
push id14533
push userbzbarsky@mozilla.com
push dateWed, 21 Jul 2010 15:42:13 +0000
treeherdermozilla-central@b20c759afb7c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs578696
milestone2.0b3pre
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 578696 part 9. Stop holding strong refs when calling ContentAppended. r=sicking
content/base/public/nsIMutationObserver.h
content/base/src/nsNodeUtils.cpp
content/events/src/nsXMLEventsManager.cpp
content/xul/document/src/nsXULDocument.cpp
editor/libeditor/html/nsHTMLEditor.cpp
layout/inspector/src/inDOMView.cpp
layout/xul/base/src/tree/src/nsTreeContentView.cpp
widget/src/cocoa/nsMenuGroupOwnerX.mm
--- a/content/base/public/nsIMutationObserver.h
+++ b/content/base/public/nsIMutationObserver.h
@@ -205,16 +205,22 @@ public:
    * child list of another node in the tree.
    *
    * @param aDocument  The owner-document of aContent. Can be null.
    * @param aContainer The container that had new children appended. Is never
    *                   null.
    * @param aFirstNewContent the node at aIndexInContainer in aContainer.
    * @param aNewIndexInContainer the index in the container of the first
    *                   new child
+   *
+   * @note Callers of this method might not hold a strong reference to the
+   *       observer.  The observer is responsible for making sure it stays
+   *       alive for the duration of the call as needed.  The observer may
+   *       assume that this call will happen when there are script blockers on
+   *       the stack.
    */
   virtual void ContentAppended(nsIDocument *aDocument,
                                nsIContent* aContainer,
                                nsIContent* aFirstNewContent,
                                PRInt32     aNewIndexInContainer) = 0;
 
   /**
    * Notification that a content node has been inserted as child to another
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -153,17 +153,17 @@ nsNodeUtils::AttributeChanged(nsIContent
 
 void
 nsNodeUtils::ContentAppended(nsIContent* aContainer,
                              nsIContent* aFirstNewContent,
                              PRInt32 aNewIndexInContainer)
 {
   nsIDocument* doc = aContainer->GetOwnerDoc();
 
-  IMPL_STRONGREF_MUTATION_NOTIFICATION(ContentAppended, aContainer,
+  IMPL_MUTATION_NOTIFICATION(ContentAppended, aContainer,
                              (doc, aContainer, aFirstNewContent,
                               aNewIndexInContainer));
 }
 
 void
 nsNodeUtils::ContentInserted(nsINode* aContainer,
                              nsIContent* aChild,
                              PRInt32 aIndexInContainer)
--- a/content/events/src/nsXMLEventsManager.cpp
+++ b/content/events/src/nsXMLEventsManager.cpp
@@ -301,16 +301,18 @@ PRBool nsXMLEventsManager::RemoveListene
     mListeners.Remove(aContent);
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
 void nsXMLEventsManager::AddListeners(nsIDocument* aDocument)
 {
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
   nsIContent *cur;
   for (int i = 0; i < mIncomplete.Count(); ++i) {
     cur = mIncomplete[i];
     //If this succeeds, the object will be removed from mIncomplete
     if (nsXMLEventsListener::InitXMLEventsListener(aDocument, this, cur))
       --i;
   }
 }
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -1097,16 +1097,19 @@ nsXULDocument::AttributeChanged(nsIDocum
 void
 nsXULDocument::ContentAppended(nsIDocument* aDocument,
                                nsIContent* aContainer,
                                nsIContent* aFirstNewContent,
                                PRInt32 aNewIndexInContainer)
 {
     NS_ASSERTION(aDocument == this, "unexpected doc");
     
+    // Might not need this, but be safe for now.
+    nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
     // Update our element map
     nsresult rv = NS_OK;
     for (nsIContent* cur = aFirstNewContent; cur && NS_SUCCEEDED(rv);
          cur = cur->GetNextSibling()) {
         rv = AddSubtreeToDocument(cur);
     }
 }
 
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -5834,16 +5834,18 @@ nsHTMLEditor::ShouldReplaceRootElement()
   nsCOMPtr<nsIDOMHTMLElement> docBody;
   GetBodyElement(getter_AddRefs(docBody));
   return !SameCOMIdentity(docBody, mRootElement);
 }
 
 void
 nsHTMLEditor::ResetRootElementAndEventTarget()
 {
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
   // Need to remove the event listeners first because BeginningOfDocument
   // could set a new root (and event target is set by InstallEventListeners())
   // and we won't be able to remove them from the old event target then.
   RemoveEventListeners();
   mRootElement = nsnull;
   nsresult rv = InstallEventListeners();
   NS_ENSURE_SUCCESS(rv, );
 
--- a/layout/inspector/src/inDOMView.cpp
+++ b/layout/inspector/src/inDOMView.cpp
@@ -852,16 +852,18 @@ inDOMView::ContentInserted(nsIDocument *
   // find the inDOMViewNode for the parent of the inserted content
   PRInt32 parentRow = 0;
   if (NS_FAILED(rv = NodeToRow(parent, &parentRow)))
     return;
   inDOMViewNode* parentNode = nsnull;
   if (NS_FAILED(rv = RowToNode(parentRow, &parentNode)))
     return;
 
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+  
   if (!parentNode->isOpen) {
     // Parent is not open, so don't bother creating tree rows for the
     // kids.  But do indicate that it's now a container, if needed.
     if (!parentNode->isContainer) {
       parentNode->isContainer = PR_TRUE;
       mTree->InvalidateRow(parentRow);
     }
     return;
--- a/layout/xul/base/src/tree/src/nsTreeContentView.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeContentView.cpp
@@ -1022,16 +1022,19 @@ nsTreeContentView::ContentInserted(nsIDo
     if (!element)
       return; // this is not for us
     nsIAtom *parentTag = element->Tag();
     if ((element->IsXUL() && parentTag == nsGkAtoms::tree) ||
         (element->IsHTML() && parentTag == nsGkAtoms::select))
       return; // this is not for us
   }
 
+  // Lots of codepaths under here that do all sorts of stuff, so be safe.
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
+
   if (childTag == nsGkAtoms::treechildren) {
     PRInt32 index = FindContent(aContainer);
     if (index >= 0) {
       Row* row = mRows[index];
       row->SetEmpty(PR_FALSE);
       if (mBoxObject)
         mBoxObject->InvalidateRow(index);
       if (row->IsContainer() && row->IsOpen()) {
--- a/widget/src/cocoa/nsMenuGroupOwnerX.mm
+++ b/widget/src/cocoa/nsMenuGroupOwnerX.mm
@@ -180,16 +180,17 @@ void nsMenuGroupOwnerX::ContentRemoved(n
 }
 
 
 void nsMenuGroupOwnerX::ContentInserted(nsIDocument * aDocument,
                                         nsIContent * aContainer,
                                         nsIContent * aChild,
                                         PRInt32 aIndexInContainer)
 {
+  nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
   nsChangeObserver* obs = LookupContentChangeObserver(aContainer);
   if (obs)
     obs->ObserveContentInserted(aDocument, aChild, aIndexInContainer);
   else if (aContainer != mContent) {
     // We do a lookup on the parent container in case things were removed
     // under a "menupopup" item. That is basically a wrapper for the contents
     // of a "menu" node.
     nsCOMPtr<nsIContent> parent = aContainer->GetParent();