Bug 570350 - Crash [@ nsTextServicesDocument::NodeHasOffsetEntry(nsTArray<OffsetEntry*>*, nsIDOMNode*, int*, int*) ] when enabling/disabling the spell checker; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 08 Jun 2010 00:20:23 -0400
changeset 43303 8a37644190b72d887a66cc5ea20b5118bafa8046
parent 43302 0e1c7c4f51cda94e2bcd47d5096fb85568452e0f
child 43304 e8550654d33dc38b83da82eb1165eb713d06422c
push id13643
push usereakhgari@mozilla.com
push dateTue, 08 Jun 2010 14:35:20 +0000
treeherderautoland@8a37644190b7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs570350
milestone1.9.3a5pre
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 570350 - Crash [@ nsTextServicesDocument::NodeHasOffsetEntry(nsTArray<OffsetEntry*>*, nsIDOMNode*, int*, int*) ] when enabling/disabling the spell checker; r=roc
browser/components/preferences/tests/browser_privacypane_8.js
editor/txtsvc/src/Makefile.in
editor/txtsvc/src/nsTSDNotifier.cpp
editor/txtsvc/src/nsTSDNotifier.h
editor/txtsvc/src/nsTextServicesDocument.cpp
editor/txtsvc/src/nsTextServicesDocument.h
layout/base/tests/bug570378-arabic-1-ref.html
layout/base/tests/bug570378-arabic-1.html
layout/base/tests/bug570378-arabic-2-ref.html
layout/base/tests/bug570378-arabic-2.html
layout/base/tests/bug570378-arabic-3-ref.html
layout/base/tests/bug570378-arabic-3.html
layout/base/tests/bug570378-arabic-4-ref.html
layout/base/tests/bug570378-arabic-4.html
layout/base/tests/bug570378-arabic-5-ref.html
layout/base/tests/bug570378-arabic-5.html
layout/base/tests/bug570378-persian-1-ref.html
layout/base/tests/bug570378-persian-1.html
layout/base/tests/bug570378-persian-2-ref.html
layout/base/tests/bug570378-persian-2.html
layout/base/tests/bug570378-persian-3-ref.html
layout/base/tests/bug570378-persian-3.html
layout/base/tests/bug570378-persian-4-ref.html
layout/base/tests/bug570378-persian-4.html
layout/base/tests/bug570378-persian-5-ref.html
layout/base/tests/bug570378-persian-5.html
layout/base/tests/test_bug570378-arabic-1a.html
layout/base/tests/test_bug570378-arabic-1b.html
layout/base/tests/test_bug570378-arabic-1c.html
layout/base/tests/test_bug570378-arabic-1d.html
layout/base/tests/test_bug570378-arabic-1e.html
layout/base/tests/test_bug570378-arabic-2a.html
layout/base/tests/test_bug570378-arabic-2b.html
layout/base/tests/test_bug570378-arabic-2c.html
layout/base/tests/test_bug570378-arabic-2d.html
layout/base/tests/test_bug570378-arabic-2e.html
layout/base/tests/test_bug570378-arabic-3a.html
layout/base/tests/test_bug570378-arabic-3b.html
layout/base/tests/test_bug570378-arabic-3c.html
layout/base/tests/test_bug570378-arabic-3d.html
layout/base/tests/test_bug570378-arabic-3e.html
layout/base/tests/test_bug570378-arabic-4a.html
layout/base/tests/test_bug570378-arabic-4b.html
layout/base/tests/test_bug570378-arabic-4c.html
layout/base/tests/test_bug570378-arabic-4d.html
layout/base/tests/test_bug570378-arabic-4e.html
layout/base/tests/test_bug570378-arabic-5a.html
layout/base/tests/test_bug570378-arabic-5b.html
layout/base/tests/test_bug570378-arabic-5c.html
layout/base/tests/test_bug570378-arabic-5d.html
layout/base/tests/test_bug570378-arabic-5e.html
layout/base/tests/test_bug570378-persian-1a.html
layout/base/tests/test_bug570378-persian-1b.html
layout/base/tests/test_bug570378-persian-1c.html
layout/base/tests/test_bug570378-persian-1d.html
layout/base/tests/test_bug570378-persian-1e.html
layout/base/tests/test_bug570378-persian-1f.html
layout/base/tests/test_bug570378-persian-1g.html
layout/base/tests/test_bug570378-persian-2a.html
layout/base/tests/test_bug570378-persian-2b.html
layout/base/tests/test_bug570378-persian-2c.html
layout/base/tests/test_bug570378-persian-2d.html
layout/base/tests/test_bug570378-persian-2e.html
layout/base/tests/test_bug570378-persian-2f.html
layout/base/tests/test_bug570378-persian-2g.html
layout/base/tests/test_bug570378-persian-3a.html
layout/base/tests/test_bug570378-persian-3b.html
layout/base/tests/test_bug570378-persian-3c.html
layout/base/tests/test_bug570378-persian-3d.html
layout/base/tests/test_bug570378-persian-3e.html
layout/base/tests/test_bug570378-persian-3f.html
layout/base/tests/test_bug570378-persian-3g.html
layout/base/tests/test_bug570378-persian-4a.html
layout/base/tests/test_bug570378-persian-4b.html
layout/base/tests/test_bug570378-persian-4c.html
layout/base/tests/test_bug570378-persian-4d.html
layout/base/tests/test_bug570378-persian-4e.html
layout/base/tests/test_bug570378-persian-4f.html
layout/base/tests/test_bug570378-persian-4g.html
layout/base/tests/test_bug570378-persian-5a.html
layout/base/tests/test_bug570378-persian-5b.html
layout/base/tests/test_bug570378-persian-5c.html
layout/base/tests/test_bug570378-persian-5d.html
layout/base/tests/test_bug570378-persian-5e.html
layout/base/tests/test_bug570378-persian-5f.html
layout/base/tests/test_bug570378-persian-5g.html
--- a/editor/txtsvc/src/Makefile.in
+++ b/editor/txtsvc/src/Makefile.in
@@ -47,17 +47,16 @@ LIBRARY_NAME	= txtsvc_s
 FORCE_STATIC_LIB = 1
 MODULE_NAME	= nsTextServicesModule
 LIBXUL_LIBRARY	= 1
 
 
 CPPSRCS		= \
 		nsFilteredContentIterator.cpp \
 		nsTextServicesDocument.cpp \
