Implement cycle collection for transaction manager and editor transactions. (Bug 488799) r+sr=peterv a=blocking1.9.1+ on bug 420670
authorL. David Baron <dbaron@dbaron.org>
Fri, 08 May 2009 21:59:25 -0700
changeset 25165 0d898991dbd9330905104765ad53a1e13880b9ef
parent 25164 7cf5bc404a486c1b5bcdec7f02bd9097acb33e18
child 25166 69b776e23172bc2e3d2f4f3fe03c65c90d289a78
push id1395
push userdbaron@mozilla.com
push dateWed, 13 May 2009 21:50:21 +0000
reviewersblocking1.9.1
bugs488799, 420670
milestone1.9.1b5pre
Implement cycle collection for transaction manager and editor transactions. (Bug 488799) r+sr=peterv a=blocking1.9.1+ on bug 420670
editor/libeditor/base/ChangeAttributeTxn.cpp
editor/libeditor/base/ChangeAttributeTxn.h
editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp
editor/libeditor/base/ChangeCSSInlineStyleTxn.h
editor/libeditor/base/CreateElementTxn.cpp
editor/libeditor/base/CreateElementTxn.h
editor/libeditor/base/DeleteElementTxn.cpp
editor/libeditor/base/DeleteElementTxn.h
editor/libeditor/base/DeleteRangeTxn.cpp
editor/libeditor/base/DeleteRangeTxn.h
editor/libeditor/base/DeleteTextTxn.cpp
editor/libeditor/base/DeleteTextTxn.h
editor/libeditor/base/EditAggregateTxn.cpp
editor/libeditor/base/EditAggregateTxn.h
editor/libeditor/base/EditTxn.cpp
editor/libeditor/base/EditTxn.h
editor/libeditor/base/IMETextTxn.cpp
editor/libeditor/base/IMETextTxn.h
editor/libeditor/base/InsertElementTxn.cpp
editor/libeditor/base/InsertElementTxn.h
editor/libeditor/base/InsertTextTxn.cpp
editor/libeditor/base/InsertTextTxn.h
editor/libeditor/base/JoinElementTxn.cpp
editor/libeditor/base/JoinElementTxn.h
editor/libeditor/base/PlaceholderTxn.cpp
editor/libeditor/base/PlaceholderTxn.h
editor/libeditor/base/SplitElementTxn.cpp
editor/libeditor/base/SplitElementTxn.h
editor/libeditor/base/nsSelectionState.cpp
editor/libeditor/base/nsSelectionState.h
editor/libeditor/base/nsStyleSheetTxns.cpp
editor/libeditor/base/nsStyleSheetTxns.h
editor/txmgr/src/nsTransactionItem.cpp
editor/txmgr/src/nsTransactionItem.h
editor/txmgr/src/nsTransactionManager.cpp
editor/txmgr/src/nsTransactionManager.h
editor/txmgr/src/nsTransactionStack.cpp
editor/txmgr/src/nsTransactionStack.h
--- a/editor/libeditor/base/ChangeAttributeTxn.cpp
+++ b/editor/libeditor/base/ChangeAttributeTxn.cpp
@@ -38,16 +38,29 @@
 #include "ChangeAttributeTxn.h"
 #include "nsIDOMElement.h"
 
 ChangeAttributeTxn::ChangeAttributeTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(ChangeAttributeTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ChangeAttributeTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ChangeAttributeTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeAttributeTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor      *aEditor,
                                        nsIDOMElement  *aElement,
                                        const nsAString& aAttribute,
                                        const nsAString& aValue,
                                        PRBool aRemoveAttribute)
 {
   NS_ASSERTION(aEditor && aElement, "bad arg");
   if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
--- a/editor/libeditor/base/ChangeAttributeTxn.h
+++ b/editor/libeditor/base/ChangeAttributeTxn.h
@@ -70,16 +70,18 @@ public:
                   const nsAString& aAttribute,
                   const nsAString& aValue,
                   PRBool aRemoveAttribute);
 
 private:
   ChangeAttributeTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeAttributeTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
 
 protected:
 
   /** the editor that created this transaction */
