Bug 481881 - use better template arguments for nsTArray<T> after bug 474369, content part; r+sr=sicking
authorArpad Borsos <arpad.borsos@googlemail.com>
Thu, 26 Mar 2009 09:29:49 +0100
changeset 26621 52c7758d5a4d473fde4e2e8ecd11e856a68ae2fe
parent 26620 839fbc4a9e3de050fd1a79d51dde1e54efd94a3d
child 26622 be12595f2d01ebb2963d0834f49e2ebf7c283beb
push idunknown
push userunknown
push dateunknown
bugs481881, 474369
milestone1.9.2a1pre
Bug 481881 - use better template arguments for nsTArray<T> after bug 474369, content part; r+sr=sicking
content/base/public/nsXMLNameSpaceMap.h
content/base/src/nsHTMLContentSerializer.cpp
content/base/src/nsHTMLContentSerializer.h
content/base/src/nsXMLContentSerializer.cpp
content/base/src/nsXMLContentSerializer.h
content/base/src/nsXMLNameSpaceMap.cpp
content/svg/content/src/nsSVGValue.cpp
content/svg/content/src/nsSVGValue.h
content/xslt/src/xslt/txInstructions.cpp
content/xslt/src/xslt/txInstructions.h
content/xul/templates/src/nsTemplateRule.cpp
content/xul/templates/src/nsTemplateRule.h
content/xul/templates/src/nsXULTemplateBuilder.cpp
--- a/content/base/public/nsXMLNameSpaceMap.h
+++ b/content/base/public/nsXMLNameSpaceMap.h
@@ -36,19 +36,27 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsXMLNameSpaceMap_h_
 #define nsXMLNameSpaceMap_h_
 
 #include "nsString.h"
 #include "nsTArray.h"
+#include "nsCOMPtr.h"
+#include "nsIAtom.h"
 
-class nsIAtom;
-class nsNameSpaceEntry;
+struct nsNameSpaceEntry
+{
+  nsNameSpaceEntry(nsIAtom *aPrefix)
+    : prefix(aPrefix) {}
+
+  nsCOMPtr<nsIAtom> prefix;
+  PRInt32 nameSpaceID;
+};
 
 /**
  * nsXMLNameSpaceMap contains a set of prefixes which are mapped onto
  * namespaces.  It allows the set to be searched by prefix or by namespace ID.
  */
 class nsXMLNameSpaceMap
 {
 public:
@@ -91,12 +99,12 @@ public:
   /* Removes all prefix mappings. */
   NS_HIDDEN_(void) Clear();
 
   ~nsXMLNameSpaceMap() { Clear(); }
 
 private:
   nsXMLNameSpaceMap() NS_HIDDEN;  // use Create() to create new instances
 
-  nsTArray<nsNameSpaceEntry*> mNameSpaces;
+  nsTArray<nsNameSpaceEntry> mNameSpaces;
 };
 
 #endif
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -97,21 +97,16 @@ nsHTMLContentSerializer::nsHTMLContentSe
   mIsWholeDocument(PR_FALSE),
   mInCDATA(PR_FALSE)
 {
 }
 
 nsHTMLContentSerializer::~nsHTMLContentSerializer()
 {
   NS_ASSERTION(mOLStateStack.IsEmpty(), "Expected OL State stack to be empty");
-  if (!mOLStateStack.IsEmpty()){
-    for (PRUint32 i = 0; i < mOLStateStack.Length(); i++){
-      delete mOLStateStack[i];
-    }
-  }
 }
 
 NS_IMETHODIMP 
 nsHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
                               const char* aCharSet, PRBool aIsCopying,
                               PRBool aIsWholeDocument)
 {
   nsresult rv;
@@ -683,19 +678,17 @@ nsHTMLContentSerializer::AppendElementSt
       //If OL has "start" attribute, first LI element has to start with that value
       //Therefore subtracting 1 as all the LI elements are incrementing it before using it;
       //In failure of ToInteger(), default StartAttrValue to 0.
       if (NS_SUCCEEDED(rv))
         startAttrVal--; 
       else
         startAttrVal = 0;
     }
