From 0734590f00c55413ae03297da329244e946f2572 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Mon, 29 Jun 2009 00:44:22 +0200 Subject: [PATCH] Bug 487949 - Land HTML5 parser on trunk preffed off r=mrbkap, sr=jonas --- content/base/public/nsINode.h | 5 +- content/base/src/Makefile.in | 1 + content/base/src/nsContentSink.cpp | 12 +- content/base/src/nsContentSink.h | 9 +- content/base/src/nsContentUtils.cpp | 58 +- content/base/src/nsDOMAttribute.cpp | 3 +- content/base/src/nsDOMAttribute.h | 2 +- content/base/src/nsDocument.cpp | 6 +- content/base/src/nsDocument.h | 2 +- content/base/src/nsGenericDOMDataNode.cpp | 2 +- content/base/src/nsGenericDOMDataNode.h | 2 +- content/base/src/nsGenericElement.cpp | 8 +- content/base/src/nsGenericElement.h | 5 +- content/base/src/nsHTMLContentSerializer.cpp | 41 +- content/base/test/test_bug417255.html | 14 +- .../content/src/nsHTMLOptGroupElement.cpp | 7 +- .../html/content/src/nsHTMLSelectElement.cpp | 5 +- .../html/content/src/nsHTMLSelectElement.h | 2 +- .../reftests/bug448564-2_malformed.html | 11 - .../reftests/bug448564-2_well-formed.html | 14 - .../reftests/bug448564-3_malformed.html | 4 - .../reftests/bug448564-3_well-formed.html | 8 - .../reftests/bug448564-5_malformed.html | 16 - .../reftests/bug448564-5_well-formed.html | 17 - content/html/document/reftests/reftests.list | 6 - content/html/document/src/Makefile.in | 1 + .../html/document/src/nsHTMLContentSink.cpp | 29 - content/html/document/src/nsHTMLDocument.cpp | 70 +- content/html/parser/Makefile.in | 52 + .../html/parser/javasrc/AttributeName.java | 2793 +++ content/html/parser/javasrc/ElementName.java | 1513 ++ .../html/parser/javasrc/HtmlAttributes.java | 484 + content/html/parser/javasrc/MetaScanner.java | 696 + content/html/parser/javasrc/Portability.java | 167 + content/html/parser/javasrc/README.txt | 9 + content/html/parser/javasrc/StackNode.java | 155 + .../html/parser/javasrc/StateSnapshot.java | 59 + content/html/parser/javasrc/Tokenizer.java | 5709 +++++ content/html/parser/javasrc/TreeBuilder.java | 5089 +++++ content/html/parser/javasrc/UTF16Buffer.java | 99 + content/html/parser/public/Makefile.in | 51 + .../svg/content/src/nsSVGSwitchElement.cpp | 5 +- content/svg/content/src/nsSVGSwitchElement.h | 2 +- content/xml/document/src/nsXMLContentSink.cpp | 27 - content/xml/document/src/nsXMLContentSink.h | 2 - content/xtf/src/nsXTFElementWrapper.cpp | 5 +- content/xtf/src/nsXTFElementWrapper.h | 2 +- content/xul/content/src/nsXULElement.cpp | 5 +- content/xul/content/src/nsXULElement.h | 2 +- layout/build/Makefile.in | 2 + layout/build/nsLayoutStatics.cpp | 5 + layout/reftests/bugs/394534-1-ref.html | 3 +- layout/reftests/bugs/394534-1.html | 3 +- layout/reftests/bugs/444375-1-ref.html | 3 +- layout/reftests/bugs/482659-1a.html | 2 +- layout/reftests/bugs/482659-1b.html | 2 +- layout/reftests/bugs/482659-1c.html | 2 +- layout/reftests/bugs/482659-1d.html | 2 +- layout/reftests/bugs/490182-1a.html | 6 +- layout/reftests/bugs/490182-1b.html | 3 +- .../reftests/font-face/ex-unit-1-dynamic.html | 2 +- layout/reftests/table-dom/deleteCol1.html | 6 +- layout/reftests/table-dom/deleteCol2.html | 6 +- layout/reftests/table-dom/deleteCol3.html | 6 +- layout/reftests/table-dom/insertCols1.html | 5 +- layout/reftests/table-dom/insertCols2.html | 5 +- layout/reftests/table-dom/insertCols3.html | 5 +- layout/reftests/text/justification-1.html | 3 +- modules/libpref/src/init/all.js | 3 + parser/Makefile.in | 3 +- parser/html/Makefile.in | 100 + parser/html/jArray.h | 103 + parser/html/nsHtml5ArrayCopy.h | 88 + parser/html/nsHtml5AtomList.h | 1049 + parser/html/nsHtml5Atoms.cpp | 63 + parser/html/nsHtml5Atoms.h | 62 + parser/html/nsHtml5AttributeName.cpp | 1981 ++ parser/html/nsHtml5AttributeName.h | 1279 ++ parser/html/nsHtml5ByteReadable.h | 68 + parser/html/nsHtml5DocumentMode.h | 47 + parser/html/nsHtml5ElementName.cpp | 1314 ++ parser/html/nsHtml5ElementName.h | 875 + parser/html/nsHtml5HtmlAttributes.cpp | 237 + parser/html/nsHtml5HtmlAttributes.h | 96 + parser/html/nsHtml5MetaScanner.cpp | 713 + parser/html/nsHtml5MetaScanner.h | 121 + parser/html/nsHtml5MetaScannerCppSupplement.h | 137 + parser/html/nsHtml5MetaScannerHSupplement.h | 47 + parser/html/nsHtml5Module.cpp | 115 + parser/html/nsHtml5Module.h | 57 + parser/html/nsHtml5NamedCharacters.cpp | 17159 ++++++++++++++++ parser/html/nsHtml5NamedCharacters.h | 18 + parser/html/nsHtml5Parser.cpp | 1447 ++ parser/html/nsHtml5Parser.h | 666 + parser/html/nsHtml5PendingNotification.h | 79 + parser/html/nsHtml5Portability.cpp | 193 + parser/html/nsHtml5Portability.h | 86 + .../html/nsHtml5ReleasableAttributeName.cpp | 49 + parser/html/nsHtml5ReleasableAttributeName.h | 50 + parser/html/nsHtml5ReleasableElementName.cpp | 49 + parser/html/nsHtml5ReleasableElementName.h | 50 + parser/html/nsHtml5StackNode.cpp | 165 + parser/html/nsHtml5StackNode.h | 92 + parser/html/nsHtml5StackNodeCppSupplement.h | 56 + parser/html/nsHtml5StackNodeHSupplement.h | 38 + parser/html/nsHtml5StateSnapshot.cpp | 92 + parser/html/nsHtml5StateSnapshot.h | 75 + parser/html/nsHtml5Tokenizer.cpp | 3257 +++ parser/html/nsHtml5Tokenizer.h | 357 + parser/html/nsHtml5TreeBuilder.cpp | 3723 ++++ parser/html/nsHtml5TreeBuilder.h | 330 + parser/html/nsHtml5TreeBuilderCppSupplement.h | 562 + parser/html/nsHtml5TreeBuilderHSupplement.h | 169 + parser/html/nsHtml5TreeOperation.cpp | 167 + parser/html/nsHtml5TreeOperation.h | 113 + parser/html/nsHtml5UTF16Buffer.cpp | 121 + parser/html/nsHtml5UTF16Buffer.h | 84 + parser/html/nsHtml5UTF16BufferCppSupplement.h | 64 + parser/html/nsHtml5UTF16BufferHSupplement.h | 43 + parser/htmlparser/public/nsIParser.h | 26 +- parser/htmlparser/src/nsParser.cpp | 10 + parser/htmlparser/src/nsParser.h | 7 +- toolkit/toolkit-tiers.mk | 4 +- 123 files changed, 55066 insertions(+), 250 deletions(-) delete mode 100644 content/html/document/reftests/bug448564-2_malformed.html delete mode 100644 content/html/document/reftests/bug448564-2_well-formed.html delete mode 100644 content/html/document/reftests/bug448564-3_malformed.html delete mode 100644 content/html/document/reftests/bug448564-3_well-formed.html delete mode 100644 content/html/document/reftests/bug448564-5_malformed.html delete mode 100644 content/html/document/reftests/bug448564-5_well-formed.html create mode 100644 content/html/parser/Makefile.in create mode 100644 content/html/parser/javasrc/AttributeName.java create mode 100644 content/html/parser/javasrc/ElementName.java create mode 100644 content/html/parser/javasrc/HtmlAttributes.java create mode 100644 content/html/parser/javasrc/MetaScanner.java create mode 100644 content/html/parser/javasrc/Portability.java create mode 100644 content/html/parser/javasrc/README.txt create mode 100644 content/html/parser/javasrc/StackNode.java create mode 100644 content/html/parser/javasrc/StateSnapshot.java create mode 100644 content/html/parser/javasrc/Tokenizer.java create mode 100644 content/html/parser/javasrc/TreeBuilder.java create mode 100644 content/html/parser/javasrc/UTF16Buffer.java create mode 100644 content/html/parser/public/Makefile.in create mode 100644 parser/html/Makefile.in create mode 100644 parser/html/jArray.h create mode 100644 parser/html/nsHtml5ArrayCopy.h create mode 100644 parser/html/nsHtml5AtomList.h create mode 100755 parser/html/nsHtml5Atoms.cpp create mode 100755 parser/html/nsHtml5Atoms.h create mode 100644 parser/html/nsHtml5AttributeName.cpp create mode 100644 parser/html/nsHtml5AttributeName.h create mode 100644 parser/html/nsHtml5ByteReadable.h create mode 100644 parser/html/nsHtml5DocumentMode.h create mode 100644 parser/html/nsHtml5ElementName.cpp create mode 100644 parser/html/nsHtml5ElementName.h create mode 100644 parser/html/nsHtml5HtmlAttributes.cpp create mode 100644 parser/html/nsHtml5HtmlAttributes.h create mode 100644 parser/html/nsHtml5MetaScanner.cpp create mode 100644 parser/html/nsHtml5MetaScanner.h create mode 100644 parser/html/nsHtml5MetaScannerCppSupplement.h create mode 100644 parser/html/nsHtml5MetaScannerHSupplement.h create mode 100644 parser/html/nsHtml5Module.cpp create mode 100644 parser/html/nsHtml5Module.h create mode 100644 parser/html/nsHtml5NamedCharacters.cpp create mode 100644 parser/html/nsHtml5NamedCharacters.h create mode 100644 parser/html/nsHtml5Parser.cpp create mode 100644 parser/html/nsHtml5Parser.h create mode 100644 parser/html/nsHtml5PendingNotification.h create mode 100644 parser/html/nsHtml5Portability.cpp create mode 100644 parser/html/nsHtml5Portability.h create mode 100644 parser/html/nsHtml5ReleasableAttributeName.cpp create mode 100644 parser/html/nsHtml5ReleasableAttributeName.h create mode 100644 parser/html/nsHtml5ReleasableElementName.cpp create mode 100644 parser/html/nsHtml5ReleasableElementName.h create mode 100644 parser/html/nsHtml5StackNode.cpp create mode 100644 parser/html/nsHtml5StackNode.h create mode 100644 parser/html/nsHtml5StackNodeCppSupplement.h create mode 100644 parser/html/nsHtml5StackNodeHSupplement.h create mode 100644 parser/html/nsHtml5StateSnapshot.cpp create mode 100644 parser/html/nsHtml5StateSnapshot.h create mode 100644 parser/html/nsHtml5Tokenizer.cpp create mode 100644 parser/html/nsHtml5Tokenizer.h create mode 100644 parser/html/nsHtml5TreeBuilder.cpp create mode 100644 parser/html/nsHtml5TreeBuilder.h create mode 100644 parser/html/nsHtml5TreeBuilderCppSupplement.h create mode 100644 parser/html/nsHtml5TreeBuilderHSupplement.h create mode 100644 parser/html/nsHtml5TreeOperation.cpp create mode 100644 parser/html/nsHtml5TreeOperation.h create mode 100644 parser/html/nsHtml5UTF16Buffer.cpp create mode 100644 parser/html/nsHtml5UTF16Buffer.h create mode 100644 parser/html/nsHtml5UTF16BufferCppSupplement.h create mode 100644 parser/html/nsHtml5UTF16BufferHSupplement.h diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index d07101598e2..4a8a0aa36fd 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -439,10 +439,13 @@ public: * @param aNotify whether to notify the document (current document for * nsIContent, and |this| for nsIDocument) that the remove has * occurred + * @param aMutationEvent whether to fire a mutation event * * Note: If there is no child at aIndex, this method will simply do nothing. */ - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify) = 0; + virtual nsresult RemoveChildAt(PRUint32 aIndex, + PRBool aNotify, + PRBool aMutationEvent = PR_TRUE) = 0; /** * Get a property associated with this node. diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 0500ec21887..4d7e9490782 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -84,6 +84,7 @@ REQUIRES = xpcom \ shistory \ editor \ windowwatcher \ + html5 \ $(NULL) ifdef ACCESSIBILITY diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index cfb95ecb2f8..79ecf16f933 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -794,7 +794,7 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement, nsresult nsContentSink::ProcessMETATag(nsIContent* aContent) { - NS_ASSERTION(aContent, "missing base-element"); + NS_ASSERTION(aContent, "missing meta-element"); nsresult rv = NS_OK; @@ -810,6 +810,16 @@ nsContentSink::ProcessMETATag(nsIContent* aContent) rv = ProcessHeaderData(fieldAtom, result, aContent); } } + NS_ENSURE_SUCCESS(rv, rv); + + /* Look for the viewport meta tag. If we find it, process it and put the + * data into the document header. */ + if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, + nsGkAtoms::viewport, eIgnoreCase)) { + nsAutoString value; + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value); + rv = nsContentUtils::ProcessViewportInfo(mDocument, value); + } return rv; } diff --git a/content/base/src/nsContentSink.h b/content/base/src/nsContentSink.h index 5f6d705d664..432d20525d4 100644 --- a/content/base/src/nsContentSink.h +++ b/content/base/src/nsContentSink.h @@ -146,6 +146,8 @@ class nsContentSink : public nsICSSLoaderObserver, virtual void UpdateChildCounts() = 0; + PRBool IsTimeToNotify(); + protected: nsContentSink(); virtual ~nsContentSink(); @@ -241,12 +243,14 @@ protected: nsIURI **aManifestURI, CacheSelectionAction *aAction); +public: // Searches for the offline cache manifest attribute and calls one // of the above defined methods to select the document's application // cache, let it be associated with the document and eventually // schedule the cache update process. void ProcessOfflineManifest(nsIContent *aElement); +protected: // Tries to scroll to the URI's named anchor. Once we've successfully // done that, further calls to this method will be ignored. void ScrollToRef(); @@ -255,10 +259,9 @@ protected: // Start layout. If aIgnorePendingSheets is true, this will happen even if // we still have stylesheet loads pending. Otherwise, we'll wait until the // stylesheets are all done loading. +public: void StartLayout(PRBool aIgnorePendingSheets); - - PRBool IsTimeToNotify(); - +protected: void FavorPerformanceHint(PRBool perfOverStarvation, PRUint32 starvationDelay); diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index c4b03591506..9e4f4c9f94b 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -164,6 +164,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsIMIMEHeaderParam.h" #include "nsIDOMDragEvent.h" #include "nsDOMDataTransfer.h" +#include "nsHtml5Module.h" #ifdef IBMBIDI #include "nsIBidiKeyboard.h" @@ -3578,6 +3579,58 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode, // for compiling event handlers... so just bail out. nsCOMPtr document = node->GetOwnerDoc(); NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE); + + PRBool bCaseSensitive = document->IsCaseSensitive(); + + nsCOMPtr htmlDoc(do_QueryInterface(document)); + PRBool bHTML = htmlDoc && !bCaseSensitive; + + if (bHTML && nsHtml5Module::Enabled) { + // See if the document has a cached fragment parser. nsHTMLDocument is the + // only one that should really have one at the moment. + nsCOMPtr parser = document->GetFragmentParser(); + if (parser) { + // Get the parser ready to use. + parser->Reset(); + } + else { + // Create a new parser for this operation. + parser = nsHtml5Module::NewHtml5Parser(); + if (!parser) { + return NS_ERROR_OUT_OF_MEMORY; + } + document->SetFragmentParser(parser); + } + nsCOMPtr frag; + rv = NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager()); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr contextAsContent = do_QueryInterface(aContextNode); + if (contextAsContent && !contextAsContent->IsNodeOfType(nsINode::eELEMENT)) { + contextAsContent = contextAsContent->GetParent(); + if (contextAsContent && !contextAsContent->IsNodeOfType(nsINode::eELEMENT)) { + // can this even happen? + contextAsContent = nsnull; + } + } + + if (contextAsContent) { + parser->ParseFragment(aFragment, + frag, + contextAsContent->Tag(), + contextAsContent->GetNameSpaceID(), + (document->GetCompatibilityMode() == eCompatibility_NavQuirks)); + } else { + parser->ParseFragment(aFragment, + frag, + nsGkAtoms::body, + kNameSpaceID_XHTML, + (document->GetCompatibilityMode() == eCompatibility_NavQuirks)); + } + + NS_ADDREF(*aReturn = frag); + return NS_OK; + } nsAutoTArray tagStack; nsAutoString uriStr, nameStr; @@ -3635,14 +3688,9 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode, } nsCAutoString contentType; - PRBool bCaseSensitive = PR_TRUE; nsAutoString buf; document->GetContentType(buf); LossyCopyUTF16toASCII(buf, contentType); - bCaseSensitive = document->IsCaseSensitive(); - - nsCOMPtr htmlDoc(do_QueryInterface(document)); - PRBool bHTML = htmlDoc && !bCaseSensitive; // See if the document has a cached fragment parser. nsHTMLDocument is the // only one that should really have one at the moment. diff --git a/content/base/src/nsDOMAttribute.cpp b/content/base/src/nsDOMAttribute.cpp index fab7e7f9a2a..d27d8585c14 100644 --- a/content/base/src/nsDOMAttribute.cpp +++ b/content/base/src/nsDOMAttribute.cpp @@ -699,8 +699,9 @@ nsDOMAttribute::AppendChildTo(nsIContent* aKid, PRBool aNotify) } nsresult -nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsDOMAttribute::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { + NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on attribute child removal."); if (aIndex != 0 || !mChild) { return NS_OK; } diff --git a/content/base/src/nsDOMAttribute.h b/content/base/src/nsDOMAttribute.h index fca0ef49974..e6efc5c21ce 100644 --- a/content/base/src/nsDOMAttribute.h +++ b/content/base/src/nsDOMAttribute.h @@ -98,7 +98,7 @@ public: virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 9d0ba64a776..f602da6f214 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3221,8 +3221,9 @@ nsDocument::AppendChildTo(nsIContent* aKid, PRBool aNotify) } nsresult -nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { + NS_ASSERTION(aMutationEvent, "Someone tried to inhibit mutations on document child removal."); nsCOMPtr oldKid = GetChildAt(aIndex); if (!oldKid) { return NS_OK; @@ -3234,7 +3235,8 @@ nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) } nsresult rv = nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid, - nsnull, this, mChildren); + nsnull, this, mChildren, + aMutationEvent); mCachedRootContent = nsnull; return rv; } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index bced2bef936..c424b20c401 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -810,7 +810,7 @@ public: virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 416ad049c23..fb4c4f8bfa9 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -752,7 +752,7 @@ nsGenericDOMDataNode::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, } nsresult -nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsGenericDOMDataNode::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { return NS_OK; } diff --git a/content/base/src/nsGenericDOMDataNode.h b/content/base/src/nsGenericDOMDataNode.h index 42661ff6990..93e410abd1c 100644 --- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -166,7 +166,7 @@ public: virtual PRInt32 IndexOf(nsINode* aPossibleChild) const; virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 73218beb3c8..ec40c94743d 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -3246,14 +3246,14 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, } nsresult -nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) +nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent) { nsCOMPtr oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex); NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt"); if (oldKid) { return doRemoveChildAt(aIndex, aNotify, oldKid, this, GetCurrentDoc(), - mAttrsAndChildren); + mAttrsAndChildren, aMutationEvent); } return NS_OK; @@ -3264,7 +3264,8 @@ nsresult nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid, nsIContent* aParent, nsIDocument* aDocument, - nsAttrAndChildArray& aChildArray) + nsAttrAndChildArray& aChildArray, + PRBool aMutationEvent) { NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!"); NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument, @@ -3300,6 +3301,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, mozAutoSubtreeModified subtree(nsnull, nsnull); if (aNotify && + aMutationEvent && nsContentUtils::HasMutationListeners(aKid, NS_EVENT_BITS_MUTATION_NODEREMOVED, container)) { mozAutoRemovableBlockerRemover blockerRemover; diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 87962975cf3..d11e541757a 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -354,7 +354,7 @@ public: virtual PRInt32 IndexOf(nsINode* aPossibleChild) const; virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify); - virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify); + virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify, PRBool aMutationEvent = PR_TRUE); virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, @@ -654,7 +654,8 @@ public: static nsresult doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid, nsIContent* aParent, nsIDocument* aDocument, - nsAttrAndChildArray& aChildArray); + nsAttrAndChildArray& aChildArray, + PRBool aMutationEvent); /** * Helper methods for implementing querySelector/querySelectorAll diff --git a/content/base/src/nsHTMLContentSerializer.cpp b/content/base/src/nsHTMLContentSerializer.cpp index 85c03c5bd1c..2e9354c6912 100644 --- a/content/base/src/nsHTMLContentSerializer.cpp +++ b/content/base/src/nsHTMLContentSerializer.cpp @@ -68,6 +68,7 @@ #include "nsLWBrkCIID.h" #include "nsIScriptElement.h" #include "nsAttrName.h" +#include "nsHtml5Module.h" static const char kMozStr[] = "moz"; @@ -100,6 +101,7 @@ nsHTMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument, return NS_OK; } +#include "nsIHTMLDocument.h" void nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent, nsIDOMElement *aOriginalElement, @@ -108,19 +110,40 @@ nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent, nsIAtom* aTagName, nsAString& aStr) { + PRInt32 count = aContent->GetAttrCount(); + if (!count) + return; + nsresult rv; - PRUint32 index, count; nsAutoString nameStr, valueStr; - - count = aContent->GetAttrCount(); - NS_NAMED_LITERAL_STRING(_mozStr, "_moz"); - // Loop backward over the attributes, since the order they are stored in is - // the opposite of the order they were parsed in (see bug 213347 for reason). - // index is unsigned, hence index >= 0 is always true. - for (index = count; index > 0; ) { - --index; + // HTML5 parser stored them in the order they were parsed so we want to + // loop forward in that case. + nsIDocument* doc = aContent->GetOwnerDocument(); + PRBool caseSensitive = doc && doc->IsCaseSensitive(); + PRBool loopForward = PR_FALSE; + if (!caseSensitive) { + nsCOMPtr htmlDoc(do_QueryInterface(doc)); + if (htmlDoc) { + loopForward = nsHtml5Module::Enabled; + } + } + PRInt32 index, limit, step; + if (loopForward) { + index = 0; + limit = count; + step = 1; + } + else { + // Loop backward over the attributes, since the order they are stored in is + // the opposite of the order they were parsed in (see bug 213347 for reason). + index = count - 1; + limit = -1; + step = -1; + } + + for (; index != limit; index += step) { const nsAttrName* name = aContent->GetAttrNameAt(index); PRInt32 namespaceID = name->NamespaceID(); nsIAtom* attrName = name->LocalName(); diff --git a/content/base/test/test_bug417255.html b/content/base/test/test_bug417255.html index ef0563ae8d9..96e7b2c8c8f 100644 --- a/content/base/test/test_bug417255.html +++ b/content/base/test/test_bug417255.html @@ -15,20 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=417255 Mozilla Bug 417255 -

+
-

+

-
+
-

+

-
+
-

+

-
+