--- a/editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp
+++ b/editor/libeditor/base/ChangeCSSInlineStyleTxn.cpp
@@ -42,16 +42,31 @@
 #include "nsIDOMElementCSSInlineStyle.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsIAtom.h"
 
 #define kNullCh (PRUnichar('\0'))
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(ChangeCSSInlineStyleTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ChangeCSSInlineStyleTxn,
+                                                EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ChangeCSSInlineStyleTxn,
+                                                  EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeCSSInlineStyleTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 // answers true if aValue is in the string list of white-space separated values aValueList
 // a case-sensitive search is performed if aCaseSensitive is true
 PRBool
 ChangeCSSInlineStyleTxn::ValueIncludes(const nsAString &aValueList, const nsAString &aValue, PRBool aCaseSensitive)
 {
   nsAutoString  valueList(aValueList);
   PRBool result = PR_FALSE;
 
--- a/editor/libeditor/base/ChangeCSSInlineStyleTxn.h
+++ b/editor/libeditor/base/ChangeCSSInlineStyleTxn.h
@@ -107,16 +107,19 @@ private:
   /** If the boolean is true and if the value is not the empty string,
     * set the property in the transaction to that value; if the value
     * is empty, remove the property from element's styles. If the boolean
     * is false, just remove the style attribute.
     */
   nsresult SetStyle(PRBool aAttributeWasSet, nsAString & aValue);
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeCSSInlineStyleTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
 
 protected:
 
   /** the editor that created this transaction */
   nsIEditor *mEditor;
--- a/editor/libeditor/base/CreateElementTxn.cpp
+++ b/editor/libeditor/base/CreateElementTxn.cpp
@@ -51,16 +51,32 @@
 static PRBool gNoisy = PR_FALSE;
 #endif
 
 CreateElementTxn::CreateElementTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(CreateElementTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CreateElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNewNode)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRefNode)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CreateElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNewNode)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRefNode)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 NS_IMETHODIMP CreateElementTxn::Init(nsEditor      *aEditor,
                                      const nsAString &aTag,
                                      nsIDOMNode     *aParent,
                                      PRUint32        aOffsetInParent)
 {
   NS_ASSERTION(aEditor&&aParent, "null args");
   if (!aEditor || !aParent) { return NS_ERROR_NULL_POINTER; }
 
--- a/editor/libeditor/base/CreateElementTxn.h
+++ b/editor/libeditor/base/CreateElementTxn.h
@@ -70,16 +70,19 @@ public:
                   const nsAString& aTag,
                   nsIDOMNode *aParent,
                   PRUint32 aOffsetInParent);
 
 private:
   CreateElementTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CreateElementTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
 
   NS_IMETHOD GetNewNode(nsIDOMNode **aNewNode);
 
 protected:
   