-		nsTSDNotifier.cpp \
 		$(NULL)
 
 
 EXTRA_DSO_LDOPTS = \
 		$(MOZ_UNICHARUTIL_LIBS) \
 		$(MOZ_COMPONENT_LIBS) \
 		$(NULL)
 
deleted file mode 100644
--- a/editor/txtsvc/src/nsTSDNotifier.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 "nsString.h"
-#include "nsIEditActionListener.h"
-#include "nsTSDNotifier.h"
-#include "nsTextServicesDocument.h"
-
-
-nsTSDNotifier::nsTSDNotifier(nsTextServicesDocument *aDoc) : mDoc(aDoc)
-{
-}
-
-nsTSDNotifier::~nsTSDNotifier()
-{
-  mDoc = 0;
-}
-
-#define DEBUG_TSD_NOTIFIER_REFCNT 1
-
-#ifdef DEBUG_TSD_NOTIFIER_REFCNT
-
-nsrefcnt nsTSDNotifier::AddRef(void)
-{
-  return ++mRefCnt;
-}
-
-nsrefcnt nsTSDNotifier::Release(void)
-{
-  NS_PRECONDITION(0 != mRefCnt, "dup release");
-  if (--mRefCnt == 0) {
-    NS_DELETEXPCOM(this);
-    return 0;
-  }
-  return mRefCnt;
-}
-
-#else
-
-NS_IMPL_ADDREF(nsTSDNotifier)
-NS_IMPL_RELEASE(nsTSDNotifier)
-
-#endif
-
-NS_IMPL_QUERY_INTERFACE1(nsTSDNotifier, nsIEditActionListener)
-
-NS_IMETHODIMP
-nsTSDNotifier::WillInsertNode(nsIDOMNode *aNode,
-                              nsIDOMNode *aParent,
-                              PRInt32     aPosition)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidInsertNode(nsIDOMNode *aNode,
-                             nsIDOMNode *aParent,
-                             PRInt32     aPosition,
-                             nsresult    aResult)
-{
-  if (NS_FAILED(aResult))
-    return NS_OK;
-
-  if (!mDoc)
-    return NS_ERROR_FAILURE;
-
-  return mDoc->InsertNode(aNode, aParent, aPosition);
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::WillDeleteNode(nsIDOMNode *aChild)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidDeleteNode(nsIDOMNode *aChild, nsresult aResult)
-{
-  if (NS_FAILED(aResult))
-    return NS_OK;
-
-  if (!mDoc)
-    return NS_ERROR_FAILURE;
-
-  return mDoc->DeleteNode(aChild);
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::WillSplitNode(nsIDOMNode *aExistingRightNode,
-                             PRInt32     aOffset)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidSplitNode(nsIDOMNode *aExistingRightNode,
-                            PRInt32     aOffset,
-                            nsIDOMNode *aNewLeftNode,
-                            nsresult    aResult)
-{
-  if (NS_FAILED(aResult))
-    return NS_OK;
-
-  if (!mDoc)
-    return NS_ERROR_FAILURE;
-
-  return mDoc->SplitNode(aExistingRightNode, aOffset, aNewLeftNode);
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::WillJoinNodes(nsIDOMNode  *aLeftNode,
-                             nsIDOMNode  *aRightNode,
-                             nsIDOMNode  *aParent)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidJoinNodes(nsIDOMNode  *aLeftNode,
-                            nsIDOMNode  *aRightNode,
-                            nsIDOMNode  *aParent,
-                            nsresult     aResult)
-{
-  if (NS_FAILED(aResult))
-    return NS_OK;
-
-  if (!mDoc)
-    return NS_ERROR_FAILURE;
-
-  return mDoc->JoinNodes(aLeftNode, aRightNode, aParent);
-}
-
-// -------------------------------
-// stubs for unused listen methods
-// -------------------------------
-
-NS_IMETHODIMP
-nsTSDNotifier::WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, PRInt32 aPosition)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aPosition, nsresult aResult)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::WillInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString, nsresult aResult)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::WillDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength, nsresult aResult)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::WillDeleteSelection(nsISelection *aSelection)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsTSDNotifier::DidDeleteSelection(nsISelection *aSelection)
-{
-  return NS_OK;
-}
-
-
-
deleted file mode 100644
--- a/editor/txtsvc/src/nsTSDNotifier.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * 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 ***** */
-
-#ifndef nsTSDNotifier_h__
-#define nsTSDNotifier_h__
-
-#include "nsCOMPtr.h"
-#include "nsIEditActionListener.h"
-
-class nsTextServicesDocument;
-
-class nsTSDNotifier : public nsIEditActionListener
-{
-private:
-
-  nsTextServicesDocument *mDoc;
-
-public:
-
-  /** The default constructor.
-   */
-  nsTSDNotifier(nsTextServicesDocument *aDoc);
-
-  /** The default destructor.
-   */
-  virtual ~nsTSDNotifier();
-
-  /* Macro for AddRef(), Release(), and QueryInterface() */
-  NS_DECL_ISUPPORTS
-
-  /* nsIEditActionListener method implementations. */
-  NS_IMETHOD WillInsertNode(nsIDOMNode *aNode,
-                            nsIDOMNode *aParent,
-                            PRInt32      aPosition);
-  NS_IMETHOD DidInsertNode(nsIDOMNode *aNode,
-                           nsIDOMNode *aParent,
-                           PRInt32     aPosition,
-                           nsresult    aResult);
-
-  NS_IMETHOD WillDeleteNode(nsIDOMNode *aChild);
-  NS_IMETHOD DidDeleteNode(nsIDOMNode *aChild, nsresult aResult);
-
-  NS_IMETHOD WillSplitNode(nsIDOMNode * aExistingRightNode,
-                           PRInt32      aOffset);
-  NS_IMETHOD DidSplitNode(nsIDOMNode *aExistingRightNode,
-                          PRInt32     aOffset,
-                          nsIDOMNode *aNewLeftNode,
-                          nsresult    aResult);
-
-  NS_IMETHOD WillJoinNodes(nsIDOMNode  *aLeftNode,
-                           nsIDOMNode  *aRightNode,
-                           nsIDOMNode  *aParent);
-  NS_IMETHOD DidJoinNodes(nsIDOMNode  *aLeftNode,
-                          nsIDOMNode  *aRightNode,
-                          nsIDOMNode  *aParent,
-                          nsresult     aResult);
-  // these listen methods are unused:                        
-  NS_IMETHOD WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, PRInt32 aPosition);
-  NS_IMETHOD DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aPosition, nsresult aResult);
-  NS_IMETHOD WillInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString);
-  NS_IMETHOD DidInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString, nsresult aResult);
-  NS_IMETHOD WillDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength);
-  NS_IMETHOD DidDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength, nsresult aResult);
-  NS_IMETHOD WillDeleteSelection(nsISelection *aSelection);
-  NS_IMETHOD DidDeleteSelection(nsISelection *aSelection);
-};
-
-#endif // nsTSDNotifier_h__
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -111,20 +111,16 @@ nsTextServicesDocument::nsTextServicesDo
   mSelEndIndex    = -1;
   mSelEndOffset   = -1;
 
   mIteratorStatus = eIsDone;
 }
 
 nsTextServicesDocument::~nsTextServicesDocument()
 {
-  nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
-  if (editor && mNotifier)
-    editor->RemoveEditActionListener(mNotifier);
-
   ClearOffsetTable(&mOffsetTable);
 }
 
 #define TS_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
 #include "nsTSAtomList.h"
 #undef TS_ATOM
 
 /* static */
