Bug 403549: Avoid memory churn from nsContentUtils::CreateContextualFragment by giving nsIParser::ParseFragment a better signature. r/sr=stuart
authorjonas@sicking.cc
Mon, 12 Nov 2007 17:41:40 -0800
changeset 7883 841461f0a87fe79ab05b77b65c96f5cb06daa508
parent 7882 bb89f72d29c58f064944894a2aebea9084223d24
child 7884 302700e9ce9f0f9241e7a2cba8b7b73a13e22058
push idunknown
push userunknown
push dateunknown
bugs403549
milestone1.9b2pre
Bug 403549: Avoid memory churn from nsContentUtils::CreateContextualFragment by giving nsIParser::ParseFragment a better signature. r/sr=stuart
content/base/src/nsContentUtils.cpp
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/nsHTMLEditor.h
parser/htmlparser/public/nsIParser.h
parser/htmlparser/src/nsParser.cpp
parser/htmlparser/src/nsParser.h
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3201,156 +3201,117 @@ nsContentUtils::CreateContextualFragment
   NS_ENSURE_ARG(aContextNode);
   *aReturn = nsnull;
 
   // Create a new parser for this entire operation
   nsresult rv;
   nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIDocument> document;
-  nsCOMPtr<nsIDOMDocument> domDocument;
-
-  aContextNode->GetOwnerDocument(getter_AddRefs(domDocument));
-  document = do_QueryInterface(domDocument);
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode);
+  NS_ENSURE_TRUE(content, NS_ERROR_NOT_AVAILABLE);
 
   // If we don't have a document here, we can't get the right security context
   // for compiling event handlers... so just bail out.
+  nsCOMPtr<nsIDocument> document = content->GetOwnerDoc();
   NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE);
 
