Bug 633709: Fix editor's handling of txn objects. r+a=ehsan
authorKyle Huey <khuey@kylehuey.com>
Sat, 19 Feb 2011 17:18:37 -0500
changeset 62873 0a195cda5293e5a63fe958d0aa72b1ab81646ae4
parent 62872 61ab16f6fa0b35e9bd2008f6f883067b8a1603d2
child 62874 5ba5ed2e239d2972e29bea25435ca85f47cf35f8
push idunknown
push userunknown
push dateunknown
bugs633709
milestone2.0b12pre
Bug 633709: Fix editor's handling of txn objects. r+a=ehsan
editor/libeditor/base/ChangeAttributeTxn.cpp
editor/libeditor/base/ChangeAttributeTxn.h
editor/libeditor/base/CreateElementTxn.cpp
editor/libeditor/base/CreateElementTxn.h
editor/libeditor/base/DeleteElementTxn.cpp
editor/libeditor/base/DeleteElementTxn.h
editor/libeditor/base/EditAggregateTxn.cpp
editor/libeditor/base/EditAggregateTxn.h
editor/libeditor/base/InsertElementTxn.cpp
editor/libeditor/base/InsertElementTxn.h
editor/libeditor/base/InsertTextTxn.cpp
editor/libeditor/base/InsertTextTxn.h
editor/libeditor/base/SplitElementTxn.cpp
editor/libeditor/base/SplitElementTxn.h
editor/libeditor/base/nsEditor.cpp
--- a/editor/libeditor/base/ChangeAttributeTxn.cpp
+++ b/editor/libeditor/base/ChangeAttributeTxn.cpp
@@ -48,16 +48,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(ChangeAtt
 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_IMPL_ADDREF_INHERITED(ChangeAttributeTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(ChangeAttributeTxn, EditTxn)
 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)
--- a/editor/libeditor/base/ChangeAttributeTxn.h
+++ b/editor/libeditor/base/ChangeAttributeTxn.h
@@ -60,18 +60,18 @@ public:
   NS_IMETHOD Init(nsIEditor      *aEditor,
                   nsIDOMElement  *aNode,
                   const nsAString& aAttribute,
                   const nsAString& aValue,
                   PRBool aRemoveAttribute);
 
   ChangeAttributeTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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/CreateElementTxn.cpp
+++ b/editor/libeditor/base/CreateElementTxn.cpp
@@ -65,16 +65,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
 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_IMPL_ADDREF_INHERITED(CreateElementTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(CreateElementTxn, EditTxn)
 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");
--- a/editor/libeditor/base/CreateElementTxn.h
+++ b/editor/libeditor/base/CreateElementTxn.h
@@ -60,18 +60,18 @@ public:
     */
   NS_IMETHOD Init(nsEditor *aEditor,
                   const nsAString& aTag,
                   nsIDOMNode *aParent,
                   PRUint32 aOffsetInParent);
 
   CreateElementTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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
@@ -67,16 +67,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
 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_IMPL_ADDREF_INHERITED(DeleteElementTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(DeleteElementTxn, EditTxn)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteElementTxn)
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
 NS_IMETHODIMP DeleteElementTxn::Init(nsIEditor *aEditor,
                                      nsIDOMNode *aElement,
                                      nsRangeUpdater *aRangeUpdater)
 {
   NS_ENSURE_TRUE(aEditor && aElement, NS_ERROR_NULL_POINTER);
--- a/editor/libeditor/base/DeleteElementTxn.h
+++ b/editor/libeditor/base/DeleteElementTxn.h
@@ -54,18 +54,18 @@ class DeleteElementTxn : public EditTxn
 public:
   /** initialize the transaction.
     * @param aElement the node to delete
     */
   NS_IMETHOD Init(nsIEditor *aEditor, nsIDOMNode *aElement, nsRangeUpdater *aRangeUpdater);
 
   DeleteElementTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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 */
--- a/editor/libeditor/base/EditAggregateTxn.cpp
+++ b/editor/libeditor/base/EditAggregateTxn.cpp
@@ -50,16 +50,18 @@ 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_IMPL_ADDREF_INHERITED(EditAggregateTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(EditAggregateTxn, EditTxn)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditAggregateTxn)
 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)
   {
--- a/editor/libeditor/base/EditAggregateTxn.h
+++ b/editor/libeditor/base/EditAggregateTxn.h
@@ -46,20 +46,19 @@
 
 /**
  * base class for all document editing transactions that require aggregation.
  * provides a list of child transactions.
  */
 class EditAggregateTxn : public EditTxn
 {
 public:
-  NS_IMETHOD QueryInterface(REFNSIID aIID, void **aInstancePtr);
-
   EditAggregateTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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 */
--- a/editor/libeditor/base/InsertElementTxn.cpp
+++ b/editor/libeditor/base/InsertElementTxn.cpp
@@ -58,16 +58,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   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_IMPL_ADDREF_INHERITED(InsertElementTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(InsertElementTxn, EditTxn)
 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)
 {
--- a/editor/libeditor/base/InsertElementTxn.h
+++ b/editor/libeditor/base/InsertElementTxn.h
@@ -56,18 +56,18 @@ public:
     */
   NS_IMETHOD Init(nsIDOMNode *aNode,
                   nsIDOMNode *aParent,
                   PRInt32     aOffset,
                   nsIEditor  *aEditor);
 
   InsertElementTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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;
 
--- a/editor/libeditor/base/InsertTextTxn.cpp
+++ b/editor/libeditor/base/InsertTextTxn.cpp
@@ -54,16 +54,18 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(InsertTex
 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_IMPL_ADDREF_INHERITED(InsertTextTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(InsertTextTxn, EditTxn)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InsertTextTxn)
   if (aIID.Equals(InsertTextTxn::GetCID())) {
     *aInstancePtr = (void*)(InsertTextTxn*)this;
     NS_ADDREF_THIS();
     return NS_OK;
   } else
 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
 
--- a/editor/libeditor/base/InsertTextTxn.h
+++ b/editor/libeditor/base/InsertTextTxn.h
@@ -65,27 +65,23 @@ public:
     */
   NS_IMETHOD Init(nsIDOMCharacterData *aElement,
                   PRUint32 aOffset,
                   const nsAString& aString,
                   nsIEditor *aEditor);
 
   InsertTextTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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
-  NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
-
   /** return the string data associated with this transaction */
   NS_IMETHOD GetData(nsString& aResult);
 
 protected:
 
   /** return PR_TRUE if aOtherTxn immediately follows this txn */
   virtual PRBool IsSequentialInsert(InsertTextTxn *aOtherTxn);
   
--- a/editor/libeditor/base/SplitElementTxn.cpp
+++ b/editor/libeditor/base/SplitElementTxn.cpp
@@ -59,16 +59,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   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_IMPL_ADDREF_INHERITED(SplitElementTxn, EditTxn)
+NS_IMPL_RELEASE_INHERITED(SplitElementTxn, EditTxn)
 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");
--- a/editor/libeditor/base/SplitElementTxn.h
+++ b/editor/libeditor/base/SplitElementTxn.h
@@ -60,18 +60,18 @@ public:
     *                 The left node will have child|content 0..aOffset-1.
     */
   NS_IMETHOD Init (nsEditor   *aEditor,
                    nsIDOMNode *aNode,
                    PRInt32     aOffset);
 
   SplitElementTxn();
 
+  NS_DECL_ISUPPORTS_INHERITED
   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/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -2650,23 +2650,26 @@ nsEditor::NotifyDocumentListeners(TDocum
 
 
 NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsAString & aStringToInsert,
                                                nsIDOMCharacterData *aTextNode,
                                                PRInt32 aOffset,
                                                InsertTextTxn ** aTxn)
 {
   NS_ENSURE_TRUE(aTextNode && aTxn, NS_ERROR_NULL_POINTER);
-  nsresult result;
-
-  *aTxn = new InsertTextTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-  result = (*aTxn)->Init(aTextNode, aOffset, aStringToInsert, this);
-  return result;
+  nsresult rv;
+
+  nsRefPtr<InsertTextTxn> txn = new InsertTextTxn();
+  rv = txn->Init(aTextNode, aOffset, aStringToInsert, this);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
                               PRUint32             aOffset,
                               PRUint32             aLength)
 {
   nsRefPtr<DeleteTextTxn> txn;
@@ -2692,49 +2695,62 @@ NS_IMETHODIMP nsEditor::DeleteText(nsIDO
 
 NS_IMETHODIMP nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement,
                                                PRUint32             aOffset,
                                                PRUint32             aLength,
                                                DeleteTextTxn      **aTxn)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new DeleteTextTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-  return (*aTxn)->Init(this, aElement, aOffset, aLength, &mRangeUpdater);
+  nsRefPtr<DeleteTextTxn> txn = new DeleteTextTxn();
+
+  nsresult rv = txn->Init(this, aElement, aOffset, aLength, &mRangeUpdater);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 
 
 NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
                                          PRUint32    aOffset,
                                          SplitElementTxn **aTxn)
 {
   NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new SplitElementTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aNode, aOffset);
+  nsRefPtr<SplitElementTxn> txn = new SplitElementTxn();
+
+  nsresult rv = txn->Init(this, aNode, aOffset);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode  *aLeftNode,
                                              nsIDOMNode  *aRightNode,
                                              JoinElementTxn **aTxn)
 {
   NS_ENSURE_TRUE(aLeftNode && aRightNode, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new JoinElementTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aLeftNode, aRightNode);
+  nsRefPtr<JoinElementTxn> txn = new JoinElementTxn();
+
+  nsresult rv = txn->Init(this, aLeftNode, aRightNode);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 // END nsEditor core implementation
 
 #ifdef XP_MAC
 #pragma mark -
 #pragma mark  nsEditor public static helper methods 
@@ -4506,146 +4522,176 @@ nsEditor::DoAfterRedoTransaction()
 NS_IMETHODIMP 
 nsEditor::CreateTxnForSetAttribute(nsIDOMElement *aElement, 
                                    const nsAString& aAttribute, 
                                    const nsAString& aValue,
                                    ChangeAttributeTxn ** aTxn)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new ChangeAttributeTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-  return (*aTxn)->Init(this, aElement, aAttribute, aValue, PR_FALSE);
+  nsRefPtr<ChangeAttributeTxn> txn = new ChangeAttributeTxn();
+
+  nsresult rv = txn->Init(this, aElement, aAttribute, aValue, PR_FALSE);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 NS_IMETHODIMP 
 nsEditor::CreateTxnForRemoveAttribute(nsIDOMElement *aElement, 
                                       const nsAString& aAttribute,
                                       ChangeAttributeTxn ** aTxn)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new ChangeAttributeTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aElement, aAttribute, EmptyString(), PR_TRUE);
+  nsRefPtr<ChangeAttributeTxn> txn = new ChangeAttributeTxn();
+
+  nsresult rv = txn->Init(this, aElement, aAttribute, EmptyString(), PR_TRUE);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 NS_IMETHODIMP nsEditor::CreateTxnForCreateElement(const nsAString& aTag,
                                                   nsIDOMNode     *aParent,
                                                   PRInt32         aPosition,
                                                   CreateElementTxn ** aTxn)
 {
   NS_ENSURE_TRUE(aParent, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new CreateElementTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aTag, aParent, aPosition);
+  nsRefPtr<CreateElementTxn> txn = new CreateElementTxn();
+
+  nsresult rv = txn->Init(this, aTag, aParent, aPosition);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode,
                                                   nsIDOMNode * aParent,
                                                   PRInt32      aPosition,
                                                   InsertElementTxn ** aTxn)
 {
   NS_ENSURE_TRUE(aNode && aParent, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new InsertElementTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(aNode, aParent, aPosition, this);
+  nsRefPtr<InsertElementTxn> txn = new InsertElementTxn();
+
+  nsresult rv = txn->Init(aNode, aParent, aPosition, this);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP nsEditor::CreateTxnForDeleteElement(nsIDOMNode * aElement,
                                              DeleteElementTxn ** aTxn)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
 
-  *aTxn = new DeleteElementTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aElement, &mRangeUpdater);
+  nsRefPtr<DeleteElementTxn> txn = new DeleteElementTxn();
+
+  nsresult rv = txn->Init(this, aElement, &mRangeUpdater);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP 
 nsEditor::CreateTxnForIMEText(const nsAString& aStringToInsert,
                               IMETextTxn ** aTxn)
 {
   NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn");
      
-  *aTxn = new IMETextTxn();
-  NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(mIMETextNode, mIMETextOffset, mIMEBufferLength,
-                       mIMETextRangeList, aStringToInsert, mSelConWeak);
+  nsRefPtr<IMETextTxn> txn = new IMETextTxn();
+
+  nsresult rv = txn->Init(mIMETextNode, mIMETextOffset, mIMEBufferLength,
+                          mIMETextRangeList, aStringToInsert, mSelConWeak);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 NS_IMETHODIMP 
 nsEditor::CreateTxnForAddStyleSheet(nsCSSStyleSheet* aSheet, AddStyleSheetTxn* *aTxn)
 {
-  *aTxn = new AddStyleSheetTxn();
-  NS_ENSURE_TRUE( *aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aSheet);
+  nsRefPtr<AddStyleSheetTxn> txn = new AddStyleSheetTxn();
+
+  nsresult rv = txn->Init(this, aSheet);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 
 NS_IMETHODIMP 
 nsEditor::CreateTxnForRemoveStyleSheet(nsCSSStyleSheet* aSheet, RemoveStyleSheetTxn* *aTxn)
 {
-  *aTxn = new RemoveStyleSheetTxn();
-  NS_ENSURE_TRUE( *aTxn, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aTxn);
-
-  return (*aTxn)->Init(this, aSheet);
+  nsRefPtr<RemoveStyleSheetTxn> txn = new RemoveStyleSheetTxn();
+
+  nsresult rv = txn->Init(this, aSheet);
+  if (NS_SUCCEEDED(rv))
+  {
+    txn.swap(*aTxn);
+  }
+
+  return rv;
 }
 
 
 NS_IMETHODIMP
 nsEditor::CreateTxnForDeleteSelection(nsIEditor::EDirection aAction,
                                       EditAggregateTxn ** aTxn,
                                       nsIDOMNode ** aNode,
                                       PRInt32 *aOffset,
                                       PRInt32 *aLength)
 {
   NS_ENSURE_TRUE(aTxn, NS_ERROR_NULL_POINTER);
   *aTxn = nsnull;
 
+  nsRefPtr<EditAggregateTxn> aggTxn;
   nsCOMPtr<nsISelectionController> selCon = do_QueryReferent(mSelConWeak);
   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
   nsCOMPtr<nsISelection> selection;
   nsresult result = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
                                          getter_AddRefs(selection));
   if ((NS_SUCCEEDED(result)) && selection)
   {
     // Check whether the selection is collapsed and we should do nothing:
     PRBool isCollapsed;
     result = (selection->GetIsCollapsed(&isCollapsed));
     if (NS_SUCCEEDED(result) && isCollapsed && aAction == eNone)
       return NS_OK;
 
     // allocate the out-param transaction
-    *aTxn = new EditAggregateTxn();
-    if (!*aTxn) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-    NS_ADDREF(*aTxn);
+    aggTxn = new EditAggregateTxn();
 
     nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(selection));
     nsCOMPtr<nsIEnumerator> enumerator;
     result = selPrivate->GetEnumerator(getter_AddRefs(enumerator));
     if (NS_SUCCEEDED(result) && enumerator)
     {
       for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next())
       {
@@ -4656,36 +4702,37 @@ nsEditor::CreateTxnForDeleteSelection(ns
           nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
           range->GetCollapsed(&isCollapsed);
           if (!isCollapsed)
           {
             nsRefPtr<DeleteRangeTxn> txn = new DeleteRangeTxn();
             if (txn)
             {
               txn->Init(this, range, &mRangeUpdater);
-              (*aTxn)->AppendChild(txn);
+              aggTxn->AppendChild(txn);
             }
             else
               result = NS_ERROR_OUT_OF_MEMORY;
           }
           // Same with range as with selection; if it is collapsed and action
           // is eNone, do nothing.
           else if (aAction != eNone)
           { // we have an insertion point.  delete the thing in front of it or behind it, depending on aAction
-            result = CreateTxnForDeleteInsertionPoint(range, aAction, *aTxn, aNode, aOffset, aLength);
+            result = CreateTxnForDeleteInsertionPoint(range, aAction, aggTxn, aNode, aOffset, aLength);
           }
         }
       }
     }
   }
 
-  // if we didn't build the transaction correctly, destroy the out-param transaction so we don't leak it.
-  if (NS_FAILED(result))
+  // Only set the outparam if building the txn was a success, otherwise
+  // we let the aggregation txn be destroyed when the refptr goes out of scope
+  if (NS_SUCCEEDED(result))
   {
-    NS_IF_RELEASE(*aTxn);
+    aggTxn.swap(*aTxn);
   }
 
   return result;
 }
 
 nsresult
 nsEditor::CreateTxnForDeleteCharacter(nsIDOMCharacterData  *aData,
                                       PRUint32              aOffset,