@@ -147,27 +143,27 @@ nsTextServicesDocument::Shutdown()
   NS_IF_RELEASE(sRangeHelper);
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTextServicesDocument)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTextServicesDocument)
 
 NS_INTERFACE_MAP_BEGIN(nsTextServicesDocument)
   NS_INTERFACE_MAP_ENTRY(nsITextServicesDocument)
+  NS_INTERFACE_MAP_ENTRY(nsIEditActionListener)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITextServicesDocument)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsTextServicesDocument)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_8(nsTextServicesDocument,
+NS_IMPL_CYCLE_COLLECTION_7(nsTextServicesDocument,
                            mDOMDocument,
                            mSelCon,
                            mIterator,
                            mPrevTextBlock,
                            mNextTextBlock,
-                           mNotifier,
                            mExtent,
                            mTxtSvcFilter)
 
 NS_IMETHODIMP
 nsTextServicesDocument::InitWithEditor(nsIEditor *aEditor)
 {
   nsresult result = NS_OK;
   nsCOMPtr<nsISelectionController> selCon;
@@ -234,27 +230,18 @@ nsTextServicesDocument::InitWithEditor(n
     if (NS_FAILED(result))
     {
       UNLOCK_DOC(this);
       return result;
     }
   }
 
   mEditor = do_GetWeakReference(aEditor);
-  nsTSDNotifier *notifier = new nsTSDNotifier(this);
-
-  if (!notifier)
-  {
-    UNLOCK_DOC(this);
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  mNotifier = do_QueryInterface(notifier);
-
-  result = aEditor->AddEditActionListener(mNotifier);
+
+  result = aEditor->AddEditActionListener(this);
 
   UNLOCK_DOC(this);
 
   return result;
 }
 
 NS_IMETHODIMP 
 nsTextServicesDocument::GetDocument(nsIDOMDocument **aDoc)
@@ -1807,27 +1794,31 @@ nsTextServicesDocument::InsertText(const
 
   result = editor->EndTransaction();
 
   UNLOCK_DOC(this);
 
   return result;
 }
 
-nsresult
-nsTextServicesDocument::InsertNode(nsIDOMNode *aNode,
-                                   nsIDOMNode *aParent,
-                                   PRInt32 aPosition)
+NS_IMETHODIMP
+nsTextServicesDocument::DidInsertNode(nsIDOMNode *aNode,
+                                      nsIDOMNode *aParent,
+                                      PRInt32     aPosition,
+                                      nsresult    aResult)
 {
   return NS_OK;
 }
 
-nsresult
-nsTextServicesDocument::DeleteNode(nsIDOMNode *aChild)
+NS_IMETHODIMP
+nsTextServicesDocument::DidDeleteNode(nsIDOMNode *aChild, nsresult aResult)
 {
+  if (NS_FAILED(aResult))
+    return NS_OK;
+
   NS_ENSURE_TRUE(mIterator, NS_ERROR_FAILURE);
 
   //**** KDEBUG ****
   // printf("** DeleteNode: 0x%.8x\n", aChild);
   // fflush(stdout);
   //**** KDEBUG ****
 
   LOCK_DOC(this);
@@ -1887,33 +1878,38 @@ nsTextServicesDocument::DeleteNode(nsIDO
     nodeIndex++;
   }
 
   UNLOCK_DOC(this);
 
   return NS_OK;
 }
 
-nsresult
-nsTextServicesDocument::SplitNode(nsIDOMNode *aExistingRightNode,
-                                  PRInt32 aOffset,
-                                  nsIDOMNode *aNewLeftNode)
+NS_IMETHODIMP
+nsTextServicesDocument::DidSplitNode(nsIDOMNode *aExistingRightNode,
+                                     PRInt32     aOffset,
+                                     nsIDOMNode *aNewLeftNode,
+                                     nsresult    aResult)
 {
   //**** KDEBUG ****
   // printf("** SplitNode: 0x%.8x  %d  0x%.8x\n", aExistingRightNode, aOffset, aNewLeftNode);
   // fflush(stdout);
   //**** KDEBUG ****
   return NS_OK;
 }
 
-nsresult
-nsTextServicesDocument::JoinNodes(nsIDOMNode  *aLeftNode,
-                                  nsIDOMNode  *aRightNode,
-                                  nsIDOMNode  *aParent)
+NS_IMETHODIMP
+nsTextServicesDocument::DidJoinNodes(nsIDOMNode  *aLeftNode,
+                                     nsIDOMNode  *aRightNode,
+                                     nsIDOMNode  *aParent,
+                                     nsresult     aResult)
 {
+  if (NS_FAILED(aResult))
+    return NS_OK;
+
   PRInt32 i;
   PRUint16 type;
   nsresult result;
 
   //**** KDEBUG ****
   // printf("** JoinNodes: 0x%.8x  0x%.8x  0x%.8x\n", aLeftNode, aRightNode, aParent);
   // fflush(stdout);
   //**** KDEBUG ****
@@ -4132,8 +4128,91 @@ nsTextServicesDocument::PrintContentNode
       printf(":  \"%s\"", NS_LossyConvertUTF16toASCII(str).get());
     }
   }
 
   printf("\n");
   fflush(stdout);
 }
 #endif
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillInsertNode(nsIDOMNode *aNode,
+                              nsIDOMNode *aParent,
+                              PRInt32     aPosition)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillDeleteNode(nsIDOMNode *aChild)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillSplitNode(nsIDOMNode *aExistingRightNode,
+                             PRInt32     aOffset)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillJoinNodes(nsIDOMNode  *aLeftNode,
+                             nsIDOMNode  *aRightNode,
+                             nsIDOMNode  *aParent)
+{
+  return NS_OK;
+}
+
+
+// -------------------------------
+// stubs for unused listen methods
+// -------------------------------
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, PRInt32 aPosition)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aPosition, nsresult aResult)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::DidInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString, nsresult aResult)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::DidDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength, nsresult aResult)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::WillDeleteSelection(nsISelection *aSelection)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTextServicesDocument::DidDeleteSelection(nsISelection *aSelection)
+{
+  return NS_OK;
+}
+
--- a/editor/txtsvc/src/nsTextServicesDocument.h
+++ b/editor/txtsvc/src/nsTextServicesDocument.h
@@ -42,29 +42,29 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsIEditor.h"
 #include "nsIEditActionListener.h"
 #include "nsITextServicesDocument.h"
 #include "nsTArray.h"