--- a/editor/libeditor/base/DeleteElementTxn.cpp
+++ b/editor/libeditor/base/DeleteElementTxn.cpp
@@ -53,16 +53,33 @@ DeleteElementTxn::DeleteElementTxn()
 : EditTxn()
 ,mElement()
 ,mParent()
 ,mRefNode()
 ,mRangeUpdater(nsnull)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DeleteElementTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DeleteElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRefNode)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DeleteElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRefNode)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteElementTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP DeleteElementTxn::Init(nsIEditor *aEditor,
                                      nsIDOMNode *aElement,
                                      nsRangeUpdater *aRangeUpdater)
 {
   if (!aEditor || !aElement) return NS_ERROR_NULL_POINTER;
   mEditor = aEditor;
   mElement = do_QueryInterface(aElement);
   nsresult result = mElement->GetParentNode(getter_AddRefs(mParent));
--- a/editor/libeditor/base/DeleteElementTxn.h
+++ b/editor/libeditor/base/DeleteElementTxn.h
@@ -64,16 +64,19 @@ public:
     * @param aElement the node to delete
     */
   NS_IMETHOD Init(nsIEditor *aEditor, nsIDOMNode *aElement, nsRangeUpdater *aRangeUpdater);
 
 private:
   DeleteElementTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteElementTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
 
 protected:
   
   /** the element to delete */
   nsCOMPtr<nsIDOMNode> mElement;
--- a/editor/libeditor/base/DeleteRangeTxn.cpp
+++ b/editor/libeditor/base/DeleteRangeTxn.cpp
@@ -61,16 +61,37 @@ DeleteRangeTxn::DeleteRangeTxn()
 ,mEndParent()
 ,mCommonParent()
 ,mEndOffset(0)
 ,mEditor(nsnull)
 ,mRangeUpdater(nsnull)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DeleteRangeTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DeleteRangeTxn,
+                                                EditAggregateTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRange)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStartParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEndParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCommonParent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DeleteRangeTxn,
+                                                  EditAggregateTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStartParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEndParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCommonParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteRangeTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
+
 NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, 
                                    nsIDOMRange *aRange,
                                    nsRangeUpdater *aRangeUpdater)
 {
   NS_ASSERTION(aEditor && aRange, "bad state");
   if (!aEditor || !aRange) { return NS_ERROR_NOT_INITIALIZED; }
 
   mEditor = aEditor;
--- a/editor/libeditor/base/DeleteRangeTxn.h
+++ b/editor/libeditor/base/DeleteRangeTxn.h
@@ -69,16 +69,19 @@ public:
   NS_IMETHOD Init(nsIEditor *aEditor, 
                   nsIDOMRange *aRange,
                   nsRangeUpdater *aRangeUpdater);
 
 private:
   DeleteRangeTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteRangeTxn, EditAggregateTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
 
 protected:
 
   NS_IMETHOD CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent, 
                                              PRUint32    aStartOffset, 
--- a/editor/libeditor/base/DeleteTextTxn.cpp
+++ b/editor/libeditor/base/DeleteTextTxn.cpp
@@ -49,16 +49,29 @@ DeleteTextTxn::DeleteTextTxn()
 ,mEditor(nsnull)
 ,mElement()
 ,mOffset(0)
 ,mNumCharsToDelete(0)
 ,mRangeUpdater(nsnull)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(DeleteTextTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DeleteTextTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DeleteTextTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor,
                                   nsIDOMCharacterData *aElement,
                                   PRUint32 aOffset,
                                   PRUint32 aNumCharsToDelete,
                                   nsRangeUpdater *aRangeUpdater)
 {
   NS_ASSERTION(aEditor&&aElement, "bad arg");
   if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
--- a/editor/libeditor/base/DeleteTextTxn.h
+++ b/editor/libeditor/base/DeleteTextTxn.h
@@ -70,16 +70,19 @@ public:
                   PRUint32 aOffset,
                   PRUint32 aNumCharsToDelete,
                   nsRangeUpdater *aRangeUpdater);
 
 private:
   DeleteTextTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DeleteTextTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
   PRUint32 GetOffset() { return mOffset; }
 
   PRUint32 GetNumCharsToDelete() { return mNumCharsToDelete; }
 
 protected:
 
--- a/editor/libeditor/base/EditAggregateTxn.cpp
+++ b/editor/libeditor/base/EditAggregateTxn.cpp
@@ -37,16 +37,36 @@
 
 #include "EditAggregateTxn.h"
 #include "nsCOMPtr.h"
 
 EditAggregateTxn::EditAggregateTxn()
   : EditTxn()
 {
 }
+NS_IMPL_CYCLE_COLLECTION_CLASS(EditAggregateTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(EditAggregateTxn, EditTxn)
+  tmp->mChildren.Clear();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(EditAggregateTxn, EditTxn)
+  for (PRUint32 i = 0; i < tmp->mChildren.Length(); ++i) {
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
+    cb.NoteXPCOMChild(static_cast<nsITransaction*>(tmp->mChildren[i]));
+  }
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditAggregateTxn)
+  if (aIID.Equals(EditAggregateTxn::GetCID())) {
+    *aInstancePtr = static_cast<EditAggregateTxn*>(this);
+    NS_ADDREF_THIS();
+    return NS_OK;
+  }
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
 NS_IMETHODIMP EditAggregateTxn::DoTransaction(void)
 {
   nsresult result=NS_OK;  // it's legal (but not very useful) to have an empty child list
   for (PRUint32 i = 0, length = mChildren.Length(); i < length; ++i)
   {
     nsITransaction *txn = mChildren[i];
     if (!txn) { return NS_ERROR_NULL_POINTER; }
@@ -174,21 +194,8 @@ NS_IMETHODIMP EditAggregateTxn::GetName(
   if (aName && mName)
   {
     *aName = mName;
     NS_ADDREF(*aName);
     return NS_OK;
   }
   return NS_ERROR_NULL_POINTER;
 }
-
-NS_IMETHODIMP EditAggregateTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
- 
-  if (aIID.Equals(EditAggregateTxn::GetCID())) {
-    *aInstancePtr = static_cast<EditAggregateTxn*>(this);
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-  return EditTxn::QueryInterface(aIID, aInstancePtr);
-}
-
--- a/editor/libeditor/base/EditAggregateTxn.h
+++ b/editor/libeditor/base/EditAggregateTxn.h
@@ -58,16 +58,18 @@ class EditAggregateTxn : public EditTxn
 {
 public:
   NS_IMETHOD QueryInterface(REFNSIID aIID, void **aInstancePtr);
 
   static const nsIID& GetCID() { static const nsIID cid = EDIT_AGGREGATE_TXN_CID; return cid; }
 
   EditAggregateTxn();
 
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(EditAggregateTxn, EditTxn)
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
   NS_IMETHOD Merge(nsITransaction *aTransaction, PRBool *aDidMerge);
 
   /** append a transaction to this aggregate */
   NS_IMETHOD AppendChild(EditTxn *aTxn);
 
--- a/editor/libeditor/base/EditTxn.cpp
+++ b/editor/libeditor/base/EditTxn.cpp
@@ -33,17 +33,26 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "EditTxn.h"
 
-NS_IMPL_ISUPPORTS2(EditTxn, nsITransaction, nsPIEditorTransaction)
+NS_IMPL_CYCLE_COLLECTION_0(EditTxn)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditTxn)
+  NS_INTERFACE_MAP_ENTRY(nsITransaction)
+  NS_INTERFACE_MAP_ENTRY(nsPIEditorTransaction)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransaction)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(EditTxn, nsITransaction)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(EditTxn, nsITransaction)
 
 EditTxn::~EditTxn()
 {
 }
 
 NS_IMETHODIMP
 EditTxn::RedoTransaction(void)
 {
--- a/editor/libeditor/base/EditTxn.h
+++ b/editor/libeditor/base/EditTxn.h
@@ -36,33 +36,35 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef EditTxn_h__
 #define EditTxn_h__
 
 #include "nsITransaction.h"
 #include "nsString.h"
 #include "nsPIEditorTransaction.h"
+#include "nsCycleCollectionParticipant.h"
 
 #define EDIT_TXN_CID \
 {/* c5ea31b0-ac48-11d2-86d8-000064657374 */ \
 0xc5ea31b0, 0xac48, 0x11d2, \
 {0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
 
 /**
  * Base class for all document editing transactions.
  */
 class EditTxn : public nsITransaction,
                 public nsPIEditorTransaction
 {
 public:
 
   static const nsIID& GetCID() { static const nsIID iid = EDIT_TXN_CID; return iid; }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditTxn, nsITransaction)
 
   virtual ~EditTxn();
 
   NS_IMETHOD RedoTransaction(void);
   NS_IMETHOD GetIsTransient(PRBool *aIsTransient);
   NS_IMETHOD Merge(nsITransaction *aTransaction, PRBool *aDidMerge);
 };
 
--- a/editor/libeditor/base/IMETextTxn.cpp
+++ b/editor/libeditor/base/IMETextTxn.cpp
@@ -47,16 +47,36 @@
 
 // #define DEBUG_IMETXN
 
 IMETextTxn::IMETextTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(IMETextTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IMETextTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElement)
+  // mRangeList can't lead to cycles
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IMETextTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
+  // mRangeList can't lead to cycles
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IMETextTxn)
+  if (aIID.Equals(IMETextTxn::GetCID())) {
+    *aInstancePtr = (void*)(IMETextTxn*)this;
+    NS_ADDREF_THIS();
+    return NS_OK;
+  }
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP IMETextTxn::Init(nsIDOMCharacterData     *aElement,
                                PRUint32                 aOffset,
                                PRUint32                 aReplaceLength,
                                nsIPrivateTextRangeList *aTextRangeList,
                                const nsAString         &aStringToInsert,
                                nsWeakPtr                aSelConWeak)
 {
   NS_ASSERTION(aElement, "illegal value- null ptr- aElement");
@@ -171,32 +191,16 @@ NS_IMETHODIMP IMETextTxn::MarkFixed(void
 
 NS_IMETHODIMP IMETextTxn::GetTxnDescription(nsAString& aString)
 {
   aString.AssignLiteral("IMETextTxn: ");
   aString += mStringToInsert;
   return NS_OK;
 }
 
-/* ============= nsISupports implementation ====================== */
-
-NS_IMETHODIMP
-IMETextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  if (nsnull == aInstancePtr) {
-    return NS_ERROR_NULL_POINTER;
-  }
-  if (aIID.Equals(IMETextTxn::GetCID())) {
-    *aInstancePtr = (void*)(IMETextTxn*)this;
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-  return (EditTxn::QueryInterface(aIID, aInstancePtr));
-}
-
 /* ============ protected methods ================== */
 static SelectionType TextRangeToSelection(int aTextRangeType)
 {
    switch(aTextRangeType)
    {
       case nsIPrivateTextRange::TEXTRANGE_RAWINPUT:
            return nsISelectionController::SELECTION_IME_RAWINPUT;
       case nsIPrivateTextRange::TEXTRANGE_SELECTEDRAWTEXT:
--- a/editor/libeditor/base/IMETextTxn.h
+++ b/editor/libeditor/base/IMETextTxn.h
@@ -77,16 +77,18 @@ public:
                   const nsAString& aString,
                   nsWeakPtr aSelCon);
 
 private:
 	
 	IMETextTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IMETextTxn, EditTxn)
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD Merge(nsITransaction *aTransaction, PRBool *aDidMerge);
 
   NS_IMETHOD MarkFixed(void);
 
 // nsISupports declarations
 
--- a/editor/libeditor/base/InsertElementTxn.cpp
+++ b/editor/libeditor/base/InsertElementTxn.cpp
@@ -46,16 +46,31 @@ static PRBool gNoisy = PR_FALSE;
 #endif
 
 
 InsertElementTxn::InsertElementTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(InsertElementTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InsertElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNode)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InsertElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNode)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertElementTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP InsertElementTxn::Init(nsIDOMNode *aNode,
                                      nsIDOMNode *aParent,
                                      PRInt32     aOffset,
                                      nsIEditor  *aEditor)
 {
   NS_ASSERTION(aNode && aParent && aEditor, "bad arg");
   if (!aNode || !aParent || !aEditor)
     return NS_ERROR_NULL_POINTER;
--- a/editor/libeditor/base/InsertElementTxn.h
+++ b/editor/libeditor/base/InsertElementTxn.h
@@ -66,16 +66,19 @@ public:
                   nsIDOMNode *aParent,
                   PRInt32     aOffset,
                   nsIEditor  *aEditor);
 
 private:
   InsertElementTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertElementTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
 protected:
   
   /** the element to insert */
   nsCOMPtr<nsIDOMNode> mNode;
 
   /** the node into which the new node will be inserted */
--- a/editor/libeditor/base/InsertTextTxn.cpp
+++ b/editor/libeditor/base/InsertTextTxn.cpp
@@ -44,16 +44,34 @@
 static PRBool gNoisy = PR_FALSE;
 #endif
 
 InsertTextTxn::InsertTextTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(InsertTextTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InsertTextTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InsertTextTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTxn)
+  if (aIID.Equals(InsertTextTxn::GetCID())) {
+    *aInstancePtr = (void*)(InsertTextTxn*)this;
+    NS_ADDREF_THIS();
+    return NS_OK;
+  }
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
                                   PRUint32             aOffset,
                                   const nsAString     &aStringToInsert,
                                   nsIEditor           *aEditor)
 {
 #if 0
       nsAutoString text;
       aElement->GetData(text);
@@ -149,32 +167,16 @@ NS_IMETHODIMP InsertTextTxn::Merge(nsITr
 
 NS_IMETHODIMP InsertTextTxn::GetTxnDescription(nsAString& aString)
 {
   aString.AssignLiteral("InsertTextTxn: ");
   aString += mStringToInsert;
   return NS_OK;
 }
 
-/* ============= nsISupports implementation ====================== */
-
-NS_IMETHODIMP
-InsertTextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  if (!aInstancePtr) {
-    return NS_ERROR_NULL_POINTER;
-  }
-  if (aIID.Equals(InsertTextTxn::GetCID())) {
-    *aInstancePtr = (void*)(InsertTextTxn*)this;
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-  return (EditTxn::QueryInterface(aIID, aInstancePtr));
-}
-
 /* ============ protected methods ================== */
 
 NS_IMETHODIMP InsertTextTxn::GetData(nsString& aResult)
 {
   aResult = mStringToInsert;
   return NS_OK;
 }
 
--- a/editor/libeditor/base/InsertTextTxn.h
+++ b/editor/libeditor/base/InsertTextTxn.h
@@ -68,16 +68,17 @@ public:
                   const nsAString& aString,
                   nsIEditor *aEditor);
 
 private:
 	
 	InsertTextTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertTextTxn, EditTxn)
 	
   NS_DECL_EDITTXN
 
   NS_IMETHOD Merge(nsITransaction *aTransaction, PRBool *aDidMerge);
 
 // nsISupports declarations
 
   // override QueryInterface to handle InsertTextTxn request
--- a/editor/libeditor/base/JoinElementTxn.cpp
+++ b/editor/libeditor/base/JoinElementTxn.cpp
@@ -44,16 +44,33 @@
 static PRBool gNoisy = PR_FALSE;
 #endif
 
 JoinElementTxn::JoinElementTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(JoinElementTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(JoinElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLeftNode)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRightNode)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(JoinElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLeftNode)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRightNode)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinElementTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP JoinElementTxn::Init(nsEditor   *aEditor,
                                    nsIDOMNode *aLeftNode,
                                    nsIDOMNode *aRightNode)
 {
   NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg");
   if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; }
   mEditor = aEditor;
   mLeftNode = do_QueryInterface(aLeftNode);
--- a/editor/libeditor/base/JoinElementTxn.h
+++ b/editor/libeditor/base/JoinElementTxn.h
@@ -70,16 +70,19 @@ public:
     */
   NS_IMETHOD Init(nsEditor   *aEditor,
                   nsIDOMNode *aLeftNode,
                   nsIDOMNode *aRightNode);
 protected:
   JoinElementTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(JoinElementTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
 protected:
   
   /** the elements to operate upon.  
     * After the merge, mRightNode remains and mLeftNode is removed from the content tree.
     */
   nsCOMPtr<nsIDOMNode> mLeftNode;
--- a/editor/libeditor/base/PlaceholderTxn.cpp
+++ b/editor/libeditor/base/PlaceholderTxn.cpp
@@ -47,19 +47,37 @@ PlaceholderTxn::PlaceholderTxn() :  Edit
                                     mIMETextTxn(nsnull),
                                     mCommitted(PR_FALSE),
                                     mStartSel(nsnull),
                                     mEndSel(),
                                     mEditor(nsnull)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTxn)
 
-NS_IMPL_ISUPPORTS_INHERITED2(PlaceholderTxn, EditAggregateTxn,
-                             nsIAbsorbingTransaction, nsISupportsWeakReference)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTxn,
+                                                EditAggregateTxn)
+  tmp->mStartSel->DoUnlink();
+  tmp->mEndSel.DoUnlink();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTxn,
+                                                  EditAggregateTxn)
+  tmp->mStartSel->DoTraverse(cb);
+  tmp->mEndSel.DoTraverse(cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTxn)
+  NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
+
+NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
+NS_IMPL_RELEASE_INHERITED(PlaceholderTxn, EditAggregateTxn)
 
 NS_IMETHODIMP PlaceholderTxn::Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)
 {
   if (!aEditor || !aSelState) return NS_ERROR_NULL_POINTER;
 
   mName = aName;
   mStartSel = aSelState;
   mEditor = aEditor;
--- a/editor/libeditor/base/PlaceholderTxn.h
+++ b/editor/libeditor/base/PlaceholderTxn.h
@@ -71,16 +71,17 @@ public:
   static const nsIID& GetCID() { static const nsIID iid = PLACEHOLDER_TXN_CID; return iid; }
 
   NS_DECL_ISUPPORTS_INHERITED  
   
 private:
   PlaceholderTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PlaceholderTxn, EditAggregateTxn)
 // ------------ EditAggregateTxn -----------------------
 
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
   NS_IMETHOD Merge(nsITransaction *aTransaction, PRBool *aDidMerge);
 
 // ------------ nsIAbsorbingTransaction -----------------------