-  nsVoidArray tagStack;
-  nsCOMPtr<nsIDOMNode> parent = aContextNode;
-  while (parent && (parent != domDocument)) {
-    PRUint16 nodeType;
-    parent->GetNodeType(&nodeType);
-    if (nsIDOMNode::ELEMENT_NODE == nodeType) {
-      nsAutoString tagName, uriStr;
-      parent->GetNodeName(tagName);
-
-      // see if we need to add xmlns declarations
-      nsCOMPtr<nsIContent> content = do_QueryInterface(parent);
-      if (!content) {
-        rv = NS_ERROR_FAILURE;
-        break;
-      }
-
-      PRUint32 count = content->GetAttrCount();
-      PRBool setDefaultNamespace = PR_FALSE;
-      if (count > 0) {
-        PRUint32 index;
-        nsAutoString nameStr, prefixStr, valueStr;
-
-        for (index = 0; index < count; index++) {
-          const nsAttrName* name = content->GetAttrNameAt(index);
-          if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
-            content->GetAttr(kNameSpaceID_XMLNS, name->LocalName(), uriStr);
-
-            // really want something like nsXMLContentSerializer::SerializeAttr
-            tagName.Append(NS_LITERAL_STRING(" xmlns")); // space important
-            if (name->GetPrefix()) {
-              tagName.Append(PRUnichar(':'));
-              name->LocalName()->ToString(nameStr);
-              tagName.Append(nameStr);
-            } else {
-              setDefaultNamespace = PR_TRUE;
-            }
-            tagName.Append(NS_LITERAL_STRING("=\"") + uriStr +
-              NS_LITERAL_STRING("\""));
+  nsAutoTArray<nsAutoString, 32> tagStack;
+  nsAutoString uriStr, nameStr;
+
+  while (content && content->IsNodeOfType(nsINode::eELEMENT)) {
+    nsAutoString& tagName = *tagStack.AppendElement();
+    NS_ENSURE_TRUE(&tagName, NS_ERROR_OUT_OF_MEMORY);
+
+    content->NodeInfo()->GetQualifiedName(tagName);
+
+    // see if we need to add xmlns declarations
+    PRUint32 count = content->GetAttrCount();
+    PRBool setDefaultNamespace = PR_FALSE;
+    if (count > 0) {
+      PRUint32 index;
+
+      for (index = 0; index < count; index++) {
+        const nsAttrName* name = content->GetAttrNameAt(index);
+        if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
+          content->GetAttr(kNameSpaceID_XMLNS, name->LocalName(), uriStr);
+
+          // really want something like nsXMLContentSerializer::SerializeAttr
+          tagName.Append(NS_LITERAL_STRING(" xmlns")); // space important
+          if (name->GetPrefix()) {
+            tagName.Append(PRUnichar(':'));
+            name->LocalName()->ToString(nameStr);
+            tagName.Append(nameStr);
+          } else {
+            setDefaultNamespace = PR_TRUE;
           }
-        }
-      }
-
-      if (!setDefaultNamespace) {
-        nsINodeInfo* info = content->NodeInfo();
-        if (!info->GetPrefixAtom() &&
-            info->NamespaceID() != kNameSpaceID_None) {
-          // We have no namespace prefix, but have a namespace ID.  Push
-          // default namespace attr in, so that our kids will be in our
-          // namespace.
-          nsAutoString uri;
-          info->GetNamespaceURI(uri);
-          tagName.Append(NS_LITERAL_STRING(" xmlns=\"") + uri +
-                         NS_LITERAL_STRING("\""));
+          tagName.Append(NS_LITERAL_STRING("=\"") + uriStr +
+            NS_LITERAL_STRING("\""));
         }
       }
-
-      // XXX Wish we didn't have to allocate here
-      PRUnichar* name = ToNewUnicode(tagName);
-      if (name) {
-        tagStack.AppendElement(name);
-        nsCOMPtr<nsIDOMNode> temp = parent;
-        rv = temp->GetParentNode(getter_AddRefs(parent));
-        if (NS_FAILED(rv)) {
-          break;
-        }
-      } else {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-        break;
-      }
-    } else {
-      nsCOMPtr<nsIDOMNode> temp = parent;
-      rv = temp->GetParentNode(getter_AddRefs(parent));
-      if (NS_FAILED(rv)) {
-        break;
+    }
+
+    if (!setDefaultNamespace) {
+      nsINodeInfo* info = content->NodeInfo();
+      if (!info->GetPrefixAtom() &&
+          info->NamespaceID() != kNameSpaceID_None) {
+        // We have no namespace prefix, but have a namespace ID.  Push
+        // default namespace attr in, so that our kids will be in our
+        // namespace.
+        info->GetNamespaceURI(uriStr);
+        tagName.Append(NS_LITERAL_STRING(" xmlns=\"") + uriStr +
+                       NS_LITERAL_STRING("\""));
       }
     }
+
+    content = content->GetParent();
   }
 
+  nsCAutoString contentType;
+  PRBool bCaseSensitive = PR_TRUE;
+  nsAutoString buf;
+  document->GetContentType(buf);
+  LossyCopyUTF16toASCII(buf, contentType);
+  bCaseSensitive = document->IsCaseSensitive();
+
+  nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(document));
+  PRBool bHTML = htmlDoc && !bCaseSensitive;
+  nsCOMPtr<nsIFragmentContentSink> sink;
+  if (bHTML) {
+    rv = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
+  } else {
+    rv = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
+  }
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  sink->SetTargetDocument(document);
+  nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink));
+  parser->SetContentSink(contentsink);
+
+  nsDTDMode mode = eDTDMode_autodetect;
+  switch (document->GetCompatibilityMode()) {
+    case eCompatibility_NavQuirks:
+      mode = eDTDMode_quirks;
+      break;
+    case eCompatibility_AlmostStandards:
+      mode = eDTDMode_almost_standards;
+      break;
+    case eCompatibility_FullStandards:
+      mode = eDTDMode_full_standards;
+      break;
+    default:
+      NS_NOTREACHED("unknown mode");
+      break;
+  }
+
+  // XXX Shouldn't we be returning rv if it's a failure code?
+  rv = parser->ParseFragment(aFragment, nsnull, tagStack,
+                             !bHTML, contentType, mode);
   if (NS_SUCCEEDED(rv)) {
-    nsCAutoString contentType;
-    PRBool bCaseSensitive = PR_TRUE;
-    nsAutoString buf;
-    document->GetContentType(buf);
-    LossyCopyUTF16toASCII(buf, contentType);
-    bCaseSensitive = document->IsCaseSensitive();
-
-    nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(domDocument));
-    PRBool bHTML = htmlDoc && !bCaseSensitive;
-    nsCOMPtr<nsIFragmentContentSink> sink;
-    if (bHTML) {
-      rv = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
-    } else {
-      rv = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
-    }
-    if (NS_SUCCEEDED(rv)) {
-      sink->SetTargetDocument(document);
-      nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink));
-      parser->SetContentSink(contentsink);
-
-      nsDTDMode mode = eDTDMode_autodetect;
-      switch (document->GetCompatibilityMode()) {
-        case eCompatibility_NavQuirks:
-          mode = eDTDMode_quirks;
-          break;
-        case eCompatibility_AlmostStandards:
-          mode = eDTDMode_almost_standards;
-          break;
-        case eCompatibility_FullStandards:
-          mode = eDTDMode_full_standards;
-          break;
-        default:
-          NS_NOTREACHED("unknown mode");
-          break;
-      }
-      rv = parser->ParseFragment(aFragment, nsnull, tagStack,
-                                 !bHTML, contentType, mode);
-
-      if (NS_SUCCEEDED(rv)) {
-        rv = sink->GetFragment(aReturn);
-      }
-    }
-  }
-
-  // XXX Ick! Delete strings we allocated above.
-  PRInt32 count = tagStack.Count();
-  for (PRInt32 i = 0; i < count; i++) {
-    PRUnichar* str = (PRUnichar*)tagStack.ElementAt(i);
-    if (str) {
-      NS_Free(str);
-    }
+    rv = sink->GetFragment(aReturn);
   }
 
   return NS_OK;
 }
 
 /* static */
 nsresult
 nsContentUtils::CreateDocument(const nsAString& aNamespaceURI, 
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -2541,17 +2541,17 @@ nsresult nsHTMLEditor::CreateDOMFragment
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   GetDocument(getter_AddRefs(domDoc));
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   
   // if we have context info, create a fragment for that
-  nsVoidArray tagStack;
+  nsAutoTArray<nsAutoString, 32> tagStack;
   nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
   nsCOMPtr<nsIDOMNode> contextLeaf, junk;
   if (!aContextStr.IsEmpty())
   {
     res = ParseFragment(aContextStr, tagStack, doc, address_of(contextAsNode));
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE);
 
@@ -2563,25 +2563,20 @@ nsresult nsHTMLEditor::CreateDOMFragment
     res = FindTargetNode(contextAsNode, contextLeaf);
     if (res == NS_FOUND_TARGET)
       res = NS_OK;
     NS_ENSURE_SUCCESS(res, res);
   }
 
   // get the tagstack for the context
   res = CreateTagStack(tagStack, contextLeaf);
