From b5688d68bbd68126b47b4d90e617e3c39254fbc7 Mon Sep 17 00:00:00 2001 From: "sicking%bigfoot.com" Date: Wed, 2 Nov 2005 07:41:05 +0000 Subject: [PATCH] Bug 207377: Change the way tbody-elements are inserted into tables to increase speed and make sure that only tablerows are inserted. r=Pike sr=peterv --- content/xslt/src/xslt/txHTMLAtomList.h | 2 + content/xslt/src/xslt/txMozillaXMLOutput.cpp | 157 ++++++++++--------- content/xslt/src/xslt/txMozillaXMLOutput.h | 14 +- 3 files changed, 97 insertions(+), 76 deletions(-) diff --git a/content/xslt/src/xslt/txHTMLAtomList.h b/content/xslt/src/xslt/txHTMLAtomList.h index 7b9e8048e38..2137503a458 100644 --- a/content/xslt/src/xslt/txHTMLAtomList.h +++ b/content/xslt/src/xslt/txHTMLAtomList.h @@ -84,9 +84,11 @@ TX_ATOM(src, "src"); TX_ATOM(style, "style"); TX_ATOM(table, "table"); TX_ATOM(target, "target"); +TX_ATOM(tbody, "tbody"); TX_ATOM(td, "td"); TX_ATOM(textarea, "textarea"); TX_ATOM(th, "th"); TX_ATOM(title, "title"); +TX_ATOM(tr, "tr"); TX_ATOM(type, "type"); TX_ATOM(ul, "ul"); diff --git a/content/xslt/src/xslt/txMozillaXMLOutput.cpp b/content/xslt/src/xslt/txMozillaXMLOutput.cpp index ce7fa6cb364..b8f4f559393 100644 --- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp +++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp @@ -93,7 +93,8 @@ txMozillaXMLOutput::txMozillaXMLOutput(const nsAString& aRootName, mDontAddCurrent(PR_FALSE), mHaveTitleElement(PR_FALSE), mHaveBaseElement(PR_FALSE), - mCreatingNewDocument(PR_TRUE) + mCreatingNewDocument(PR_TRUE), + mTableState(NORMAL) { if (aObserver) { mNotifier = new txTransformNotifier(); @@ -114,7 +115,8 @@ txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat, mDontAddCurrent(PR_FALSE), mHaveTitleElement(PR_FALSE), mHaveBaseElement(PR_FALSE), - mCreatingNewDocument(PR_FALSE) + mCreatingNewDocument(PR_FALSE), + mTableState(NORMAL) { mOutputFormat.merge(*aFormat); mOutputFormat.setFromDefaults(); @@ -237,10 +239,22 @@ void txMozillaXMLOutput::endElement(const nsAString& aName, const PRInt32 aNsID) } #ifdef DEBUG - nsAutoString nodeName; - mCurrentNode->GetNodeName(nodeName); - NS_ASSERTION(nodeName.Equals(aName, nsCaseInsensitiveStringComparator()), - "Unbalanced startElement and endElement calls!"); + if (mTableState != ADDED_TBODY) { + nsAutoString nodeName; + mCurrentNode->GetNodeName(nodeName); + NS_ASSERTION(nodeName.Equals(aName, + nsCaseInsensitiveStringComparator()), + "Unbalanced startElement and endElement calls!"); + } + else { + nsCOMPtr parent; + mCurrentNode->GetParentNode(getter_AddRefs(parent)); + nsAutoString nodeName; + parent->GetNodeName(nodeName); + NS_ASSERTION(nodeName.Equals(aName, + nsCaseInsensitiveStringComparator()), + "Unbalanced startElement and endElement calls!"); + } #endif closePrevious(eCloseElement | eFlushText); @@ -250,7 +264,7 @@ void txMozillaXMLOutput::endElement(const nsAString& aName, const PRInt32 aNsID) aNsID == kNameSpaceID_XHTML) { nsCOMPtr element = do_QueryInterface(mCurrentNode); NS_ASSERTION(element, "endElement'ing non-element"); - endHTMLElement(element, aNsID == kNameSpaceID_XHTML); + endHTMLElement(element); } // Add the element to the tree if it wasn't added before and take one step @@ -279,6 +293,9 @@ void txMozillaXMLOutput::endElement(const nsAString& aName, const PRInt32 aNsID) mCurrentNode->GetParentNode(getter_AddRefs(parent)); mCurrentNode = parent; } + + mTableState = + NS_STATIC_CAST(TableState, NS_PTR_TO_INT32(mTableStateStack.pop())); } void txMozillaXMLOutput::getOutputDocument(nsIDOMDocument** aDocument) @@ -360,7 +377,11 @@ void txMozillaXMLOutput::startElement(const nsAString& aName, return; } - nsresult rv; + nsresult rv = mTableStateStack.push(NS_INT32_TO_PTR(mTableState)); + if (NS_FAILED(rv)) { + return; + } + mTableState = NORMAL; nsCOMPtr element; mDontAddCurrent = PR_FALSE; @@ -381,7 +402,7 @@ void txMozillaXMLOutput::startElement(const nsAString& aName, return; } - startHTMLElement(element); + startHTMLElement(element, PR_FALSE); } else { nsAutoString nsURI; @@ -394,7 +415,7 @@ void txMozillaXMLOutput::startElement(const nsAString& aName, } if (aNsID == kNameSpaceID_XHTML) - startHTMLElement(element); + startHTMLElement(element, PR_TRUE); } if (mCreatingNewDocument) { @@ -491,15 +512,54 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction) } } -void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement) +void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement, PRBool aXHTML) { + nsresult rv = NS_OK; nsCOMPtr atom; nsCOMPtr content = do_QueryInterface(aElement); content->GetTag(getter_AddRefs(atom)); mDontAddCurrent = (atom == txHTMLAtoms::script); - if (atom == txHTMLAtoms::head) { + if ((atom != txHTMLAtoms::tr || aXHTML) && + NS_PTR_TO_INT32(mTableStateStack.peek()) == ADDED_TBODY) { + nsCOMPtr parent; + mCurrentNode->GetParentNode(getter_AddRefs(parent)); + mCurrentNode.swap(parent); + mTableStateStack.pop(); + } + + if (atom == txHTMLAtoms::table && !aXHTML) { + mTableState = TABLE; + } + else if (atom == txHTMLAtoms::tr && !aXHTML && + NS_PTR_TO_INT32(mTableStateStack.peek()) == TABLE) { + nsCOMPtr elem; + if (mDocumentIsHTML) { + rv = mDocument->CreateElement(NS_LITERAL_STRING("tbody"), + getter_AddRefs(elem)); + } + else { + rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kXHTMLNameSpaceURI), + NS_LITERAL_STRING("tbody"), + getter_AddRefs(elem)); + } + if (NS_FAILED(rv)) { + return; + } + nsCOMPtr dummy; + rv = mCurrentNode->AppendChild(elem, getter_AddRefs(dummy)); + if (NS_FAILED(rv)) { + return; + } + nsresult rv = mTableStateStack.push(NS_INT32_TO_PTR(ADDED_TBODY)); + if (NS_FAILED(rv)) { + return; + } + mCurrentNode = elem; + } + else if (atom == txHTMLAtoms::head && + mOutputFormat.mMethod == eHTMLOutput) { // Insert META tag, according to spec, 16.2, like // nsresult rv; @@ -531,8 +591,7 @@ void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement) } } -void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, - PRBool aXHTML) +void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement) { nsresult rv; nsCOMPtr content = do_QueryInterface(aElement); @@ -541,47 +600,20 @@ void txMozillaXMLOutput::endHTMLElement(nsIDOMElement* aElement, nsCOMPtr atom; content->GetTag(getter_AddRefs(atom)); - // add to tables if there is none (not in xhtml) - if (atom == txHTMLAtoms::table && !aXHTML) { - // Check if we have any table section. - nsCOMPtr section; - nsCOMPtr childContent; - PRInt32 count, i = 0; + if (mTableState == ADDED_TBODY) { + NS_ASSERTION(atom == txHTMLAtoms::tbody, + "Element flagged as added tbody isn't a tbody"); + nsCOMPtr parent; + mCurrentNode->GetParentNode(getter_AddRefs(parent)); + mCurrentNode = parent; + mTableState = NS_STATIC_CAST(TableState, + NS_PTR_TO_INT32(mTableStateStack.pop())); - content->ChildCount(count); - while (!section && (i < count)) { - rv = content->ChildAt(i, getter_AddRefs(childContent)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Something went wrong while getting a child"); - section = do_QueryInterface(childContent); - ++i; - } - - if (!section && (count > 0)) { - // If no section, wrap table's children in a tbody. - nsCOMPtr wrapper; - - if (mDocumentIsHTML) { - rv = mDocument->CreateElement(NS_LITERAL_STRING("tbody"), - getter_AddRefs(wrapper)); - } - else { - rv = mDocument->CreateElementNS(NS_LITERAL_STRING(kXHTMLNameSpaceURI), - NS_LITERAL_STRING("tbody"), - getter_AddRefs(wrapper)); - } - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create tbody element"); - - if (wrapper) { - nsCOMPtr resultNode; - - wrapChildren(mCurrentNode, wrapper); - rv = mCurrentNode->AppendChild(wrapper, getter_AddRefs(resultNode)); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't append tbody element"); - } - } + return; } + // Load scripts - else if (mNotifier && atom == txHTMLAtoms::script) { + if (mNotifier && atom == txHTMLAtoms::script) { // Add this script element to the array of loading script elements. nsCOMPtr scriptElement = do_QueryInterface(mCurrentNode); @@ -664,27 +696,6 @@ void txMozillaXMLOutput::processHTTPEquiv(nsIAtom* aHeader, const nsAString& aVa CopyUCS2toASCII(aValue, mRefreshString); } -void txMozillaXMLOutput::wrapChildren(nsIDOMNode* aCurrentNode, - nsIDOMElement* aWrapper) -{ - nsCOMPtr children; - nsresult rv = aCurrentNode->GetChildNodes(getter_AddRefs(children)); - if (NS_FAILED(rv)) { - NS_ASSERTION(0, "Can't get children!"); - return; - } - - nsCOMPtr child, resultNode; - PRUint32 count, i; - children->GetLength(&count); - for (i = 0; i < count; ++i) { - rv = children->Item(0, getter_AddRefs(child)); - if (NS_SUCCEEDED(rv)) { - aWrapper->AppendChild(child, getter_AddRefs(resultNode)); - } - } -} - nsresult txMozillaXMLOutput::createResultDocument(const nsAString& aName, PRInt32 aNsID, nsIDOMDocument* aSourceDocument, diff --git a/content/xslt/src/xslt/txMozillaXMLOutput.h b/content/xslt/src/xslt/txMozillaXMLOutput.h index 0d8536a9a9a..ec8e88ee6f5 100644 --- a/content/xslt/src/xslt/txMozillaXMLOutput.h +++ b/content/xslt/src/xslt/txMozillaXMLOutput.h @@ -45,6 +45,7 @@ #include "txOutputFormat.h" #include "nsCOMArray.h" #include "nsICSSLoaderObserver.h" +#include "txStack.h" class nsIContent; class nsIDOMDocument; @@ -102,10 +103,9 @@ public: private: void closePrevious(PRInt8 aAction); - void startHTMLElement(nsIDOMElement* aElement); - void endHTMLElement(nsIDOMElement* aElement, PRBool aXHTML); + void startHTMLElement(nsIDOMElement* aElement, PRBool aXHTML); + void endHTMLElement(nsIDOMElement* aElement); void processHTTPEquiv(nsIAtom* aHeader, const nsAString& aValue); - void wrapChildren(nsIDOMNode* aCurrentNode, nsIDOMElement* aWrapper); nsresult createResultDocument(const nsAString& aName, PRInt32 aNsID, nsIDOMDocument* aSourceDocument, nsIDOMDocument* aResultDocument); @@ -123,6 +123,14 @@ private: PRUint32 mBadChildLevel; nsCString mRefreshString; + txStack mTableStateStack; + enum TableState { + NORMAL, // An element needing no special treatment + TABLE, // A HTML table element + ADDED_TBODY // An inserted tbody not coming from the stylesheet + }; + TableState mTableState; + nsAutoString mText; txOutputFormat mOutputFormat;