--- a/editor/libeditor/base/SplitElementTxn.cpp
+++ b/editor/libeditor/base/SplitElementTxn.cpp
@@ -47,16 +47,31 @@ static PRBool gNoisy = PR_FALSE;
 
 
 // note that aEditor is not refcounted
 SplitElementTxn::SplitElementTxn()
   : EditTxn()
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(SplitElementTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SplitElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNewLeftNode)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SplitElementTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNewLeftNode)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SplitElementTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP SplitElementTxn::Init(nsEditor   *aEditor,
                                     nsIDOMNode *aNode,
                                     PRInt32     aOffset)
 {
   NS_ASSERTION(aEditor && aNode, "bad args");
   if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; }
 
   mEditor = aEditor;
--- a/editor/libeditor/base/SplitElementTxn.h
+++ b/editor/libeditor/base/SplitElementTxn.h
@@ -69,16 +69,19 @@ public:
     */
   NS_IMETHOD Init (nsEditor   *aEditor,
                    nsIDOMNode *aNode,
                    PRInt32     aOffset);
 protected:
   SplitElementTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SplitElementTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction(void);
 
   NS_IMETHOD GetNewNode(nsIDOMNode **aNewNode);
 
 protected:
   
--- a/editor/libeditor/base/nsSelectionState.cpp
+++ b/editor/libeditor/base/nsSelectionState.cpp
@@ -51,16 +51,32 @@
  */
 nsSelectionState::nsSelectionState() : mArray(){}
 
 nsSelectionState::~nsSelectionState() 
 {
   MakeEmpty();
 }
 
