From a1cc30339715766b38de90a35234eb3fae586899 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 21 Sep 2009 14:43:43 +0300 Subject: [PATCH] Bug 515338 - Make HTML5 parser internals not hold nsIContent or regular dynamic atoms. r=bnewman. --HG-- extra : rebase_source : 955eb137d96a4ea1461417ada9809404a1218dd1 --- parser/html/nsHtml5AttributeName.cpp | 7 +- parser/html/nsHtml5AttributeName.h | 3 +- parser/html/nsHtml5ElementName.cpp | 7 +- parser/html/nsHtml5ElementName.h | 3 +- parser/html/nsHtml5HtmlAttributes.cpp | 1 + parser/html/nsHtml5HtmlAttributes.h | 1 + parser/html/nsHtml5MetaScanner.cpp | 1 + parser/html/nsHtml5MetaScanner.h | 1 + parser/html/nsHtml5Parser.cpp | 16 +- parser/html/nsHtml5Parser.h | 10 +- parser/html/nsHtml5Portability.cpp | 17 +- parser/html/nsHtml5Portability.h | 7 +- parser/html/nsHtml5StackNode.cpp | 13 +- parser/html/nsHtml5StackNode.h | 15 +- parser/html/nsHtml5StackNodeCppSupplement.h | 56 ---- parser/html/nsHtml5StackNodeHSupplement.h | 38 --- parser/html/nsHtml5StateSnapshot.cpp | 3 +- parser/html/nsHtml5StateSnapshot.h | 5 +- parser/html/nsHtml5StreamParser.cpp | 5 +- parser/html/nsHtml5Tokenizer.cpp | 50 +++- parser/html/nsHtml5Tokenizer.h | 3 + parser/html/nsHtml5TreeBuilder.cpp | 128 +++++++-- parser/html/nsHtml5TreeBuilder.h | 48 ++-- parser/html/nsHtml5TreeBuilderCppSupplement.h | 240 +++++++--------- parser/html/nsHtml5TreeBuilderHSupplement.h | 32 ++- parser/html/nsHtml5TreeOpExecutor.cpp | 23 +- parser/html/nsHtml5TreeOpExecutor.h | 28 +- parser/html/nsHtml5TreeOperation.cpp | 258 ++++++++++++++---- parser/html/nsHtml5TreeOperation.h | 139 ++++++++-- parser/html/nsHtml5UTF16Buffer.cpp | 1 + parser/html/nsHtml5UTF16Buffer.h | 1 + 31 files changed, 713 insertions(+), 447 deletions(-) delete mode 100644 parser/html/nsHtml5StackNodeCppSupplement.h delete mode 100644 parser/html/nsHtml5StackNodeHSupplement.h diff --git a/parser/html/nsHtml5AttributeName.cpp b/parser/html/nsHtml5AttributeName.cpp index a2c4295275f..a7d40b4adc5 100644 --- a/parser/html/nsHtml5AttributeName.cpp +++ b/parser/html/nsHtml5AttributeName.cpp @@ -29,6 +29,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -96,17 +97,17 @@ nsHtml5AttributeName::SAME_LOCAL(nsIAtom* name) } nsHtml5AttributeName* -nsHtml5AttributeName::nameByBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length) +nsHtml5AttributeName::nameByBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length, nsHtml5AtomTable* interner) { PRInt32 hash = nsHtml5AttributeName::bufToHash(buf, length); PRInt32 index = nsHtml5AttributeName::ATTRIBUTE_HASHES.binarySearch(hash); if (index < 0) { - return nsHtml5AttributeName::createAttributeName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length)); + return nsHtml5AttributeName::createAttributeName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length, interner)); } else { nsHtml5AttributeName* attributeName = nsHtml5AttributeName::ATTRIBUTE_NAMES[index]; nsIAtom* name = attributeName->getLocal(NS_HTML5ATTRIBUTE_NAME_HTML); if (!nsHtml5Portability::localEqualsBuffer(name, buf, offset, length)) { - return nsHtml5AttributeName::createAttributeName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length)); + return nsHtml5AttributeName::createAttributeName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length, interner)); } return attributeName; } diff --git a/parser/html/nsHtml5AttributeName.h b/parser/html/nsHtml5AttributeName.h index 2ce00319dd8..ca6e538ad8a 100644 --- a/parser/html/nsHtml5AttributeName.h +++ b/parser/html/nsHtml5AttributeName.h @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -74,7 +75,7 @@ class nsHtml5AttributeName static nsIAtom** COLONIFIED_LOCAL(nsIAtom* name, nsIAtom* suffix); public: static nsIAtom** SAME_LOCAL(nsIAtom* name); - static nsHtml5AttributeName* nameByBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length); + static nsHtml5AttributeName* nameByBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length, nsHtml5AtomTable* interner); private: static PRInt32 bufToHash(PRUnichar* buf, PRInt32 len); PRInt32* uri; diff --git a/parser/html/nsHtml5ElementName.cpp b/parser/html/nsHtml5ElementName.cpp index 95457b2b960..d9cff19209a 100644 --- a/parser/html/nsHtml5ElementName.cpp +++ b/parser/html/nsHtml5ElementName.cpp @@ -29,6 +29,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -56,17 +57,17 @@ #include "nsHtml5ReleasableElementName.h" nsHtml5ElementName* -nsHtml5ElementName::elementNameByBuffer(jArray buf, PRInt32 offset, PRInt32 length) +nsHtml5ElementName::elementNameByBuffer(jArray buf, PRInt32 offset, PRInt32 length, nsHtml5AtomTable* interner) { PRInt32 hash = nsHtml5ElementName::bufToHash(buf, length); PRInt32 index = nsHtml5ElementName::ELEMENT_HASHES.binarySearch(hash); if (index < 0) { - return new nsHtml5ReleasableElementName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length)); + return new nsHtml5ReleasableElementName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length, interner)); } else { nsHtml5ElementName* elementName = nsHtml5ElementName::ELEMENT_NAMES[index]; nsIAtom* name = elementName->name; if (!nsHtml5Portability::localEqualsBuffer(name, buf, offset, length)) { - return new nsHtml5ReleasableElementName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length)); + return new nsHtml5ReleasableElementName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length, interner)); } return elementName; } diff --git a/parser/html/nsHtml5ElementName.h b/parser/html/nsHtml5ElementName.h index 33d6bb70a01..74fba554b61 100644 --- a/parser/html/nsHtml5ElementName.h +++ b/parser/html/nsHtml5ElementName.h @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -65,7 +66,7 @@ class nsHtml5ElementName PRBool special; PRBool scoping; PRBool fosterParenting; - static nsHtml5ElementName* elementNameByBuffer(jArray buf, PRInt32 offset, PRInt32 length); + static nsHtml5ElementName* elementNameByBuffer(jArray buf, PRInt32 offset, PRInt32 length, nsHtml5AtomTable* interner); private: static PRInt32 bufToHash(jArray buf, PRInt32 len); nsHtml5ElementName(nsIAtom* name, nsIAtom* camelCaseName, PRInt32 group, PRBool special, PRBool scoping, PRBool fosterParenting); diff --git a/parser/html/nsHtml5HtmlAttributes.cpp b/parser/html/nsHtml5HtmlAttributes.cpp index 58a38aaef65..45800c6c91e 100644 --- a/parser/html/nsHtml5HtmlAttributes.cpp +++ b/parser/html/nsHtml5HtmlAttributes.cpp @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" diff --git a/parser/html/nsHtml5HtmlAttributes.h b/parser/html/nsHtml5HtmlAttributes.h index 8af1dcf5570..9ab6b0f441c 100644 --- a/parser/html/nsHtml5HtmlAttributes.h +++ b/parser/html/nsHtml5HtmlAttributes.h @@ -31,6 +31,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" diff --git a/parser/html/nsHtml5MetaScanner.cpp b/parser/html/nsHtml5MetaScanner.cpp index 4fcc795bcea..3ef50c396e6 100644 --- a/parser/html/nsHtml5MetaScanner.cpp +++ b/parser/html/nsHtml5MetaScanner.cpp @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" diff --git a/parser/html/nsHtml5MetaScanner.h b/parser/html/nsHtml5MetaScanner.h index 3ca27c5831d..765e34b3be5 100644 --- a/parser/html/nsHtml5MetaScanner.h +++ b/parser/html/nsHtml5MetaScanner.h @@ -31,6 +31,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" diff --git a/parser/html/nsHtml5Parser.cpp b/parser/html/nsHtml5Parser.cpp index 107f6f7fefa..9bff4e12ed8 100644 --- a/parser/html/nsHtml5Parser.cpp +++ b/parser/html/nsHtml5Parser.cpp @@ -59,6 +59,7 @@ #include "nsHtml5UTF16Buffer.h" #include "nsHtml5TreeBuilder.h" #include "nsHtml5Parser.h" +#include "nsHtml5AtomTable.h" //-------------- Begin ParseContinue Event Definition ------------------------ /* @@ -96,13 +97,11 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5Parser) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5Parser) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mExecutor, nsIContentSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mStreamParser, nsIStreamListener) - tmp->mTreeBuilder->DoTraverse(cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5Parser) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mExecutor) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStreamParser) - tmp->mTreeBuilder->DoUnlink(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END nsHtml5Parser::nsHtml5Parser() @@ -111,8 +110,11 @@ nsHtml5Parser::nsHtml5Parser() , mExecutor(new nsHtml5TreeOpExecutor()) , mTreeBuilder(new nsHtml5TreeBuilder(mExecutor)) , mTokenizer(new nsHtml5Tokenizer(mTreeBuilder)) + , mAtomTable(new nsHtml5AtomTable()) { mExecutor->SetTreeBuilder(mTreeBuilder); + mAtomTable->Init(); // we aren't checking for OOM anyway... + mTokenizer->setInterner(mAtomTable); // There's a zeroing operator new for everything else } @@ -455,7 +457,10 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer, nsIURI* uri = doc->GetDocumentURI(); NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE); - Initialize(doc, uri, nsnull, nsnull); + nsCOMPtr container = doc->GetContainer(); + NS_ENSURE_TRUE(container, NS_ERROR_NOT_AVAILABLE); + + Initialize(doc, uri, container, nsnull); // Initialize() doesn't deal with base URI mExecutor->SetBaseUriFromDocument(); @@ -463,7 +468,8 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer, mExecutor->SetParser(this); mExecutor->SetNodeInfoManager(target->GetOwnerDoc()->NodeInfoManager()); - mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace, target, aQuirks); + nsIContent* weakTarget = target; + mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace, &weakTarget, aQuirks); mFragmentMode = PR_TRUE; NS_PRECONDITION(mExecutor->GetLifeCycle() == NOT_STARTED, "Tried to start parse without initializing the parser properly."); @@ -489,6 +495,7 @@ nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer, mExecutor->Flush(); mTokenizer->end(); mExecutor->DropParserAndPerfHint(); + mAtomTable->Clear(); return NS_OK; } @@ -518,6 +525,7 @@ nsHtml5Parser::Reset() mStreamParser = nsnull; mRootContextKey = nsnull; mContinueEvent = nsnull; // weak ref + mAtomTable->Clear(); // should be already cleared in the fragment case anyway // Portable parser objects while (mFirstBuffer->next) { nsHtml5UTF16Buffer* oldBuf = mFirstBuffer; diff --git a/parser/html/nsHtml5Parser.h b/parser/html/nsHtml5Parser.h index baf58fbbf4a..5a7fb4220d4 100644 --- a/parser/html/nsHtml5Parser.h +++ b/parser/html/nsHtml5Parser.h @@ -60,6 +60,7 @@ #include "nsHtml5UTF16Buffer.h" #include "nsHtml5TreeOpExecutor.h" #include "nsHtml5StreamParser.h" +#include "nsHtml5AtomTable.h" class nsHtml5Parser : public nsIParser { public: @@ -338,7 +339,7 @@ class nsHtml5Parser : public nsIParser { /** * The tree operation executor */ - nsRefPtr mExecutor; + nsRefPtr mExecutor; /** * The HTML5 tree builder @@ -353,7 +354,12 @@ class nsHtml5Parser : public nsIParser { /** * The stream parser. */ - nsRefPtr mStreamParser; + nsRefPtr mStreamParser; + + /** + * The scoped atom service + */ + const nsAutoPtr mAtomTable; }; #endif diff --git a/parser/html/nsHtml5Portability.cpp b/parser/html/nsHtml5Portability.cpp index 0e979227408..dfb85bb1afa 100644 --- a/parser/html/nsHtml5Portability.cpp +++ b/parser/html/nsHtml5Portability.cpp @@ -42,10 +42,11 @@ #include "nsHtml5Portability.h" nsIAtom* -nsHtml5Portability::newLocalNameFromBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length) +nsHtml5Portability::newLocalNameFromBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length, nsHtml5AtomTable* interner) { NS_ASSERTION(!offset, "The offset should always be zero here."); - return NS_NewAtom(nsDependentSubstring(buf, buf + length)); + NS_ASSERTION(interner, "Didn't get an atom service."); + return interner->GetAtom(nsDependentSubstring(buf, buf + length)); } nsString* @@ -101,28 +102,28 @@ nsHtml5Portability::releaseString(nsString* str) delete str; } +// XXX useless code void nsHtml5Portability::retainLocal(nsIAtom* local) { - NS_IF_ADDREF(local); } +// XXX useless code void nsHtml5Portability::releaseLocal(nsIAtom* local) { - NS_IF_RELEASE(local); } +// XXX Useless code void -nsHtml5Portability::retainElement(nsIContent* element) +nsHtml5Portability::retainElement(nsIContent** element) { - NS_IF_ADDREF(element); } +// XXX Useless code void -nsHtml5Portability::releaseElement(nsIContent* element) +nsHtml5Portability::releaseElement(nsIContent** element) { - NS_IF_RELEASE(element); } PRBool diff --git a/parser/html/nsHtml5Portability.h b/parser/html/nsHtml5Portability.h index 671e61ba885..09424087056 100644 --- a/parser/html/nsHtml5Portability.h +++ b/parser/html/nsHtml5Portability.h @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -58,7 +59,7 @@ class nsHtml5StateSnapshot; class nsHtml5Portability { public: - static nsIAtom* newLocalNameFromBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length); + static nsIAtom* newLocalNameFromBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length, nsHtml5AtomTable* interner); static nsString* newStringFromBuffer(PRUnichar* buf, PRInt32 offset, PRInt32 length); static nsString* newEmptyString(); static nsString* newStringFromLiteral(const char* literal); @@ -68,8 +69,8 @@ class nsHtml5Portability static void releaseString(nsString* str); static void retainLocal(nsIAtom* local); static void releaseLocal(nsIAtom* local); - static void retainElement(nsIContent* elt); - static void releaseElement(nsIContent* elt); + static void retainElement(nsIContent** elt); + static void releaseElement(nsIContent** elt); static PRBool localEqualsBuffer(nsIAtom* local, PRUnichar* buf, PRInt32 offset, PRInt32 length); static PRBool lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(const char* lowerCaseLiteral, nsString* string); static PRBool lowerCaseLiteralEqualsIgnoreAsciiCaseString(const char* lowerCaseLiteral, nsString* string); diff --git a/parser/html/nsHtml5StackNode.cpp b/parser/html/nsHtml5StackNode.cpp index cc566021a9d..6c29c78e58d 100644 --- a/parser/html/nsHtml5StackNode.cpp +++ b/parser/html/nsHtml5StackNode.cpp @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -56,7 +57,7 @@ #include "nsHtml5StackNode.h" -nsHtml5StackNode::nsHtml5StackNode(PRInt32 group, PRInt32 ns, nsIAtom* name, nsIContent* node, PRBool scoping, PRBool special, PRBool fosterParenting, nsIAtom* popName, nsHtml5HtmlAttributes* attributes) +nsHtml5StackNode::nsHtml5StackNode(PRInt32 group, PRInt32 ns, nsIAtom* name, nsIContent** node, PRBool scoping, PRBool special, PRBool fosterParenting, nsIAtom* popName, nsHtml5HtmlAttributes* attributes) : group(group), name(name), popName(popName), @@ -75,7 +76,7 @@ nsHtml5StackNode::nsHtml5StackNode(PRInt32 group, PRInt32 ns, nsIAtom* name, nsI } -nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node) +nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node) : group(elementName->group), name(elementName->name), popName(elementName->name), @@ -94,7 +95,7 @@ nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, } -nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node, nsHtml5HtmlAttributes* attributes) +nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node, nsHtml5HtmlAttributes* attributes) : group(elementName->group), name(elementName->name), popName(elementName->name), @@ -113,7 +114,7 @@ nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, } -nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node, nsIAtom* popName) +nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName) : group(elementName->group), name(elementName->name), popName(popName), @@ -132,7 +133,7 @@ nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, } -nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node, nsIAtom* popName, PRBool scoping) +nsHtml5StackNode::nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName, PRBool scoping) : group(elementName->group), name(elementName->name), popName(popName), @@ -192,5 +193,3 @@ nsHtml5StackNode::releaseStatics() } -#include "nsHtml5StackNodeCppSupplement.h" - diff --git a/parser/html/nsHtml5StackNode.h b/parser/html/nsHtml5StackNode.h index 31d517b1bc2..9be20fd9b13 100644 --- a/parser/html/nsHtml5StackNode.h +++ b/parser/html/nsHtml5StackNode.h @@ -31,6 +31,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -64,7 +65,7 @@ class nsHtml5StackNode nsIAtom* name; nsIAtom* popName; PRInt32 ns; - nsIContent* node; + nsIContent** node; PRBool scoping; PRBool special; PRBool fosterParenting; @@ -72,19 +73,17 @@ class nsHtml5StackNode private: PRInt32 refcount; public: - nsHtml5StackNode(PRInt32 group, PRInt32 ns, nsIAtom* name, nsIContent* node, PRBool scoping, PRBool special, PRBool fosterParenting, nsIAtom* popName, nsHtml5HtmlAttributes* attributes); - nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node); - nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node, nsHtml5HtmlAttributes* attributes); - nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node, nsIAtom* popName); - nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent* node, nsIAtom* popName, PRBool scoping); + nsHtml5StackNode(PRInt32 group, PRInt32 ns, nsIAtom* name, nsIContent** node, PRBool scoping, PRBool special, PRBool fosterParenting, nsIAtom* popName, nsHtml5HtmlAttributes* attributes); + nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node); + nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node, nsHtml5HtmlAttributes* attributes); + nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName); + nsHtml5StackNode(PRInt32 ns, nsHtml5ElementName* elementName, nsIContent** node, nsIAtom* popName, PRBool scoping); ~nsHtml5StackNode(); void dropAttributes(); void retain(); void release(); static void initializeStatics(); static void releaseStatics(); - -#include "nsHtml5StackNodeHSupplement.h" }; #ifdef nsHtml5StackNode_cpp__ diff --git a/parser/html/nsHtml5StackNodeCppSupplement.h b/parser/html/nsHtml5StackNodeCppSupplement.h deleted file mode 100644 index cd003de6848..00000000000 --- a/parser/html/nsHtml5StackNodeCppSupplement.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ***** 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 HTML Parser C++ Translator code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Henri Sivonen - * - * Alternatively, the contents of this file may be used under the terms of - * either 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 ***** */ - -NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5StackNode) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsHtml5StackNode) - NS_IF_RELEASE(tmp->node); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMETHODIMP -nsHtml5StackNode::NS_CYCLE_COLLECTION_INNERCLASS::Traverse - (void *p, nsCycleCollectionTraversalCallback &cb) -{ - nsHtml5StackNode *tmp = static_cast(p); - NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsHtml5StackNode, tmp->refcount) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(node); - return NS_OK; -} - -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsHtml5StackNode, retain) - -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsHtml5StackNode, release) diff --git a/parser/html/nsHtml5StackNodeHSupplement.h b/parser/html/nsHtml5StackNodeHSupplement.h deleted file mode 100644 index a39ed7e09fd..00000000000 --- a/parser/html/nsHtml5StackNodeHSupplement.h +++ /dev/null @@ -1,38 +0,0 @@ -/* ***** 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 HTML Parser C++ Translator code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Henri Sivonen - * - * Alternatively, the contents of this file may be used under the terms of - * either 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 ***** */ - -NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsHtml5StackNode) diff --git a/parser/html/nsHtml5StateSnapshot.cpp b/parser/html/nsHtml5StateSnapshot.cpp index 639a69bbe51..4701738ee34 100644 --- a/parser/html/nsHtml5StateSnapshot.cpp +++ b/parser/html/nsHtml5StateSnapshot.cpp @@ -29,6 +29,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -55,7 +56,7 @@ #include "nsHtml5StateSnapshot.h" -nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray stack, jArray listOfActiveFormattingElements, nsIContent* formPointer) +nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray stack, jArray listOfActiveFormattingElements, nsIContent** formPointer) : stack(stack), listOfActiveFormattingElements(listOfActiveFormattingElements), formPointer(formPointer) diff --git a/parser/html/nsHtml5StateSnapshot.h b/parser/html/nsHtml5StateSnapshot.h index 2a6322defdd..1f56487a1cc 100644 --- a/parser/html/nsHtml5StateSnapshot.h +++ b/parser/html/nsHtml5StateSnapshot.h @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -58,10 +59,10 @@ class nsHtml5Portability; class nsHtml5StateSnapshot { public: - nsHtml5StateSnapshot(jArray stack, jArray listOfActiveFormattingElements, nsIContent* formPointer); + nsHtml5StateSnapshot(jArray stack, jArray listOfActiveFormattingElements, nsIContent** formPointer); jArray stack; jArray listOfActiveFormattingElements; - nsIContent* formPointer; + nsIContent** formPointer; ~nsHtml5StateSnapshot(); static void initializeStatics(); static void releaseStatics(); diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp index 37a1e37ae3c..156e669917d 100644 --- a/parser/html/nsHtml5StreamParser.cpp +++ b/parser/html/nsHtml5StreamParser.cpp @@ -581,7 +581,10 @@ nsHtml5StreamParser::ParseUntilSuspend() return; // no more data for now but expecting more case STREAM_ENDING: mDone = PR_TRUE; - mExecutor->DidBuildModel(PR_FALSE); + { + nsRefPtr kungFuDeathGrip(this); + mExecutor->DidBuildModel(PR_FALSE); + } return; // no more data and not expecting more default: NS_NOTREACHED("It should be impossible to reach this."); diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 2f3db47aed4..96a655d193d 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -32,6 +32,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -72,11 +73,20 @@ nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler) : tokenHandler(tokenHandler), encodingDeclarationHandler(nsnull), bmpChar(jArray(1)), - astralChar(jArray(2)) + astralChar(jArray(2)), + attributes(nsnull), + tagName(nsnull), + attributeName(nsnull) { MOZ_COUNT_CTOR(nsHtml5Tokenizer); } +void +nsHtml5Tokenizer::setInterner(nsHtml5AtomTable* interner) +{ + this->interner = interner; +} + void nsHtml5Tokenizer::initLocation(nsString* newPublicId, nsString* newSystemId) { @@ -100,7 +110,7 @@ nsHtml5Tokenizer::setContentModelFlag(PRInt32 contentModelFlag, nsIAtom* content return; } jArray asArray = nsHtml5Portability::newCharArrayFromLocal(contentModelElement); - this->contentModelElement = nsHtml5ElementName::elementNameByBuffer(asArray, 0, asArray.length); + this->contentModelElement = nsHtml5ElementName::elementNameByBuffer(asArray, 0, asArray.length, interner); asArray.release(); contentModelElementToArray(); } @@ -229,7 +239,7 @@ nsHtml5Tokenizer::strBufToString() void nsHtml5Tokenizer::strBufToDoctypeName() { - doctypeName = nsHtml5Portability::newLocalNameFromBuffer(strBuf, 0, strBufLen); + doctypeName = nsHtml5Portability::newLocalNameFromBuffer(strBuf, 0, strBufLen, interner); } void @@ -342,13 +352,13 @@ nsHtml5Tokenizer::flushChars(PRUnichar* buf, PRInt32 pos) void nsHtml5Tokenizer::resetAttributes() { - attributes->clear(0); + attributes = nsnull; } void nsHtml5Tokenizer::strBufToElementNameString() { - tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen); + tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen, interner); } PRInt32 @@ -364,6 +374,8 @@ nsHtml5Tokenizer::emitCurrentTagToken(PRBool selfClosing, PRInt32 pos) } else { tokenHandler->startTag(tagName, attrs, selfClosing); } + tagName->release(); + tagName = nsnull; resetAttributes(); return stateSave; } @@ -371,7 +383,10 @@ nsHtml5Tokenizer::emitCurrentTagToken(PRBool selfClosing, PRInt32 pos) void nsHtml5Tokenizer::attributeNameComplete() { - attributeName = nsHtml5AttributeName::nameByBuffer(strBuf, 0, strBufLen); + attributeName = nsHtml5AttributeName::nameByBuffer(strBuf, 0, strBufLen, interner); + if (!attributes) { + attributes = new nsHtml5HtmlAttributes(0); + } if (attributes->contains(attributeName)) { attributeName->release(); @@ -426,7 +441,18 @@ nsHtml5Tokenizer::start() value = 0; seenDigits = PR_FALSE; shouldSuspend = PR_FALSE; - attributes = new nsHtml5HtmlAttributes(0); + if (!!tagName) { + tagName->release(); + tagName = nsnull; + } + if (!!attributeName) { + attributeName->release(); + attributeName = nsnull; + } + if (!!attributes) { + delete attributes; + attributes = nsnull; + } } PRBool @@ -3282,8 +3308,14 @@ nsHtml5Tokenizer::end() systemIdentifier = nsnull; publicIdentifier = nsnull; doctypeName = nsnull; - tagName = nsnull; - attributeName = nsnull; + if (!!tagName) { + tagName->release(); + tagName = nsnull; + } + if (!!attributeName) { + attributeName->release(); + attributeName = nsnull; + } tokenHandler->endTokenization(); if (!!attributes) { attributes->clear(0); diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h index 32b566f8710..2bacfb2c7d0 100644 --- a/parser/html/nsHtml5Tokenizer.h +++ b/parser/html/nsHtml5Tokenizer.h @@ -33,6 +33,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" @@ -134,8 +135,10 @@ class nsHtml5Tokenizer PRBool confident; private: PRInt32 line; + nsHtml5AtomTable* interner; public: nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler); + void setInterner(nsHtml5AtomTable* interner); void initLocation(nsString* newPublicId, nsString* newSystemId); ~nsHtml5Tokenizer(); void setContentModelFlag(PRInt32 contentModelFlag, nsIAtom* contentModelElement); diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index 9c0c82c63d8..eeeae554603 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -82,7 +82,7 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) charBufferLen = 0; charBuffer = jArray(1024); if (fragment) { - nsIContent* elt; + nsIContent** elt; if (!!contextNode) { elt = contextNode; nsHtml5Portability::retainElement(elt); @@ -618,6 +618,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } else { appendToCurrentNodeAndPushElementMayFosterCamelCase(currNs, elementName, attributes); } + attributes = nsnull; goto starttagloop_end; } else { attributes->adjustForMath(); @@ -627,6 +628,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } else { appendToCurrentNodeAndPushElementMayFosterNoScoping(currNs, elementName, attributes); } + attributes = nsnull; goto starttagloop_end; } } @@ -641,6 +643,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu clearStackBackTo(findLastInTableScopeOrRootTbodyTheadTfoot()); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_ROW; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_TD_OR_TH: { @@ -676,6 +679,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_CELL; insertMarker(); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_CAPTION: @@ -706,12 +710,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu insertMarker(); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_CAPTION; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_COLGROUP: { clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE)); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_COL: { @@ -724,6 +730,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE)); appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_TR: @@ -756,6 +763,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_INPUT: { @@ -764,6 +772,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } appendVoidElementToCurrent(kNameSpaceID_XHTML, name, attributes, formPointer); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } default: { @@ -839,6 +848,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_FRAMESET; + attributes = nsnull; goto starttagloop_end; } } else { @@ -877,6 +887,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BASE: @@ -891,6 +902,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_BODY: { addAttributesToBody(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_P: @@ -899,6 +911,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_DIALOG_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION: { implicitlyCloseP(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: { @@ -908,17 +921,20 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu pop(); } appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_FIELDSET: { implicitlyCloseP(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_PRE_OR_LISTING: { implicitlyCloseP(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); needToDropLF = PR_TRUE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_FORM: { @@ -928,6 +944,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } else { implicitlyCloseP(); appendToCurrentNodeAndPushFormElementMayFoster(attributes); + attributes = nsnull; goto starttagloop_end; } } @@ -952,12 +969,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } implicitlyCloseP(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_PLAINTEXT: { implicitlyCloseP(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_PLAINTEXT, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_A: { @@ -976,12 +995,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushFormattingElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: case NS_HTML5TREE_BUILDER_FONT: { reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushFormattingElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_NOBR: { @@ -991,6 +1012,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu adoptionAgencyEndTag(nsHtml5Atoms::nobr); } appendToCurrentNodeAndPushFormattingElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BUTTON: { @@ -1010,6 +1032,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer); insertMarker(); + attributes = nsnull; goto starttagloop_end; } } @@ -1017,12 +1040,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer); insertMarker(); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET: { reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); insertMarker(); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_XMP: { @@ -1031,6 +1056,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_TABLE: { @@ -1039,6 +1065,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_TABLE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BR: @@ -1049,12 +1076,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE: { appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_HR: { implicitlyCloseP(); appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_IMAGE: { @@ -1067,6 +1096,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu reconstructTheActiveFormattingElements(); appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, name, attributes, formPointer); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_ISINDEX: { @@ -1111,6 +1141,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu selfClosing = PR_FALSE; delete formAttrs; delete inputAttributes; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_TEXTAREA: { @@ -1119,12 +1150,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; needToDropLF = PR_TRUE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_NOSCRIPT: { if (!scriptingEnabled) { reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } else { } @@ -1136,6 +1169,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_SELECT: { @@ -1156,6 +1190,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu break; } } + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_OPTGROUP: @@ -1185,6 +1220,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_RT_OR_RP: { @@ -1199,6 +1235,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu } } appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_MATH: { @@ -1211,6 +1248,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_MathML, elementName, attributes); foreignFlag = NS_HTML5TREE_BUILDER_IN_FOREIGN; } + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_SVG: { @@ -1223,6 +1261,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_SVG, elementName, attributes); foreignFlag = NS_HTML5TREE_BUILDER_IN_FOREIGN; } + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_CAPTION: @@ -1240,11 +1279,13 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_OUTPUT_OR_LABEL: { reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer); + attributes = nsnull; goto starttagloop_end; } default: { reconstructTheActiveFormattingElements(); appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } } @@ -1257,12 +1298,14 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BASE: case NS_HTML5TREE_BUILDER_COMMAND_OR_EVENT_SOURCE: { appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_META: @@ -1274,6 +1317,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RCDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_NOSCRIPT: { @@ -1286,6 +1330,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT; } + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_SCRIPT: @@ -1295,6 +1340,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_HEAD: { @@ -1315,17 +1361,20 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_LINK: { appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_META: { checkMetaCharset(attributes); appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_STYLE: @@ -1334,6 +1383,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_HEAD: { @@ -1357,11 +1407,13 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_COL: { appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } default: { @@ -1396,6 +1448,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_OPTION: { @@ -1403,6 +1456,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu pop(); } appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_OPTGROUP: { @@ -1413,6 +1467,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu pop(); } appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_SELECT: { @@ -1441,6 +1496,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } default: { @@ -1454,6 +1510,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } default: { @@ -1467,11 +1524,13 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu switch(group) { case NS_HTML5TREE_BUILDER_FRAMESET: { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_FRAME: { appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; + attributes = nsnull; goto starttagloop_end; } default: @@ -1483,6 +1542,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_NOFRAMES: { @@ -1490,6 +1550,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } default: { @@ -1512,6 +1573,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendHtmlElementToDocumentAndPush(attributes); } mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD; + attributes = nsnull; goto starttagloop_end; } default: { @@ -1526,11 +1588,13 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_HEAD: { appendToCurrentNodeAndPushHeadElement(attributes); mode = NS_HTML5TREE_BUILDER_IN_HEAD; + attributes = nsnull; goto starttagloop_end; } default: { @@ -1545,6 +1609,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BODY: { @@ -1554,11 +1619,13 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendToCurrentNodeAndPushBodyElement(attributes); } mode = NS_HTML5TREE_BUILDER_FRAMESET_OK; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_FRAMESET: { appendToCurrentNodeAndPushElement(kNameSpaceID_XHTML, elementName, attributes); mode = NS_HTML5TREE_BUILDER_IN_FRAMESET; + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_BASE: { @@ -1567,6 +1634,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; pop(); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_LINK: { @@ -1575,6 +1643,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; pop(); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_META: { @@ -1584,6 +1653,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu appendVoidElementToCurrentMayFoster(kNameSpaceID_XHTML, elementName, attributes); selfClosing = PR_FALSE; pop(); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_SCRIPT: { @@ -1593,6 +1663,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_STYLE: @@ -1603,6 +1674,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_TITLE: { @@ -1612,6 +1684,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_RCDATA, elementName); + attributes = nsnull; goto starttagloop_end; } case NS_HTML5TREE_BUILDER_HEAD: { @@ -1630,6 +1703,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_HTML: { addAttributesToHtml(attributes); + attributes = nsnull; goto starttagloop_end; } default: { @@ -1647,6 +1721,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu originalMode = mode; mode = NS_HTML5TREE_BUILDER_IN_CDATA_RCDATA; tokenizer->setContentModelFlag(NS_HTML5TOKENIZER_CDATA, elementName); + attributes = nsnull; goto starttagloop_end; } default: { @@ -1666,6 +1741,9 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu if (selfClosing) { } + if (attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + delete attributes; + } } nsString* @@ -3058,7 +3136,7 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name) } - nsIContent* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes()); + nsIContent** clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes()); nsHtml5StackNode* newNode = new nsHtml5StackNode(node->group, node->ns, node->name, clone, node->scoping, node->special, node->fosterParenting, node->popName, node->attributes); node->dropAttributes(); stack[nodePos] = newNode; @@ -3080,7 +3158,7 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name) detachFromParent(lastNode->node); appendElement(lastNode->node, commonAncestor->node); } - nsIContent* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes()); + nsIContent** clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes()); nsHtml5StackNode* formattingClone = new nsHtml5StackNode(formattingElt->group, formattingElt->ns, formattingElt->name, clone, formattingElt->scoping, formattingElt->special, formattingElt->fosterParenting, formattingElt->popName, formattingElt->attributes); formattingElt->dropAttributes(); appendChildrenToNewParent(furthestBlock->node, clone); @@ -3227,7 +3305,7 @@ nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() while (entryPos < listPtr) { entryPos++; nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos]; - nsIContent* clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes()); + nsIContent** clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes()); nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->group, entry->ns, entry->name, clone, entry->scoping, entry->special, entry->fosterParenting, entry->popName, entry->attributes); entry->dropAttributes(); nsHtml5StackNode* currentNode = stack[currentPtr]; @@ -3244,11 +3322,11 @@ nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() } void -nsHtml5TreeBuilder::insertIntoFosterParent(nsIContent* child) +nsHtml5TreeBuilder::insertIntoFosterParent(nsIContent** child) { PRInt32 eltPos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE); nsHtml5StackNode* node = stack[eltPos]; - nsIContent* elt = node->node; + nsIContent** elt = node->node; if (!eltPos) { appendElement(child, elt); return; @@ -3293,7 +3371,7 @@ nsHtml5TreeBuilder::popOnEof() void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes) { - nsIContent* elt = createHtmlElementSetAsRoot(attributes); + nsIContent** elt = createHtmlElementSetAsRoot(attributes); nsHtml5StackNode* node = new nsHtml5StackNode(kNameSpaceID_XHTML, nsHtml5ElementName::ELT_HTML, elt); push(node); nsHtml5Portability::releaseElement(elt); @@ -3309,7 +3387,7 @@ void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes) { flushCharacters(); - nsIContent* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes); + nsIContent** elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes); appendElement(elt, stack[currentPtr]->node); headPointer = elt; nsHtml5Portability::retainElement(headPointer); @@ -3334,7 +3412,7 @@ void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes) { flushCharacters(); - nsIContent* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes); + nsIContent** elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes); formPointer = elt; nsHtml5Portability::retainElement(formPointer); nsHtml5StackNode* current = stack[currentPtr]; @@ -3353,7 +3431,7 @@ void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { flushCharacters(); - nsIContent* elt = createElement(ns, elementName->name, attributes); + nsIContent** elt = createElement(ns, elementName->name, attributes); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3372,7 +3450,7 @@ void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { flushCharacters(); - nsIContent* elt = createElement(ns, elementName->name, attributes); + nsIContent** elt = createElement(ns, elementName->name, attributes); appendElement(elt, stack[currentPtr]->node); nsHtml5StackNode* node = new nsHtml5StackNode(ns, elementName, elt); push(node); @@ -3384,7 +3462,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtm { flushCharacters(); nsIAtom* popName = elementName->name; - nsIContent* elt = createElement(ns, popName, attributes); + nsIContent** elt = createElement(ns, popName, attributes); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3402,7 +3480,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterNoScoping(PRInt32 { flushCharacters(); nsIAtom* popName = elementName->name; - nsIContent* elt = createElement(ns, popName, attributes); + nsIContent** elt = createElement(ns, popName, attributes); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3420,7 +3498,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterCamelCase(PRInt32 { flushCharacters(); nsIAtom* popName = elementName->camelCaseName; - nsIContent* elt = createElement(ns, popName, attributes); + nsIContent** elt = createElement(ns, popName, attributes); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3434,10 +3512,10 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterCamelCase(PRInt32 } void -nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent* form) +nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent** form) { flushCharacters(); - nsIContent* elt = createElement(ns, elementName->name, attributes, form); + nsIContent** elt = createElement(ns, elementName->name, attributes, form); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3451,10 +3529,10 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtm } void -nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent* form) +nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form) { flushCharacters(); - nsIContent* elt = createElement(ns, name, attributes, form); + nsIContent** elt = createElement(ns, name, attributes, form); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3472,7 +3550,7 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(PRInt32 ns, nsHtml5Eleme { flushCharacters(); nsIAtom* popName = elementName->name; - nsIContent* elt = createElement(ns, popName, attributes); + nsIContent** elt = createElement(ns, popName, attributes); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3490,7 +3568,7 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterCamelCase(PRInt32 ns, nsH { flushCharacters(); nsIAtom* popName = elementName->camelCaseName; - nsIContent* elt = createElement(ns, popName, attributes); + nsIContent** elt = createElement(ns, popName, attributes); nsHtml5StackNode* current = stack[currentPtr]; if (current->fosterParenting) { @@ -3504,10 +3582,10 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterCamelCase(PRInt32 ns, nsH } void -nsHtml5TreeBuilder::appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent* form) +nsHtml5TreeBuilder::appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form) { flushCharacters(); - nsIContent* elt = createElement(ns, name, attributes, form); + nsIContent** elt = createElement(ns, name, attributes, form); nsHtml5StackNode* current = stack[currentPtr]; appendElement(elt, current->node); elementPushed(ns, name, elt); @@ -3536,7 +3614,7 @@ nsHtml5TreeBuilder::requestSuspension() } void -nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent* node, PRBool quirks) +nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent** node, PRBool quirks) { this->contextName = context; nsHtml5Portability::retainLocal(context); @@ -3547,7 +3625,7 @@ nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent* this->quirks = quirks; } -nsIContent* +nsIContent** nsHtml5TreeBuilder::currentNode() { return stack[currentPtr]->node; @@ -3580,7 +3658,7 @@ nsHtml5TreeBuilder::flushCharacters() PRInt32 eltPos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE); nsHtml5StackNode* node = stack[eltPos]; - nsIContent* elt = node->node; + nsIContent** elt = node->node; if (!eltPos) { appendCharacters(elt, charBuffer, 0, charBufferLen); charBufferLen = 0; diff --git a/parser/html/nsHtml5TreeBuilder.h b/parser/html/nsHtml5TreeBuilder.h index 03b164d4dca..cda5bc99af9 100644 --- a/parser/html/nsHtml5TreeBuilder.h +++ b/parser/html/nsHtml5TreeBuilder.h @@ -81,13 +81,13 @@ class nsHtml5TreeBuilder PRBool fragment; nsIAtom* contextName; PRInt32 contextNamespace; - nsIContent* contextNode; + nsIContent** contextNode; jArray stack; PRInt32 currentPtr; jArray listOfActiveFormattingElements; PRInt32 listPtr; - nsIContent* formPointer; - nsIContent* headPointer; + nsIContent** formPointer; + nsIContent** headPointer; protected: jArray charBuffer; PRInt32 charBufferLen; @@ -154,7 +154,7 @@ class nsHtml5TreeBuilder void addAttributesToHtml(nsHtml5HtmlAttributes* attributes); void pushHeadPointerOntoStack(); void reconstructTheActiveFormattingElements(); - void insertIntoFosterParent(nsIContent* child); + void insertIntoFosterParent(nsIContent** child); PRBool isInStack(nsHtml5StackNode* node); void pop(); void popOnEof(); @@ -169,38 +169,38 @@ class nsHtml5TreeBuilder void appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); void appendToCurrentNodeAndPushElementMayFosterNoScoping(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); void appendToCurrentNodeAndPushElementMayFosterCamelCase(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); - void appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent* form); - void appendVoidElementToCurrentMayFoster(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent* form); + void appendToCurrentNodeAndPushElementMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContent** form); + void appendVoidElementToCurrentMayFoster(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form); void appendVoidElementToCurrentMayFoster(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); void appendVoidElementToCurrentMayFosterCamelCase(PRInt32 ns, nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes); - void appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent* form); + void appendVoidElementToCurrent(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form); protected: void accumulateCharacters(PRUnichar* buf, PRInt32 start, PRInt32 length); void accumulateCharacter(PRUnichar c); void requestSuspension(); - nsIContent* createElement(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes); - nsIContent* createElement(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent* form); - nsIContent* createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes); - void detachFromParent(nsIContent* element); - PRBool hasChildren(nsIContent* element); - void appendElement(nsIContent* child, nsIContent* newParent); - void appendChildrenToNewParent(nsIContent* oldParent, nsIContent* newParent); - void insertFosterParentedChild(nsIContent* child, nsIContent* table, nsIContent* stackParent); - void insertFosterParentedCharacters(PRUnichar* buf, PRInt32 start, PRInt32 length, nsIContent* table, nsIContent* stackParent); - void appendCharacters(nsIContent* parent, PRUnichar* buf, PRInt32 start, PRInt32 length); - void appendComment(nsIContent* parent, PRUnichar* buf, PRInt32 start, PRInt32 length); + nsIContent** createElement(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes); + nsIContent** createElement(PRInt32 ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContent** form); + nsIContent** createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* attributes); + void detachFromParent(nsIContent** element); + PRBool hasChildren(nsIContent** element); + void appendElement(nsIContent** child, nsIContent** newParent); + void appendChildrenToNewParent(nsIContent** oldParent, nsIContent** newParent); + void insertFosterParentedChild(nsIContent** child, nsIContent** table, nsIContent** stackParent); + void insertFosterParentedCharacters(PRUnichar* buf, PRInt32 start, PRInt32 length, nsIContent** table, nsIContent** stackParent); + void appendCharacters(nsIContent** parent, PRUnichar* buf, PRInt32 start, PRInt32 length); + void appendComment(nsIContent** parent, PRUnichar* buf, PRInt32 start, PRInt32 length); void appendCommentToDocument(PRUnichar* buf, PRInt32 start, PRInt32 length); - void addAttributesToElement(nsIContent* element, nsHtml5HtmlAttributes* attributes); - void markMalformedIfScript(nsIContent* elt); + void addAttributesToElement(nsIContent** element, nsHtml5HtmlAttributes* attributes); + void markMalformedIfScript(nsIContent** elt); void start(PRBool fragment); void end(); void appendDoctypeToDocument(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier); - void elementPushed(PRInt32 ns, nsIAtom* name, nsIContent* node); - void elementPopped(PRInt32 ns, nsIAtom* name, nsIContent* node); + void elementPushed(PRInt32 ns, nsIAtom* name, nsIContent** node); + void elementPopped(PRInt32 ns, nsIAtom* name, nsIContent** node); public: - void setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent* node, PRBool quirks); + void setFragmentContext(nsIAtom* context, PRInt32 ns, nsIContent** node, PRBool quirks); protected: - nsIContent* currentNode(); + nsIContent** currentNode(); public: PRBool isScriptingEnabled(); void setScriptingEnabled(PRBool scriptingEnabled); diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 11373ec4924..afae73e6017 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -39,22 +39,13 @@ * ***** END LICENSE BLOCK ***** */ #include "nsContentErrors.h" -#include "nsContentCreatorFunctions.h" -#include "nsIDOMDocumentType.h" #include "nsIPresShell.h" #include "nsPresContext.h" #include "nsEvent.h" #include "nsGUIEvent.h" #include "nsEventDispatcher.h" #include "nsContentUtils.h" -#include "nsIDOMHTMLFormElement.h" -#include "nsIFormControl.h" #include "nsNodeUtils.h" -#include "nsIStyleSheetLinkingElement.h" -#include "nsTraceRefcnt.h" -#include "mozAutoDocUpdate.h" -#include "nsIScriptElement.h" -#include "nsIDTD.h" // this really should be autogenerated... jArray nsHtml5TreeBuilder::ISINDEX_PROMPT = jArray(); @@ -65,6 +56,8 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5TreeOpExecutor* aExec) , formPointer(nsnull) , headPointer(nsnull) , mExecutor(aExec) + , mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH]) + , mHandlesUsed(0) #ifdef DEBUG , mActive(PR_FALSE) #endif @@ -79,54 +72,32 @@ nsHtml5TreeBuilder::~nsHtml5TreeBuilder() mOpQueue.Clear(); } -nsIContent* +nsIContent** nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes) { - nsIContent* newContent; - nsCOMPtr nodeInfo = mExecutor->GetNodeInfoManager()->GetNodeInfo(aName, nsnull, aNamespace); - NS_ASSERTION(nodeInfo, "Got null nodeinfo."); - NS_NewElement(&newContent, nodeInfo->NamespaceID(), nodeInfo, PR_TRUE); - NS_ASSERTION(newContent, "Element creation created null pointer."); - PRInt32 len = aAttributes->getLength(); - for (PRInt32 i = 0; i < len; ++i) { - newContent->SetAttr(aAttributes->getURI(i), aAttributes->getLocalName(i), aAttributes->getPrefix(i), *(aAttributes->getValue(i)), PR_FALSE); - // XXX what to do with nsresult? - } - if (aNamespace != kNameSpaceID_MathML && (aName == nsHtml5Atoms::style || (aNamespace == kNameSpaceID_XHTML && aName == nsHtml5Atoms::link))) { - nsCOMPtr ssle(do_QueryInterface(newContent)); - if (ssle) { - ssle->InitStyleLinkElement(PR_FALSE); - ssle->SetEnableUpdates(PR_FALSE); -#if 0 - if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) { - ssle->SetLineNumber(aLineNumber); - } -#endif - } - } - return newContent; + nsIContent** content = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! + treeOp->Init(aNamespace, aName, aAttributes, content); + return content; } -nsIContent* -nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContent* aFormElement) +nsIContent** +nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5HtmlAttributes* aAttributes, nsIContent** aFormElement) { - nsIContent* content = createElement(aNamespace, aName, aAttributes); + nsIContent** content = createElement(aNamespace, aName, aAttributes); if (aFormElement) { - nsCOMPtr formControl(do_QueryInterface(content)); - NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl."); - nsCOMPtr formElement(do_QueryInterface(aFormElement)); - NS_ASSERTION(formElement, "The form element doesn't implement nsIDOMHTMLFormElement."); - if (formControl) { // avoid crashing on - formControl->SetForm(formElement); - } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! + treeOp->Init(eTreeOpSetFormElement, content, aFormElement); } return content; } -nsIContent* +nsIContent** nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttributes) { - nsIContent* content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes); + nsIContent** content = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::html, aAttributes); nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! treeOp->Init(eTreeOpAppendToDocument, content); @@ -134,7 +105,7 @@ nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes* aAttribute } void -nsHtml5TreeBuilder::detachFromParent(nsIContent* aElement) +nsHtml5TreeBuilder::detachFromParent(nsIContent** aElement) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! @@ -142,7 +113,7 @@ nsHtml5TreeBuilder::detachFromParent(nsIContent* aElement) } void -nsHtml5TreeBuilder::appendElement(nsIContent* aChild, nsIContent* aParent) +nsHtml5TreeBuilder::appendElement(nsIContent** aChild, nsIContent** aParent) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! @@ -150,7 +121,7 @@ nsHtml5TreeBuilder::appendElement(nsIContent* aChild, nsIContent* aParent) } void -nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContent* aOldParent, nsIContent* aNewParent) +nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContent** aOldParent, nsIContent** aNewParent) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! @@ -158,20 +129,24 @@ nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContent* aOldParent, nsIContent } void -nsHtml5TreeBuilder::insertFosterParentedCharacters(PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength, nsIContent* aTable, nsIContent* aStackParent) +nsHtml5TreeBuilder::insertFosterParentedCharacters(PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength, nsIContent** aTable, nsIContent** aStackParent) { - nsCOMPtr text; - NS_NewTextNode(getter_AddRefs(text), mExecutor->GetNodeInfoManager()); - // XXX nsresult and comment null check? - text->SetText(aBuffer + aStart, aLength, PR_FALSE); - // XXX nsresult + PRUnichar* bufferCopy = new PRUnichar[aLength]; + memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar)); + + nsIContent** text = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! + treeOp->Init(eTreeOpCreateTextNode, bufferCopy, aLength, text); + + treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! treeOp->Init(eTreeOpFosterParent, text, aStackParent, aTable); } void -nsHtml5TreeBuilder::insertFosterParentedChild(nsIContent* aChild, nsIContent* aTable, nsIContent* aStackParent) +nsHtml5TreeBuilder::insertFosterParentedChild(nsIContent** aChild, nsIContent** aTable, nsIContent** aStackParent) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! @@ -179,61 +154,73 @@ nsHtml5TreeBuilder::insertFosterParentedChild(nsIContent* aChild, nsIContent* aT } void -nsHtml5TreeBuilder::appendCharacters(nsIContent* aParent, PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength) +nsHtml5TreeBuilder::appendCharacters(nsIContent** aParent, PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength) { - nsCOMPtr text; - NS_NewTextNode(getter_AddRefs(text), mExecutor->GetNodeInfoManager()); - // XXX nsresult and comment null check? - text->SetText(aBuffer + aStart, aLength, PR_FALSE); - // XXX nsresult + PRUnichar* bufferCopy = new PRUnichar[aLength]; + memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar)); + + nsIContent** text = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! + treeOp->Init(eTreeOpCreateTextNode, bufferCopy, aLength, text); + + treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! treeOp->Init(text, aParent); } void -nsHtml5TreeBuilder::appendComment(nsIContent* aParent, PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength) +nsHtml5TreeBuilder::appendComment(nsIContent** aParent, PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength) { - nsCOMPtr comment; - NS_NewCommentNode(getter_AddRefs(comment), mExecutor->GetNodeInfoManager()); - // XXX nsresult and comment null check? - comment->SetText(aBuffer + aStart, aLength, PR_FALSE); - // XXX nsresult + PRUnichar* bufferCopy = new PRUnichar[aLength]; + memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar)); + + nsIContent** comment = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! + treeOp->Init(eTreeOpCreateComment, bufferCopy, aLength, comment); + + treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! treeOp->Init(comment, aParent); } void nsHtml5TreeBuilder::appendCommentToDocument(PRUnichar* aBuffer, PRInt32 aStart, PRInt32 aLength) { - nsCOMPtr comment; - NS_NewCommentNode(getter_AddRefs(comment), mExecutor->GetNodeInfoManager()); - // XXX nsresult and comment null check? - comment->SetText(aBuffer + aStart, aLength, PR_FALSE); - // XXX nsresult + PRUnichar* bufferCopy = new PRUnichar[aLength]; + memcpy(bufferCopy, aBuffer, aLength * sizeof(PRUnichar)); + + nsIContent** comment = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! + treeOp->Init(eTreeOpCreateComment, bufferCopy, aLength, comment); + + treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! treeOp->Init(eTreeOpAppendToDocument, comment); } void -nsHtml5TreeBuilder::addAttributesToElement(nsIContent* aElement, nsHtml5HtmlAttributes* aAttributes) +nsHtml5TreeBuilder::addAttributesToElement(nsIContent** aElement, nsHtml5HtmlAttributes* aAttributes) { - nsIContent* holder = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::div, aAttributes); + if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + return; + } nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! - treeOp->Init(eTreeOpAddAttributes, holder, aElement); + treeOp->Init(aElement, aAttributes); } void -nsHtml5TreeBuilder::markMalformedIfScript(nsIContent* elt) +nsHtml5TreeBuilder::markMalformedIfScript(nsIContent** elt) { - nsCOMPtr sele = do_QueryInterface(elt); - if (sele) { - // Make sure to serialize this script correctly, for nice round tripping. - sele->SetIsMalformed(); - } + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! + treeOp->Init(eTreeOpMarkMalformedIfScript, elt); } void @@ -267,32 +254,21 @@ nsHtml5TreeBuilder::end() void nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId, nsString* aSystemId) { - // Adapted from nsXMLContentSink - // Create a new doctype node - nsCOMPtr docType; - nsAutoString voidString; - voidString.SetIsVoid(PR_TRUE); - NS_NewDOMDocumentType(getter_AddRefs(docType), - mExecutor->GetNodeInfoManager(), - nsnull, - aName, - nsnull, - nsnull, - *aPublicId, - *aSystemId, - voidString); - NS_ASSERTION(docType, "Doctype creation failed."); - nsCOMPtr content = do_QueryInterface(docType); - NS_ASSERTION(content, "doctype isn't content?"); + nsIContent** content = AllocateContentHandle(); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); // XXX if null, OOM! + treeOp->Init(aName, *aPublicId, *aSystemId, content); + + treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! treeOp->Init(eTreeOpAppendToDocument, content); // nsXMLContentSink can flush here, but what's the point? // It can also interrupt here, but we can't. } void -nsHtml5TreeBuilder::elementPushed(PRInt32 aNamespace, nsIAtom* aName, nsIContent* aElement) +nsHtml5TreeBuilder::elementPushed(PRInt32 aNamespace, nsIAtom* aName, nsIContent** aElement) { NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!"); NS_ASSERTION(aName, "Element doesn't have local name!"); @@ -314,7 +290,7 @@ nsHtml5TreeBuilder::elementPushed(PRInt32 aNamespace, nsIAtom* aName, nsIContent } void -nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent* aElement) +nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent** aElement) { NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!"); NS_ASSERTION(aName, "Element doesn't have local name!"); @@ -326,7 +302,9 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent // we now have only SVG and HTML if (aName == nsHtml5Atoms::script) { requestSuspension(); - mExecutor->SetScriptElement(aElement); + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + // XXX if null, OOM! + treeOp->Init(eTreeOpRunScript, aElement); return; } if (aName == nsHtml5Atoms::title) { @@ -415,59 +393,25 @@ nsHtml5TreeBuilder::accumulateCharacters(PRUnichar* aBuf, PRInt32 aStart, PRInt3 charBufferLen = newFillLen; } -void -nsHtml5TreeBuilder::DoUnlink() +nsIContent** +nsHtml5TreeBuilder::AllocateContentHandle() { - nsHtml5TreeBuilder* tmp = this; - NS_IF_RELEASE(contextNode); - NS_IF_RELEASE(formPointer); - NS_IF_RELEASE(headPointer); - while (currentPtr > -1) { - stack[currentPtr]->release(); - currentPtr--; + if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) { + mOldHandles.AppendElement(mHandles.forget()); + mHandles = new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH]; + mHandlesUsed = 0; } - while (listPtr > -1) { - if (listOfActiveFormattingElements[listPtr]) { - listOfActiveFormattingElements[listPtr]->release(); - } - listPtr--; - } - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mOpQueue); + return &mHandles[mHandlesUsed++]; } -void -nsHtml5TreeBuilder::DoTraverse(nsCycleCollectionTraversalCallback &cb) +PRBool +nsHtml5TreeBuilder::HasScript() { - nsHtml5TreeBuilder* tmp = this; - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(contextNode); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(formPointer); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(headPointer); - if (stack) { - for (PRInt32 i = 0; i <= currentPtr; i++) { -#ifdef DEBUG_CC - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "stack[i]"); -#endif - cb.NoteNativeChild(stack[i], &NS_CYCLE_COLLECTION_NAME(nsHtml5StackNode)); - } - } - if (listOfActiveFormattingElements) { - for (PRInt32 i = 0; i <= listPtr; i++) { - if (listOfActiveFormattingElements[i]) { -#ifdef DEBUG_CC - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "listOfActiveFormattingElements[i]"); -#endif - cb.NoteNativeChild(listOfActiveFormattingElements[i], &NS_CYCLE_COLLECTION_NAME(nsHtml5StackNode)); - } - } - } - const nsHtml5TreeOperation* start = mOpQueue.Elements(); - const nsHtml5TreeOperation* end = start + mOpQueue.Length(); - for (nsHtml5TreeOperation* iter = (nsHtml5TreeOperation*)start; iter < end; ++iter) { -#ifdef DEBUG_CC - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mOpQueue[i]"); -#endif - iter->DoTraverse(cb); + PRUint32 len = mOpQueue.Length(); + if (!len) { + return PR_FALSE; } + return mOpQueue.ElementAt(len - 1).IsRunScript(); } // DocumentModeHandler diff --git a/parser/html/nsHtml5TreeBuilderHSupplement.h b/parser/html/nsHtml5TreeBuilderHSupplement.h index 1efcee97829..dba1c85ffc1 100644 --- a/parser/html/nsHtml5TreeBuilderHSupplement.h +++ b/parser/html/nsHtml5TreeBuilderHSupplement.h @@ -35,30 +35,33 @@ * * ***** END LICENSE BLOCK ***** */ +#define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512 + private: - nsTArray mOpQueue; - nsHtml5TreeOpExecutor* mExecutor; + nsTArray mOpQueue; + nsHtml5TreeOpExecutor* mExecutor; + nsAutoArrayPtr mHandles; + PRInt32 mHandlesUsed; + nsTArray > mOldHandles; #ifdef DEBUG - PRBool mActive; + PRBool mActive; #endif - public: - - nsHtml5TreeBuilder(nsHtml5TreeOpExecutor* aExec); - - ~nsHtml5TreeBuilder(); - - void DoUnlink(); - - void DoTraverse(nsCycleCollectionTraversalCallback &cb); - // DocumentModeHandler /** * Tree builder uses this to report quirkiness of the document */ void documentMode(nsHtml5DocumentMode m); + + nsIContent** AllocateContentHandle(); + public: + + nsHtml5TreeBuilder(nsHtml5TreeOpExecutor* aExec); + + ~nsHtml5TreeBuilder(); + inline PRUint32 GetOpQueueLength() { return mOpQueue.Length(); } @@ -70,3 +73,6 @@ inline void ReqSuspension() { requestSuspension(); } + + PRBool HasScript(); + diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 70fab4819eb..6eca15a5e96 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -74,19 +74,22 @@ NS_IMPL_ADDREF_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) NS_IMPL_RELEASE_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFlushTimer); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFlushTimer) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptElement) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mOwnedElements) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mOwnedNonElements) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHtml5TreeOpExecutor, nsContentSink) if (tmp->mFlushTimer) { tmp->mFlushTimer->Cancel(); } - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFlushTimer); + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFlushTimer) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptElement) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mOwnedElements) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mOwnedNonElements) NS_IMPL_CYCLE_COLLECTION_UNLINK_END - nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor() : mSuppressEOF(PR_FALSE) , mHasProcessedBase(PR_FALSE) @@ -504,12 +507,14 @@ nsHtml5TreeOpExecutor::MaybeSuspend() { void nsHtml5TreeOpExecutor::MaybeExecuteScript() { - if (mScriptElement) { - // mUninterruptibleDocWrite = PR_FALSE; - ExecuteScript(); - if (mStreamParser) { - mStreamParser->Suspend(); - } + if (!mTreeBuilder->HasScript()) { + return; + } + Flush(); // Let the doc update end before we start executing the script + NS_ASSERTION(mScriptElement, "No script to run"); + ExecuteScript(); + if (mStreamParser) { + mStreamParser->Suspend(); } } diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index d9209aac182..09c08c6d2e5 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -53,6 +53,7 @@ #include "nsITimer.h" #include "nsIScriptElement.h" #include "nsIParser.h" +#include "nsCOMArray.h" class nsHtml5TreeBuilder; class nsHtml5Tokenizer; @@ -112,6 +113,12 @@ class nsHtml5TreeOpExecutor : public nsIContentSink, nsTArray mElementsSeenInThisAppendBatch; nsTArray mPendingNotifications; nsHtml5StreamParser* mStreamParser; + nsCOMArray mOwnedElements; + + // This could be optimized away by introducing more tree ops so that + // non-elements wouldn't use the handle setup but the text node / comment + // / doctype operand would be remembered by the tree op executor. + nsCOMArray mOwnedNonElements; /** * The character encoding to which to switch in a late renavigation @@ -244,6 +251,10 @@ class nsHtml5TreeOpExecutor : public nsIContentSink, */ nsresult MaybePerformCharsetSwitch(); + inline void SetScriptElement(nsIContent* aScript) { + mScriptElement = aScript; + } + /** * Runs mScriptElement */ @@ -376,19 +387,20 @@ class nsHtml5TreeOpExecutor : public nsIContentSink, mScriptElement = nsnull; } } - - /** - * Request execution of the script element when the tokenizer returns - */ - void SetScriptElement(nsIContent* aScript) { - mScriptElement = aScript; - } - + void SetTreeBuilder(nsHtml5TreeBuilder* aBuilder) { mTreeBuilder = aBuilder; } void Reset(); + + inline void HoldElement(nsIContent* aContent) { + mOwnedElements.AppendObject(aContent); + } + + inline void HoldNonElement(nsIContent* aContent) { + mOwnedNonElements.AppendObject(aContent); + } private: diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index b9d70693d67..5d5476fa7cd 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -48,6 +48,15 @@ #include "nsBindingManager.h" #include "nsXBLBinding.h" #include "nsHtml5DocumentMode.h" +#include "nsHtml5HtmlAttributes.h" +#include "nsContentCreatorFunctions.h" +#include "nsIScriptElement.h" +#include "nsIDTD.h" +#include "nsTraceRefcnt.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIFormControl.h" +#include "nsIStyleSheetLinkingElement.h" +#include "nsIDOMDocumentType.h" nsHtml5TreeOperation::nsHtml5TreeOperation() : mOpCode(eTreeOpAppend) @@ -58,6 +67,23 @@ nsHtml5TreeOperation::nsHtml5TreeOperation() nsHtml5TreeOperation::~nsHtml5TreeOperation() { MOZ_COUNT_DTOR(nsHtml5TreeOperation); + switch(mOpCode) { + case eTreeOpAddAttributes: + delete mTwo.attributes; + break; + case eTreeOpCreateElement: + delete mThree.attributes; + break; + case eTreeOpCreateDoctype: + delete mTwo.stringPair; + break; + case eTreeOpCreateTextNode: + case eTreeOpCreateComment: + delete[] mTwo.unicharPtr; + break; + default: // keep the compiler happy + break; + } } nsresult @@ -66,15 +92,18 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) nsresult rv = NS_OK; switch(mOpCode) { case eTreeOpAppend: { - aBuilder->PostPendingAppendNotification(mParent, mNode); - rv = mParent->AppendChildTo(mNode, PR_FALSE); + nsIContent* node = *(mOne.node); + nsIContent* parent = *(mTwo.node); + aBuilder->PostPendingAppendNotification(parent, node); + rv = parent->AppendChildTo(node, PR_FALSE); return rv; } case eTreeOpDetach: { + nsIContent* node = *(mOne.node); aBuilder->FlushPendingAppendNotifications(); - nsIContent* parent = mNode->GetParent(); + nsIContent* parent = node->GetParent(); if (parent) { - PRUint32 pos = parent->IndexOf(mNode); + PRUint32 pos = parent->IndexOf(node); NS_ASSERTION((pos >= 0), "Element not found as child of its parent"); rv = parent->RemoveChildAt(pos, PR_TRUE, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); @@ -82,115 +111,248 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) return rv; } case eTreeOpAppendChildrenToNewParent: { + nsIContent* node = *(mOne.node); + nsIContent* parent = *(mTwo.node); aBuilder->FlushPendingAppendNotifications(); - PRUint32 childCount = mParent->GetChildCount(); + PRUint32 childCount = parent->GetChildCount(); PRBool didAppend = PR_FALSE; - while (mNode->GetChildCount()) { - nsCOMPtr child = mNode->GetChildAt(0); - rv = mNode->RemoveChildAt(0, PR_TRUE, PR_FALSE); + while (node->GetChildCount()) { + nsCOMPtr child = node->GetChildAt(0); + rv = node->RemoveChildAt(0, PR_TRUE, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); - rv = mParent->AppendChildTo(child, PR_FALSE); + rv = parent->AppendChildTo(child, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); didAppend = PR_TRUE; } if (didAppend) { - nsNodeUtils::ContentAppended(mParent, childCount); + nsNodeUtils::ContentAppended(parent, childCount); } return rv; } case eTreeOpFosterParent: { - nsIContent* parent = mTable->GetParent(); - if (parent && parent->IsNodeOfType(nsINode::eELEMENT)) { + nsIContent* node = *(mOne.node); + nsIContent* parent = *(mTwo.node); + nsIContent* table = *(mThree.node); + nsIContent* foster = table->GetParent(); + if (foster && foster->IsNodeOfType(nsINode::eELEMENT)) { aBuilder->FlushPendingAppendNotifications(); - PRUint32 pos = parent->IndexOf(mTable); - rv = parent->InsertChildAt(mNode, pos, PR_FALSE); + PRUint32 pos = foster->IndexOf(table); + rv = foster->InsertChildAt(node, pos, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); - nsNodeUtils::ContentInserted(parent, mNode, pos); + nsNodeUtils::ContentInserted(foster, node, pos); } else { - aBuilder->PostPendingAppendNotification(mParent, mNode); - rv = mParent->AppendChildTo(mNode, PR_FALSE); + aBuilder->PostPendingAppendNotification(parent, node); + rv = parent->AppendChildTo(node, PR_FALSE); } return rv; } case eTreeOpAppendToDocument: { + nsIContent* node = *(mOne.node); aBuilder->FlushPendingAppendNotifications(); nsIDocument* doc = aBuilder->GetDocument(); PRUint32 childCount = doc->GetChildCount(); - rv = doc->AppendChildTo(mNode, PR_FALSE); + rv = doc->AppendChildTo(node, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); - nsNodeUtils::ContentInserted(doc, mNode, childCount); + nsNodeUtils::ContentInserted(doc, node, childCount); return rv; } case eTreeOpAddAttributes: { - // mNode holds the new attributes and mParent is the target - nsIDocument* document = mParent->GetCurrentDoc(); - - PRUint32 len = mNode->GetAttrCount(); - for (PRUint32 i = 0; i < len; ++i) { - const nsAttrName* attrName = mNode->GetAttrNameAt(i); - nsIAtom* localName = attrName->LocalName(); - PRInt32 nsuri = attrName->NamespaceID(); - if (!mParent->HasAttr(nsuri, localName)) { - nsAutoString value; - mNode->GetAttr(nsuri, localName, value); - + nsIContent* node = *(mOne.node); + nsHtml5HtmlAttributes* attributes = mTwo.attributes; + + nsIDocument* document = node->GetCurrentDoc(); + + PRInt32 len = attributes->getLength(); + for (PRInt32 i = 0; i < len; ++i) { + // prefix doesn't need regetting. it is always null or a static atom + // local name is never null + nsCOMPtr localName = Reget(attributes->getLocalName(i)); + PRInt32 nsuri = attributes->getURI(i); + if (!node->HasAttr(nsuri, localName)) { + // the manual notification code is based on nsGenericElement - PRUint32 stateMask = PRUint32(mParent->IntrinsicState()); - nsNodeUtils::AttributeWillChange(mParent, + PRUint32 stateMask = PRUint32(node->IntrinsicState()); + nsNodeUtils::AttributeWillChange(node, nsuri, localName, static_cast(nsIDOMMutationEvent::ADDITION)); + + // prefix doesn't need regetting. it is always null or a static atom + // local name is never null + node->SetAttr(nsuri, localName, attributes->getPrefix(i), *(attributes->getValue(i)), PR_FALSE); + // XXX what to do with nsresult? - mParent->SetAttr(nsuri, localName, attrName->GetPrefix(), value, PR_FALSE); - - if (document || mParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) { - nsIDocument* ownerDoc = mParent->GetOwnerDoc(); + if (document || node->HasFlag(NODE_FORCE_XBL_BINDINGS)) { + nsIDocument* ownerDoc = node->GetOwnerDoc(); if (ownerDoc) { nsRefPtr binding = - ownerDoc->BindingManager()->GetBinding(mParent); + ownerDoc->BindingManager()->GetBinding(node); if (binding) { binding->AttributeChanged(localName, nsuri, PR_FALSE, PR_FALSE); } } } - stateMask = stateMask ^ PRUint32(mParent->IntrinsicState()); + stateMask ^= PRUint32(node->IntrinsicState()); if (stateMask && document) { MOZ_AUTO_DOC_UPDATE(document, UPDATE_CONTENT_STATE, PR_TRUE); - document->ContentStatesChanged(mParent, nsnull, stateMask); + document->ContentStatesChanged(node, nsnull, stateMask); } - nsNodeUtils::AttributeChanged(mParent, + nsNodeUtils::AttributeChanged(node, nsuri, localName, static_cast(nsIDOMMutationEvent::ADDITION), stateMask); } } + + return rv; + } + case eTreeOpCreateElement: { + nsIContent** target = mOne.node; + PRInt32 ns = mInt; + nsCOMPtr name = Reget(mTwo.atom); + nsHtml5HtmlAttributes* attributes = mThree.attributes; + + nsCOMPtr newContent; + nsCOMPtr nodeInfo = aBuilder->GetNodeInfoManager()->GetNodeInfo(name, nsnull, ns); + NS_ASSERTION(nodeInfo, "Got null nodeinfo."); + NS_NewElement(getter_AddRefs(newContent), nodeInfo->NamespaceID(), nodeInfo, PR_TRUE); + NS_ASSERTION(newContent, "Element creation created null pointer."); + + aBuilder->HoldElement(*target = newContent); + + if (!attributes) { + return rv; + } + + PRInt32 len = attributes->getLength(); + for (PRInt32 i = 0; i < len; ++i) { + // prefix doesn't need regetting. it is always null or a static atom + // local name is never null + nsCOMPtr localName = Reget(attributes->getLocalName(i)); + newContent->SetAttr(attributes->getURI(i), localName, attributes->getPrefix(i), *(attributes->getValue(i)), PR_FALSE); + // XXX what to do with nsresult? + } + if (ns != kNameSpaceID_MathML && (name == nsHtml5Atoms::style || (ns == kNameSpaceID_XHTML && name == nsHtml5Atoms::link))) { + nsCOMPtr ssle(do_QueryInterface(newContent)); + if (ssle) { + ssle->InitStyleLinkElement(PR_FALSE); + ssle->SetEnableUpdates(PR_FALSE); + } + } + return rv; + } + case eTreeOpSetFormElement: { + nsIContent* node = *(mOne.node); + nsIContent* parent = *(mTwo.node); + nsCOMPtr formControl(do_QueryInterface(node)); + NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl."); + nsCOMPtr formElement(do_QueryInterface(parent)); + NS_ASSERTION(formElement, "The form element doesn't implement nsIDOMHTMLFormElement."); + if (formControl) { // avoid crashing on + formControl->SetForm(formElement); + } + return rv; + } + case eTreeOpCreateTextNode: { + nsIContent** target = mOne.node; + PRUnichar* buffer = mTwo.unicharPtr; + PRInt32 length = mInt; + + nsCOMPtr text; + NS_NewTextNode(getter_AddRefs(text), aBuilder->GetNodeInfoManager()); + // XXX nsresult and comment null check? + text->SetText(buffer, length, PR_FALSE); + // XXX nsresult + + aBuilder->HoldNonElement(*target = text); + return rv; + } + case eTreeOpCreateComment: { + nsIContent** target = mOne.node; + PRUnichar* buffer = mTwo.unicharPtr; + PRInt32 length = mInt; + + nsCOMPtr comment; + NS_NewCommentNode(getter_AddRefs(comment), aBuilder->GetNodeInfoManager()); + // XXX nsresult and comment null check? + comment->SetText(buffer, length, PR_FALSE); + // XXX nsresult + + aBuilder->HoldNonElement(*target = comment); + return rv; + } + case eTreeOpCreateDoctype: { + nsCOMPtr name = Reget(mOne.atom); + nsHtml5TreeOperationStringPair* pair = mTwo.stringPair; + nsString publicId; + nsString systemId; + pair->Get(publicId, systemId); + nsIContent** target = mThree.node; + + // Adapted from nsXMLContentSink + // Create a new doctype node + nsCOMPtr docType; + nsAutoString voidString; + voidString.SetIsVoid(PR_TRUE); + NS_NewDOMDocumentType(getter_AddRefs(docType), + aBuilder->GetNodeInfoManager(), + nsnull, + name, + nsnull, + nsnull, + publicId, + systemId, + voidString); + NS_ASSERTION(docType, "Doctype creation failed."); + nsCOMPtr asContent = do_QueryInterface(docType); + aBuilder->HoldNonElement(*target = asContent); + return rv; + } + case eTreeOpRunScript: { + nsIContent* node = *(mOne.node); + aBuilder->SetScriptElement(node); return rv; } case eTreeOpDoneAddingChildren: { - mNode->DoneAddingChildren(aBuilder->HaveNotified(mNode)); + nsIContent* node = *(mOne.node); + node->DoneAddingChildren(aBuilder->HaveNotified(node)); return rv; } case eTreeOpDoneCreatingElement: { - mNode->DoneCreatingElement(); + nsIContent* node = *(mOne.node); + node->DoneCreatingElement(); return rv; } case eTreeOpUpdateStyleSheet: { - aBuilder->UpdateStyleSheet(mNode); + nsIContent* node = *(mOne.node); + aBuilder->UpdateStyleSheet(node); return rv; } case eTreeOpProcessBase: { - rv = aBuilder->ProcessBASETag(mNode); + nsIContent* node = *(mOne.node); + rv = aBuilder->ProcessBASETag(node); return rv; } case eTreeOpProcessMeta: { - rv = aBuilder->ProcessMETATag(mNode); + nsIContent* node = *(mOne.node); + rv = aBuilder->ProcessMETATag(node); return rv; } case eTreeOpProcessOfflineManifest: { - aBuilder->ProcessOfflineManifest(mNode); + nsIContent* node = *(mOne.node); + aBuilder->ProcessOfflineManifest(node); + return rv; + } + case eTreeOpMarkMalformedIfScript: { + nsIContent* node = *(mOne.node); + nsCOMPtr sele = do_QueryInterface(node); + if (sele) { + // Make sure to serialize this script correctly, for nice round tripping. + sele->SetIsMalformed(); + } return rv; } case eTreeOpStartLayout: { @@ -198,7 +360,7 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder) return rv; } case eTreeOpDocumentMode: { - aBuilder->DocumentMode(mMode); + aBuilder->DocumentMode(mOne.mode); return rv; } default: { diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h index 699a92ec46b..01cb2908e76 100644 --- a/parser/html/nsHtml5TreeOperation.h +++ b/parser/html/nsHtml5TreeOperation.h @@ -40,6 +40,7 @@ #include "nsIContent.h" #include "nsHtml5DocumentMode.h" +#include "nsHtml5HtmlAttributes.h" class nsHtml5TreeOpExecutor; @@ -52,16 +53,45 @@ enum eHtml5TreeOperation { eTreeOpAppendToDocument, eTreeOpAddAttributes, eTreeOpDocumentMode, + eTreeOpCreateElement, + eTreeOpSetFormElement, + eTreeOpCreateTextNode, + eTreeOpCreateComment, + eTreeOpCreateDoctype, // Gecko-specific on-pop ops + eTreeOpRunScript, eTreeOpDoneAddingChildren, eTreeOpDoneCreatingElement, eTreeOpUpdateStyleSheet, eTreeOpProcessBase, eTreeOpProcessMeta, eTreeOpProcessOfflineManifest, + eTreeOpMarkMalformedIfScript, eTreeOpStartLayout }; +class nsHtml5TreeOperationStringPair { + private: + nsString mPublicId; + nsString mSystemId; + public: + nsHtml5TreeOperationStringPair(const nsAString& aPublicId, + const nsAString& aSystemId) + : mPublicId(aPublicId) + , mSystemId(aSystemId) { + MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair); + } + + ~nsHtml5TreeOperationStringPair() { + MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair); + } + + inline void Get(nsAString& aPublicId, nsAString& aSystemId) { + aPublicId.Assign(mPublicId); + aSystemId.Assign(mSystemId); + } +}; + class nsHtml5TreeOperation { public: @@ -69,54 +99,113 @@ class nsHtml5TreeOperation { ~nsHtml5TreeOperation(); - inline void Init(nsIContent* aNode, nsIContent* aParent) { - mNode = aNode; - mParent = aParent; + inline void Init(nsIContent** aNode, nsIContent** aParent) { + mOne.node = aNode; + mTwo.node = aParent; } - inline void Init(eHtml5TreeOperation aOpCode, nsIContent* aNode) { + inline void Init(eHtml5TreeOperation aOpCode, nsIContent** aNode) { mOpCode = aOpCode; - mNode = aNode; + mOne.node = aNode; } inline void Init(eHtml5TreeOperation aOpCode, - nsIContent* aNode, - nsIContent* aParent) { + nsIContent** aNode, + nsIContent** aParent) { mOpCode = aOpCode; - mNode = aNode; - mParent = aParent; + mOne.node = aNode; + mTwo.node = aParent; } inline void Init(eHtml5TreeOperation aOpCode, - nsIContent* aNode, - nsIContent* aParent, - nsIContent* aTable) { + nsIContent** aNode, + nsIContent** aParent, + nsIContent** aTable) { mOpCode = aOpCode; - mNode = aNode; - mParent = aParent; - mTable = aTable; + mOne.node = aNode; + mTwo.node = aParent; + mThree.node = aTable; } inline void Init(nsHtml5DocumentMode aMode) { mOpCode = eTreeOpDocumentMode; - mMode = aMode; + mOne.mode = aMode; + } + + inline void Init(PRInt32 aNamespace, + nsIAtom* aName, + nsHtml5HtmlAttributes* aAttributes, + nsIContent** aTarget) { + mOpCode = eTreeOpCreateElement; + mInt = aNamespace; + mOne.node = aTarget; + mTwo.atom = aName; + if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) { + mThree.attributes = nsnull; + } else { + mThree.attributes = aAttributes; + } } - inline void DoTraverse(nsCycleCollectionTraversalCallback &cb) { - nsHtml5TreeOperation* tmp = this; - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNode); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent); - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTable); + inline void Init(eHtml5TreeOperation aOpCode, + PRUnichar* aBuffer, + PRInt32 aLength, + nsIContent** aTarget) { + mOpCode = aOpCode; + mOne.node = aTarget; + mTwo.unicharPtr = aBuffer; + mInt = aLength; + } + + inline void Init(nsIContent** aElement, + nsHtml5HtmlAttributes* aAttributes) { + mOpCode = eTreeOpAddAttributes; + mOne.node = aElement; + mTwo.attributes = aAttributes; + } + + inline void Init(nsIAtom* aName, + const nsAString& aPublicId, + const nsAString& aSystemId, nsIContent** aTarget) { + mOpCode = eTreeOpCreateDoctype; + mOne.atom = aName; + mTwo.stringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId); + mThree.node = aTarget; + } + + inline PRBool IsRunScript() { + return mOpCode == eTreeOpRunScript; } nsresult Perform(nsHtml5TreeOpExecutor* aBuilder); + inline already_AddRefed Reget(nsIAtom* aAtom) { + if (!aAtom || aAtom->IsStaticAtom()) { + return aAtom; + } + nsAutoString str; + aAtom->ToString(str); + return do_GetAtom(str); + } + private: + + // possible optimization: + // Make the queue take items the size of pointer and make the op code + // decide how many operands it dequeues after it. eHtml5TreeOperation mOpCode; - nsCOMPtr mNode; - nsCOMPtr mParent; - nsCOMPtr mTable; - nsHtml5DocumentMode mMode; // space-wasting temporary solution + union { + nsIContent** node; + nsIAtom* atom; + nsHtml5HtmlAttributes* attributes; + nsHtml5DocumentMode mode; + PRUnichar* unicharPtr; + nsHtml5TreeOperationStringPair* stringPair; + } mOne, mTwo, mThree; + PRInt32 mInt; // optimize this away later by using an end + // pointer instead of string length and distinct + // element creation opcodes for HTML, MathML and + // SVG. }; #endif // nsHtml5TreeOperation_h__ diff --git a/parser/html/nsHtml5UTF16Buffer.cpp b/parser/html/nsHtml5UTF16Buffer.cpp index 753a837ef85..24258f32f22 100644 --- a/parser/html/nsHtml5UTF16Buffer.cpp +++ b/parser/html/nsHtml5UTF16Buffer.cpp @@ -29,6 +29,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h" diff --git a/parser/html/nsHtml5UTF16Buffer.h b/parser/html/nsHtml5UTF16Buffer.h index 1ab9469967b..85929a9a24e 100644 --- a/parser/html/nsHtml5UTF16Buffer.h +++ b/parser/html/nsHtml5UTF16Buffer.h @@ -30,6 +30,7 @@ #include "prtypes.h" #include "nsIAtom.h" +#include "nsHtml5AtomTable.h" #include "nsString.h" #include "nsINameSpaceManager.h" #include "nsIContent.h"