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
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 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,