+void
+nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
+{
+  nsRangeStore *item;
+  for (PRInt32 i = 0, iEnd = mArray.Count(); i < iEnd; ++i)
+  {
+    nsRangeStore *item = static_cast<nsRangeStore*>(mArray.ElementAt(i));
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+                                       "selection state mArray[i]->startNode");
+    cb.NoteXPCOMChild(item->startNode);
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+                                       "selection state mArray[i]->endNode");
+    cb.NoteXPCOMChild(item->endNode);
+  }
+}
+
 nsresult  
 nsSelectionState::SaveSelection(nsISelection *aSel)
 {
   if (!aSel) return NS_ERROR_NULL_POINTER;
   PRInt32 i,rangeCount, arrayCount = mArray.Count();
   aSel->GetRangeCount(&rangeCount);
   nsRangeStore *item;
   
--- a/editor/libeditor/base/nsSelectionState.h
+++ b/editor/libeditor/base/nsSelectionState.h
@@ -37,16 +37,17 @@
 
 #ifndef __selectionstate_h__
 #define __selectionstate_h__
 
 #include "nsCOMPtr.h"
 #include "nsVoidArray.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsIDOMCharacterData;
 class nsISelection;
 
 /***************************************************************************
  * class for recording selection info.  stores selection as collection of
  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
  * ranges since dom gravity will possibly change the ranges.
@@ -68,16 +69,19 @@ struct nsRangeStore
 };
 
 class nsSelectionState
 {
   public:
       
     nsSelectionState();
     ~nsSelectionState();
+
+    void DoTraverse(nsCycleCollectionTraversalCallback &cb);
+    void DoUnlink() { MakeEmpty(); }
   
     nsresult SaveSelection(nsISelection *aSel);
     nsresult RestoreSelection(nsISelection *aSel);
     PRBool   IsCollapsed();
     PRBool   IsEqual(nsSelectionState *aSelState);
     void     MakeEmpty();
     PRBool   IsEmpty();
   protected:    
--- a/editor/libeditor/base/nsStyleSheetTxns.cpp
+++ b/editor/libeditor/base/nsStyleSheetTxns.cpp
@@ -74,16 +74,29 @@ RemoveStyleSheet(nsIEditor *aEditor, nsI
 }
 
 AddStyleSheetTxn::AddStyleSheetTxn()
 :  EditTxn()
 ,  mEditor(NULL)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(AddStyleSheetTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AddStyleSheetTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSheet)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AddStyleSheetTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSheet)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddStyleSheetTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP
 AddStyleSheetTxn::Init(nsIEditor *aEditor, nsICSSStyleSheet *aSheet)
 {
   if (!aEditor)
     return NS_ERROR_INVALID_ARG;
 
   if (!aSheet)
     return NS_ERROR_INVALID_ARG;
@@ -128,16 +141,29 @@ AddStyleSheetTxn::GetTxnDescription(nsAS
 
 
 RemoveStyleSheetTxn::RemoveStyleSheetTxn()
 :  EditTxn()
 ,  mEditor(NULL)
 {
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(RemoveStyleSheetTxn)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RemoveStyleSheetTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSheet)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RemoveStyleSheetTxn, EditTxn)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSheet)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RemoveStyleSheetTxn)
+NS_INTERFACE_MAP_END_INHERITING(EditTxn)
+
 NS_IMETHODIMP
 RemoveStyleSheetTxn::Init(nsIEditor *aEditor, nsICSSStyleSheet *aSheet)
 {
   if (!aEditor)
     return NS_ERROR_INVALID_ARG;
 
   if (!aSheet)
     return NS_ERROR_INVALID_ARG;
--- a/editor/libeditor/base/nsStyleSheetTxns.h
+++ b/editor/libeditor/base/nsStyleSheetTxns.h
@@ -66,16 +66,19 @@ public:
     */
   NS_IMETHOD Init(nsIEditor         *aEditor,
                   nsICSSStyleSheet  *aSheet);
 
 private:
   AddStyleSheetTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AddStyleSheetTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
 protected:
 
   nsIEditor*  mEditor;									// the editor that created this transaction
   nsCOMPtr<nsICSSStyleSheet>	mSheet;		// the style sheet to add
   
 };
