diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp index 8388d36d5d1..31b50cca48c 100644 --- a/htmlparser/src/CNavDTD.cpp +++ b/htmlparser/src/CNavDTD.cpp @@ -408,7 +408,8 @@ nsresult CNavDTD::WillBuildModel(nsString& aFilename,PRBool aNotifySink,nsString START_TIMER(); - CStartToken theToken(eHTMLTag_html); + nsAutoString theTagName("html"); + CStartToken theToken(theTagName,eHTMLTag_html); HandleStartToken(&theToken); mSkipTarget=eHTMLTag_unknown; @@ -1203,14 +1204,19 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { if(nsHTMLElement::IsSectionTag(theChildTag)){ switch(theChildTag){ case eHTMLTag_body: - if(mHasOpenBody) - return OpenContainer(*theNode,PR_FALSE); + if(mHasOpenBody) { + result=OpenContainer(*theNode,PR_FALSE); + RecycleNode(theNode); + return result; + } break; case eHTMLTag_head: if(mHadBody || mHadFrameset) { result=HandleOmittedTag(aToken,theChildTag,theParent,*theNode); - if(result == NS_OK) + if(result == NS_OK) { + RecycleNode(theNode); return result; + } } break; default: @@ -1430,20 +1436,19 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { if((kNotFound==GetIndexOfChildOrSynonym(mBodyContext->mStack,theChildTag)) || (!gHTMLElements[theChildTag].CanAutoCloseTag(mBodyContext->Last()))) { UpdateStyleStackForCloseTag(theChildTag,theChildTag); - if(gHTMLElements[theChildTag].IsMemberOf(kBlockEntity)) { + if(gHTMLElements[theChildTag].IsMemberOf(kBlockEntity) && + mParseMode!=eParseMode_noquirks) { // Oh boy!! we found a "stray" block entity. Nav4.x and IE introduce line break in // such cases. So, let's simulate that effect for compatibility. // Ex. Hello

There -#if 0 - mTokenizer->PushTokenFront(aToken); //put this end token back... - CHTMLToken* theToken = (CHTMLToken*)gRecycler->CreateTokenOfType(eToken_start,theChildTag); - mTokenizer->PushTokenFront(theToken); //put this new token onto stack... -#endif - CHTMLToken* theToken = (CHTMLToken*)gRecycler->CreateTokenOfType(eToken_start,theChildTag); - result=HandleToken(theToken,mParser); - + if(!CanOmit(mBodyContext->Last(),theChildTag)) { + mTokenizer->PushTokenFront(aToken); //put this end token back... + aToken->mRecycle=PR_FALSE; // make sure not to recycle this token because it's not used yet!! + CHTMLToken* theToken = (CHTMLToken*)gRecycler->CreateTokenOfType(eToken_start,theChildTag); + mTokenizer->PushTokenFront(theToken); //put this new token onto stack... + } } - else return result; + return result; } if(result==NS_OK) { eHTMLTags theTarget=FindAutoCloseTargetForEndTag(theChildTag,mBodyContext->mStack); @@ -1689,20 +1694,17 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ WriteTokenToLog(aToken); #endif - CParserContext* pc=(mParser)? mParser->PeekContext():nsnull; - if(pc) { - nsString& docTypeStr=aToken->GetStringValueXXX(); - mLineNumber += (docTypeStr).CountChar(kNewLine); - docTypeStr.Trim(""); - nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler()); + nsString& docTypeStr=aToken->GetStringValueXXX(); + mLineNumber += (docTypeStr).CountChar(kNewLine); + docTypeStr.Trim(""); + nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler()); - STOP_TIMER(); + STOP_TIMER(); + + result = (mSink)? mSink->AddDocTypeDecl(theNode,mParseMode):NS_OK; + + START_TIMER(); - result = (mSink)? mSink->AddDocTypeDecl(theNode, pc->mParseMode):NS_OK; - - START_TIMER(); - - } return result; } @@ -1858,7 +1860,8 @@ PRBool CNavDTD::CanPropagate(eHTMLTags aParentTag,eHTMLTags aChildTag) const { theTempTag=aChildTag; while(eHTMLTag_unknown!=aChildTag) { if(parentCanContain){ - result=PR_TRUE; + if(!CanOmit(aParentTag,aChildTag)) + result=PR_TRUE; break; }//if TagList* theTagList=gHTMLElements[aChildTag].GetRootTags(); @@ -2779,7 +2782,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode& aNode){ PRBool done=PR_FALSE; nsCParserNode* theNode=CreateNode(); - CTokenRecycler* theRecycler=(CTokenRecycler*)mTokenizer->GetTokenRecycler(); while(!done) { @@ -2993,7 +2995,7 @@ nsITokenRecycler* CNavDTD::GetTokenRecycler(void){ */ nsITokenizer* CNavDTD::GetTokenizer(void) { if(!mTokenizer) - mTokenizer=new nsHTMLTokenizer(); + mTokenizer=new nsHTMLTokenizer(mParseMode); return mTokenizer; } diff --git a/htmlparser/src/nsElementTable.cpp b/htmlparser/src/nsElementTable.cpp index 46faa3a6a55..0eee2ef7ae8 100644 --- a/htmlparser/src/nsElementTable.cpp +++ b/htmlparser/src/nsElementTable.cpp @@ -121,6 +121,7 @@ TagList gFramesetKids={3,eHTMLTag_frame,eHTMLTag_frameset,eHTMLTag_noframes}; TagList gHtmlKids={8,eHTMLTag_body,eHTMLTag_frameset,eHTMLTag_head,eHTMLTag_map,eHTMLTag_noscript,eHTMLTag_script,eHTMLTag_newline,eHTMLTag_whitespace}; TagList gHeadKids={9,eHTMLTag_base,eHTMLTag_bgsound,eHTMLTag_link,eHTMLTag_meta,eHTMLTag_script,eHTMLTag_style,eHTMLTag_title,eHTMLTag_noembed,eHTMLTag_noscript}; +TagList gLabelKids={1,eHTMLTag_span}; TagList gLIKids={2,eHTMLTag_ol,eHTMLTag_ul}; TagList gMapKids={1,eHTMLTag_area}; TagList gNoframesKids={1,eHTMLTag_body}; @@ -776,7 +777,7 @@ void InitializeElementTable(void) { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ kFormControl, kInlineEntity, kSelf, /*special props, prop-range*/ 0,kDefaultPropRange, - /*special parents,kids,skip*/ 0,0,eHTMLTag_unknown); + /*special parents,kids,skip*/ 0,&gLabelKids,eHTMLTag_unknown); Initialize( /*tag*/ eHTMLTag_layer, diff --git a/htmlparser/src/nsExpatTokenizer.cpp b/htmlparser/src/nsExpatTokenizer.cpp index b406c6f1b1b..e1ede12ebf8 100644 --- a/htmlparser/src/nsExpatTokenizer.cpp +++ b/htmlparser/src/nsExpatTokenizer.cpp @@ -94,6 +94,10 @@ nsresult nsExpatTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr return NS_OK; } +void +nsExpatTokenizer::FreeTokenRecycler(void) { + nsHTMLTokenizer::FreeTokenRecycler(); +} /** * This method is defined in nsIParser. It is used to diff --git a/htmlparser/src/nsExpatTokenizer.h b/htmlparser/src/nsExpatTokenizer.h index 098ff8d9784..6e0802fedc9 100644 --- a/htmlparser/src/nsExpatTokenizer.h +++ b/htmlparser/src/nsExpatTokenizer.h @@ -58,6 +58,7 @@ public: virtual nsresult DidTokenize(PRBool aIsFinalChunk); virtual void FrontloadMisplacedContent(nsDeque& aDeque); + static void FreeTokenRecycler(void); protected: diff --git a/htmlparser/src/nsHTMLContentSinkStream.cpp b/htmlparser/src/nsHTMLContentSinkStream.cpp index 12aae664e31..bfdcb5b9257 100644 --- a/htmlparser/src/nsHTMLContentSinkStream.cpp +++ b/htmlparser/src/nsHTMLContentSinkStream.cpp @@ -1165,7 +1165,7 @@ nsHTMLContentSinkStream::AddComment(const nsIParserNode& aNode){ DebugDump("<",aNode.GetText(),(mNodeStackPos)*2); #endif - Write(""); + result=(mSink)? mSink->AddComment(aNode):NS_OK; + done=PR_TRUE; + } + else { + if(inContent) comment.Append(fragment); + } + recycler->RecycleToken(token); + } + } + } + return result; +} /** * diff --git a/htmlparser/src/nsXIFDTD.h b/htmlparser/src/nsXIFDTD.h index 0e954e4b5d6..d75e8dee2ac 100644 --- a/htmlparser/src/nsXIFDTD.h +++ b/htmlparser/src/nsXIFDTD.h @@ -550,6 +550,7 @@ protected: PRBool CanContainFormElement(eXIFTags aParent,eXIFTags aChild) const; nsresult CollectAttributes(nsCParserNode& aNode,PRInt32 aCount); nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount); + nsresult CollectContentComment(CToken* aToken,nsCParserNode& aNode); nsParser* mParser; nsIHTMLContentSink* mSink; diff --git a/htmlparser/src/nsXMLTokenizer.cpp b/htmlparser/src/nsXMLTokenizer.cpp index a512759483f..83e6fb6704f 100644 --- a/htmlparser/src/nsXMLTokenizer.cpp +++ b/htmlparser/src/nsXMLTokenizer.cpp @@ -74,6 +74,10 @@ nsresult nsXMLTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_OK; } +void +nsXMLTokenizer::FreeTokenRecycler(void) { + nsHTMLTokenizer::FreeTokenRecycler(); +} /** * This method is defined in nsIParser. It is used to @@ -199,7 +203,7 @@ nsresult nsXMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScanne nsAutoString theEmpty; aToken=theRecycler->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty); if(aToken) { - result=aToken->Consume(aChar,aScanner); + result=aToken->Consume(aChar,aScanner,eParseMode_noquirks); AddToken(aToken,result,mTokenDeque,theRecycler); } } @@ -242,7 +246,7 @@ nsresult nsXMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,ns if(isComment) aToken = theRecycler->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty); if(aToken) { - result=aToken->Consume(aChar,aScanner); + result=aToken->Consume(aChar,aScanner,eParseMode_noquirks); AddToken(aToken,result,mTokenDeque,theRecycler); } } diff --git a/htmlparser/src/nsXMLTokenizer.h b/htmlparser/src/nsXMLTokenizer.h index 6cd823d96c4..de136202951 100644 --- a/htmlparser/src/nsXMLTokenizer.h +++ b/htmlparser/src/nsXMLTokenizer.h @@ -57,6 +57,8 @@ public: virtual nsresult ConsumeToken(nsScanner& aScanner); virtual nsITokenRecycler* GetTokenRecycler(void); + + static void FreeTokenRecycler(void); protected: diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index 8388d36d5d1..31b50cca48c 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -408,7 +408,8 @@ nsresult CNavDTD::WillBuildModel(nsString& aFilename,PRBool aNotifySink,nsString START_TIMER(); - CStartToken theToken(eHTMLTag_html); + nsAutoString theTagName("html"); + CStartToken theToken(theTagName,eHTMLTag_html); HandleStartToken(&theToken); mSkipTarget=eHTMLTag_unknown; @@ -1203,14 +1204,19 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { if(nsHTMLElement::IsSectionTag(theChildTag)){ switch(theChildTag){ case eHTMLTag_body: - if(mHasOpenBody) - return OpenContainer(*theNode,PR_FALSE); + if(mHasOpenBody) { + result=OpenContainer(*theNode,PR_FALSE); + RecycleNode(theNode); + return result; + } break; case eHTMLTag_head: if(mHadBody || mHadFrameset) { result=HandleOmittedTag(aToken,theChildTag,theParent,*theNode); - if(result == NS_OK) + if(result == NS_OK) { + RecycleNode(theNode); return result; + } } break; default: @@ -1430,20 +1436,19 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { if((kNotFound==GetIndexOfChildOrSynonym(mBodyContext->mStack,theChildTag)) || (!gHTMLElements[theChildTag].CanAutoCloseTag(mBodyContext->Last()))) { UpdateStyleStackForCloseTag(theChildTag,theChildTag); - if(gHTMLElements[theChildTag].IsMemberOf(kBlockEntity)) { + if(gHTMLElements[theChildTag].IsMemberOf(kBlockEntity) && + mParseMode!=eParseMode_noquirks) { // Oh boy!! we found a "stray" block entity. Nav4.x and IE introduce line break in // such cases. So, let's simulate that effect for compatibility. // Ex. Hello

There -#if 0 - mTokenizer->PushTokenFront(aToken); //put this end token back... - CHTMLToken* theToken = (CHTMLToken*)gRecycler->CreateTokenOfType(eToken_start,theChildTag); - mTokenizer->PushTokenFront(theToken); //put this new token onto stack... -#endif - CHTMLToken* theToken = (CHTMLToken*)gRecycler->CreateTokenOfType(eToken_start,theChildTag); - result=HandleToken(theToken,mParser); - + if(!CanOmit(mBodyContext->Last(),theChildTag)) { + mTokenizer->PushTokenFront(aToken); //put this end token back... + aToken->mRecycle=PR_FALSE; // make sure not to recycle this token because it's not used yet!! + CHTMLToken* theToken = (CHTMLToken*)gRecycler->CreateTokenOfType(eToken_start,theChildTag); + mTokenizer->PushTokenFront(theToken); //put this new token onto stack... + } } - else return result; + return result; } if(result==NS_OK) { eHTMLTags theTarget=FindAutoCloseTargetForEndTag(theChildTag,mBodyContext->mStack); @@ -1689,20 +1694,17 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ WriteTokenToLog(aToken); #endif - CParserContext* pc=(mParser)? mParser->PeekContext():nsnull; - if(pc) { - nsString& docTypeStr=aToken->GetStringValueXXX(); - mLineNumber += (docTypeStr).CountChar(kNewLine); - docTypeStr.Trim(""); - nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler()); + nsString& docTypeStr=aToken->GetStringValueXXX(); + mLineNumber += (docTypeStr).CountChar(kNewLine); + docTypeStr.Trim(""); + nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenRecycler()); - STOP_TIMER(); + STOP_TIMER(); + + result = (mSink)? mSink->AddDocTypeDecl(theNode,mParseMode):NS_OK; + + START_TIMER(); - result = (mSink)? mSink->AddDocTypeDecl(theNode, pc->mParseMode):NS_OK; - - START_TIMER(); - - } return result; } @@ -1858,7 +1860,8 @@ PRBool CNavDTD::CanPropagate(eHTMLTags aParentTag,eHTMLTags aChildTag) const { theTempTag=aChildTag; while(eHTMLTag_unknown!=aChildTag) { if(parentCanContain){ - result=PR_TRUE; + if(!CanOmit(aParentTag,aChildTag)) + result=PR_TRUE; break; }//if TagList* theTagList=gHTMLElements[aChildTag].GetRootTags(); @@ -2779,7 +2782,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode& aNode){ PRBool done=PR_FALSE; nsCParserNode* theNode=CreateNode(); - CTokenRecycler* theRecycler=(CTokenRecycler*)mTokenizer->GetTokenRecycler(); while(!done) { @@ -2993,7 +2995,7 @@ nsITokenRecycler* CNavDTD::GetTokenRecycler(void){ */ nsITokenizer* CNavDTD::GetTokenizer(void) { if(!mTokenizer) - mTokenizer=new nsHTMLTokenizer(); + mTokenizer=new nsHTMLTokenizer(mParseMode); return mTokenizer; } diff --git a/parser/htmlparser/src/nsElementTable.cpp b/parser/htmlparser/src/nsElementTable.cpp index 46faa3a6a55..0eee2ef7ae8 100644 --- a/parser/htmlparser/src/nsElementTable.cpp +++ b/parser/htmlparser/src/nsElementTable.cpp @@ -121,6 +121,7 @@ TagList gFramesetKids={3,eHTMLTag_frame,eHTMLTag_frameset,eHTMLTag_noframes}; TagList gHtmlKids={8,eHTMLTag_body,eHTMLTag_frameset,eHTMLTag_head,eHTMLTag_map,eHTMLTag_noscript,eHTMLTag_script,eHTMLTag_newline,eHTMLTag_whitespace}; TagList gHeadKids={9,eHTMLTag_base,eHTMLTag_bgsound,eHTMLTag_link,eHTMLTag_meta,eHTMLTag_script,eHTMLTag_style,eHTMLTag_title,eHTMLTag_noembed,eHTMLTag_noscript}; +TagList gLabelKids={1,eHTMLTag_span}; TagList gLIKids={2,eHTMLTag_ol,eHTMLTag_ul}; TagList gMapKids={1,eHTMLTag_area}; TagList gNoframesKids={1,eHTMLTag_body}; @@ -776,7 +777,7 @@ void InitializeElementTable(void) { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ kFormControl, kInlineEntity, kSelf, /*special props, prop-range*/ 0,kDefaultPropRange, - /*special parents,kids,skip*/ 0,0,eHTMLTag_unknown); + /*special parents,kids,skip*/ 0,&gLabelKids,eHTMLTag_unknown); Initialize( /*tag*/ eHTMLTag_layer, diff --git a/parser/htmlparser/src/nsExpatTokenizer.cpp b/parser/htmlparser/src/nsExpatTokenizer.cpp index b406c6f1b1b..e1ede12ebf8 100644 --- a/parser/htmlparser/src/nsExpatTokenizer.cpp +++ b/parser/htmlparser/src/nsExpatTokenizer.cpp @@ -94,6 +94,10 @@ nsresult nsExpatTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr return NS_OK; } +void +nsExpatTokenizer::FreeTokenRecycler(void) { + nsHTMLTokenizer::FreeTokenRecycler(); +} /** * This method is defined in nsIParser. It is used to diff --git a/parser/htmlparser/src/nsExpatTokenizer.h b/parser/htmlparser/src/nsExpatTokenizer.h index 098ff8d9784..6e0802fedc9 100644 --- a/parser/htmlparser/src/nsExpatTokenizer.h +++ b/parser/htmlparser/src/nsExpatTokenizer.h @@ -58,6 +58,7 @@ public: virtual nsresult DidTokenize(PRBool aIsFinalChunk); virtual void FrontloadMisplacedContent(nsDeque& aDeque); + static void FreeTokenRecycler(void); protected: diff --git a/parser/htmlparser/src/nsHTMLContentSinkStream.cpp b/parser/htmlparser/src/nsHTMLContentSinkStream.cpp index 12aae664e31..bfdcb5b9257 100644 --- a/parser/htmlparser/src/nsHTMLContentSinkStream.cpp +++ b/parser/htmlparser/src/nsHTMLContentSinkStream.cpp @@ -1165,7 +1165,7 @@ nsHTMLContentSinkStream::AddComment(const nsIParserNode& aNode){ DebugDump("<",aNode.GetText(),(mNodeStackPos)*2); #endif - Write(""); + result=(mSink)? mSink->AddComment(aNode):NS_OK; + done=PR_TRUE; + } + else { + if(inContent) comment.Append(fragment); + } + recycler->RecycleToken(token); + } + } + } + return result; +} /** * diff --git a/parser/htmlparser/src/nsXIFDTD.h b/parser/htmlparser/src/nsXIFDTD.h index 0e954e4b5d6..d75e8dee2ac 100644 --- a/parser/htmlparser/src/nsXIFDTD.h +++ b/parser/htmlparser/src/nsXIFDTD.h @@ -550,6 +550,7 @@ protected: PRBool CanContainFormElement(eXIFTags aParent,eXIFTags aChild) const; nsresult CollectAttributes(nsCParserNode& aNode,PRInt32 aCount); nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount); + nsresult CollectContentComment(CToken* aToken,nsCParserNode& aNode); nsParser* mParser; nsIHTMLContentSink* mSink; diff --git a/parser/htmlparser/src/nsXMLTokenizer.cpp b/parser/htmlparser/src/nsXMLTokenizer.cpp index a512759483f..83e6fb6704f 100644 --- a/parser/htmlparser/src/nsXMLTokenizer.cpp +++ b/parser/htmlparser/src/nsXMLTokenizer.cpp @@ -74,6 +74,10 @@ nsresult nsXMLTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_OK; } +void +nsXMLTokenizer::FreeTokenRecycler(void) { + nsHTMLTokenizer::FreeTokenRecycler(); +} /** * This method is defined in nsIParser. It is used to @@ -199,7 +203,7 @@ nsresult nsXMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScanne nsAutoString theEmpty; aToken=theRecycler->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty); if(aToken) { - result=aToken->Consume(aChar,aScanner); + result=aToken->Consume(aChar,aScanner,eParseMode_noquirks); AddToken(aToken,result,mTokenDeque,theRecycler); } } @@ -242,7 +246,7 @@ nsresult nsXMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,ns if(isComment) aToken = theRecycler->CreateTokenOfType(eToken_comment,eHTMLTag_comment,theEmpty); if(aToken) { - result=aToken->Consume(aChar,aScanner); + result=aToken->Consume(aChar,aScanner,eParseMode_noquirks); AddToken(aToken,result,mTokenDeque,theRecycler); } } diff --git a/parser/htmlparser/src/nsXMLTokenizer.h b/parser/htmlparser/src/nsXMLTokenizer.h index 6cd823d96c4..de136202951 100644 --- a/parser/htmlparser/src/nsXMLTokenizer.h +++ b/parser/htmlparser/src/nsXMLTokenizer.h @@ -57,6 +57,8 @@ public: virtual nsresult ConsumeToken(nsScanner& aScanner); virtual nsITokenRecycler* GetTokenRecycler(void); + + static void FreeTokenRecycler(void); protected: