From afe6bb701c4f301c07f723b98510f57e361a8821 Mon Sep 17 00:00:00 2001 From: "harishd%netscape.com" Date: Wed, 22 Mar 2000 22:13:50 +0000 Subject: [PATCH] Fix for Bugs 29048,31392,31940,29379,29735, 25880,26488,27490,31694. Gist: General bug fixes, Mem. leaks, and a little perf. work ( in collectingskipped content ). r=pollmann --- htmlparser/src/CNavDTD.cpp | 77 ++++++++++++++---------- htmlparser/src/nsDTDUtils.cpp | 36 +++++------ htmlparser/src/nsElementTable.cpp | 57 +++++++++++++++--- htmlparser/src/nsElementTable.h | 1 + htmlparser/src/nsHTMLTokens.cpp | 12 ++-- htmlparser/src/nsToken.cpp | 2 +- parser/htmlparser/src/CNavDTD.cpp | 77 ++++++++++++++---------- parser/htmlparser/src/nsDTDUtils.cpp | 36 +++++------ parser/htmlparser/src/nsElementTable.cpp | 57 +++++++++++++++--- parser/htmlparser/src/nsElementTable.h | 1 + parser/htmlparser/src/nsHTMLTokens.cpp | 12 ++-- parser/htmlparser/src/nsToken.cpp | 2 +- 12 files changed, 236 insertions(+), 134 deletions(-) diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp index 23183b245fa9..743c4d0f8767 100644 --- a/htmlparser/src/CNavDTD.cpp +++ b/htmlparser/src/CNavDTD.cpp @@ -209,7 +209,7 @@ nsCParserNode* CNavDTD::CreateNode(void) { void CNavDTD::RecycleNode(nsCParserNode* aNode) { if(aNode && (!aNode->mUseCount)) { - if(aNode->mToken) { + if(aNode->mToken) { if(!aNode->mToken->mUseCount) { mTokenRecycler->RecycleToken(aNode->mToken); } @@ -694,8 +694,8 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ case eHTMLTag_comment: case eHTMLTag_script: case eHTMLTag_markupDecl: - case eHTMLTag_userdefined: - break; //simply pass these through to token handler without further ado... + break; // simply pass these through to token handler without further ado... + // Userdefined tags shouldn't just pass through. -- Fix for 31694,31940 case eHTMLTag_newline: case eHTMLTag_whitespace: if(mMisplacedContent.GetSize()<=0) // fix for bugs 17017,18308,23765, and 24275 @@ -842,7 +842,8 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ eHTMLTokenTypes theType=eHTMLTokenTypes(theNextToken->GetTokenType()); if(eToken_newline==theType){ mLineNumber++; - mTokenizer->PopToken(); //skip 1st newline inside PRE and LISTING + theNextToken=mTokenizer->PopToken(); //skip 1st newline inside PRE and LISTING + if(theNextToken) mTokenRecycler->RecycleToken(theNextToken); // fix for Bug 29379 }//if }//if } @@ -1017,31 +1018,33 @@ nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsI } if(theChildAgrees && theChildIsContainer) { - if ((theParentTag!=aChildTag) && (!nsHTMLElement::IsResidualStyleTag(aChildTag))) { + if (!nsHTMLElement::IsResidualStyleTag(aChildTag)) { + if(theParentTag!=aChildTag) { - //trying is blockcloser to widen the set of elements that this effects, re: bug 27865... + //trying is blockcloser to widen the set of elements that this effects, re: bug 27865... - if(nsHTMLElement::IsBlockCloser(theParentTag)) { - PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag); + if(nsHTMLElement::IsBlockCloser(theParentTag)) { + PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag); - if((kNotFound
  • + /*------------------------------------------------------------------------------------- + 1. Here's a tricky case from bug 22596:
  • - How do we know that the 2nd
    should close the
  • rather than nest inside the
  • ? - (Afterall, the
    is a legal child of the
  • ). + How do we know that the 2nd
    should close the
  • rather than nest inside the
  • ? + (Afterall, the
    is a legal child of the
  • ). - The way you know is that there is no root between the two, so the
    binds more - tightly to the 1st
    than to the
  • . + The way you know is that there is no root between the two, so the
    binds more + tightly to the 1st
    than to the
  • . - 2. Also, bug 6148 shows this case:
    - From this case we learned not to execute this logic if the parent is a block. - -------------------------------------------------------------------------------------*/ + 2. Also, bug 6148 shows this case:
    + From this case we learned not to execute this logic if the parent is a block. + -------------------------------------------------------------------------------------*/ - theChildAgrees=CanBeContained(aChildTag,*mBodyContext); - } //if - }//if + theChildAgrees=CanBeContained(aChildTag,*mBodyContext); + } //if + }//if + } } //if } //if } //if parentcontains @@ -2028,23 +2031,22 @@ nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) { eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); - mScratch.Truncate(); // Dont worry about attributes here because it's already stored in // the start token as mTrailing content and will get appended in // start token's GetSource(); if(eToken_attribute!=theTokenType) { if (eToken_entity==theTokenType) { if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) { + mScratch.Truncate(); ((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch); // since this is an entity, we know that it's only one character. // check to see if it's a CR, in which case we'll need to do line // termination conversion at the end. aMustConvertLinebreaks |= (mScratch[0] == kCR); + aNode.mSkippedContent->Append(mScratch); } } - else theNextToken->GetSource(mScratch); - - aNode.mSkippedContent->Append(mScratch); + else theNextToken->GetSource(*aNode.mSkippedContent); } mTokenRecycler->RecycleToken(theNextToken); } @@ -2684,8 +2686,9 @@ nsresult CNavDTD::CloseBody(const nsIParserNode *aNode){ * @return TRUE if ok, FALSE if error */ nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){ - static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_col, - eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup}; + // Include TD and TH to fix bug 29735. + static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th, + eHTMLTag_col,eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup}; if(mHasOpenForm) CloseForm(aNode); @@ -3116,7 +3119,9 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC } } else if(1==theNode->mUseCount) { - //this fixes bug 30885 and 29626 + // This fixes bug 30885 and 29626 + // Make sure that the node, which is about to + // get released does not stay on the style stack... mBodyContext->PopStyle(theTag); } mBodyContext->PushStyles(theChildStyleStack); @@ -3348,7 +3353,10 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ eHTMLTags theTag=(eHTMLTags)aNode->GetNodeType(); - if(eHTMLTag_meta==theTag) { + // XXX - SCRIPT inside NOTAGS should not get executed unless the pref. + // says so. Since we don't have this support yet..lets ignore the + // SCRIPT inside NOTAGS. Ref Bug 25880. + if(eHTMLTag_meta==theTag || eHTMLTag_script==theTag) { if(HasOpenContainer(gNoXTags,sizeof(gNoXTags)/sizeof(eHTMLTag_unknown))) { return result; } @@ -3374,10 +3382,13 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ } else result=AddLeaf(aNode); - // XXX If the return value tells us to block, go - // ahead and close the tag out anyway, since its - // contents will be consumed. - if (NS_SUCCEEDED(result)) { + // XXX If the return value tells us to block, go + // ahead and close the tag out anyway, since its + // contents will be consumed. + + // Fix for Bug 31392 + // Do not leave a head context open no matter what the result is. + if(mHasOpenHead) { nsresult rv=CloseHead(aNode); // XXX Only send along a failure. If the close // succeeded we still may need to indicate that the diff --git a/htmlparser/src/nsDTDUtils.cpp b/htmlparser/src/nsDTDUtils.cpp index 5a9074460f4d..0fb6f09b3e3a 100644 --- a/htmlparser/src/nsDTDUtils.cpp +++ b/htmlparser/src/nsDTDUtils.cpp @@ -73,23 +73,14 @@ nsEntryStack::~nsEntryStack() { MOZ_COUNT_DTOR(nsEntryStack); if(mEntries) { - if(0Append(aStyles); - } //if - }//if + } //if(theEntry ) + else if(mStack.mCount==0) { + // If you're here it means that we have hit the rock bottom + // ,of the stack, and there's no need to handle anymore styles. + // Fix for bug 29048 + delete aStyles; + aStyles=0; + } + }//if(aStyles) } @@ -592,20 +590,21 @@ nsIParserNode* nsDTDContext::PopStyle(void){ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){ PRInt32 theLevel=0; + nsIParserNode* result=0; for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; if(theStack) { if(aTag==theStack->Last()) { + result=theStack->Pop(); mResidualStyleCount--; - return theStack->Pop(); } else { // NS_ERROR("bad residual style entry"); } } } - return 0; + return result; } /** @@ -619,20 +618,21 @@ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){ PRInt32 theLevel=0; + nsIParserNode* result=0; for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; if(theStack) { if(aTag==theStack->Last()) { + result=theStack->Pop(); mResidualStyleCount--; - return theStack->Pop(); } else { // NS_ERROR("bad residual style entry"); } } } - return 0; + return result; } /************************************************************** diff --git a/htmlparser/src/nsElementTable.cpp b/htmlparser/src/nsElementTable.cpp index aed8a0baa77a..b2bfd1ac5240 100644 --- a/htmlparser/src/nsElementTable.cpp +++ b/htmlparser/src/nsElementTable.cpp @@ -136,7 +136,8 @@ TagList gDTCloseTags={3,{eHTMLTag_dt,eHTMLTag_dd,eHTMLTag_p}}; TagList gULCloseTags={1,{eHTMLTag_li}}; -TagList gExcludableParents={1,{eHTMLTag_pre}}; // Ref Bug 22913,23680 +TagList gExcludableParents={1,{eHTMLTag_pre}}; // Ref Bug 22913 +TagList gCaptionExcludableParents={1,{eHTMLTag_td}}; //Ref Bug 26488 //********************************************************************************************* //Lastly, bind tags with their rules, their special parents and special kids. @@ -1389,10 +1390,12 @@ PRBool nsHTMLElement::IsBlockCloser(eHTMLTags aTag){ if(!result) { // NOBR is a block closure - Ref. Bug# 24462 // DIR is a block closure -- Ref. Bug# 25845 + // TD is a block closure - Ref. Bug# 27490 + // TR is a block closure - Ref. Bug# 26488 static eHTMLTags gClosers[]={ eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_caption,eHTMLTag_dd,eHTMLTag_dt, - eHTMLTag_td,eHTMLTag_th, - /* eHTMLTag_tfoot, eHTMLTag_thead,eHTMLTag_tr, */ + eHTMLTag_td,eHTMLTag_th,eHTMLTag_tr, + /* eHTMLTag_tfoot, eHTMLTag_thead,*/ eHTMLTag_nobr,eHTMLTag_optgroup,eHTMLTag_ol,eHTMLTag_ul,eHTMLTag_dir}; result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body)); @@ -1549,6 +1552,45 @@ PRBool nsHTMLElement::CanExclude(eHTMLTags aChild) const{ return result; } +/** + * + * @update harishd 03/01/00 + * @param + * @return + */ +PRBool nsHTMLElement::IsExcludableParent(eHTMLTags aParent) const{ + PRBool result=PR_FALSE; + + if(!IsTextTag(mTagID)) { + if(mExcludableParents) { + TagList* theParents=mExcludableParents; + if(FindTagInSet(aParent,theParents->mTags,theParents->mCount)) + result=PR_TRUE; + } + if(!result) { + // If you're a block parent make sure that you're not the + // parent of a TABLE element. ex.
    + // IE & Nav. render this as table with two cells ( which I think is correct ). + // NOTE: If need arise we could use the root node to solve this problem + if(nsHTMLElement::IsBlockParent(aParent)){ + switch(mTagID) { + case eHTMLTag_caption: + case eHTMLTag_thead: + case eHTMLTag_tbody: + case eHTMLTag_tfoot: + case eHTMLTag_td: + case eHTMLTag_th: + case eHTMLTag_tr: + result=PR_TRUE; + default: + break; + } + } + } + } + return result; +} + /** * * @update gess 01/04/99 @@ -1907,12 +1949,9 @@ PRBool nsHTMLElement::CanContain(eHTMLTags aChild) const{ if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount)) return PR_FALSE; } - - if(gHTMLElements[aChild].mExcludableParents) { - TagList* theParents=gHTMLElements[aChild].mExcludableParents; - if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount)) - return PR_FALSE; - } + + if(gHTMLElements[aChild].IsExcludableParent(mTagID)) + return PR_FALSE; if(gHTMLElements[aChild].IsBlockCloser(aChild)){ if(nsHTMLElement::IsBlockParent(mTagID)){ diff --git a/htmlparser/src/nsElementTable.h b/htmlparser/src/nsElementTable.h index f67f3295b41a..25b010466c57 100644 --- a/htmlparser/src/nsElementTable.h +++ b/htmlparser/src/nsElementTable.h @@ -171,6 +171,7 @@ struct nsHTMLElement { PRBool CanAutoCloseTag(nsDTDContext& aContext,eHTMLTags aTag) const; PRBool HasSpecialProperty(PRInt32 aProperty) const; PRBool IsSpecialParent(eHTMLTags aTag) const; + PRBool IsExcludableParent(eHTMLTags aParent) const; PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch); static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild); diff --git a/htmlparser/src/nsHTMLTokens.cpp b/htmlparser/src/nsHTMLTokens.cpp index e823b8f0e0bb..5af921f049c8 100644 --- a/htmlparser/src/nsHTMLTokens.cpp +++ b/htmlparser/src/nsHTMLTokens.cpp @@ -297,7 +297,7 @@ void CStartToken::DebugDumpSource(nsOutputStream& out) { * @return nada */ void CStartToken::GetSource(nsString& anOutputString){ - anOutputString="<"; + anOutputString+="<"; /* * mTextValue used to contain the name of the tag. * But for the sake of performance we now rely on the tagID @@ -429,7 +429,7 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) { * @return nada */ void CEndToken::GetSource(nsString& anOutputString){ - anOutputString=""; } @@ -486,8 +486,8 @@ PRInt32 CTextToken::GetTokenType(void) { * @param aScanner -- controller of underlying input source * @return error result */ -nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { - static nsString theTerminals("\n\r&<",4); +nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {; + static nsString theTerminals("\n\r&<",4); nsresult result=NS_OK; PRBool done=PR_FALSE; @@ -1176,7 +1176,7 @@ void CAttributeToken::DebugDumpToken(nsOutputStream& out) { * @return nada */ void CAttributeToken::GetSource(nsString& anOutputString){ - anOutputString=mTextKey; + anOutputString+=mTextKey; anOutputString+="="; anOutputString+=mTextValue; anOutputString+=";"; @@ -1670,7 +1670,7 @@ void CEntityToken::DebugDumpSource(nsOutputStream& out) { * @return nada */ void CEntityToken::GetSource(nsString& anOutputString){ - anOutputString="&"; + anOutputString+="&"; anOutputString+=mTextValue; //anOutputString+=";"; } diff --git a/htmlparser/src/nsToken.cpp b/htmlparser/src/nsToken.cpp index 8554ae97aa24..f3232b1f65aa 100644 --- a/htmlparser/src/nsToken.cpp +++ b/htmlparser/src/nsToken.cpp @@ -183,7 +183,7 @@ nsString& CToken::GetStringValueXXX(void) { * @return reference to string containing string value */ void CToken::GetSource(nsString& anOutputString){ - anOutputString=mTextValue; + anOutputString+=mTextValue; } /** diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index 23183b245fa9..743c4d0f8767 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -209,7 +209,7 @@ nsCParserNode* CNavDTD::CreateNode(void) { void CNavDTD::RecycleNode(nsCParserNode* aNode) { if(aNode && (!aNode->mUseCount)) { - if(aNode->mToken) { + if(aNode->mToken) { if(!aNode->mToken->mUseCount) { mTokenRecycler->RecycleToken(aNode->mToken); } @@ -694,8 +694,8 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ case eHTMLTag_comment: case eHTMLTag_script: case eHTMLTag_markupDecl: - case eHTMLTag_userdefined: - break; //simply pass these through to token handler without further ado... + break; // simply pass these through to token handler without further ado... + // Userdefined tags shouldn't just pass through. -- Fix for 31694,31940 case eHTMLTag_newline: case eHTMLTag_whitespace: if(mMisplacedContent.GetSize()<=0) // fix for bugs 17017,18308,23765, and 24275 @@ -842,7 +842,8 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ eHTMLTokenTypes theType=eHTMLTokenTypes(theNextToken->GetTokenType()); if(eToken_newline==theType){ mLineNumber++; - mTokenizer->PopToken(); //skip 1st newline inside PRE and LISTING + theNextToken=mTokenizer->PopToken(); //skip 1st newline inside PRE and LISTING + if(theNextToken) mTokenRecycler->RecycleToken(theNextToken); // fix for Bug 29379 }//if }//if } @@ -1017,31 +1018,33 @@ nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsI } if(theChildAgrees && theChildIsContainer) { - if ((theParentTag!=aChildTag) && (!nsHTMLElement::IsResidualStyleTag(aChildTag))) { + if (!nsHTMLElement::IsResidualStyleTag(aChildTag)) { + if(theParentTag!=aChildTag) { - //trying is blockcloser to widen the set of elements that this effects, re: bug 27865... + //trying is blockcloser to widen the set of elements that this effects, re: bug 27865... - if(nsHTMLElement::IsBlockCloser(theParentTag)) { - PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag); + if(nsHTMLElement::IsBlockCloser(theParentTag)) { + PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag); - if((kNotFound
  • + /*------------------------------------------------------------------------------------- + 1. Here's a tricky case from bug 22596:
  • - How do we know that the 2nd
    should close the
  • rather than nest inside the
  • ? - (Afterall, the
    is a legal child of the
  • ). + How do we know that the 2nd
    should close the
  • rather than nest inside the
  • ? + (Afterall, the
    is a legal child of the
  • ). - The way you know is that there is no root between the two, so the
    binds more - tightly to the 1st
    than to the
  • . + The way you know is that there is no root between the two, so the
    binds more + tightly to the 1st
    than to the
  • . - 2. Also, bug 6148 shows this case:
    - From this case we learned not to execute this logic if the parent is a block. - -------------------------------------------------------------------------------------*/ + 2. Also, bug 6148 shows this case:
    + From this case we learned not to execute this logic if the parent is a block. + -------------------------------------------------------------------------------------*/ - theChildAgrees=CanBeContained(aChildTag,*mBodyContext); - } //if - }//if + theChildAgrees=CanBeContained(aChildTag,*mBodyContext); + } //if + }//if + } } //if } //if } //if parentcontains @@ -2028,23 +2031,22 @@ nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) { eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); - mScratch.Truncate(); // Dont worry about attributes here because it's already stored in // the start token as mTrailing content and will get appended in // start token's GetSource(); if(eToken_attribute!=theTokenType) { if (eToken_entity==theTokenType) { if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) { + mScratch.Truncate(); ((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch); // since this is an entity, we know that it's only one character. // check to see if it's a CR, in which case we'll need to do line // termination conversion at the end. aMustConvertLinebreaks |= (mScratch[0] == kCR); + aNode.mSkippedContent->Append(mScratch); } } - else theNextToken->GetSource(mScratch); - - aNode.mSkippedContent->Append(mScratch); + else theNextToken->GetSource(*aNode.mSkippedContent); } mTokenRecycler->RecycleToken(theNextToken); } @@ -2684,8 +2686,9 @@ nsresult CNavDTD::CloseBody(const nsIParserNode *aNode){ * @return TRUE if ok, FALSE if error */ nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){ - static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_col, - eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup}; + // Include TD and TH to fix bug 29735. + static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th, + eHTMLTag_col,eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup}; if(mHasOpenForm) CloseForm(aNode); @@ -3116,7 +3119,9 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC } } else if(1==theNode->mUseCount) { - //this fixes bug 30885 and 29626 + // This fixes bug 30885 and 29626 + // Make sure that the node, which is about to + // get released does not stay on the style stack... mBodyContext->PopStyle(theTag); } mBodyContext->PushStyles(theChildStyleStack); @@ -3348,7 +3353,10 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ eHTMLTags theTag=(eHTMLTags)aNode->GetNodeType(); - if(eHTMLTag_meta==theTag) { + // XXX - SCRIPT inside NOTAGS should not get executed unless the pref. + // says so. Since we don't have this support yet..lets ignore the + // SCRIPT inside NOTAGS. Ref Bug 25880. + if(eHTMLTag_meta==theTag || eHTMLTag_script==theTag) { if(HasOpenContainer(gNoXTags,sizeof(gNoXTags)/sizeof(eHTMLTag_unknown))) { return result; } @@ -3374,10 +3382,13 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ } else result=AddLeaf(aNode); - // XXX If the return value tells us to block, go - // ahead and close the tag out anyway, since its - // contents will be consumed. - if (NS_SUCCEEDED(result)) { + // XXX If the return value tells us to block, go + // ahead and close the tag out anyway, since its + // contents will be consumed. + + // Fix for Bug 31392 + // Do not leave a head context open no matter what the result is. + if(mHasOpenHead) { nsresult rv=CloseHead(aNode); // XXX Only send along a failure. If the close // succeeded we still may need to indicate that the diff --git a/parser/htmlparser/src/nsDTDUtils.cpp b/parser/htmlparser/src/nsDTDUtils.cpp index 5a9074460f4d..0fb6f09b3e3a 100644 --- a/parser/htmlparser/src/nsDTDUtils.cpp +++ b/parser/htmlparser/src/nsDTDUtils.cpp @@ -73,23 +73,14 @@ nsEntryStack::~nsEntryStack() { MOZ_COUNT_DTOR(nsEntryStack); if(mEntries) { - if(0Append(aStyles); - } //if - }//if + } //if(theEntry ) + else if(mStack.mCount==0) { + // If you're here it means that we have hit the rock bottom + // ,of the stack, and there's no need to handle anymore styles. + // Fix for bug 29048 + delete aStyles; + aStyles=0; + } + }//if(aStyles) } @@ -592,20 +590,21 @@ nsIParserNode* nsDTDContext::PopStyle(void){ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){ PRInt32 theLevel=0; + nsIParserNode* result=0; for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; if(theStack) { if(aTag==theStack->Last()) { + result=theStack->Pop(); mResidualStyleCount--; - return theStack->Pop(); } else { // NS_ERROR("bad residual style entry"); } } } - return 0; + return result; } /** @@ -619,20 +618,21 @@ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){ PRInt32 theLevel=0; + nsIParserNode* result=0; for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; if(theStack) { if(aTag==theStack->Last()) { + result=theStack->Pop(); mResidualStyleCount--; - return theStack->Pop(); } else { // NS_ERROR("bad residual style entry"); } } } - return 0; + return result; } /************************************************************** diff --git a/parser/htmlparser/src/nsElementTable.cpp b/parser/htmlparser/src/nsElementTable.cpp index aed8a0baa77a..b2bfd1ac5240 100644 --- a/parser/htmlparser/src/nsElementTable.cpp +++ b/parser/htmlparser/src/nsElementTable.cpp @@ -136,7 +136,8 @@ TagList gDTCloseTags={3,{eHTMLTag_dt,eHTMLTag_dd,eHTMLTag_p}}; TagList gULCloseTags={1,{eHTMLTag_li}}; -TagList gExcludableParents={1,{eHTMLTag_pre}}; // Ref Bug 22913,23680 +TagList gExcludableParents={1,{eHTMLTag_pre}}; // Ref Bug 22913 +TagList gCaptionExcludableParents={1,{eHTMLTag_td}}; //Ref Bug 26488 //********************************************************************************************* //Lastly, bind tags with their rules, their special parents and special kids. @@ -1389,10 +1390,12 @@ PRBool nsHTMLElement::IsBlockCloser(eHTMLTags aTag){ if(!result) { // NOBR is a block closure - Ref. Bug# 24462 // DIR is a block closure -- Ref. Bug# 25845 + // TD is a block closure - Ref. Bug# 27490 + // TR is a block closure - Ref. Bug# 26488 static eHTMLTags gClosers[]={ eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_caption,eHTMLTag_dd,eHTMLTag_dt, - eHTMLTag_td,eHTMLTag_th, - /* eHTMLTag_tfoot, eHTMLTag_thead,eHTMLTag_tr, */ + eHTMLTag_td,eHTMLTag_th,eHTMLTag_tr, + /* eHTMLTag_tfoot, eHTMLTag_thead,*/ eHTMLTag_nobr,eHTMLTag_optgroup,eHTMLTag_ol,eHTMLTag_ul,eHTMLTag_dir}; result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body)); @@ -1549,6 +1552,45 @@ PRBool nsHTMLElement::CanExclude(eHTMLTags aChild) const{ return result; } +/** + * + * @update harishd 03/01/00 + * @param + * @return + */ +PRBool nsHTMLElement::IsExcludableParent(eHTMLTags aParent) const{ + PRBool result=PR_FALSE; + + if(!IsTextTag(mTagID)) { + if(mExcludableParents) { + TagList* theParents=mExcludableParents; + if(FindTagInSet(aParent,theParents->mTags,theParents->mCount)) + result=PR_TRUE; + } + if(!result) { + // If you're a block parent make sure that you're not the + // parent of a TABLE element. ex.
    + // IE & Nav. render this as table with two cells ( which I think is correct ). + // NOTE: If need arise we could use the root node to solve this problem + if(nsHTMLElement::IsBlockParent(aParent)){ + switch(mTagID) { + case eHTMLTag_caption: + case eHTMLTag_thead: + case eHTMLTag_tbody: + case eHTMLTag_tfoot: + case eHTMLTag_td: + case eHTMLTag_th: + case eHTMLTag_tr: + result=PR_TRUE; + default: + break; + } + } + } + } + return result; +} + /** * * @update gess 01/04/99 @@ -1907,12 +1949,9 @@ PRBool nsHTMLElement::CanContain(eHTMLTags aChild) const{ if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount)) return PR_FALSE; } - - if(gHTMLElements[aChild].mExcludableParents) { - TagList* theParents=gHTMLElements[aChild].mExcludableParents; - if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount)) - return PR_FALSE; - } + + if(gHTMLElements[aChild].IsExcludableParent(mTagID)) + return PR_FALSE; if(gHTMLElements[aChild].IsBlockCloser(aChild)){ if(nsHTMLElement::IsBlockParent(mTagID)){ diff --git a/parser/htmlparser/src/nsElementTable.h b/parser/htmlparser/src/nsElementTable.h index f67f3295b41a..25b010466c57 100644 --- a/parser/htmlparser/src/nsElementTable.h +++ b/parser/htmlparser/src/nsElementTable.h @@ -171,6 +171,7 @@ struct nsHTMLElement { PRBool CanAutoCloseTag(nsDTDContext& aContext,eHTMLTags aTag) const; PRBool HasSpecialProperty(PRInt32 aProperty) const; PRBool IsSpecialParent(eHTMLTags aTag) const; + PRBool IsExcludableParent(eHTMLTags aParent) const; PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch); static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild); diff --git a/parser/htmlparser/src/nsHTMLTokens.cpp b/parser/htmlparser/src/nsHTMLTokens.cpp index e823b8f0e0bb..5af921f049c8 100644 --- a/parser/htmlparser/src/nsHTMLTokens.cpp +++ b/parser/htmlparser/src/nsHTMLTokens.cpp @@ -297,7 +297,7 @@ void CStartToken::DebugDumpSource(nsOutputStream& out) { * @return nada */ void CStartToken::GetSource(nsString& anOutputString){ - anOutputString="<"; + anOutputString+="<"; /* * mTextValue used to contain the name of the tag. * But for the sake of performance we now rely on the tagID @@ -429,7 +429,7 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) { * @return nada */ void CEndToken::GetSource(nsString& anOutputString){ - anOutputString=""; } @@ -486,8 +486,8 @@ PRInt32 CTextToken::GetTokenType(void) { * @param aScanner -- controller of underlying input source * @return error result */ -nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { - static nsString theTerminals("\n\r&<",4); +nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {; + static nsString theTerminals("\n\r&<",4); nsresult result=NS_OK; PRBool done=PR_FALSE; @@ -1176,7 +1176,7 @@ void CAttributeToken::DebugDumpToken(nsOutputStream& out) { * @return nada */ void CAttributeToken::GetSource(nsString& anOutputString){ - anOutputString=mTextKey; + anOutputString+=mTextKey; anOutputString+="="; anOutputString+=mTextValue; anOutputString+=";"; @@ -1670,7 +1670,7 @@ void CEntityToken::DebugDumpSource(nsOutputStream& out) { * @return nada */ void CEntityToken::GetSource(nsString& anOutputString){ - anOutputString="&"; + anOutputString+="&"; anOutputString+=mTextValue; //anOutputString+=";"; } diff --git a/parser/htmlparser/src/nsToken.cpp b/parser/htmlparser/src/nsToken.cpp index 8554ae97aa24..f3232b1f65aa 100644 --- a/parser/htmlparser/src/nsToken.cpp +++ b/parser/htmlparser/src/nsToken.cpp @@ -183,7 +183,7 @@ nsString& CToken::GetStringValueXXX(void) { * @return reference to string containing string value */ void CToken::GetSource(nsString& anOutputString){ - anOutputString=mTextValue; + anOutputString+=mTextValue; } /**