@@ -95,16 +98,19 @@ public:
     */
   NS_IMETHOD Init(nsIEditor         *aEditor,
                   nsICSSStyleSheet  *aSheet);
 	
 private:
   RemoveStyleSheetTxn();
 
 public:
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RemoveStyleSheetTxn, EditTxn)
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
   NS_DECL_EDITTXN
 
 protected:
 
   nsIEditor*  mEditor;									// the editor that created this transaction
   nsCOMPtr<nsICSSStyleSheet>	mSheet;		// the style sheet to remove
   
 };
--- a/editor/txmgr/src/nsTransactionItem.cpp
+++ b/editor/txmgr/src/nsTransactionItem.cpp
@@ -72,16 +72,41 @@ nsTransactionItem::Release() {
   if (mRefCnt == 0) {
     mRefCnt = 1;
     delete this;
     return 0;
   }
   return mRefCnt;
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionItem)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsTransactionItem)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction)
+  if (tmp->mRedoStack) {
+    tmp->mRedoStack->DoUnlink();
+  }
+  if (tmp->mUndoStack) {
+    tmp->mUndoStack->DoUnlink();
+  }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTransactionItem)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTransaction)
+  if (tmp->mRedoStack) {
+    tmp->mRedoStack->DoTraverse(cb);
+  }
+  if (tmp->mUndoStack) {
+    tmp->mUndoStack->DoTraverse(cb);
+  }
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTransactionItem, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransactionItem, Release)
+
 nsresult
 nsTransactionItem::AddChild(nsTransactionItem *aTransactionItem)
 {
   if (!aTransactionItem)
     return NS_ERROR_NULL_POINTER;
 
   if (!mUndoStack) {
     mUndoStack = new nsTransactionStack();
--- a/editor/txmgr/src/nsTransactionItem.h
+++ b/editor/txmgr/src/nsTransactionItem.h
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsTransactionItem_h__
 #define nsTransactionItem_h__
 
 #include "nsITransaction.h"
 #include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsTransactionStack;
 class nsTransactionRedoStack;
 class nsTransactionManager;
 
 class nsTransactionItem
 {
   nsCOMPtr<nsITransaction> mTransaction;
@@ -54,16 +55,18 @@ class nsTransactionItem
 
 public:
 
   nsTransactionItem(nsITransaction *aTransaction);
   virtual ~nsTransactionItem();
   nsrefcnt AddRef();
   nsrefcnt Release();
 
+  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransactionItem)
+
   virtual nsresult AddChild(nsTransactionItem *aTransactionItem);
   virtual nsresult GetTransaction(nsITransaction **aTransaction);
   virtual nsresult GetIsBatch(PRBool *aIsBatch);
   virtual nsresult GetNumberOfChildren(PRInt32 *aNumChildren);
   virtual nsresult GetChild(PRInt32 aIndex, nsTransactionItem **aChild);
 
   virtual nsresult DoTransaction(void);
   virtual nsresult UndoTransaction(nsTransactionManager *aTxMgr);
--- a/editor/txmgr/src/nsTransactionManager.cpp
+++ b/editor/txmgr/src/nsTransactionManager.cpp
@@ -60,40 +60,42 @@ nsTransactionManager::~nsTransactionMana
 {
   if (mMonitor)
   {
     ::PR_DestroyMonitor(mMonitor);
     mMonitor = 0;
   }
 }
 
-#ifdef DEBUG_TXMGR_REFCNT
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionManager)
 
-nsrefcnt nsTransactionManager::AddRef(void)
-{
-  return ++mRefCnt;
-}
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTransactionManager)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mListeners)
+  tmp->mDoStack.DoUnlink();
+  tmp->mUndoStack.DoUnlink();
+  tmp->mRedoStack.DoUnlink();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-nsrefcnt nsTransactionManager::Release(void)
-{
-  NS_PRECONDITION(0 != mRefCnt, "dup release");
-  if (--mRefCnt == 0) {
-    NS_DELETEXPCOM(this);
-    return 0;
-  }
-  return mRefCnt;
-}
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTransactionManager)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mListeners)
+  tmp->mDoStack.DoTraverse(cb);
+  tmp->mUndoStack.DoTraverse(cb);
+  tmp->mRedoStack.DoTraverse(cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_QUERY_INTERFACE2(nsTransactionManager, nsITransactionManager, nsISupportsWeakReference)
-
-#else
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTransactionManager)
+  NS_INTERFACE_MAP_ENTRY(nsITransactionManager)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransactionManager)
+NS_INTERFACE_MAP_END
 