-    olState* state = new olState(startAttrVal, PR_TRUE);
-    if (state)
-      mOLStateStack.AppendElement(state);
+    mOLStateStack.AppendElement(olState(startAttrVal, PR_TRUE));
   }
 
   if (mIsCopying && name == nsGkAtoms::li) {
     mIsFirstChildOfOL = IsFirstChildOfOL(aOriginalElement);
     if (mIsFirstChildOfOL){
       // If OL is parent of this LI, serialize attributes in different manner.
       SerializeLIValueAttribute(aElement, aStr);
     }
@@ -785,19 +778,17 @@ nsHTMLContentSerializer::AppendElementEn
     mPreLevel--;
   }
 
   if (mIsCopying && (name == nsGkAtoms::ol)){
     NS_ASSERTION(!mOLStateStack.IsEmpty(), "Cannot have an empty OL Stack");
     /* Though at this point we must always have an state to be deleted as all 
     the OL opening tags are supposed to push an olState object to the stack*/
     if (!mOLStateStack.IsEmpty()) {
-      olState* state = mOLStateStack.ElementAt(mOLStateStack.Length() -1);
       mOLStateStack.RemoveElementAt(mOLStateStack.Length() -1);
-      delete state;
     }
   }
   
   nsIParserService* parserService = nsContentUtils::GetParserService();
 
   if (parserService && (name != nsGkAtoms::style)) {
     PRBool isContainer;
 
@@ -1237,17 +1228,17 @@ nsHTMLContentSerializer::SerializeLIValu
   // Note that we get into this condition only once per a OL.
   PRBool found = PR_FALSE;
   nsCOMPtr<nsIDOMNode> currNode = do_QueryInterface(aElement);
   nsAutoString valueStr;
   PRInt32 offset = 0;
   olState defaultOLState(0, PR_FALSE);
   olState* state = nsnull;
   if (!mOLStateStack.IsEmpty())
-    state = mOLStateStack.ElementAt(mOLStateStack.Length()-1);
+    state = &mOLStateStack.ElementAt(mOLStateStack.Length()-1);
   /* Though we should never reach to a "state" as null or mOLStateStack.IsEmpty()
   at this point as all LI are supposed to be inside some OL and OL tag should have 
   pushed a state to the olStateStack.*/
   if (!state || mOLStateStack.IsEmpty())
     state = &defaultOLState;
   PRInt32 startVal = state->startVal;
   state->isFirstListItem = PR_FALSE;
   // Traverse previous siblings until we find one with "value" attribute.
@@ -1309,17 +1300,17 @@ nsHTMLContentSerializer::IsFirstChildOfO
     else
       return PR_FALSE;
   }
   
   if (parentName.LowerCaseEqualsLiteral("ol")) {
     olState defaultOLState(0, PR_FALSE);
     olState* state = nsnull;
     if (!mOLStateStack.IsEmpty())
-      state = mOLStateStack.ElementAt(mOLStateStack.Length()-1);
+      state = &mOLStateStack.ElementAt(mOLStateStack.Length()-1);
     /* Though we should never reach to a "state" as null at this point as 
     all LI are supposed to be inside some OL and OL tag should have pushed
     a state to the mOLStateStack.*/
     if (!state)
       state = &defaultOLState;
     
     if (state->isFirstListItem)
       return PR_TRUE;
--- a/content/base/src/nsHTMLContentSerializer.h
+++ b/content/base/src/nsHTMLContentSerializer.h
@@ -165,15 +165,15 @@ class nsHTMLContentSerializer : public n
     olState(PRInt32 aStart, PRBool aIsFirst):startVal(aStart),isFirstListItem(aIsFirst)
     {
     }
     PRInt32 startVal;
     PRBool isFirstListItem;
   };
 
   // Stack to store one olState struct per <OL>.
-  nsAutoTArray<olState*, 8> mOLStateStack;
+  nsAutoTArray<olState, 8> mOLStateStack;
 };
 
 nsresult
 NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer);
 
 #endif
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -59,22 +59,16 @@
 #include "nsTextFragment.h"
 #include "nsString.h"
 #include "prprf.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 #include "nsAttrName.h"
 
