diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp index 5dc39b27e34..0ef7f919f7d 100644 --- a/htmlparser/src/CNavDTD.cpp +++ b/htmlparser/src/CNavDTD.cpp @@ -147,7 +147,7 @@ CNavDTD::CNavDTD() : nsIDTD(), mHasOpenBody=PR_FALSE; mHasOpenHead=0; mHasOpenForm=PR_FALSE; - mHasOpenMap=PR_FALSE; + mOpenMapCount=0; mHasOpenNoXXX=0; mFormContext=0; mMapContext=0; @@ -802,8 +802,13 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ if(theToken){ //Before dealing with the token normally, we need to deal with skip targets - if((!execSkipContent) && (theType!=eToken_end) && - (eHTMLTag_unknown==mSkipTarget) && (gHTMLElements[theTag].mSkipTarget)){ //create a new target + CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken); + if((!execSkipContent) && + (theType!=eToken_end) && + (eHTMLTag_unknown==mSkipTarget) && + (gHTMLElements[theTag].mSkipTarget) && + (!theStartToken->IsEmpty())) { // added empty token check for bug 44186 + //create a new target mSkipTarget=gHTMLElements[theTag].mSkipTarget; mSkippedContent.Push(theToken); } @@ -1611,12 +1616,12 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { break; case eHTMLTag_area: - if(!mHasOpenMap) isTokenHandled=PR_TRUE; + if(!mOpenMapCount) isTokenHandled=PR_TRUE; STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleStartToken(), this=%p\n", this)); - if (mHasOpenMap && mSink) { + if (mOpenMapCount>0 && mSink) { result=mSink->AddLeaf(*theNode); isTokenHandled=PR_TRUE; } @@ -2756,7 +2761,7 @@ PRBool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const { case eHTMLTag_form: result=mHasOpenForm; break; case eHTMLTag_map: - result=mHasOpenMap; break; + result=mOpenMapCount>0; break; default: result=mBodyContext->HasOpenContainer(aContainer); break; @@ -3162,8 +3167,6 @@ nsresult CNavDTD::CloseForm(const nsIParserNode *aNode){ * @return TRUE if ok, FALSE if error */ nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){ - if(mHasOpenMap) - CloseMap(aNode); STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenMap(), this=%p\n", this)); @@ -3175,7 +3178,7 @@ nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){ if(NS_OK==result) { mBodyContext->Push(aNode); - mHasOpenMap=PR_TRUE; + mOpenMapCount++; } return result; } @@ -3191,8 +3194,8 @@ nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){ nsresult CNavDTD::CloseMap(const nsIParserNode *aNode){ // NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos); nsresult result=NS_OK; - if(mHasOpenMap) { - mHasOpenMap=PR_FALSE; + if(mOpenMapCount) { + mOpenMapCount--; STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseMap(), this=%p\n", this)); diff --git a/htmlparser/src/CNavDTD.h b/htmlparser/src/CNavDTD.h index 3915b6b4e6a..63856d7bfb8 100644 --- a/htmlparser/src/CNavDTD.h +++ b/htmlparser/src/CNavDTD.h @@ -500,8 +500,8 @@ protected: nsDTDContext* mFormContext; nsDTDContext* mMapContext; nsDTDContext* mTempContext; - PRBool mHasOpenForm; - PRBool mHasOpenMap; + PRInt32 mHasOpenForm; + PRInt32 mOpenMapCount; PRInt32 mHasOpenHead; PRBool mHasOpenBody; PRInt32 mHasOpenNoXXX; //true when NOFRAMES, NOSCRIPT, NOEMBED, NOLAYER are open diff --git a/htmlparser/src/nsDTDUtils.cpp b/htmlparser/src/nsDTDUtils.cpp index bfeb72c2749..2bb2d22834a 100644 --- a/htmlparser/src/nsDTDUtils.cpp +++ b/htmlparser/src/nsDTDUtils.cpp @@ -371,7 +371,7 @@ nsDTDContext::nsDTDContext() : mStack(), mEntities(0){ MOZ_COUNT_CTOR(nsDTDContext); mResidualStyleCount=0; - mContextTopIndex=0; + mContextTopIndex=-1; mTableStates=0; mCounters=0; mTokenAllocator=0; diff --git a/htmlparser/src/nsElementTable.cpp b/htmlparser/src/nsElementTable.cpp index a93ac9c9368..5be7f9a5683 100644 --- a/htmlparser/src/nsElementTable.cpp +++ b/htmlparser/src/nsElementTable.cpp @@ -857,7 +857,7 @@ void InitializeElementTable(void) { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ kBlock, kFlowEntity, kNone, /*special props, prop-range*/ 0, kNoPropRange, - /*special parents,kids,skip*/ &gNoframeRoot,0,eHTMLTag_unknown); + /*special parents,kids,skip*/ &gNoframeRoot,0,eHTMLTag_noframes); // Added noframes - fix bug 62803 - since Mozilla supports frames. Initialize( /*tag*/ eHTMLTag_nolayer, diff --git a/htmlparser/src/nsHTMLTokenizer.cpp b/htmlparser/src/nsHTMLTokenizer.cpp index 3e8a207f89e..31294b781bb 100644 --- a/htmlparser/src/nsHTMLTokenizer.cpp +++ b/htmlparser/src/nsHTMLTokenizer.cpp @@ -576,17 +576,21 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, //and a textkey of "/". We should destroy it, and tell the //start token it was empty. if(NS_SUCCEEDED(result)) { + PRBool isUsableAttr=PR_TRUE; const nsAReadableString& key=theToken->GetKey(); const nsAReadableString& text=theToken->GetValue(); - if((mDoXMLEmptyTags) && (kForwardSlash==key.CharAt(0)) && (0==text.Length())){ - //tada! our special case! Treat it like an empty start tag... + // support XML like syntax to fix bugs like 44186 + if((kForwardSlash==key.CharAt(0)) && (0==text.Length())){ aToken->SetEmpty(PR_TRUE); - IF_FREE(theToken); + isUsableAttr=!mDoXMLEmptyTags; } - else { + if(isUsableAttr) { theAttrCount++; AddToken((CToken*&)theToken,result,&mTokenDeque,theAllocator); } + else { + IF_FREE(theToken); + } } else { //if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result){ aToken->SetEmpty(PR_TRUE); @@ -677,6 +681,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan }//if } + CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken); if(theTagHasAttributes) { if (eViewSource==mParserCommand) { // Since we conserve whitespace in view-source mode, @@ -684,7 +689,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan // and let the first attribute grab it. aScanner.SetPosition(start, PR_FALSE, PR_TRUE); } - result=ConsumeAttributes(aChar,(CStartToken*)aToken,aScanner); + result=ConsumeAttributes(aChar,theStartToken,aScanner); } /* Now that that's over with, we have one more problem to solve. @@ -700,7 +705,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan } if(mRecordTrailingContent) - RecordTrailingContent((CStartToken*)aToken,aScanner,origin); + RecordTrailingContent(theStartToken,aScanner,origin); //if((eHTMLTag_style==theTag) || (eHTMLTag_script==theTag)) { if(gHTMLElements[theTag].CanContainType(kCDATA)) { @@ -709,12 +714,22 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan endText.Assign(endTagName); endText.InsertWithConversion("CreateTokenOfType(eToken_text,eHTMLTag_text); - result=((CTextToken*)textToken)->ConsumeUntil(0,PRBool(theTag!=eHTMLTag_script),aScanner,endText,mParseMode,aFlushTokens); //tell new token to finish consuming text... - - CToken* endToken=theAllocator->CreateTokenOfType(eToken_end,theTag,endTagName); - AddToken(textToken,result,&mTokenDeque,theAllocator); - AddToken(endToken,result,&mTokenDeque,theAllocator); + CToken* text=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text); + CTextToken* textToken=NS_STATIC_CAST(CTextToken*,text); + result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,aScanner,endText,mParseMode,aFlushTokens); //tell new token to finish consuming text... + + // Fix bug 44186 + // Support XML like syntax, i.e., + // Note: if aFlushTokens is TRUE then we have seen an + if(!theStartToken->IsEmpty() || aFlushTokens) { + theStartToken->SetEmpty(PR_FALSE); // Setting this would make cases like work. + CToken* endToken=theAllocator->CreateTokenOfType(eToken_end,theTag,endTagName); + AddToken(text,result,&mTokenDeque,theAllocator); + AddToken(endToken,result,&mTokenDeque,theAllocator); + } + else { + IF_FREE(text); + } } } diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index 5dc39b27e34..0ef7f919f7d 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -147,7 +147,7 @@ CNavDTD::CNavDTD() : nsIDTD(), mHasOpenBody=PR_FALSE; mHasOpenHead=0; mHasOpenForm=PR_FALSE; - mHasOpenMap=PR_FALSE; + mOpenMapCount=0; mHasOpenNoXXX=0; mFormContext=0; mMapContext=0; @@ -802,8 +802,13 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ if(theToken){ //Before dealing with the token normally, we need to deal with skip targets - if((!execSkipContent) && (theType!=eToken_end) && - (eHTMLTag_unknown==mSkipTarget) && (gHTMLElements[theTag].mSkipTarget)){ //create a new target + CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken); + if((!execSkipContent) && + (theType!=eToken_end) && + (eHTMLTag_unknown==mSkipTarget) && + (gHTMLElements[theTag].mSkipTarget) && + (!theStartToken->IsEmpty())) { // added empty token check for bug 44186 + //create a new target mSkipTarget=gHTMLElements[theTag].mSkipTarget; mSkippedContent.Push(theToken); } @@ -1611,12 +1616,12 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { break; case eHTMLTag_area: - if(!mHasOpenMap) isTokenHandled=PR_TRUE; + if(!mOpenMapCount) isTokenHandled=PR_TRUE; STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleStartToken(), this=%p\n", this)); - if (mHasOpenMap && mSink) { + if (mOpenMapCount>0 && mSink) { result=mSink->AddLeaf(*theNode); isTokenHandled=PR_TRUE; } @@ -2756,7 +2761,7 @@ PRBool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const { case eHTMLTag_form: result=mHasOpenForm; break; case eHTMLTag_map: - result=mHasOpenMap; break; + result=mOpenMapCount>0; break; default: result=mBodyContext->HasOpenContainer(aContainer); break; @@ -3162,8 +3167,6 @@ nsresult CNavDTD::CloseForm(const nsIParserNode *aNode){ * @return TRUE if ok, FALSE if error */ nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){ - if(mHasOpenMap) - CloseMap(aNode); STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenMap(), this=%p\n", this)); @@ -3175,7 +3178,7 @@ nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){ if(NS_OK==result) { mBodyContext->Push(aNode); - mHasOpenMap=PR_TRUE; + mOpenMapCount++; } return result; } @@ -3191,8 +3194,8 @@ nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){ nsresult CNavDTD::CloseMap(const nsIParserNode *aNode){ // NS_PRECONDITION(mBodyContext->GetCount() > 0, kInvalidTagStackPos); nsresult result=NS_OK; - if(mHasOpenMap) { - mHasOpenMap=PR_FALSE; + if(mOpenMapCount) { + mOpenMapCount--; STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseMap(), this=%p\n", this)); diff --git a/parser/htmlparser/src/CNavDTD.h b/parser/htmlparser/src/CNavDTD.h index 3915b6b4e6a..63856d7bfb8 100644 --- a/parser/htmlparser/src/CNavDTD.h +++ b/parser/htmlparser/src/CNavDTD.h @@ -500,8 +500,8 @@ protected: nsDTDContext* mFormContext; nsDTDContext* mMapContext; nsDTDContext* mTempContext; - PRBool mHasOpenForm; - PRBool mHasOpenMap; + PRInt32 mHasOpenForm; + PRInt32 mOpenMapCount; PRInt32 mHasOpenHead; PRBool mHasOpenBody; PRInt32 mHasOpenNoXXX; //true when NOFRAMES, NOSCRIPT, NOEMBED, NOLAYER are open diff --git a/parser/htmlparser/src/nsDTDUtils.cpp b/parser/htmlparser/src/nsDTDUtils.cpp index bfeb72c2749..2bb2d22834a 100644 --- a/parser/htmlparser/src/nsDTDUtils.cpp +++ b/parser/htmlparser/src/nsDTDUtils.cpp @@ -371,7 +371,7 @@ nsDTDContext::nsDTDContext() : mStack(), mEntities(0){ MOZ_COUNT_CTOR(nsDTDContext); mResidualStyleCount=0; - mContextTopIndex=0; + mContextTopIndex=-1; mTableStates=0; mCounters=0; mTokenAllocator=0; diff --git a/parser/htmlparser/src/nsElementTable.cpp b/parser/htmlparser/src/nsElementTable.cpp index a93ac9c9368..5be7f9a5683 100644 --- a/parser/htmlparser/src/nsElementTable.cpp +++ b/parser/htmlparser/src/nsElementTable.cpp @@ -857,7 +857,7 @@ void InitializeElementTable(void) { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ kBlock, kFlowEntity, kNone, /*special props, prop-range*/ 0, kNoPropRange, - /*special parents,kids,skip*/ &gNoframeRoot,0,eHTMLTag_unknown); + /*special parents,kids,skip*/ &gNoframeRoot,0,eHTMLTag_noframes); // Added noframes - fix bug 62803 - since Mozilla supports frames. Initialize( /*tag*/ eHTMLTag_nolayer, diff --git a/parser/htmlparser/src/nsHTMLTokenizer.cpp b/parser/htmlparser/src/nsHTMLTokenizer.cpp index 3e8a207f89e..31294b781bb 100644 --- a/parser/htmlparser/src/nsHTMLTokenizer.cpp +++ b/parser/htmlparser/src/nsHTMLTokenizer.cpp @@ -576,17 +576,21 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, //and a textkey of "/". We should destroy it, and tell the //start token it was empty. if(NS_SUCCEEDED(result)) { + PRBool isUsableAttr=PR_TRUE; const nsAReadableString& key=theToken->GetKey(); const nsAReadableString& text=theToken->GetValue(); - if((mDoXMLEmptyTags) && (kForwardSlash==key.CharAt(0)) && (0==text.Length())){ - //tada! our special case! Treat it like an empty start tag... + // support XML like syntax to fix bugs like 44186 + if((kForwardSlash==key.CharAt(0)) && (0==text.Length())){ aToken->SetEmpty(PR_TRUE); - IF_FREE(theToken); + isUsableAttr=!mDoXMLEmptyTags; } - else { + if(isUsableAttr) { theAttrCount++; AddToken((CToken*&)theToken,result,&mTokenDeque,theAllocator); } + else { + IF_FREE(theToken); + } } else { //if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result){ aToken->SetEmpty(PR_TRUE); @@ -677,6 +681,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan }//if } + CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken); if(theTagHasAttributes) { if (eViewSource==mParserCommand) { // Since we conserve whitespace in view-source mode, @@ -684,7 +689,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan // and let the first attribute grab it. aScanner.SetPosition(start, PR_FALSE, PR_TRUE); } - result=ConsumeAttributes(aChar,(CStartToken*)aToken,aScanner); + result=ConsumeAttributes(aChar,theStartToken,aScanner); } /* Now that that's over with, we have one more problem to solve. @@ -700,7 +705,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan } if(mRecordTrailingContent) - RecordTrailingContent((CStartToken*)aToken,aScanner,origin); + RecordTrailingContent(theStartToken,aScanner,origin); //if((eHTMLTag_style==theTag) || (eHTMLTag_script==theTag)) { if(gHTMLElements[theTag].CanContainType(kCDATA)) { @@ -709,12 +714,22 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan endText.Assign(endTagName); endText.InsertWithConversion("CreateTokenOfType(eToken_text,eHTMLTag_text); - result=((CTextToken*)textToken)->ConsumeUntil(0,PRBool(theTag!=eHTMLTag_script),aScanner,endText,mParseMode,aFlushTokens); //tell new token to finish consuming text... - - CToken* endToken=theAllocator->CreateTokenOfType(eToken_end,theTag,endTagName); - AddToken(textToken,result,&mTokenDeque,theAllocator); - AddToken(endToken,result,&mTokenDeque,theAllocator); + CToken* text=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text); + CTextToken* textToken=NS_STATIC_CAST(CTextToken*,text); + result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,aScanner,endText,mParseMode,aFlushTokens); //tell new token to finish consuming text... + + // Fix bug 44186 + // Support XML like syntax, i.e., + // Note: if aFlushTokens is TRUE then we have seen an + if(!theStartToken->IsEmpty() || aFlushTokens) { + theStartToken->SetEmpty(PR_FALSE); // Setting this would make cases like work. + CToken* endToken=theAllocator->CreateTokenOfType(eToken_end,theTag,endTagName); + AddToken(text,result,&mTokenDeque,theAllocator); + AddToken(endToken,result,&mTokenDeque,theAllocator); + } + else { + IF_FREE(text); + } } }