-#include "nsTSDNotifier.h"
 #include "nsISelectionController.h"
 #include "nsITextServicesFilter.h"
 #include "nsWeakReference.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsIRangeUtils;
 class OffsetEntry;
 
 /** implementation of a text services object.
  *
  */
-class nsTextServicesDocument : public nsITextServicesDocument
+class nsTextServicesDocument : public nsITextServicesDocument,
+                               public nsIEditActionListener
 {
 private:
   static nsIAtom *sAAtom;
   static nsIAtom *sAddressAtom;
   static nsIAtom *sBigAtom;
   static nsIAtom *sBlinkAtom;
   static nsIAtom *sBAtom;
   static nsIAtom *sCiteAtom;
@@ -98,17 +98,16 @@ private:
 
   nsCOMPtr<nsIDOMDocument>        mDOMDocument;
   nsCOMPtr<nsISelectionController>mSelCon;
   nsWeakPtr                       mEditor;  // avoid a cycle with the spell checker and editor
   nsCOMPtr<nsIContentIterator>    mIterator;
   TSDIteratorStatus               mIteratorStatus;
   nsCOMPtr<nsIContent>            mPrevTextBlock;
   nsCOMPtr<nsIContent>            mNextTextBlock;
-  nsCOMPtr<nsIEditActionListener> mNotifier;
   nsTArray<OffsetEntry*>          mOffsetTable;
 
   PRInt32                         mSelStartIndex;
   PRInt32                         mSelStartOffset;
   PRInt32                         mSelEndIndex;
   PRInt32                         mSelEndOffset;
 
   nsCOMPtr<nsIDOMRange>           mExtent;
@@ -132,17 +131,17 @@ public:
   static void RegisterAtoms();
 
   /** To be called at module shutdown
    */
   static void Shutdown();
 
   /* Macro for AddRef(), Release(), and QueryInterface() */
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsTextServicesDocument)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTextServicesDocument, nsITextServicesDocument)
 
   /* nsITextServicesDocument method implementations. */
   NS_IMETHOD InitWithEditor(nsIEditor *aEditor);
   NS_IMETHOD GetDocument(nsIDOMDocument **aDoc);
   NS_IMETHOD SetExtent(nsIDOMRange* aDOMRange);
   NS_IMETHOD ExpandRangeToWordBoundaries(nsIDOMRange *aRange);
   NS_IMETHOD SetFilter(nsITextServicesFilter *aFilter);
   NS_IMETHOD GetCurrentTextBlock(nsString *aStr);
