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
This commit is contained in:
harishd%netscape.com 2000-03-22 22:13:50 +00:00
Родитель 3dfc17d3d0
Коммит afe6bb701c
12 изменённых файлов: 236 добавлений и 134 удалений

Просмотреть файл

@ -209,7 +209,7 @@ nsCParserNode* CNavDTD::CreateNode(void) {
void CNavDTD::RecycleNode(nsCParserNode* aNode) { void CNavDTD::RecycleNode(nsCParserNode* aNode) {
if(aNode && (!aNode->mUseCount)) { if(aNode && (!aNode->mUseCount)) {
if(aNode->mToken) { if(aNode->mToken) {
if(!aNode->mToken->mUseCount) { if(!aNode->mToken->mUseCount) {
mTokenRecycler->RecycleToken(aNode->mToken); mTokenRecycler->RecycleToken(aNode->mToken);
} }
@ -694,8 +694,8 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eHTMLTag_comment: case eHTMLTag_comment:
case eHTMLTag_script: case eHTMLTag_script:
case eHTMLTag_markupDecl: 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_newline:
case eHTMLTag_whitespace: case eHTMLTag_whitespace:
if(mMisplacedContent.GetSize()<=0) // fix for bugs 17017,18308,23765, and 24275 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()); eHTMLTokenTypes theType=eHTMLTokenTypes(theNextToken->GetTokenType());
if(eToken_newline==theType){ if(eToken_newline==theType){
mLineNumber++; 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
}//if }//if
} }
@ -1017,31 +1018,33 @@ nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsI
} }
if(theChildAgrees && theChildIsContainer) { 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)) { if(nsHTMLElement::IsBlockCloser(theParentTag)) {
PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag); PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) { if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
/*------------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------------
1. Here's a tricky case from bug 22596: <h5><li><h5> 1. Here's a tricky case from bug 22596: <h5><li><h5>
How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>? How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
(Afterall, the <h5> is a legal child of the <LI>). (Afterall, the <h5> is a legal child of the <LI>).
The way you know is that there is no root between the two, so the <h5> binds more The way you know is that there is no root between the two, so the <h5> binds more
tightly to the 1st <h5> than to the <LI>. tightly to the 1st <h5> than to the <LI>.
2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN> 2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
From this case we learned not to execute this logic if the parent is a block. From this case we learned not to execute this logic if the parent is a block.
-------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------------*/
theChildAgrees=CanBeContained(aChildTag,*mBodyContext); theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
} //if } //if
}//if }//if
}
} //if } //if
} //if } //if
} //if parentcontains } //if parentcontains
@ -2028,23 +2031,22 @@ nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) {
eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType();
mScratch.Truncate();
// Dont worry about attributes here because it's already stored in // Dont worry about attributes here because it's already stored in
// the start token as mTrailing content and will get appended in // the start token as mTrailing content and will get appended in
// start token's GetSource(); // start token's GetSource();
if(eToken_attribute!=theTokenType) { if(eToken_attribute!=theTokenType) {
if (eToken_entity==theTokenType) { if (eToken_entity==theTokenType) {
if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) { if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) {
mScratch.Truncate();
((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch); ((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
// since this is an entity, we know that it's only one character. // 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 // check to see if it's a CR, in which case we'll need to do line
// termination conversion at the end. // termination conversion at the end.
aMustConvertLinebreaks |= (mScratch[0] == kCR); aMustConvertLinebreaks |= (mScratch[0] == kCR);
aNode.mSkippedContent->Append(mScratch);
} }
} }
else theNextToken->GetSource(mScratch); else theNextToken->GetSource(*aNode.mSkippedContent);
aNode.mSkippedContent->Append(mScratch);
} }
mTokenRecycler->RecycleToken(theNextToken); mTokenRecycler->RecycleToken(theNextToken);
} }
@ -2684,8 +2686,9 @@ nsresult CNavDTD::CloseBody(const nsIParserNode *aNode){
* @return TRUE if ok, FALSE if error * @return TRUE if ok, FALSE if error
*/ */
nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){ nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){
static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_col, // Include TD and TH to fix bug 29735.
eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup}; static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th,
eHTMLTag_col,eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup};
if(mHasOpenForm) if(mHasOpenForm)
CloseForm(aNode); CloseForm(aNode);
@ -3116,7 +3119,9 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
} }
} }
else if(1==theNode->mUseCount) { 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->PopStyle(theTag);
} }
mBodyContext->PushStyles(theChildStyleStack); mBodyContext->PushStyles(theChildStyleStack);
@ -3348,7 +3353,10 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){
eHTMLTags theTag=(eHTMLTags)aNode->GetNodeType(); 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))) { if(HasOpenContainer(gNoXTags,sizeof(gNoXTags)/sizeof(eHTMLTag_unknown))) {
return result; return result;
} }
@ -3374,10 +3382,13 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){
} }
else result=AddLeaf(aNode); else result=AddLeaf(aNode);
// XXX If the return value tells us to block, go // XXX If the return value tells us to block, go
// ahead and close the tag out anyway, since its // ahead and close the tag out anyway, since its
// contents will be consumed. // contents will be consumed.
if (NS_SUCCEEDED(result)) {
// Fix for Bug 31392
// Do not leave a head context open no matter what the result is.
if(mHasOpenHead) {
nsresult rv=CloseHead(aNode); nsresult rv=CloseHead(aNode);
// XXX Only send along a failure. If the close // XXX Only send along a failure. If the close
// succeeded we still may need to indicate that the // succeeded we still may need to indicate that the

Просмотреть файл

@ -73,23 +73,14 @@ nsEntryStack::~nsEntryStack() {
MOZ_COUNT_DTOR(nsEntryStack); MOZ_COUNT_DTOR(nsEntryStack);
if(mEntries) { if(mEntries) {
if(0<mCount) { //add code here to recycle the node if you have one...
PRInt32 anIndex=0;
for(anIndex=0;anIndex<mCount;anIndex++){
if(mEntries[anIndex].mStyles)
delete mEntries[anIndex].mStyles;
//add code here to recycle the node if you have one...
}
}
delete [] mEntries; delete [] mEntries;
mEntries=0; mEntries=0;
} }
mCount=mCapacity=0; mCount=mCapacity=0;
} }
/** /**
* Resets state of stack to be empty. * Resets state of stack to be empty.
* @update harishd 04/04/99 * @update harishd 04/04/99
@ -117,7 +108,7 @@ void nsEntryStack::EnsureCapacityFor(PRInt32 aNewMax,PRInt32 aShiftOffset) {
for(index=0;index<mCount;index++) { for(index=0;index<mCount;index++) {
temp[aShiftOffset+index]=mEntries[index]; temp[aShiftOffset+index]=mEntries[index];
} }
delete [] mEntries; if(mEntries) delete [] mEntries;
mEntries=temp; mEntries=temp;
} }
else{ else{
@ -562,8 +553,15 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
} }
else theStyles->Append(aStyles); else theStyles->Append(aStyles);
} //if } //if(theEntry )
}//if 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){ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
PRInt32 theLevel=0; PRInt32 theLevel=0;
nsIParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
if(theStack) { if(theStack) {
if(aTag==theStack->Last()) { if(aTag==theStack->Last()) {
result=theStack->Pop();
mResidualStyleCount--; mResidualStyleCount--;
return theStack->Pop();
} else { } else {
// NS_ERROR("bad residual style entry"); // NS_ERROR("bad residual style entry");
} }
} }
} }
return 0; return result;
} }
/** /**
@ -619,20 +618,21 @@ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
PRInt32 theLevel=0; PRInt32 theLevel=0;
nsIParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
if(theStack) { if(theStack) {
if(aTag==theStack->Last()) { if(aTag==theStack->Last()) {
result=theStack->Pop();
mResidualStyleCount--; mResidualStyleCount--;
return theStack->Pop();
} else { } else {
// NS_ERROR("bad residual style entry"); // NS_ERROR("bad residual style entry");
} }
} }
} }
return 0; return result;
} }
/************************************************************** /**************************************************************

Просмотреть файл

@ -136,7 +136,8 @@ TagList gDTCloseTags={3,{eHTMLTag_dt,eHTMLTag_dd,eHTMLTag_p}};
TagList gULCloseTags={1,{eHTMLTag_li}}; 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. //Lastly, bind tags with their rules, their special parents and special kids.
@ -1389,10 +1390,12 @@ PRBool nsHTMLElement::IsBlockCloser(eHTMLTags aTag){
if(!result) { if(!result) {
// NOBR is a block closure - Ref. Bug# 24462 // NOBR is a block closure - Ref. Bug# 24462
// DIR is a block closure -- Ref. Bug# 25845 // 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, static eHTMLTags gClosers[]={ eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_caption,eHTMLTag_dd,eHTMLTag_dt,
eHTMLTag_td,eHTMLTag_th, eHTMLTag_td,eHTMLTag_th,eHTMLTag_tr,
/* eHTMLTag_tfoot, eHTMLTag_thead,eHTMLTag_tr, */ /* eHTMLTag_tfoot, eHTMLTag_thead,*/
eHTMLTag_nobr,eHTMLTag_optgroup,eHTMLTag_ol,eHTMLTag_ul,eHTMLTag_dir}; eHTMLTag_nobr,eHTMLTag_optgroup,eHTMLTag_ol,eHTMLTag_ul,eHTMLTag_dir};
result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body)); result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body));
@ -1549,6 +1552,45 @@ PRBool nsHTMLElement::CanExclude(eHTMLTags aChild) const{
return result; 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. <table><tr><td><div><td></tr></table>
// 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 * @update gess 01/04/99
@ -1907,12 +1949,9 @@ PRBool nsHTMLElement::CanContain(eHTMLTags aChild) const{
if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount)) if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount))
return PR_FALSE; return PR_FALSE;
} }
if(gHTMLElements[aChild].mExcludableParents) { if(gHTMLElements[aChild].IsExcludableParent(mTagID))
TagList* theParents=gHTMLElements[aChild].mExcludableParents; return PR_FALSE;
if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount))
return PR_FALSE;
}
if(gHTMLElements[aChild].IsBlockCloser(aChild)){ if(gHTMLElements[aChild].IsBlockCloser(aChild)){
if(nsHTMLElement::IsBlockParent(mTagID)){ if(nsHTMLElement::IsBlockParent(mTagID)){

Просмотреть файл

@ -171,6 +171,7 @@ struct nsHTMLElement {
PRBool CanAutoCloseTag(nsDTDContext& aContext,eHTMLTags aTag) const; PRBool CanAutoCloseTag(nsDTDContext& aContext,eHTMLTags aTag) const;
PRBool HasSpecialProperty(PRInt32 aProperty) const; PRBool HasSpecialProperty(PRInt32 aProperty) const;
PRBool IsSpecialParent(eHTMLTags aTag) const; PRBool IsSpecialParent(eHTMLTags aTag) const;
PRBool IsExcludableParent(eHTMLTags aParent) const;
PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch); PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch);
static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild); static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild);

Просмотреть файл

@ -297,7 +297,7 @@ void CStartToken::DebugDumpSource(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CStartToken::GetSource(nsString& anOutputString){ void CStartToken::GetSource(nsString& anOutputString){
anOutputString="<"; anOutputString+="<";
/* /*
* mTextValue used to contain the name of the tag. * mTextValue used to contain the name of the tag.
* But for the sake of performance we now rely on the tagID * But for the sake of performance we now rely on the tagID
@ -429,7 +429,7 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CEndToken::GetSource(nsString& anOutputString){ void CEndToken::GetSource(nsString& anOutputString){
anOutputString="</"; anOutputString+="</";
anOutputString+=mTextValue; anOutputString+=mTextValue;
anOutputString+=">"; anOutputString+=">";
} }
@ -486,8 +486,8 @@ PRInt32 CTextToken::GetTokenType(void) {
* @param aScanner -- controller of underlying input source * @param aScanner -- controller of underlying input source
* @return error result * @return error result
*/ */
nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {;
static nsString theTerminals("\n\r&<",4); static nsString theTerminals("\n\r&<",4);
nsresult result=NS_OK; nsresult result=NS_OK;
PRBool done=PR_FALSE; PRBool done=PR_FALSE;
@ -1176,7 +1176,7 @@ void CAttributeToken::DebugDumpToken(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CAttributeToken::GetSource(nsString& anOutputString){ void CAttributeToken::GetSource(nsString& anOutputString){
anOutputString=mTextKey; anOutputString+=mTextKey;
anOutputString+="="; anOutputString+="=";
anOutputString+=mTextValue; anOutputString+=mTextValue;
anOutputString+=";"; anOutputString+=";";
@ -1670,7 +1670,7 @@ void CEntityToken::DebugDumpSource(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CEntityToken::GetSource(nsString& anOutputString){ void CEntityToken::GetSource(nsString& anOutputString){
anOutputString="&"; anOutputString+="&";
anOutputString+=mTextValue; anOutputString+=mTextValue;
//anOutputString+=";"; //anOutputString+=";";
} }

Просмотреть файл

@ -183,7 +183,7 @@ nsString& CToken::GetStringValueXXX(void) {
* @return reference to string containing string value * @return reference to string containing string value
*/ */
void CToken::GetSource(nsString& anOutputString){ void CToken::GetSource(nsString& anOutputString){
anOutputString=mTextValue; anOutputString+=mTextValue;
} }
/** /**

Просмотреть файл

@ -209,7 +209,7 @@ nsCParserNode* CNavDTD::CreateNode(void) {
void CNavDTD::RecycleNode(nsCParserNode* aNode) { void CNavDTD::RecycleNode(nsCParserNode* aNode) {
if(aNode && (!aNode->mUseCount)) { if(aNode && (!aNode->mUseCount)) {
if(aNode->mToken) { if(aNode->mToken) {
if(!aNode->mToken->mUseCount) { if(!aNode->mToken->mUseCount) {
mTokenRecycler->RecycleToken(aNode->mToken); mTokenRecycler->RecycleToken(aNode->mToken);
} }
@ -694,8 +694,8 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eHTMLTag_comment: case eHTMLTag_comment:
case eHTMLTag_script: case eHTMLTag_script:
case eHTMLTag_markupDecl: 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_newline:
case eHTMLTag_whitespace: case eHTMLTag_whitespace:
if(mMisplacedContent.GetSize()<=0) // fix for bugs 17017,18308,23765, and 24275 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()); eHTMLTokenTypes theType=eHTMLTokenTypes(theNextToken->GetTokenType());
if(eToken_newline==theType){ if(eToken_newline==theType){
mLineNumber++; 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
}//if }//if
} }
@ -1017,31 +1018,33 @@ nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsI
} }
if(theChildAgrees && theChildIsContainer) { 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)) { if(nsHTMLElement::IsBlockCloser(theParentTag)) {
PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag); PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) { if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
/*------------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------------
1. Here's a tricky case from bug 22596: <h5><li><h5> 1. Here's a tricky case from bug 22596: <h5><li><h5>
How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>? How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
(Afterall, the <h5> is a legal child of the <LI>). (Afterall, the <h5> is a legal child of the <LI>).
The way you know is that there is no root between the two, so the <h5> binds more The way you know is that there is no root between the two, so the <h5> binds more
tightly to the 1st <h5> than to the <LI>. tightly to the 1st <h5> than to the <LI>.
2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN> 2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
From this case we learned not to execute this logic if the parent is a block. From this case we learned not to execute this logic if the parent is a block.
-------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------------*/
theChildAgrees=CanBeContained(aChildTag,*mBodyContext); theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
} //if } //if
}//if }//if
}
} //if } //if
} //if } //if
} //if parentcontains } //if parentcontains
@ -2028,23 +2031,22 @@ nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) {
eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType();
mScratch.Truncate();
// Dont worry about attributes here because it's already stored in // Dont worry about attributes here because it's already stored in
// the start token as mTrailing content and will get appended in // the start token as mTrailing content and will get appended in
// start token's GetSource(); // start token's GetSource();
if(eToken_attribute!=theTokenType) { if(eToken_attribute!=theTokenType) {
if (eToken_entity==theTokenType) { if (eToken_entity==theTokenType) {
if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) { if((eHTMLTag_textarea==theNodeTag) || (eHTMLTag_title==theNodeTag)) {
mScratch.Truncate();
((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch); ((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
// since this is an entity, we know that it's only one character. // 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 // check to see if it's a CR, in which case we'll need to do line
// termination conversion at the end. // termination conversion at the end.
aMustConvertLinebreaks |= (mScratch[0] == kCR); aMustConvertLinebreaks |= (mScratch[0] == kCR);
aNode.mSkippedContent->Append(mScratch);
} }
} }
else theNextToken->GetSource(mScratch); else theNextToken->GetSource(*aNode.mSkippedContent);
aNode.mSkippedContent->Append(mScratch);
} }
mTokenRecycler->RecycleToken(theNextToken); mTokenRecycler->RecycleToken(theNextToken);
} }
@ -2684,8 +2686,9 @@ nsresult CNavDTD::CloseBody(const nsIParserNode *aNode){
* @return TRUE if ok, FALSE if error * @return TRUE if ok, FALSE if error
*/ */
nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){ nsresult CNavDTD::OpenForm(const nsIParserNode *aNode){
static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_col, // Include TD and TH to fix bug 29735.
eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup}; static eHTMLTags gTableElements[]={eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th,
eHTMLTag_col,eHTMLTag_tfoot,eHTMLTag_thead,eHTMLTag_colgroup};
if(mHasOpenForm) if(mHasOpenForm)
CloseForm(aNode); CloseForm(aNode);
@ -3116,7 +3119,9 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
} }
} }
else if(1==theNode->mUseCount) { 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->PopStyle(theTag);
} }
mBodyContext->PushStyles(theChildStyleStack); mBodyContext->PushStyles(theChildStyleStack);
@ -3348,7 +3353,10 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){
eHTMLTags theTag=(eHTMLTags)aNode->GetNodeType(); 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))) { if(HasOpenContainer(gNoXTags,sizeof(gNoXTags)/sizeof(eHTMLTag_unknown))) {
return result; return result;
} }
@ -3374,10 +3382,13 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){
} }
else result=AddLeaf(aNode); else result=AddLeaf(aNode);
// XXX If the return value tells us to block, go // XXX If the return value tells us to block, go
// ahead and close the tag out anyway, since its // ahead and close the tag out anyway, since its
// contents will be consumed. // contents will be consumed.
if (NS_SUCCEEDED(result)) {
// Fix for Bug 31392
// Do not leave a head context open no matter what the result is.
if(mHasOpenHead) {
nsresult rv=CloseHead(aNode); nsresult rv=CloseHead(aNode);
// XXX Only send along a failure. If the close // XXX Only send along a failure. If the close
// succeeded we still may need to indicate that the // succeeded we still may need to indicate that the

Просмотреть файл

@ -73,23 +73,14 @@ nsEntryStack::~nsEntryStack() {
MOZ_COUNT_DTOR(nsEntryStack); MOZ_COUNT_DTOR(nsEntryStack);
if(mEntries) { if(mEntries) {
if(0<mCount) { //add code here to recycle the node if you have one...
PRInt32 anIndex=0;
for(anIndex=0;anIndex<mCount;anIndex++){
if(mEntries[anIndex].mStyles)
delete mEntries[anIndex].mStyles;
//add code here to recycle the node if you have one...
}
}
delete [] mEntries; delete [] mEntries;
mEntries=0; mEntries=0;
} }
mCount=mCapacity=0; mCount=mCapacity=0;
} }
/** /**
* Resets state of stack to be empty. * Resets state of stack to be empty.
* @update harishd 04/04/99 * @update harishd 04/04/99
@ -117,7 +108,7 @@ void nsEntryStack::EnsureCapacityFor(PRInt32 aNewMax,PRInt32 aShiftOffset) {
for(index=0;index<mCount;index++) { for(index=0;index<mCount;index++) {
temp[aShiftOffset+index]=mEntries[index]; temp[aShiftOffset+index]=mEntries[index];
} }
delete [] mEntries; if(mEntries) delete [] mEntries;
mEntries=temp; mEntries=temp;
} }
else{ else{
@ -562,8 +553,15 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
} }
else theStyles->Append(aStyles); else theStyles->Append(aStyles);
} //if } //if(theEntry )
}//if 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){ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
PRInt32 theLevel=0; PRInt32 theLevel=0;
nsIParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
if(theStack) { if(theStack) {
if(aTag==theStack->Last()) { if(aTag==theStack->Last()) {
result=theStack->Pop();
mResidualStyleCount--; mResidualStyleCount--;
return theStack->Pop();
} else { } else {
// NS_ERROR("bad residual style entry"); // NS_ERROR("bad residual style entry");
} }
} }
} }
return 0; return result;
} }
/** /**
@ -619,20 +618,21 @@ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
PRInt32 theLevel=0; PRInt32 theLevel=0;
nsIParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) { for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles; nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
if(theStack) { if(theStack) {
if(aTag==theStack->Last()) { if(aTag==theStack->Last()) {
result=theStack->Pop();
mResidualStyleCount--; mResidualStyleCount--;
return theStack->Pop();
} else { } else {
// NS_ERROR("bad residual style entry"); // NS_ERROR("bad residual style entry");
} }
} }
} }
return 0; return result;
} }
/************************************************************** /**************************************************************

Просмотреть файл

@ -136,7 +136,8 @@ TagList gDTCloseTags={3,{eHTMLTag_dt,eHTMLTag_dd,eHTMLTag_p}};
TagList gULCloseTags={1,{eHTMLTag_li}}; 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. //Lastly, bind tags with their rules, their special parents and special kids.
@ -1389,10 +1390,12 @@ PRBool nsHTMLElement::IsBlockCloser(eHTMLTags aTag){
if(!result) { if(!result) {
// NOBR is a block closure - Ref. Bug# 24462 // NOBR is a block closure - Ref. Bug# 24462
// DIR is a block closure -- Ref. Bug# 25845 // 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, static eHTMLTags gClosers[]={ eHTMLTag_table,eHTMLTag_tbody,eHTMLTag_caption,eHTMLTag_dd,eHTMLTag_dt,
eHTMLTag_td,eHTMLTag_th, eHTMLTag_td,eHTMLTag_th,eHTMLTag_tr,
/* eHTMLTag_tfoot, eHTMLTag_thead,eHTMLTag_tr, */ /* eHTMLTag_tfoot, eHTMLTag_thead,*/
eHTMLTag_nobr,eHTMLTag_optgroup,eHTMLTag_ol,eHTMLTag_ul,eHTMLTag_dir}; eHTMLTag_nobr,eHTMLTag_optgroup,eHTMLTag_ol,eHTMLTag_ul,eHTMLTag_dir};
result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body)); result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body));
@ -1549,6 +1552,45 @@ PRBool nsHTMLElement::CanExclude(eHTMLTags aChild) const{
return result; 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. <table><tr><td><div><td></tr></table>
// 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 * @update gess 01/04/99
@ -1907,12 +1949,9 @@ PRBool nsHTMLElement::CanContain(eHTMLTags aChild) const{
if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount)) if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount))
return PR_FALSE; return PR_FALSE;
} }
if(gHTMLElements[aChild].mExcludableParents) { if(gHTMLElements[aChild].IsExcludableParent(mTagID))
TagList* theParents=gHTMLElements[aChild].mExcludableParents; return PR_FALSE;
if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount))
return PR_FALSE;
}
if(gHTMLElements[aChild].IsBlockCloser(aChild)){ if(gHTMLElements[aChild].IsBlockCloser(aChild)){
if(nsHTMLElement::IsBlockParent(mTagID)){ if(nsHTMLElement::IsBlockParent(mTagID)){

Просмотреть файл

@ -171,6 +171,7 @@ struct nsHTMLElement {
PRBool CanAutoCloseTag(nsDTDContext& aContext,eHTMLTags aTag) const; PRBool CanAutoCloseTag(nsDTDContext& aContext,eHTMLTags aTag) const;
PRBool HasSpecialProperty(PRInt32 aProperty) const; PRBool HasSpecialProperty(PRInt32 aProperty) const;
PRBool IsSpecialParent(eHTMLTags aTag) const; PRBool IsSpecialParent(eHTMLTags aTag) const;
PRBool IsExcludableParent(eHTMLTags aParent) const;
PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch); PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch);
static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild); static PRBool CanContain(eHTMLTags aParent,eHTMLTags aChild);

Просмотреть файл

@ -297,7 +297,7 @@ void CStartToken::DebugDumpSource(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CStartToken::GetSource(nsString& anOutputString){ void CStartToken::GetSource(nsString& anOutputString){
anOutputString="<"; anOutputString+="<";
/* /*
* mTextValue used to contain the name of the tag. * mTextValue used to contain the name of the tag.
* But for the sake of performance we now rely on the tagID * But for the sake of performance we now rely on the tagID
@ -429,7 +429,7 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CEndToken::GetSource(nsString& anOutputString){ void CEndToken::GetSource(nsString& anOutputString){
anOutputString="</"; anOutputString+="</";
anOutputString+=mTextValue; anOutputString+=mTextValue;
anOutputString+=">"; anOutputString+=">";
} }
@ -486,8 +486,8 @@ PRInt32 CTextToken::GetTokenType(void) {
* @param aScanner -- controller of underlying input source * @param aScanner -- controller of underlying input source
* @return error result * @return error result
*/ */
nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) {;
static nsString theTerminals("\n\r&<",4); static nsString theTerminals("\n\r&<",4);
nsresult result=NS_OK; nsresult result=NS_OK;
PRBool done=PR_FALSE; PRBool done=PR_FALSE;
@ -1176,7 +1176,7 @@ void CAttributeToken::DebugDumpToken(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CAttributeToken::GetSource(nsString& anOutputString){ void CAttributeToken::GetSource(nsString& anOutputString){
anOutputString=mTextKey; anOutputString+=mTextKey;
anOutputString+="="; anOutputString+="=";
anOutputString+=mTextValue; anOutputString+=mTextValue;
anOutputString+=";"; anOutputString+=";";
@ -1670,7 +1670,7 @@ void CEntityToken::DebugDumpSource(nsOutputStream& out) {
* @return nada * @return nada
*/ */
void CEntityToken::GetSource(nsString& anOutputString){ void CEntityToken::GetSource(nsString& anOutputString){
anOutputString="&"; anOutputString+="&";
anOutputString+=mTextValue; anOutputString+=mTextValue;
//anOutputString+=";"; //anOutputString+=";";
} }

Просмотреть файл

@ -183,7 +183,7 @@ nsString& CToken::GetStringValueXXX(void) {
* @return reference to string containing string value * @return reference to string containing string value
*/ */
void CToken::GetSource(nsString& anOutputString){ void CToken::GetSource(nsString& anOutputString){
anOutputString=mTextValue; anOutputString+=mTextValue;
} }
/** /**