-  if (NS_FAILED(res))
-  {
-    FreeTagStackStrings(tagStack);
-    return res;
-  }
+  NS_ENSURE_SUCCESS(res, res);
 
   // create fragment for pasted html
   res = ParseFragment(aInputString, tagStack, doc, outFragNode);
-  FreeTagStackStrings(tagStack);
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(*outFragNode, NS_ERROR_FAILURE);
 
   RemoveBodyAndHead(*outFragNode);
 
   if (contextAsNode)
   {
     // unite the two trees
@@ -2631,22 +2626,22 @@ nsresult nsHTMLEditor::CreateDOMFragment
   }
 
   GetLengthOfDOMNode(*outEndNode, (PRUint32&)*outEndOffset);
   return res;
 }
 
 
 nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
-                                     nsVoidArray &aTagStack,
+                                     nsTArray<nsAutoString> &aTagStack,
                                      nsIDocument* aTargetDocument,
                                      nsCOMPtr<nsIDOMNode> *outNode)
 {
   // figure out if we are parsing full context or not
-  PRBool bContext = (aTagStack.Count()==0);
+  PRBool bContext = !aTagStack.IsEmpty();
 
   // create the parser to do the conversion.
   nsresult res;
   nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &res);
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(parser, NS_ERROR_FAILURE);
 
   // create the html fragment sink
@@ -2672,68 +2667,51 @@ nsresult nsHTMLEditor::ParseFragment(con
   nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
   res = fragSink->GetFragment(getter_AddRefs(contextfrag));
   NS_ENSURE_SUCCESS(res, res);
   *outNode = do_QueryInterface(contextfrag);
   
   return res;
 }
 
-nsresult nsHTMLEditor::CreateTagStack(nsVoidArray &aTagStack, nsIDOMNode *aNode)
+nsresult nsHTMLEditor::CreateTagStack(nsTArray<nsAutoString> &aTagStack, nsIDOMNode *aNode)
 {
   nsresult res = NS_OK;
   nsCOMPtr<nsIDOMNode> node= aNode;
   PRBool bSeenBody = PR_FALSE;
   
   while (node) 
   {
     if (nsTextEditUtils::IsBody(node))
       bSeenBody = PR_TRUE;
     nsCOMPtr<nsIDOMNode> temp = node;
     PRUint16 nodeType;
     
     node->GetNodeType(&nodeType);
     if (nsIDOMNode::ELEMENT_NODE == nodeType)
     {
-      nsAutoString tagName;
-      node->GetNodeName(tagName);
-      // XXX Wish we didn't have to allocate here
-      PRUnichar* name = ToNewUnicode(tagName);
-      if (!name) 
-	      return NS_ERROR_OUT_OF_MEMORY;
+      nsAutoString* tagName = aTagStack.AppendElement();
+      NS_ENSURE_TRUE(tagName, NS_ERROR_OUT_OF_MEMORY);
 
-      aTagStack.AppendElement(name);
+      node->GetNodeName(*tagName);
       // printf("%s\n",NS_LossyConvertUTF16toASCII(tagName).get());
     }
 
     res = temp->GetParentNode(getter_AddRefs(node));
     NS_ENSURE_SUCCESS(res, res);  
   }
   
   if (!bSeenBody)
   {
-      PRUnichar* bodyname = ToNewUnicode(NS_LITERAL_STRING("BODY"));
-      aTagStack.AppendElement(bodyname);
+      aTagStack.AppendElement(NS_LITERAL_STRING("BODY"));
   }
   return res;
 }
 
 