-NS_IMPL_ISUPPORTS2(nsTransactionManager, nsITransactionManager, nsISupportsWeakReference)
-
-#endif
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsTransactionManager,
+                                          nsITransactionManager)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsTransactionManager,
+                                           nsITransactionManager)
 
 NS_IMETHODIMP
 nsTransactionManager::DoTransaction(nsITransaction *aTransaction)
 {
   nsresult result;
 
   if (!aTransaction)
     return NS_ERROR_NULL_POINTER;
--- a/editor/txmgr/src/nsTransactionManager.h
+++ b/editor/txmgr/src/nsTransactionManager.h
@@ -38,16 +38,17 @@
 #ifndef nsTransactionManager_h__
 #define nsTransactionManager_h__
 
 #include "prmon.h"
 #include "nsWeakReference.h"
 #include "nsITransactionManager.h"
 #include "nsCOMArray.h"
 #include "nsITransactionListener.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsITransaction;
 class nsITransactionListener;
 class nsTransactionItem;
 class nsTransactionStack;
 class nsTransactionRedoStack;
 
 /** implementation of a transaction manager object.
@@ -72,17 +73,19 @@ public:
    */
   nsTransactionManager(PRInt32 aMaxTransactionCount=-1);
 
   /** The default destructor.
    */
   virtual ~nsTransactionManager();
 
   /* Macro for AddRef(), Release(), and QueryInterface() */
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTransactionManager,
+                                           nsITransactionManager)
 
   /* nsITransactionManager method implementations. */
   NS_DECL_NSITRANSACTIONMANAGER
 
   /* nsTransactionManager specific methods. */
   virtual nsresult ClearUndoStack(void);
   virtual nsresult ClearRedoStack(void);
 
