Fixing bug 394534. Make first attribute win in misplaced content. Patch by bzbarsky@mit.edu, r=mrbkap@gmail.com, sr=peterv@propagandism.org, a=jonas@sicking.cc/dsicore@mozilla.com
authorjst@mozilla.org
Mon, 10 Sep 2007 16:50:16 -0700
changeset 5846 311fff4ca067709c1af7f9d70ff908fe67071a72
parent 5845 8da116883551365b5f864915e394a263c668ed70
child 5847 84079104f30e393c287821490ea3ea2c066f0258
push idunknown
push userunknown
push dateunknown
reviewersmrbkap, peterv, jonas
bugs394534
milestone1.9a8pre
Fixing bug 394534. Make first attribute win in misplaced content. Patch by bzbarsky@mit.edu, r=mrbkap@gmail.com, sr=peterv@propagandism.org, a=jonas@sicking.cc/dsicore@mozilla.com
layout/reftests/bugs/reftest.list
parser/htmlparser/src/CNavDTD.cpp
parser/htmlparser/src/nsParserNode.cpp
parser/htmlparser/src/nsParserNode.h
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -372,8 +372,9 @@ random-if(MOZ_WIDGET_TOOLKIT=="cocoa") =
 == 391994-1.html 391994-1-ref.html
 == 392435-1.html 392435-1-ref.html
 == 393649-1.html 393649-1-ref.html
 == 393517-1.xhtml about:blank  # crash test
 == 393671-1.html 393671-1-ref.html
 == 393671-2.html 393671-2-ref.html
 == 393671-3.html 393671-3-ref.html
 == 394111-1.html about:blank  # Really an assertion test rather than a rendering test
+== 394534-1.html 394534-1-ref.html
--- a/parser/htmlparser/src/CNavDTD.cpp
+++ b/parser/htmlparser/src/CNavDTD.cpp
@@ -1057,17 +1057,17 @@ CNavDTD::WillHandleStartTag(CToken* aTok
 }
 
 static void
 PushMisplacedAttributes(nsIParserNode& aNode, nsDeque& aDeque)
 {
   nsCParserNode& theAttrNode = static_cast<nsCParserNode &>(aNode);
 
   for (PRInt32 count = aNode.GetAttributeCount(); count > 0; --count) {
-    CToken* theAttrToken = theAttrNode.PopAttributeToken();
+    CToken* theAttrToken = theAttrNode.PopAttributeTokenFront();
     if (theAttrToken) {
       theAttrToken->SetNewlineCount(0);
       aDeque.Push(theAttrToken);
     }
   }
 }
 
 void
@@ -1737,24 +1737,29 @@ CNavDTD::HandleSavedTokens(PRInt32 anInd
       mBodyContext->MoveEntries(*mTempContext, theTagCount - theTopIndex);
 
       // Now flush out all the bad contents.
       while (theBadTokenCount-- > 0){
         theToken = (CToken*)mMisplacedContent.PopFront();
         if (theToken) {
           theTag       = (eHTMLTags)theToken->GetTypeID();
           attrCount    = theToken->GetAttributeCount();
-          // Put back attributes, which once got popped out, into the tokenizer
+          // Put back attributes, which once got popped out, into the
+          // tokenizer.  Make sure we preserve their ordering, however!
+          // XXXbz would it be faster to get the tokens out with ObjectAt and
+          // the PopFront them all?
+          nsDeque temp;
           for (PRInt32 j = 0; j < attrCount; ++j) {
             CToken* theAttrToken = (CToken*)mMisplacedContent.PopFront();
             if (theAttrToken) {
-              mTokenizer->PushTokenFront(theAttrToken);
+              temp.Push(theAttrToken);
             }
             theBadTokenCount--;
           }
+          mTokenizer->PrependTokens(temp);
 
           if (eToken_end == theToken->GetTokenType()) {
             // Ref: Bug 25202
             // Make sure that the BeginContext() is ended only by the call to
             // EndContext(). Ex: <center><table><a></center>.
             // In the Ex. above </center> should not close <center> above table.
             // Doing so will cause the current context to get closed prematurely.
             eHTMLTags closed = FindAutoCloseTargetForEndTag(theTag, *mBodyContext,
--- a/parser/htmlparser/src/nsParserNode.cpp
+++ b/parser/htmlparser/src/nsParserNode.cpp
@@ -259,16 +259,21 @@ nsCParserNode::GetSourceLineNumber(void)
  * @return  token at anIndex
  */
 
 CToken* 
 nsCParserNode::PopAttributeToken() {
   return 0;
 }
 
+CToken* 
+nsCParserNode::PopAttributeTokenFront() {
+  return 0;
+}
+
 /** Retrieve a string containing the tag and its attributes in "source" form
  * @update	rickg 06June2000
  * @return  void
  */
 void 
 nsCParserNode::GetSource(nsString& aString) const
 {
   eHTMLTags theTag = mToken ? (eHTMLTags)mToken->GetTypeID() : eHTMLTag_unknown;
@@ -348,16 +353,22 @@ nsCParserStartNode::GetValueAt(PRUint32 
 }
 
 CToken* 
 nsCParserStartNode::PopAttributeToken() 
 {
   return static_cast<CToken*>(mAttributes.Pop());
 }
 
+CToken* 
+nsCParserStartNode::PopAttributeTokenFront() 
+{
+  return static_cast<CToken*>(mAttributes.PopFront());
+}
+
 void nsCParserStartNode::GetSource(nsString& aString) const
 {
   aString.Assign(PRUnichar('<'));
   const PRUnichar* theTagName = 
     nsHTMLTags::GetStringValue(nsHTMLTag(mToken->GetTypeID()));
   if (theTagName) {
     aString.Append(theTagName);
   }
--- a/parser/htmlparser/src/nsParserNode.h
+++ b/parser/htmlparser/src/nsParserNode.h
@@ -234,16 +234,19 @@ class nsCParserNode :  public nsIParserN
     virtual PRInt32 GetSourceLineNumber(void) const;
 
     /** This method pop the attribute token from the given index
      * @update	harishd 03/25/99
      * @return  token at anIndex
      */
     virtual CToken* PopAttributeToken();
 
+    /** Like PopAttributeToken, but pops off the front of the attribute list */
+    virtual CToken* PopAttributeTokenFront();
+
     /** Retrieve a string containing the tag and its attributes in "source" form
      * @update	rickg 06June2000
      * @return  void
      */
     virtual void GetSource(nsString& aString) const;
 
     /**
      * This pair of methods allows us to set a generic bit (for arbitrary use)
@@ -309,16 +312,17 @@ public:
     virtual nsresult Init(CToken* aToken,
                           nsTokenAllocator* aTokenAllocator,
                           nsNodeAllocator* aNodeAllocator = 0);
     virtual void     AddAttribute(CToken* aToken);
     virtual PRInt32  GetAttributeCount(PRBool askToken = PR_FALSE) const;
     virtual const    nsAString& GetKeyAt(PRUint32 anIndex) const;
     virtual const    nsAString& GetValueAt(PRUint32 anIndex) const;
     virtual CToken*  PopAttributeToken();
+    virtual CToken*  PopAttributeTokenFront();
     virtual void     GetSource(nsString& aString) const;
     virtual nsresult ReleaseAll();
 protected:
     nsDeque  mAttributes;
 };
 
 #endif