-void nsHTMLEditor::FreeTagStackStrings(nsVoidArray &tagStack)
-{
-  PRInt32 count = tagStack.Count();
-  for (PRInt32 i = 0; i < count; i++) 
-  {
-    PRUnichar* str = (PRUnichar*)tagStack.ElementAt(i);
-    if (str) {
-      NS_Free(str);
-    }
-  }
-}
-
 nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode  *aFragmentAsNode,
                                                 nsCOMArray<nsIDOMNode>& outNodeList,
                                                 nsIDOMNode *aStartNode,
                                                 PRInt32 aStartOffset,
                                                 nsIDOMNode *aEndNode,
                                                 PRInt32 aEndOffset)
 {
   if (!aFragmentAsNode) 
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -67,16 +67,17 @@
 #include "nsHTMLObjectResizer.h"
 #include "nsIHTMLAbsPosEditor.h"
 #include "nsIHTMLInlineTableEditor.h"
 #include "nsIHTMLObjectResizeListener.h"
 
 #include "nsIDocumentObserver.h"
 
 #include "nsPoint.h"
+#include "nsTArray.h"
 
 class nsIDOMKeyEvent;
 class nsITransferable;
 class nsIDOMNSRange;
 class nsIDocumentEncoder;
 class nsIClipboard;
 class TypeInState;
 class nsIContentFilter;
@@ -628,27 +629,27 @@ protected:
   nsresult   CreateDOMFragmentFromPaste(const nsAString & aInputString,
                                         const nsAString & aContextStr,
                                         const nsAString & aInfoStr,
                                         nsCOMPtr<nsIDOMNode> *outFragNode,
                                         nsCOMPtr<nsIDOMNode> *outStartNode,
                                         nsCOMPtr<nsIDOMNode> *outEndNode,
                                         PRInt32 *outStartOffset,
                                         PRInt32 *outEndOffset);
-  nsresult   ParseFragment(const nsAString & aStr, nsVoidArray &aTagStack,
+  nsresult   ParseFragment(const nsAString & aStr, nsTArray<nsAutoString> &aTagStack,
                            nsIDocument* aTargetDoc,
                            nsCOMPtr<nsIDOMNode> *outNode);
   nsresult   CreateListOfNodesToPaste(nsIDOMNode  *aFragmentAsNode,
                                       nsCOMArray<nsIDOMNode>& outNodeList,
                                       nsIDOMNode *aStartNode,
                                       PRInt32 aStartOffset,
                                       nsIDOMNode *aEndNode,
                                       PRInt32 aEndOffset);
-  nsresult CreateTagStack(nsVoidArray &aTagStack, nsIDOMNode *aNode);
-  void     FreeTagStackStrings(nsVoidArray &tagStack);
+  nsresult CreateTagStack(nsTArray<nsAutoString> &aTagStack,
+                          nsIDOMNode *aNode);
   nsresult GetListAndTableParents( PRBool aEnd, 
                                    nsCOMArray<nsIDOMNode>& aListOfNodes,
                                    nsCOMArray<nsIDOMNode>& outArray);
   nsresult DiscoverPartialListsAndTables(nsCOMArray<nsIDOMNode>& aPasteNodes,
                                          nsCOMArray<nsIDOMNode>& aListsAndTables,
                                          PRInt32 *outHighWaterMark);
   nsresult ScanForListAndTableStructure(PRBool aEnd,
                                         nsCOMArray<nsIDOMNode>& aNodes,
--- a/parser/htmlparser/public/nsIParser.h
+++ b/parser/htmlparser/public/nsIParser.h
@@ -46,22 +46,22 @@
  *  inteface is all that parser clients ever need to see.
  *
  **/
 
 #include "nsISupports.h"
 #include "nsIStreamListener.h"
 #include "nsIDTD.h"
 #include "nsStringGlue.h"
-#include "nsVoidArray.h"
+#include "nsTArray.h"
 
-// {d49b492c-1bdb-4b41-a138-9495a72fc11c}
+// {506527cc-d832-420b-ba3a-80c05aa105f4}
 #define NS_IPARSER_IID \
-{ 0xd49b492c, 0x1bdb, 0x4b41, \
-  { 0xa1, 0x38, 0x94, 0x95, 0xa7, 0x2f, 0xc1, 0x1c } }
+{ 0x506527cc, 0xd832, 0x420b, \
+  { 0xba, 0x3a, 0x80, 0xc0, 0x5a, 0xa1, 0x05, 0xf4 } }
 
 
 // {41421C60-310A-11d4-816F-000064657374}
 #define NS_IDEBUG_DUMP_CONTENT_IID \
 { 0x41421c60, 0x310a, 0x11d4, \
 { 0x81, 0x6f, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 
 class nsIContentSink;
@@ -249,17 +249,17 @@ class nsIParser : public nsISupports {
      * @param aTagStack The context of the source buffer.
      * @param aXMLMode Whether this is XML or HTML
      * @param aContentType The content-type of this document.
      * @param aMode The DTDMode that the parser should parse this fragment in.
      * @return Success or failure.
      */
     NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
                              void* aKey,
-                             nsVoidArray& aTagStack,
+                             nsTArray<nsAutoString>& aTagStack,
                              PRBool aXMLMode,
                              const nsACString& aContentType,
                              nsDTDMode aMode = eDTDMode_autodetect) = 0;
 
     /**
      * This method gets called when the tokens have been consumed, and it's time
      * to build the model via the content sink.
      * @update	gess5/11/98
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -1418,32 +1418,32 @@ nsParser::Parse(const nsAString& aSource
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsParser::ParseFragment(const nsAString& aSourceBuffer,
                         void* aKey,
-                        nsVoidArray& aTagStack,
+                        nsTArray<nsAutoString>& aTagStack,
                         PRBool aXMLMode,
                         const nsACString& aMimeType,
                         nsDTDMode aMode)
 {
   nsresult result = NS_OK;
   nsAutoString  theContext;
-  PRUint32 theCount = aTagStack.Count();
+  PRUint32 theCount = aTagStack.Length();
   PRUint32 theIndex = 0;
 
   // Disable observers for fragments
   mFlags &= ~NS_PARSER_FLAG_OBSERVERS_ENABLED;
 
   for (theIndex = 0; theIndex < theCount; theIndex++) {
     theContext.AppendLiteral("<");
-    theContext.Append((PRUnichar*)aTagStack.ElementAt(theCount - theIndex - 1));
+    theContext.Append(aTagStack[theCount - theIndex - 1]);
     theContext.AppendLiteral(">");
   }
 
   // First, parse the context to build up the DTD's tag stack. Note that we
   // pass PR_FALSE for the aLastCall parameter.
   result = Parse(theContext, (void*)&theContext, aMimeType, PR_FALSE, aMode);
   if (NS_FAILED(result)) {
     mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED;
@@ -1510,17 +1510,17 @@ nsParser::ParseFragment(const nsAString&
     if (NS_SUCCEEDED(result)) {
       nsAutoString endContext;       
       for (theIndex = 0; theIndex < theCount; theIndex++) {
          // we already added an end tag chunk above
         if (theIndex > 0) {
           endContext.AppendLiteral("</");
         }
 
-        nsAutoString thisTag( (PRUnichar*)aTagStack.ElementAt(theIndex) );
+        nsAutoString& thisTag = aTagStack[theIndex];
         // was there an xmlns=?
         PRInt32 endOfTag = thisTag.FindChar(PRUnichar(' '));
         if (endOfTag == -1) {
           endContext.Append(thisTag);
         } else {
           endContext.Append(Substring(thisTag,0,endOfTag));
         }
 
--- a/parser/htmlparser/src/nsParser.h
+++ b/parser/htmlparser/src/nsParser.h
@@ -214,17 +214,17 @@ class nsParser : public nsIParser,
 
     NS_IMETHOD_(void *) GetRootContextKey();
 
     /**
      * This method needs documentation
      */
     NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
                              void* aKey,
-                             nsVoidArray& aTagStack,
+                             nsTArray<nsAutoString>& aTagStack,
                              PRBool aXMLMode,
                              const nsACString& aContentType,
                              nsDTDMode aMode = eDTDMode_autodetect);
 
 
     /**
      * This method gets called when the tokens have been consumed, and it's time
      * to build the model via the content sink.