--- a/editor/txmgr/src/nsTransactionStack.cpp
+++ b/editor/txmgr/src/nsTransactionStack.cpp
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsITransaction.h"
 #include "nsTransactionItem.h"
 #include "nsTransactionStack.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
+#include "nsCycleCollectionParticipant.h"
 
 nsTransactionStack::nsTransactionStack()
   : mQue(0)
 {
 } 
 
 nsTransactionStack::~nsTransactionStack()
 {
@@ -154,16 +155,29 @@ nsTransactionStack::GetSize(PRInt32 *aSt
   if (!aStackSize)
     return NS_ERROR_NULL_POINTER;
 
   *aStackSize = mQue.GetSize();
 
   return NS_OK;
 }
 
+void
+nsTransactionStack::DoTraverse(nsCycleCollectionTraversalCallback &cb)
+{
+  for (PRInt32 i = 0, qcount = mQue.GetSize(); i < qcount; ++i) {
+    nsTransactionItem *item =
+      static_cast<nsTransactionItem*>(mQue.ObjectAt(i));
+    if (item) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "transaction stack mQue[i]");
+      cb.NoteNativeChild(item, &NS_CYCLE_COLLECTION_NAME(nsTransactionItem));
+    }
+  }
+}
+
 nsTransactionRedoStack::~nsTransactionRedoStack()
 {
   Clear();
 }
 
 nsresult
 nsTransactionRedoStack::Clear(void)
 {
--- a/editor/txmgr/src/nsTransactionStack.h
+++ b/editor/txmgr/src/nsTransactionStack.h
@@ -53,16 +53,19 @@ public:
 
   virtual nsresult Push(nsTransactionItem *aTransactionItem);
   virtual nsresult Pop(nsTransactionItem **aTransactionItem);
   virtual nsresult PopBottom(nsTransactionItem **aTransactionItem);
   virtual nsresult Peek(nsTransactionItem **aTransactionItem);
   virtual nsresult GetItem(PRInt32 aIndex, nsTransactionItem **aTransactionItem);
   virtual nsresult Clear(void);
   virtual nsresult GetSize(PRInt32 *aStackSize);
+
+  void DoUnlink() { Clear(); }
+  void DoTraverse(nsCycleCollectionTraversalCallback &cb);
 };
 
 class nsTransactionRedoStack: public nsTransactionStack
 {
 public:
 
   virtual ~nsTransactionRedoStack();
   virtual nsresult Clear(void);