@@ -152,34 +151,57 @@ public:
   NS_IMETHOD NextBlock();
   NS_IMETHOD IsDone(PRBool *aIsDone);
   NS_IMETHOD SetSelection(PRInt32 aOffset, PRInt32 aLength);
   NS_IMETHOD ScrollSelectionIntoView();
   NS_IMETHOD DeleteSelection();
   NS_IMETHOD InsertText(const nsString *aText);
 
   /* nsIEditActionListener method implementations. */
-  nsresult InsertNode(nsIDOMNode * aNode,
-                      nsIDOMNode * aParent,
-                      PRInt32      aPosition);
-  nsresult DeleteNode(nsIDOMNode * aChild);
-  nsresult SplitNode(nsIDOMNode * aExistingRightNode,
-                     PRInt32      aOffset,
-                     nsIDOMNode * aNewLeftNode);
-  nsresult JoinNodes(nsIDOMNode  *aLeftNode,
-                     nsIDOMNode  *aRightNode,
-                     nsIDOMNode  *aParent);
+  NS_IMETHOD WillInsertNode(nsIDOMNode *aNode,
+                            nsIDOMNode *aParent,
+                            PRInt32      aPosition);
+  NS_IMETHOD DidInsertNode(nsIDOMNode *aNode,
+                           nsIDOMNode *aParent,
+                           PRInt32     aPosition,
+                           nsresult    aResult);
+
+  NS_IMETHOD WillDeleteNode(nsIDOMNode *aChild);
+  NS_IMETHOD DidDeleteNode(nsIDOMNode *aChild, nsresult aResult);
+
+  NS_IMETHOD WillSplitNode(nsIDOMNode * aExistingRightNode,
+                           PRInt32      aOffset);
+  NS_IMETHOD DidSplitNode(nsIDOMNode *aExistingRightNode,
+                          PRInt32     aOffset,
+                          nsIDOMNode *aNewLeftNode,
+                          nsresult    aResult);
+
+  NS_IMETHOD WillJoinNodes(nsIDOMNode  *aLeftNode,
+                           nsIDOMNode  *aRightNode,
+                           nsIDOMNode  *aParent);
+  NS_IMETHOD DidJoinNodes(nsIDOMNode  *aLeftNode,
+                          nsIDOMNode  *aRightNode,
+                          nsIDOMNode  *aParent,
+                          nsresult     aResult);
+  // these listen methods are unused:
+  NS_IMETHOD WillCreateNode(const nsAString& aTag, nsIDOMNode *aParent, PRInt32 aPosition);
+  NS_IMETHOD DidCreateNode(const nsAString& aTag, nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aPosition, nsresult aResult);
+  NS_IMETHOD WillInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString);
+  NS_IMETHOD DidInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString, nsresult aResult);
+  NS_IMETHOD WillDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength);
+  NS_IMETHOD DidDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength, nsresult aResult);
+  NS_IMETHOD WillDeleteSelection(nsISelection *aSelection);
+  NS_IMETHOD DidDeleteSelection(nsISelection *aSelection);
 
   /* Helper functions */
   static nsresult ComparePoints(nsIDOMNode *aParent1, PRInt32 aOffset1, nsIDOMNode *aParent2, PRInt32 aOffset2, PRInt32 *aResult);
   static nsresult GetRangeEndPoints(nsIDOMRange *aRange, nsIDOMNode **aParent1, PRInt32 *aOffset1, nsIDOMNode **aParent2, PRInt32 *aOffset2);
   static nsresult CreateRange(nsIDOMNode *aStartParent, PRInt32 aStartOffset, nsIDOMNode *aEndParent, PRInt32 aEndOffset, nsIDOMRange **aRange);
 
 private:
-
   /* nsTextServicesDocument private methods. */
 
   nsresult CreateContentIterator(nsIDOMRange *aRange, nsIContentIterator **aIterator);
 
   nsresult GetDocumentContentRootNode(nsIDOMNode **aNode);
   nsresult CreateDocumentContentRange(nsIDOMRange **aRange);
   nsresult CreateDocumentContentRootToNodeOffsetRange(nsIDOMNode *aParent, PRInt32 aOffset, PRBool aToStart, nsIDOMRange **aRange);
   nsresult CreateDocumentContentIterator(nsIContentIterator **aIterator);