-struct NameSpaceDecl {
-  nsString mPrefix;
-  nsString mURI;
-  nsIDOMElement* mOwner;
-};
-
 nsresult NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer)
 {
   nsXMLContentSerializer* it = new nsXMLContentSerializer();
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return CallQueryInterface(it, aSerializer);
@@ -332,42 +326,38 @@ nsXMLContentSerializer::AppendDoctype(ns
 
 #define kXMLNS "xmlns"
 
 nsresult
 nsXMLContentSerializer::PushNameSpaceDecl(const nsAString& aPrefix,
                                           const nsAString& aURI,
                                           nsIDOMElement* aOwner)
 {
-  NameSpaceDecl* decl = new NameSpaceDecl();
+  NameSpaceDecl* decl = mNameSpaceStack.AppendElement();
   if (!decl) return NS_ERROR_OUT_OF_MEMORY;
 
   decl->mPrefix.Assign(aPrefix);
   decl->mURI.Assign(aURI);
   // Don't addref - this weak reference will be removed when
   // we pop the stack
   decl->mOwner = aOwner;
-
-  mNameSpaceStack.AppendElement(decl);
   return NS_OK;
 }
 
 void
 nsXMLContentSerializer::PopNameSpaceDeclsFor(nsIDOMElement* aOwner)
 {
   PRInt32 index, count;
 
   count = mNameSpaceStack.Length();
   for (index = count - 1; index >= 0; index--) {
-    NameSpaceDecl* decl = mNameSpaceStack.ElementAt(index);
-    if (decl->mOwner != aOwner) {
+    if (mNameSpaceStack[index].mOwner != aOwner) {
       break;
     }
     mNameSpaceStack.RemoveElementAt(index);
-    delete decl;
   }
 }
 
 PRBool
 nsXMLContentSerializer::ConfirmPrefix(nsAString& aPrefix,
                                       const nsAString& aURI,
                                       nsIDOMElement* aElement,
                                       PRBool aIsAttribute)
@@ -409,23 +399,23 @@ nsXMLContentSerializer::ConfirmPrefix(ns
   // Also keep track of whether we've seen aPrefix already.  If we have, that
   // means that it's already bound to a URI different from aURI, so even if we
   // later (so in a more outer scope) see it bound to aURI we can't reuse it.
   PRBool haveSeenOurPrefix = PR_FALSE;
 
   PRInt32 count = mNameSpaceStack.Length();
   PRInt32 index = count - 1;
   while (index >= 0) {
-    NameSpaceDecl* decl = mNameSpaceStack.ElementAt(index);
+    NameSpaceDecl& decl = mNameSpaceStack.ElementAt(index);
     // Check if we've found a prefix match
-    if (aPrefix.Equals(decl->mPrefix)) {
+    if (aPrefix.Equals(decl.mPrefix)) {
 
       // If the URIs match and aPrefix is not bound to any other URI, we can
       // use aPrefix
-      if (!haveSeenOurPrefix && aURI.Equals(decl->mURI)) {
+      if (!haveSeenOurPrefix && aURI.Equals(decl.mURI)) {
         // Just use our uriMatch stuff.  That will deal with an empty aPrefix
         // the right way.  We can break out of the loop now, though.
         uriMatch = PR_TRUE;
         closestURIMatch = aPrefix;
         break;
       }
 
       haveSeenOurPrefix = PR_TRUE;      
@@ -435,17 +425,17 @@ nsXMLContentSerializer::ConfirmPrefix(ns
       //    different namespace) or
       // 2) We're looking at an existing default namespace decl on aElement (so
       //    we can't create a new default namespace decl for this URI)
       // then generate a new prefix.  Note that we do NOT generate new prefixes
       // if we happen to have aPrefix == decl->mPrefix == "" and mismatching
       // URIs when |decl| doesn't have aElement as its owner.  In that case we
       // can simply push the new namespace URI as the default namespace for
       // aElement.
-      if (!aPrefix.IsEmpty() || decl->mOwner == aElement) {
+      if (!aPrefix.IsEmpty() || decl.mOwner == aElement) {
         NS_ASSERTION(!aURI.IsEmpty(),
                      "Not allowed to add a xmlns attribute with an empty "
                      "namespace name unless it declares the default "
                      "namespace.");
 
         GenerateNewPrefix(aPrefix);
         // Now we need to validate our new prefix/uri combination; check it
         // against the full namespace stack again.  Note that just restarting
@@ -453,29 +443,28 @@ nsXMLContentSerializer::ConfirmPrefix(ns
         // closestURIMatch and uriMatch state is not affected.
         index = count - 1;
         haveSeenOurPrefix = PR_FALSE;
         continue;
       }
     }
     
     // If we've found a URI match, then record the first one
-    if (!uriMatch && aURI.Equals(decl->mURI)) {
+    if (!uriMatch && aURI.Equals(decl.mURI)) {
       // Need to check that decl->mPrefix is not declared anywhere closer to
       // us.  If it is, we can't use it.
       PRBool prefixOK = PR_TRUE;
       PRInt32 index2;
       for (index2 = count-1; index2 > index && prefixOK; --index2) {
-        NameSpaceDecl* decl2 = mNameSpaceStack.ElementAt(index2);
-        prefixOK = (decl2->mPrefix != decl->mPrefix);
+        prefixOK = (mNameSpaceStack[index2].mPrefix != decl.mPrefix);
       }
       
       if (prefixOK) {
         uriMatch = PR_TRUE;
-        closestURIMatch.Assign(decl->mPrefix);
+        closestURIMatch.Assign(decl.mPrefix);
       }
     }
     
     --index;
   }
 
   // At this point the following invariants hold:
   // 1) The prefix in closestURIMatch is mapped to aURI in our scope if
--- a/content/base/src/nsXMLContentSerializer.h
+++ b/content/base/src/nsXMLContentSerializer.h
@@ -47,17 +47,16 @@
 #include "nsIContentSerializer.h"
 #include "nsISupportsUtils.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsString.h"
 
 class nsIDOMNode;
 class nsIAtom;
-struct NameSpaceDecl;
 
 class nsXMLContentSerializer : public nsIContentSerializer {
  public:
   nsXMLContentSerializer();
   virtual ~nsXMLContentSerializer();
 
   NS_DECL_ISUPPORTS
 
@@ -153,17 +152,24 @@ class nsXMLContentSerializer : public ns
                                        nsAString& aOutputStr);
 
   // Functions to check for newlines that needs to be added between nodes in
   // the root of a document.
   void MaybeAddNewline(nsAString& aStr);
   void MaybeFlagNewline(nsIDOMNode* aNode);
 
   PRInt32 mPrefixIndex;
-  nsTArray<NameSpaceDecl*> mNameSpaceStack;
+  
+  struct NameSpaceDecl {
+    nsString mPrefix;
+    nsString mURI;
+    nsIDOMElement* mOwner;
+  };
+
+  nsTArray<NameSpaceDecl> mNameSpaceStack;
 
   // nsIDocumentEncoder flags
   PRUint32  mFlags;
 
   // characters to use for line break
   nsString  mLineBreak;
 
   // The charset that was passed to Init()
--- a/content/base/src/nsXMLNameSpaceMap.cpp
+++ b/content/base/src/nsXMLNameSpaceMap.cpp
@@ -36,31 +36,37 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * A class for keeping track of prefix-to-namespace-id mappings
  */
 
 #include "nsXMLNameSpaceMap.h"
-#include "nsIAtom.h"
-#include "nsCOMPtr.h"
 #include "nsINameSpaceManager.h"
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 
-struct nsNameSpaceEntry
-{
-  nsNameSpaceEntry(nsIAtom *aPrefix)
-    : prefix(aPrefix) {}
+NS_SPECIALIZE_TEMPLATE
+class nsDefaultComparator <nsNameSpaceEntry, nsIAtom*> {
+  public:
+    PRBool Equals(const nsNameSpaceEntry& aEntry, nsIAtom* const& aPrefix) const {
+      return aEntry.prefix == aPrefix;
+    }
+};
 
-  nsCOMPtr<nsIAtom> prefix;
-  PRInt32 nameSpaceID;
+NS_SPECIALIZE_TEMPLATE
+class nsDefaultComparator <nsNameSpaceEntry, PRInt32> {
+  public:
+    PRBool Equals(const nsNameSpaceEntry& aEntry, const PRInt32& aNameSpace) const {
+      return aEntry.nameSpaceID == aNameSpace;
+    }
 };
 
+
 /* static */ nsXMLNameSpaceMap*
 nsXMLNameSpaceMap::Create()
 {
   nsXMLNameSpaceMap *map = new nsXMLNameSpaceMap();
   NS_ENSURE_TRUE(map, nsnull);
 
   nsresult rv = map->AddPrefix(nsGkAtoms::xmlns,
                                kNameSpaceID_XMLNS);
@@ -77,41 +83,20 @@ nsXMLNameSpaceMap::Create()
 nsXMLNameSpaceMap::nsXMLNameSpaceMap()
   : mNameSpaces(4)
 {
 }
 
 nsresult
 nsXMLNameSpaceMap::AddPrefix(nsIAtom *aPrefix, PRInt32 aNameSpaceID)
 {
-  PRUint32 count = mNameSpaces.Length();
-  nsNameSpaceEntry *foundEntry = nsnull;
-
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsNameSpaceEntry *entry = mNameSpaces.ElementAt(i);
-
-    NS_ASSERTION(entry, "null entry in namespace map!");
-
-    if (entry->prefix == aPrefix) {
-      foundEntry = entry;
-      break;
-    }
+  if (!mNameSpaces.Contains(aPrefix) && !mNameSpaces.AppendElement(aPrefix)) {
+    return NS_ERROR_OUT_OF_MEMORY;
   }
-
-  if (!foundEntry) {
-    foundEntry = new nsNameSpaceEntry(aPrefix);
-    NS_ENSURE_TRUE(foundEntry, NS_ERROR_OUT_OF_MEMORY);
-
-    if (mNameSpaces.AppendElement(foundEntry) == nsnull) {
-      delete foundEntry;
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  foundEntry->nameSpaceID = aNameSpaceID;
+  mNameSpaces[mNameSpaces.IndexOf(aPrefix)].nameSpaceID = aNameSpaceID;
   return NS_OK;
 }
 
 nsresult
 nsXMLNameSpaceMap::AddPrefix(nsIAtom *aPrefix, nsString &aURI)
 {
   PRInt32 id;
   nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aURI,
@@ -120,69 +105,41 @@ nsXMLNameSpaceMap::AddPrefix(nsIAtom *aP
   NS_ENSURE_SUCCESS(rv, rv);
 
   return AddPrefix(aPrefix, id);
 }
 
 void
 nsXMLNameSpaceMap::RemovePrefix(nsIAtom *aPrefix)
 {
-  PRUint32 count = mNameSpaces.Length();
-
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsNameSpaceEntry *entry = mNameSpaces.ElementAt(i);
-
-    NS_ASSERTION(entry, "null entry in namespace map!");
-
-    if (entry->prefix == aPrefix) {
-      mNameSpaces.RemoveElementAt(i);
-      return;
-    }
-  }
+  mNameSpaces.RemoveElement(aPrefix);
 }
 
 PRInt32
 nsXMLNameSpaceMap::FindNameSpaceID(nsIAtom *aPrefix) const
 {
-  PRUint32 count = mNameSpaces.Length();
-
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsNameSpaceEntry *entry = mNameSpaces.ElementAt(i);
-
-    NS_ASSERTION(entry, "null entry in namespace map!");
-
-    if (entry->prefix == aPrefix) {
-      return entry->nameSpaceID;
-    }
+  PRUint32 index = mNameSpaces.IndexOf(aPrefix);
+  if (index != mNameSpaces.NoIndex) {
+    return mNameSpaces[index].nameSpaceID;
   }
 
   // The default mapping for no prefix is no namespace.  If a non-null prefix
   // was specified and we didn't find it, we return an error.
 
   return aPrefix ? kNameSpaceID_Unknown : kNameSpaceID_None;
 }
 
 nsIAtom*
 nsXMLNameSpaceMap::FindPrefix(PRInt32 aNameSpaceID) const
 {
-  PRUint32 count = mNameSpaces.Length();
-
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsNameSpaceEntry *entry = mNameSpaces.ElementAt(i);
-
-    NS_ASSERTION(entry, "null entry in namespace map!");
-
-    if (entry->nameSpaceID == aNameSpaceID) {
-      return entry->prefix;
-    }
+  PRUint32 index = mNameSpaces.IndexOf(aNameSpaceID);
+  if (index != mNameSpaces.NoIndex) {
+    return mNameSpaces[index].prefix;
   }
 
   return nsnull;
 }
 
 void
 nsXMLNameSpaceMap::Clear()
 {
-  for (PRUint32 i = 0, len = mNameSpaces.Length(); i < len; ++i) {
-    delete mNameSpaces[i];
-  }
   mNameSpaces.Clear();
 }
--- a/content/svg/content/src/nsSVGValue.cpp
+++ b/content/svg/content/src/nsSVGValue.cpp
@@ -32,37 +32,30 @@
  * 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 "nsSVGValue.h"
-#include "nsIWeakReference.h"
 
 nsSVGValue::nsSVGValue()
     : mModifyNestCount(0)
 {
 }
 
 nsSVGValue::~nsSVGValue()
 {
   ReleaseObservers();
 }
 
 void
 nsSVGValue::ReleaseObservers()
 {
-  PRUint32 count = mObservers.Length();
-  PRUint32 i;
-  for (i = 0; i < count; ++i) {
-    nsIWeakReference* wr = mObservers.ElementAt(i);
-    NS_RELEASE(wr);
-  }
   mObservers.Clear();
 }
 
 void
 nsSVGValue::NotifyObservers(SVGObserverNotifyFunction f,
                             modificationType aModType)
 {
   PRInt32 count = mObservers.Length();
@@ -94,44 +87,37 @@ nsSVGValue::DidModify(modificationType a
     NotifyObservers(&nsISVGValueObserver::DidModifySVGObservable, aModType);
   }
 }
 
 
 NS_IMETHODIMP
 nsSVGValue::AddObserver(nsISVGValueObserver* observer)
 {
-  nsIWeakReference* wr = NS_GetWeakReference(observer);
+  nsWeakPtr wr = do_GetWeakReference(observer);
   if (!wr) return NS_ERROR_FAILURE;
 
   // Prevent duplicate observers - needed because geometry can attempt
   // to add itself as an observer of a paint server for both the
   // stroke and fill.  Safe, as on a style change we remove both, as
   // the change notification isn't fine grained, and re-add as
   // appropriate.
-  if (mObservers.Contains(wr)) {
-    NS_RELEASE(wr);
-    return NS_OK;
+  if (!mObservers.Contains(wr)) {
+    mObservers.AppendElement(wr);
   }
 
-  mObservers.AppendElement(wr);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSVGValue::RemoveObserver(nsISVGValueObserver* observer)
 {
-  nsCOMPtr<nsIWeakReference> wr = do_GetWeakReference(observer);
+  nsWeakPtr wr = do_GetWeakReference(observer);
   if (!wr) return NS_ERROR_FAILURE;
-  PRInt32 i = mObservers.IndexOf(wr);
-  if (i<0) return NS_ERROR_FAILURE;
-  nsIWeakReference* wr2 = mObservers.ElementAt(i);
-  NS_RELEASE(wr2);
-  mObservers.RemoveElementAt(i);
-  return NS_OK;
+  return mObservers.RemoveElement(wr) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsSVGValue::BeginBatchUpdate()
 {
   WillModify();
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGValue.h
+++ b/content/svg/content/src/nsSVGValue.h
@@ -39,16 +39,18 @@
 #ifndef __NS_SVGVALUE_H__
 #define __NS_SVGVALUE_H__
 
 #include "nscore.h"
 #include "nsISVGValue.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "nsISVGValueObserver.h"
+#include "nsIWeakReference.h"
+#include "nsCOMPtr.h"
 
 class nsSVGValue : public nsISVGValue
 {
 protected:
   nsSVGValue();
   virtual ~nsSVGValue();
 
   // to be called by subclass whenever value is being modified.
@@ -75,17 +77,17 @@ protected:
   // implementation helpers
   void ReleaseObservers();
   void NotifyObservers(SVGObserverNotifyFunction f,
                        modificationType aModType);
   PRInt32 GetModifyNestCount() { return mModifyNestCount; }
 private:
   virtual void OnDidModify(){} // hook that will be called before observers are notified
   
-  nsAutoTArray<nsIWeakReference*, 1> mObservers;
+  nsAutoTArray<nsWeakPtr, 1> mObservers;
   PRInt32 mModifyNestCount;
 };
 
 // Class that will automatically call WillModify and DidModify in its ctor
 // and dtor respectively (for functions that have multiple exit points).
 
 class NS_STACK_CLASS nsSVGValueAutoNotifier
 {
--- a/content/xslt/src/xslt/txInstructions.cpp
+++ b/content/xslt/src/xslt/txInstructions.cpp
@@ -637,21 +637,16 @@ txProcessingInstruction::execute(txExecu
 
 txPushNewContext::txPushNewContext(nsAutoPtr<Expr> aSelect)
     : mSelect(aSelect), mBailTarget(nsnull)
 {
 }
 
 txPushNewContext::~txPushNewContext()
 {
-    PRUint32 i;
-    for (i = 0; i < mSortKeys.Length(); ++i)
-    {
-        delete mSortKeys[i];
-    }
 }
 
 nsresult
 txPushNewContext::execute(txExecutionState& aEs)
 {
     nsRefPtr<txAExprResult> exprRes;
     nsresult rv = mSelect->evaluate(aEs.getEvalContext(),
                                     getter_AddRefs(exprRes));
@@ -670,20 +665,20 @@ txPushNewContext::execute(txExecutionSta
         aEs.gotoInstruction(mBailTarget);
         
         return NS_OK;
     }
 
     txNodeSorter sorter;
     PRUint32 i, count = mSortKeys.Length();
     for (i = 0; i < count; ++i) {
-        SortKey* sort = mSortKeys[i];
-        rv = sorter.addSortElement(sort->mSelectExpr, sort->mLangExpr,
-                                   sort->mDataTypeExpr, sort->mOrderExpr,
-                                   sort->mCaseOrderExpr,
+        SortKey& sort = mSortKeys[i];
+        rv = sorter.addSortElement(sort.mSelectExpr, sort.mLangExpr,
+                                   sort.mDataTypeExpr, sort.mOrderExpr,
+                                   sort.mCaseOrderExpr,
                                    aEs.getEvalContext());
         NS_ENSURE_SUCCESS(rv, rv);
     }
     nsRefPtr<txNodeSet> sortedNodes;
     rv = sorter.sortNodeSet(nodes, &aEs, getter_AddRefs(sortedNodes));
     NS_ENSURE_SUCCESS(rv, rv);
     
     txNodeSetContext* context = new txNodeSetContext(sortedNodes, &aEs);
@@ -702,37 +697,26 @@ txPushNewContext::execute(txExecutionSta
 
 nsresult
 txPushNewContext::addSort(nsAutoPtr<Expr> aSelectExpr,
                           nsAutoPtr<Expr> aLangExpr,
                           nsAutoPtr<Expr> aDataTypeExpr,
                           nsAutoPtr<Expr> aOrderExpr,
                           nsAutoPtr<Expr> aCaseOrderExpr)
 {
-    SortKey* sort = new SortKey(aSelectExpr, aLangExpr, aDataTypeExpr,
-                                aOrderExpr, aCaseOrderExpr);
-    NS_ENSURE_TRUE(sort, NS_ERROR_OUT_OF_MEMORY);
-
-    if (mSortKeys.AppendElement(sort) == nsnull) {
-        delete sort;
-        return NS_ERROR_OUT_OF_MEMORY;
+    if (SortKey *key = mSortKeys.AppendElement()) {
+        // workaround for not triggering the Copy Constructor
+        key->mSelectExpr = aSelectExpr;
+        key->mLangExpr = aLangExpr;
+        key->mDataTypeExpr = aDataTypeExpr;
+        key->mOrderExpr = aOrderExpr;
+        key->mCaseOrderExpr = aCaseOrderExpr;
+        return NS_OK;
     }
-   
-    return NS_OK;
-}
-
-txPushNewContext::SortKey::SortKey(nsAutoPtr<Expr> aSelectExpr,
-                                   nsAutoPtr<Expr> aLangExpr,
-                                   nsAutoPtr<Expr> aDataTypeExpr,
-                                   nsAutoPtr<Expr> aOrderExpr,
-                                   nsAutoPtr<Expr> aCaseOrderExpr)
-    : mSelectExpr(aSelectExpr), mLangExpr(aLangExpr),
-      mDataTypeExpr(aDataTypeExpr), mOrderExpr(aOrderExpr),
-      mCaseOrderExpr(aCaseOrderExpr)
-{
+    return NS_ERROR_OUT_OF_MEMORY;
 }
 
 nsresult
 txPushNullTemplateRule::execute(txExecutionState& aEs)
 {
     return aEs.pushTemplateRule(nsnull, txExpandedName(), nsnull);
 }
 
--- a/content/xslt/src/xslt/txInstructions.h
+++ b/content/xslt/src/xslt/txInstructions.h
@@ -289,28 +289,24 @@ public:
     TX_DECL_TXINSTRUCTION
     
     
     nsresult addSort(nsAutoPtr<Expr> aSelectExpr, nsAutoPtr<Expr> aLangExpr,
                      nsAutoPtr<Expr> aDataTypeExpr, nsAutoPtr<Expr> aOrderExpr,
                      nsAutoPtr<Expr> aCaseOrderExpr);
 
     struct SortKey {
-        SortKey(nsAutoPtr<Expr> aSelectExpr, nsAutoPtr<Expr> aLangExpr,
-                nsAutoPtr<Expr> aDataTypeExpr, nsAutoPtr<Expr> aOrderExpr,
-                nsAutoPtr<Expr> aCaseOrderExpr);
-
         nsAutoPtr<Expr> mSelectExpr;
         nsAutoPtr<Expr> mLangExpr;
         nsAutoPtr<Expr> mDataTypeExpr;
         nsAutoPtr<Expr> mOrderExpr;
         nsAutoPtr<Expr> mCaseOrderExpr;
     };
     
-    nsTArray<SortKey*> mSortKeys;
+    nsTArray<SortKey> mSortKeys;
     nsAutoPtr<Expr> mSelect;
     txInstruction* mBailTarget;
 };
 
 class txPushNullTemplateRule : public txInstruction
 {
 public:
     TX_DECL_TXINSTRUCTION
--- a/content/xul/templates/src/nsTemplateRule.cpp
+++ b/content/xul/templates/src/nsTemplateRule.cpp
@@ -292,20 +292,30 @@ nsTemplateRule::nsTemplateRule(nsIConten
           mAction(aAction),
           mBindings(nsnull),
           mConditions(nsnull)
 {
     MOZ_COUNT_CTOR(nsTemplateRule);
     mRuleNode = do_QueryInterface(aRuleNode);
 }
 
+nsTemplateRule::nsTemplateRule(const nsTemplateRule& aOtherRule)
+        : mQuerySet(aOtherRule.mQuerySet),
+          mAction(aOtherRule.mAction),
+          mBindings(nsnull),
+          mConditions(nsnull),
+          mRuleNode(aOtherRule.mRuleNode)
+{
+    MOZ_COUNT_CTOR(nsTemplateRule);
+}
+
 nsTemplateRule::~nsTemplateRule()
 {
     MOZ_COUNT_DTOR(nsTemplateRule);
-
+    
     while (mBindings) {
         Binding* doomed = mBindings;
         mBindings = mBindings->mNext;
         delete doomed;
     }
 
     while (mConditions) {
         nsTemplateCondition* cdel = mConditions;
--- a/content/xul/templates/src/nsTemplateRule.h
+++ b/content/xul/templates/src/nsTemplateRule.h
@@ -137,16 +137,22 @@ protected:
  *
  */
 class nsTemplateRule
 {
 public:
     nsTemplateRule(nsIContent* aRuleNode,
                    nsIContent* aAction,
                    nsTemplateQuerySet* aQuerySet);
+    /**
+     * The copy-constructor should only be called from nsTArray when appending
+     * a new rule, otherwise things break because the copy constructor expects
+     * mBindings and mConditions to be nsnull.
+     */
+    nsTemplateRule(const nsTemplateRule& aOtherRule);
 
     ~nsTemplateRule();
 
     /**
      * Return the <action> node that this rule was constructed from, or its
      * logical equivalent for shorthand syntaxes. That is, the parent node of
      * the content that should be generated for this rule.
      */
@@ -271,17 +277,17 @@ protected:
  *  explicit <queryset> tag or implied if the tag is not used.
  *
  *  These queryset objects are created and owned by the builder in its
  *  mQuerySets array.
  */
 class nsTemplateQuerySet
 {
 protected:
-    nsTArray<nsTemplateRule*> mRules; // rules owned by nsTemplateQuerySet
+    nsTArray<nsTemplateRule> mRules;
 
     // a number which increments for each successive queryset. It is stored so
     // it can be used as an optimization when updating results so that it is
     // known where to insert them into a match.
     PRInt32 mPriority;
 
 public:
 
@@ -300,52 +306,56 @@ public:
         : mPriority(aPriority)
     {
         MOZ_COUNT_CTOR(nsTemplateQuerySet);
     }
 
     ~nsTemplateQuerySet()
     {
         MOZ_COUNT_DTOR(nsTemplateQuerySet);
-        Clear();
     }
 
     PRInt32 Priority() const
     {
         return mPriority;
     }
 
     nsIAtom* GetTag() { return mTag; }
     void SetTag(nsIAtom* aTag) { mTag = aTag; }
 
-    nsresult AddRule(nsTemplateRule *aChild)
+    nsTemplateRule* NewRule(nsIContent* aRuleNode,
+                            nsIContent* aAction,
+                            nsTemplateQuerySet* aQuerySet)
     {
         // nsTemplateMatch stores the index as a 16-bit value,
         // so check to make sure for overflow
         if (mRules.Length() == PR_INT16_MAX)
-            return NS_ERROR_FAILURE;
+            return nsnull;
 
-        if (mRules.AppendElement(aChild) == nsnull)
-            return NS_ERROR_OUT_OF_MEMORY;
-        return NS_OK;
+        return mRules.AppendElement(nsTemplateRule(aRuleNode, aAction,
+                                    aQuerySet));
+    }
+    
+    void RemoveRule(nsTemplateRule *aRule)
+    {
+        mRules.RemoveElementAt(aRule - mRules.Elements());
     }
 
     PRInt16 RuleCount() const
     {
         return mRules.Length();
     }
 
     nsTemplateRule* GetRuleAt(PRInt16 aIndex)
     {
-        return mRules[aIndex];
+        if (PRUint32(aIndex) < mRules.Length()) {
+            return &mRules[aIndex];
+        }
+        return nsnull;
     }
 
     void Clear()
     {
-        for (PRInt32 r = mRules.Length() - 1; r >= 0; r--) {
-            nsTemplateRule* rule = mRules[r];
-            delete rule;
-        }
         mRules.Clear();
     }
 };
 
 #endif // nsTemplateRule_h__
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -2022,26 +2022,20 @@ nsXULTemplateBuilder::CompileTemplate(ns
 
             nsCOMPtr<nsIDOMNode> query(do_QueryInterface(aQuerySet->mQueryNode));
 
             rv = mQueryProcessor->CompileQuery(this, query,
                                                mRefVariable, memberVariable,
                                                getter_AddRefs(aQuerySet->mCompiledQuery));
 
             if (aQuerySet->mCompiledQuery) {
-                nsTemplateRule* rule = new nsTemplateRule(aTemplate, rulenode, aQuerySet);
+                nsTemplateRule* rule = aQuerySet->NewRule(aTemplate, rulenode, aQuerySet);
                 if (! rule)
                     return NS_ERROR_OUT_OF_MEMORY;
 
-                rv = aQuerySet->AddRule(rule);
-                if (NS_FAILED(rv)) {
-                    delete rule;
-                    return rv;
-                }
-
                 rule->SetVars(mRefVariable, memberVariable);
 
                 *aCanUseTemplate = PR_TRUE;
 
                 return NS_OK;
             }
         }
     }
@@ -2060,40 +2054,34 @@ nsXULTemplateBuilder::CompileExtendedQue
                                            nsIContent* aActionElement,
                                            nsIAtom* aMemberVariable,
                                            nsTemplateQuerySet* aQuerySet)
 {
     // Compile an "extended" <template> rule. An extended rule may have
     // a <conditions> child, an <action> child, and a <bindings> child.
     nsresult rv;
 
-    nsTemplateRule* rule = new nsTemplateRule(aRuleElement, aActionElement, aQuerySet);
+    nsTemplateRule* rule = aQuerySet->NewRule(aRuleElement, aActionElement, aQuerySet);
     if (! rule)
          return NS_ERROR_OUT_OF_MEMORY;
 
     nsCOMPtr<nsIContent> conditions;
     nsXULContentUtils::FindChildByTag(aRuleElement,
                                       kNameSpaceID_XUL,
                                       nsGkAtoms::conditions,
                                       getter_AddRefs(conditions));
 
     // allow the conditions to be placed directly inside the rule
     if (!conditions)
         conditions = aRuleElement;
   
     rv = CompileConditions(rule, conditions);
     // If the rule compilation failed, then we have to bail.
     if (NS_FAILED(rv)) {
-        delete rule;
-        return rv;
-    }
-
-    rv = aQuerySet->AddRule(rule);
-    if (NS_FAILED(rv)) {
-        delete rule;
+        aQuerySet->RemoveRule(rule);
         return rv;
     }
 
     rule->SetVars(mRefVariable, aMemberVariable);
 
     // If we've got bindings, add 'em.
     nsCOMPtr<nsIContent> bindings;
     nsXULContentUtils::FindChildByTag(aRuleElement,
@@ -2217,26 +2205,20 @@ nsXULTemplateBuilder::CompileSimpleQuery
     if (NS_FAILED(rv))
         return rv;
 
     if (! aQuerySet->mCompiledQuery) {
         *aCanUseTemplate = PR_FALSE;
         return NS_OK;
     }
 
-    nsTemplateRule* rule = new nsTemplateRule(aRuleElement, aRuleElement, aQuerySet);
+    nsTemplateRule* rule = aQuerySet->NewRule(aRuleElement, aRuleElement, aQuerySet);
     if (! rule)
         return NS_ERROR_OUT_OF_MEMORY;
 
-    rv = aQuerySet->AddRule(rule);
-    if (NS_FAILED(rv)) {
-        delete rule;
-        return rv;
-    }
-
     rule->SetVars(mRefVariable, memberVariable);
 
     nsAutoString tag;
     aRuleElement->GetAttr(kNameSpaceID_None, nsGkAtoms::parent, tag);
 
     if (!tag.IsEmpty()) {
         nsCOMPtr<nsIAtom> tagatom = do_GetAtom(tag);
         aQuerySet->SetTag(tagatom);