diff --git a/mozilla/htmlparser/src/CNavDTD.cpp b/mozilla/htmlparser/src/CNavDTD.cpp index da6f31eae43..7ef008c72d2 100644 --- a/mozilla/htmlparser/src/CNavDTD.cpp +++ b/mozilla/htmlparser/src/CNavDTD.cpp @@ -138,8 +138,7 @@ NS_IMPL_RELEASE(CNavDTD) */ CNavDTD::CNavDTD() : nsIDTD(), mMisplacedContent(0), - mSkippedContent(0), - mSharedNodes(0) { + mSkippedContent(0) { NS_INIT_REFCNT(); mSink = 0; mParser=0; @@ -165,8 +164,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mHeadContext=new nsDTDContext(); mBodyContext=new nsDTDContext(); - mNodeRecycler=0; - #ifdef RICKG_DEBUG //DebugDumpContainmentRules2(*this,"c:/temp/DTDRules.new","New CNavDTD Containment Rules"); nsHTMLElement::DebugDumpContainment("c:/temp/contain.new","ElementTable Rules"); @@ -189,22 +186,10 @@ void CNavDTD::RecycleNodes(nsEntryStack *aNodeStack) { PRInt32 theIndex=0; for(theIndex=0;theIndexNodeAt(theIndex); - if(theNode) { - - theNode->mUseCount=0; - - IF_FREE(theNode->mToken); - - CToken* theToken=0; - while((theToken=(CToken*)theNode->PopAttributeToken())){ - IF_FREE(theToken); - } - - mNodeRecycler->RecycleNode(theNode); - } //if - } //while - } //if + nsIParserNode* node=aNodeStack->NodeAt(theIndex); + NS_IF_RELEASE(node); + } + } } /** @@ -282,9 +267,6 @@ CNavDTD::~CNavDTD(){ mTempContext=0; } - // delete mNodeRecycler; - - if(mSink) { nsLoggingSink *theLogSink=GetLoggingSink(); if(mSink==theLogSink) { @@ -498,8 +480,6 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke mTokenAllocator=mTokenizer->GetTokenAllocator(); - result=mBodyContext->GetNodeRecycler(mNodeRecycler); // Get a copy... - if(NS_FAILED(result)) return result; if(mSink) { @@ -609,14 +589,14 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse while(mBodyContext->GetCount() > 0) { nsEntryStack *theChildStyles=0; - nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles); - theNode->mUseCount=0; - mNodeRecycler->RecycleNode(theNode); - if(theChildStyles) { - delete theChildStyles; + nsIParserNode* theNode=mBodyContext->Pop(theChildStyles); + if(theNode) { + if(theChildStyles) { + delete theChildStyles; + } + NS_IF_RELEASE(theNode); } } - } STOP_TIMER(); @@ -891,7 +871,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ * @param aChildTag is the tag itself. * @return status */ -nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ +nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){ nsresult result=NS_OK; #if 0 @@ -983,10 +963,11 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ break; }//switch - //handle tags by generating a close tag... - //added this to fix bug 48351, which contains XHTML and uses empty tags. - if(nsHTMLElement::IsContainer(aChildTag) && aNode.mToken) { //nullptr test fixes bug 56085 - CStartToken *theToken=NS_STATIC_CAST(CStartToken*,aNode.mToken); + //handle tags by generating a close tag... + //added this to fix bug 48351, which contains XHTML and uses empty tags. + nsCParserNode* theNode=NS_STATIC_CAST(nsCParserNode*,&aNode); + if(nsHTMLElement::IsContainer(aChildTag) && theNode && theNode->mToken) { //nullptr test fixes bug 56085 + CStartToken *theToken=NS_STATIC_CAST(CStartToken*,theNode->mToken); if(theToken->IsEmpty()){ CToken *theEndToken=mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag); @@ -1295,7 +1276,7 @@ void WriteTokenToLog(CToken* aToken) { * @param aNode is the node (tag) with associated attributes. * @return TRUE if tag processing should continue; FALSE if the tag has been handled. */ -nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode& aNode){ +nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode& aNode) { nsresult result=NS_OK; PRInt32 theAttrCount = aNode.GetAttributeCount(); @@ -1580,8 +1561,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { //Begin by gathering up attributes... - nsCParserNode* theNode=mNodeRecycler->CreateNode(); - theNode->Init(aToken,mLineNumber,mTokenAllocator); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,mTokenAllocator); eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID(); PRInt16 attrCount=aToken->GetAttributeCount(); @@ -1697,7 +1677,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { result=NS_OK; } - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); return result; } @@ -2006,7 +1986,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) { nsEntryStack* theChildStyleStack=0; for(i=0; i<(theTagCount - theTopIndex); i++) { - mTempContext->Push((nsCParserNode*)mBodyContext->Pop(theChildStyleStack)); + nsIParserNode* node=mBodyContext->Pop(theChildStyleStack); + mTempContext->Push(node); + NS_IF_RELEASE(node); //release the popped node since push will addref for us. } // Now flush out all the bad contents. @@ -2047,7 +2029,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) { // Bad-contents were successfully processed. Now, itz time to get // back to the original body context state. for(PRInt32 k=0; k<(theTagCount - theTopIndex); k++) { - mBodyContext->Push((nsCParserNode*)mTempContext->Pop(theChildStyleStack)); + nsIParserNode* node=mTempContext->Pop(theChildStyleStack); + mBodyContext->Push(node); + NS_IF_RELEASE(node); } STOP_TIMER() @@ -2098,23 +2082,20 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) { eHTMLTags theParentTag=mBodyContext->Last(); - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute... if(CanOmit(theParentTag,eHTMLTag_entity,theParentContains)) { eHTMLTags theCurrTag=(eHTMLTags)aToken->GetTypeID(); result=HandleOmittedTag(aToken,theCurrTag,theParentTag,theNode); - mNodeRecycler->RecycleNode(theNode); - return result; } - - #ifdef RICKG_DEBUG - WriteTokenToLog(aToken); - #endif - - result=AddLeaf(theNode); - mNodeRecycler->RecycleNode(theNode); + else { +#ifdef RICKG_DEBUG + WriteTokenToLog(aToken); +#endif + result=AddLeaf(theNode); + } + NS_IF_RELEASE(theNode); } return result; } @@ -2138,9 +2119,8 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) { const nsAReadableString& theComment = theToken->GetStringValue(); mLineNumber += CountCharInReadable(theComment, PRUnichar(kNewLine)); - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); #ifdef RICKG_DEBUG WriteTokenToLog(aToken); @@ -2151,7 +2131,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) { result=(mSink) ? mSink->AddComment(*theNode) : NS_OK; - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this)); START_TIMER(); @@ -2215,9 +2195,8 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){ nsresult result=NS_OK; - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); #ifdef RICKG_DEBUG WriteTokenToLog(aToken); @@ -2228,7 +2207,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){ result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK; - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this)); START_TIMER(); @@ -2266,9 +2245,8 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ docTypeStr.Cut(0,2); // Now remove "SetStringValue(docTypeStr); - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this)); @@ -2290,7 +2268,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ result = (mSink)? mSink->AddDocTypeDecl(*theNode,theMode):NS_OK; - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this)); START_TIMER(); @@ -2308,7 +2286,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ * @param aCount is the # of attributes you're expecting * @return error code (should be 0) */ -nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ +nsresult CNavDTD::CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ int attr=0; nsresult result=NS_OK; @@ -2319,7 +2297,8 @@ nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 for(attr=0;attrPopToken(); + else + theToken=mTokenizer->PopToken(); if(theToken) { eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); if(theType!=eToken_attribute) { @@ -2359,7 +2338,7 @@ nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 * @param holds the number of skipped content elements encountered * @return Error condition. */ -nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) { +nsresult CNavDTD::CollectSkippedContent(nsIParserNode& aNode,PRInt32 &aCount) { eHTMLTags theNodeTag=(eHTMLTags)aNode.GetNodeType(); @@ -2371,54 +2350,58 @@ nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) { PRBool aMustConvertLinebreaks = PR_FALSE; mScratch.Truncate(); - aNode.SetSkippedContent(mScratch); //this guarantees us some skipped content storage. + + nsCParserNode* theNode=NS_STATIC_CAST(nsCParserNode*,&aNode); + if(theNode) { + theNode->SetSkippedContent(mScratch); //this guarantees us some skipped content storage. - for(aIndex=0;aIndexGetTokenType(); + eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); - // 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) && - ((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. - if(mScratch.Length()>0){ - aMustConvertLinebreaks |= (mScratch[0] == kCR); - aNode.mSkippedContent->Append(mScratch); + // 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) && + ((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. + if(mScratch.Length()>0){ + aMustConvertLinebreaks |= (mScratch[0] == kCR); + theNode->mSkippedContent->Append(mScratch); + } } - } - else theNextToken->AppendSource(*aNode.mSkippedContent); + else theNextToken->AppendSource(*theNode->mSkippedContent); + } + IF_FREE(theNextToken); } - IF_FREE(theNextToken); + + // if the string contained CRs (hence is either CR, or CRLF terminated) + // we need to convert line breaks + if (aMustConvertLinebreaks) + { + /* + PRInt32 offset; + while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound) + aNode.mSkippedContent.Cut(offset, 1); // remove the CR + + // now replace remaining CRs with LFs + aNode.mSkippedContent.ReplaceChar("\r", kNewLine); + */ + #if 1 + nsLinebreakConverter::ConvertStringLineBreaks(*theNode->mSkippedContent, + nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent); + #endif + } + + // Let's hope that this does not hamper the PERFORMANCE!! + mLineNumber += theNode->mSkippedContent->CountChar(kNewLine); } - - // if the string contained CRs (hence is either CR, or CRLF terminated) - // we need to convert line breaks - if (aMustConvertLinebreaks) - { - /* - PRInt32 offset; - while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound) - aNode.mSkippedContent.Cut(offset, 1); // remove the CR - - // now replace remaining CRs with LFs - aNode.mSkippedContent.ReplaceChar("\r", kNewLine); - */ -#if 1 - nsLinebreakConverter::ConvertStringLineBreaks(*aNode.mSkippedContent, - nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent); -#endif - } - - // Let's hope that this does not hamper the PERFORMANCE!! - mLineNumber += aNode.mSkippedContent->CountChar(kNewLine); return NS_OK; } @@ -2862,10 +2845,8 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){ } else { //if the node tag can't contain the child tag, then remove the child tag from the style stack - nsCParserNode* theRemovedNode=(nsCParserNode*)theStack->Remove(sindex,theNodeTag); - if(theRemovedNode) { - mNodeRecycler->RecycleNode(theRemovedNode); - } + nsIParserNode* node=theStack->Remove(sindex,theNodeTag); + NS_IF_RELEASE(node); theEntry--; //back up by one } } //if @@ -2932,10 +2913,8 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){ if(mStyleHandlingEnabled) { #ifdef ENABLE_RESIDUALSTYLE if(nsHTMLElement::IsResidualStyleTag(aTag)) { - nsCParserNode* theNode=(nsCParserNode*)mBodyContext->PopStyle(aTag); - if(theNode) { - mNodeRecycler->RecycleNode(theNode); - } + nsIParserNode* node=mBodyContext->PopStyle(aTag); + NS_IF_RELEASE(node); } #endif } //if @@ -3547,8 +3526,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC nsEntryStack *theChildStyleStack=0; eHTMLTags theTag=mBodyContext->Last(); - nsCParserNode *theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyleStack); -// eHTMLTags theParent=mBodyContext->Last(); + nsCParserNode *theNode=NS_STATIC_CAST(nsCParserNode*,mBodyContext->Pop(theChildStyleStack)); if(theNode) { result=CloseContainer(theNode,aTarget,aClosedByStartTag); @@ -3561,15 +3539,12 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC if(!theStyleDoesntLeakOut) { theStyleDoesntLeakOut = gHTMLElements[aTarget].HasSpecialProperty(kNoStyleLeaksOut); } - // (aClosedByStartTag) ? gHTMLElements[aTarget].HasSpecialProperty(kNoStyleLeaksOut) - // : gHTMLElements[theParent].HasSpecialProperty(kNoStyleLeaksOut); - - - /************************************************************* - I've added a check (mhasOpenNoXXX) below to prevent residual - style handling from getting invoked in these cases. - This fixes bug 25214. - *************************************************************/ + + /************************************************************* + I've added a check (mhasOpenNoXXX) below to prevent residual + style handling from getting invoked in these cases. + This fixes bug 25214. + *************************************************************/ if(theTagIsStyle && (0==mHasOpenNoXXX)) { @@ -3598,7 +3573,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC //here's a case we missed: //The
pushes the 1st onto the rs-stack, then the 2nd //pops the 1st from the rs-stack altogether. - mBodyContext->PopStyle(theTag); + nsIParserNode* node=mBodyContext->PopStyle(theTag); + NS_IF_RELEASE(node); } @@ -3643,7 +3619,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC // 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); + nsIParserNode* node=mBodyContext->PopStyle(theTag); + NS_IF_RELEASE(node); } mBodyContext->PushStyles(theChildStyleStack); } @@ -3667,7 +3644,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC //style tag that got onto that tag stack from a stylestack somewhere. //Pop it from the stylestack if the target is also a style tag. if(theTargetTagIsStyle) { - theNode=(nsCParserNode*)mBodyContext->PopStyle(theTag); + nsIParserNode* node=mBodyContext->PopStyle(theTag); + NS_IF_RELEASE(node); } } } @@ -3684,8 +3662,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC } } #endif - }//if anode - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); + }//if theNode } } //if @@ -3769,7 +3747,7 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ while(!done && NS_SUCCEEDED(result)) { CToken* theToken=mTokenizer->PeekToken(); if(theToken) { - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(theToken,mLineNumber,0); if(theNode) { theTag=(eHTMLTags)theToken->GetTypeID(); switch(theTag) { @@ -3778,7 +3756,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ case eHTMLTag_whitespace: { theToken=mTokenizer->PopToken(); - theNode->Init(theToken,mLineNumber,0); STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); @@ -3798,7 +3775,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ if((mHasOpenBody) && (!mHasOpenHead) && !(nsHTMLElement::IsWhitespaceTag(thePrevTag))) { theToken=mTokenizer->PopToken(); - theNode->Init(theToken,mLineNumber); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); STOP_TIMER(); @@ -3819,7 +3795,7 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ default: done=PR_TRUE; } //switch - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); } //if }//if else done=PR_TRUE; diff --git a/mozilla/htmlparser/src/CNavDTD.h b/mozilla/htmlparser/src/CNavDTD.h index e9cfd65f7c6..3915b6b4e6a 100644 --- a/mozilla/htmlparser/src/CNavDTD.h +++ b/mozilla/htmlparser/src/CNavDTD.h @@ -91,6 +91,7 @@ #include "nsDeque.h" #include "nsParserCIID.h" #include "nsTime.h" +#include "nsDTDUtils.h" #define NS_INAVHTML_DTD_IID \ {0x5c5cce40, 0xcfd6, 0x11d1, \ @@ -106,7 +107,6 @@ class nsEntryStack; class nsITokenizer; class nsCParserNode; class nsTokenAllocator; -class CNodeRecycler; /*************************************************************** Now the main event: CNavDTD. @@ -484,10 +484,10 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD { protected: - nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); - nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount); - nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode); - nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag); + nsresult CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); + nsresult CollectSkippedContent(nsIParserNode& aNode,PRInt32& aCount); + nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); + nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag); nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode); nsresult HandleSavedTokens(PRInt32 anIndex); nsresult HandleKeyGen(nsIParserNode *aNode); @@ -513,13 +513,12 @@ protected: nsParser* mParser; nsITokenizer* mTokenizer; nsTokenAllocator* mTokenAllocator; - CNodeRecycler* mNodeRecycler; + nsNodeAllocator mNodeAllocator; nsDeque mMisplacedContent; nsDeque mSkippedContent; PRBool mHasOpenScript; PRBool mSaveBadTokens; eHTMLTags mSkipTarget; - nsDeque mSharedNodes; nsresult mDTDState; nsDTDMode mDTDMode; eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors... diff --git a/mozilla/htmlparser/src/COtherDTD.cpp b/mozilla/htmlparser/src/COtherDTD.cpp index 9b2f7bcd696..716ae924aa8 100644 --- a/mozilla/htmlparser/src/COtherDTD.cpp +++ b/mozilla/htmlparser/src/COtherDTD.cpp @@ -129,7 +129,7 @@ NS_IMPL_RELEASE(COtherDTD) * @param * @return */ -COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { +COtherDTD::COtherDTD() : nsIDTD() { NS_INIT_REFCNT(); mSink = 0; mParser=0; @@ -149,6 +149,7 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { mHadBody=PR_FALSE; mHasOpenScript=PR_FALSE; mParserCommand=eViewNormal; + mNodeAllocator=new nsNodeAllocator(); mBodyContext=new nsDTDContext(); #if 1 //set this to 1 if you want strictDTD to be based on the environment setting. @@ -169,36 +170,8 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { nsHTMLElement::DebugDumpContainType("c:/temp/ctnrules.out"); #endif -#ifdef NS_DEBUG - gNodeCount=0; -#endif } -/** - * This method creates a new parser node. It tries to get one from - * the recycle list before allocating a new one. - * @update gess1/8/99 - * @param - * @return valid node* - */ -nsCParserNode* COtherDTD::CreateNode(void) { - - nsCParserNode* result=0; - if(0GetTokenAllocator(); mBodyContext->SetTokenAllocator(mTokenAllocator); + mBodyContext->SetNodeAllocator(mNodeAllocator); if(mSink) { @@ -529,10 +486,10 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles); if(theNode) { theNode->mUseCount=0; - mBodyContext->RecycleNode(theNode); if(theChildStyles) { delete theChildStyles; } + NS_IF_RELEASE(theNode); } } } @@ -606,7 +563,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){ * @param aChildTag is the tag itself. * @return status */ -nsresult COtherDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ +nsresult COtherDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){ nsresult result=NS_OK; switch(aChildTag){ @@ -683,7 +640,7 @@ void WriteTokenToLog(CToken* aToken) { * @param aNode is the node (tag) with associated attributes. * @return TRUE if tag processing should continue; FALSE if the tag has been handled. */ -nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode& aNode){ +nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode& aNode){ nsresult result=NS_OK; //first let's see if there's some skipped content to deal with... @@ -743,9 +700,8 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) { //Begin by gathering up attributes... nsresult result=NS_OK; - nsCParserNode* theNode=CreateNode(); + nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator); if(theNode) { - theNode->Init(aToken,mLineNumber,mTokenAllocator); eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID(); PRInt16 attrCount=aToken->GetAttributeCount(); @@ -786,7 +742,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) { } //if }//if - mBodyContext->RecycleNode(theNode); + NS_IF_RELEASE(theNode); } else result=NS_ERROR_OUT_OF_MEMORY; @@ -831,11 +787,10 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) { } CElement* theElement=gElementTable->mElements[theParent]; if(theElement) { - nsCParserNode* theNode=CreateNode(); + nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator); if(theNode) { - theNode->Init(aToken,mLineNumber,mTokenAllocator); result=theElement->HandleEndToken(theNode,theChildTag,mBodyContext,mSink); - mBodyContext->RecycleNode((nsCParserNode*)theNode); + NS_IF_RELEASE(theNode); } } break; @@ -853,7 +808,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) { * @param aCount is the # of attributes you're expecting * @return error code (should be 0) */ -nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ +nsresult COtherDTD::CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ int attr=0; nsresult result=NS_OK; diff --git a/mozilla/htmlparser/src/COtherDTD.h b/mozilla/htmlparser/src/COtherDTD.h index d2fd78f245e..1f2af7ba893 100644 --- a/mozilla/htmlparser/src/COtherDTD.h +++ b/mozilla/htmlparser/src/COtherDTD.h @@ -91,7 +91,6 @@ #include "nsDeque.h" #include "nsParserCIID.h" - #define NS_IOTHERHTML_DTD_IID \ {0x8a5e89c0, 0xd16d, 0x11d1, \ {0x80, 0x22, 0x00, 0x60, 0x8, 0x14, 0x98, 0x89}} @@ -103,8 +102,9 @@ class nsParser; class nsDTDContext; class nsEntryStack; class nsITokenizer; -class nsCParserNode; +class nsIParserNode; class nsTokenAllocator; +class nsNodeAllocator; /*************************************************************** Now the main event: COtherDTD. @@ -313,10 +313,10 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD { protected: - nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); - nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode); - nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag); - nsCParserNode* CreateNode(void); + nsresult CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); + nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); + nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag); + nsIParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); nsIHTMLContentSink* mSink; @@ -332,10 +332,10 @@ protected: PRInt32 mLineNumber; nsParser* mParser; nsITokenizer* mTokenizer; - nsTokenAllocator* mTokenAllocator; + nsTokenAllocator* mTokenAllocator; + nsNodeAllocator* mNodeAllocator; PRBool mHasOpenScript; eHTMLTags mSkipTarget; - nsDeque mSharedNodes; nsresult mDTDState; nsDTDMode mDTDMode; eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors... @@ -346,10 +346,6 @@ protected: eParserDocType mDocType; PRBool mEnableStrict; -#ifdef NS_DEBUG - PRInt32 gNodeCount; -#endif - }; extern NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult); diff --git a/mozilla/htmlparser/src/COtherElements.h b/mozilla/htmlparser/src/COtherElements.h index 6f261ba8817..2e5410f7094 100644 --- a/mozilla/htmlparser/src/COtherElements.h +++ b/mozilla/htmlparser/src/COtherElements.h @@ -323,8 +323,7 @@ public: CElement *theElement=(aTag==mTag) ? this : GetElement(aTag); result=theElement->NotifyClose(theNode,aTag,aContext,aSink); - aContext->RecycleNode((nsCParserNode*)theNode); - + NS_IF_RELEASE(aNode); return result; } @@ -808,9 +807,8 @@ public: if(aContext->mTableStates) { if(aContext->mTableStates->CanOpenTBody()) { - nsCParserNode* theNode=aContext->gNodeRecycler->CreateNode(); CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_tbody); - theNode->Init(theToken,0,0); //this will likely leak... + nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0); result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink); } @@ -1797,8 +1795,7 @@ public: //let's auto open the body CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body); - nsCParserNode* theNode=aContext->gNodeRecycler->CreateNode(); - theNode->Init(theToken,0,0); + nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0); result=theBody->HandleStartToken(theNode,eHTMLTag_body,aContext,aSink); diff --git a/mozilla/htmlparser/src/nsDTDUtils.cpp b/mozilla/htmlparser/src/nsDTDUtils.cpp index 3033f757597..5ca27e7bbcf 100644 --- a/mozilla/htmlparser/src/nsDTDUtils.cpp +++ b/mozilla/htmlparser/src/nsDTDUtils.cpp @@ -132,6 +132,9 @@ void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) { mEntries[mCount].mTag=(eHTMLTags)aNode->GetNodeType(); mEntries[mCount].mNode=(nsIParserNode*)aNode; + + NS_ADDREF(mEntries[mCount].mNode); + mEntries[mCount].mParent=aStyleStack; mEntries[mCount++].mStyles=0; } @@ -159,6 +162,9 @@ void nsEntryStack::PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStac mEntries[0].mTag=(eHTMLTags)aNode->GetNodeType(); mEntries[0].mNode=(nsIParserNode*)aNode; + + NS_ADDREF(mEntries[0].mNode); + mEntries[0].mParent=aStyleStack; mEntries[0].mStyles=0; mCount++; @@ -210,6 +216,7 @@ nsIParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) { for(theIndex=anIndex;theIndexRecycleNode((nsCParserNode*)aStyles->Pop()); + nsIParserNode* theNode=aStyles->Pop(); + NS_IF_RELEASE(theNode); delete aStyles; aStyles=0; } @@ -1118,51 +1125,12 @@ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){ return result; } -/** - * - * @update harishd 04/10/00 - */ -nsresult nsDTDContext::GetNodeRecycler(CNodeRecycler*& aNodeRecycler){ - nsresult result=NS_OK; - if(!gNodeRecycler) { - gNodeRecycler=new CNodeRecycler(); - if(gNodeRecycler==0) result=NS_ERROR_OUT_OF_MEMORY; - } - aNodeRecycler=gNodeRecycler; - return result; -} - -/** - * - * @update rickg 16June2000 - */ -void nsDTDContext::RecycleNode(nsCParserNode* aNode) { - nsresult result=NS_OK; - - if(aNode) { - if(!gNodeRecycler) - result=nsDTDContext::GetNodeRecycler(gNodeRecycler); - - if(NS_SUCCEEDED(result)) { - gNodeRecycler->RecycleNode(aNode); - } - else { - delete aNode; - } - } -} - - /** * This gets called when the parser module is getting unloaded * * @return nada */ void nsDTDContext::ReleaseGlobalObjects(){ - if(gNodeRecycler) { - delete gNodeRecycler; - gNodeRecycler=0; - } } @@ -1170,9 +1138,9 @@ void nsDTDContext::ReleaseGlobalObjects(){ Now define the nsTokenAllocator class... **************************************************************/ -static const size_t kBucketSizes[] ={sizeof(CStartToken),sizeof(CAttributeToken),sizeof(CCommentToken),sizeof(CEndToken)}; -static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t); -static const PRInt32 kInitialPoolSize = NS_SIZE_IN_HEAP(sizeof(CToken)) * 1536; +static const size_t kTokenBuckets[] ={sizeof(CStartToken),sizeof(CAttributeToken),sizeof(CCommentToken),sizeof(CEndToken)}; +static const PRInt32 kNumTokenBuckets = sizeof(kTokenBuckets) / sizeof(size_t); +static const PRInt32 kInitialTokenPoolSize = NS_SIZE_IN_HEAP(sizeof(CToken)) * 200; /** * @@ -1183,7 +1151,7 @@ nsTokenAllocator::nsTokenAllocator() { MOZ_COUNT_CTOR(nsTokenAllocator); - mArenaPool.Init("TheTokenPool", kBucketSizes, kNumBuckets, kInitialPoolSize); + mArenaPool.Init("TokenPool", kTokenBuckets, kNumTokenBuckets, kInitialTokenPoolSize); #ifdef NS_DEBUG int i=0; @@ -1295,7 +1263,6 @@ CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag return result; } -#define DEBUG_TRACK_NODES #ifdef DEBUG_TRACK_NODES static nsCParserNode* gAllNodes[100]; @@ -1329,69 +1296,72 @@ void RemoveNode(nsCParserNode *aNode) { #endif -CNodeRecycler::CNodeRecycler(): mSharedNodes(0) { - - MOZ_COUNT_CTOR(CNodeRecycler); +#ifdef HEAP_ALLOCATED_NODES +nsNodeAllocator::nsNodeAllocator():mSharedNodes(0){ +#ifdef DEBUG_TRACK_NODES + mCount=0; +#endif +#else + static const size_t kNodeBuckets[] ={sizeof(nsCParserNode)}; + static const PRInt32 kNumNodeBuckets = sizeof(kNodeBuckets) / sizeof(size_t); + static const PRInt32 kInitialNodePoolSize = NS_SIZE_IN_HEAP(sizeof(nsCParserNode)) * 50; +nsNodeAllocator::nsNodeAllocator() { + mNodePool.Init("NodePool", kNodeBuckets, kNumNodeBuckets, kInitialNodePoolSize); +#endif + MOZ_COUNT_CTOR(nsNodeAllocator); } + +nsNodeAllocator::~nsNodeAllocator() { + MOZ_COUNT_DTOR(nsNodeAllocator); -CNodeRecycler::~CNodeRecycler() { - - MOZ_COUNT_DTOR(CNodeRecycler); - +#ifdef HEAP_ALLOCATED_NODES nsCParserNode* theNode=0; while((theNode=(nsCParserNode*)mSharedNodes.Pop())){ -#ifdef DEBUG_TRACK_NODES +#ifdef DEBUG_TRACK_NODES RemoveNode(theNode); #endif - delete theNode; + ::operator delete(theNode); + theNode=nsnull; } - #ifdef DEBUG_TRACK_NODES - if(0mUseCount)) { - - IF_FREE(aNode->mToken); +nsIParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) { + nsCParserNode* result=0; - CToken* theToken=0; - while((theToken=(CToken*)aNode->PopAttributeToken())){ - IF_FREE(theToken); - } - mSharedNodes.Push(aNode); - } -} - -nsCParserNode* CNodeRecycler::CreateNode(void) { - -#ifdef DEBUG_TRACK_NODES +#ifdef HEAP_ALLOCATED_NODES #if 0 if(gAllNodeCount!=mSharedNodes.GetSize()) { int x=10; //this is very BAD! } -#endif #endif - nsCParserNode* result=0; - if(0Init(aToken,aLineNumber,aTokenAllocator,this); } else{ - result=new nsCParserNode(); + result=new nsCParserNode(aToken,aLineNumber,aTokenAllocator,this); #ifdef DEBUG_TRACK_NODES - AddNode(result); + mCount++; + AddNode(NS_STATIC_CAST(nsCParserNode*,result)); #endif - + NS_IF_ADDREF(result); } - return result; +#else + result=new(mNodePool) nsCParserNode(aToken,aLineNumber,aTokenAllocator); + NS_IF_ADDREF(result); +#endif + return NS_STATIC_CAST(nsIParserNode*,result); } void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) { diff --git a/mozilla/htmlparser/src/nsDTDUtils.h b/mozilla/htmlparser/src/nsDTDUtils.h index 603c9456850..7338250cd5d 100644 --- a/mozilla/htmlparser/src/nsDTDUtils.h +++ b/mozilla/htmlparser/src/nsDTDUtils.h @@ -46,11 +46,11 @@ #include "nsVoidArray.h" #define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); } -#define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr +#define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr class nsIParserNode; class nsCParserNode; -class CNodeRecycler; +class nsNodeAllocator; void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle); @@ -238,7 +238,6 @@ protected: #endif }; - /************************************************************************ CNodeRecycler class implementation. This class is used to recycle nodes. @@ -246,23 +245,25 @@ protected: that get created during the run of the system. ************************************************************************/ -class CNodeRecycler { +class nsNodeAllocator { public: - CNodeRecycler(); - virtual ~CNodeRecycler(); - virtual nsCParserNode* CreateNode(void); - virtual void RecycleNode(nsCParserNode* aNode); - + nsNodeAllocator(); + virtual ~nsNodeAllocator(); + virtual nsIParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); +#ifdef HEAP_ALLOCATED_NODES + void Recycle(nsIParserNode* aNode) { mSharedNodes.Push(NS_STATIC_CAST(void*,aNode)); } protected: - nsDeque mSharedNodes; - -#ifdef NS_DEBUG - PRInt32 gNodeCount; + nsDeque mSharedNodes; +#ifdef DEBUG_TRACK_NODES + PRInt32 mCount; +#endif +#else +protected: + nsFixedSizeAllocator mNodePool; #endif }; - /************************************************************************ The dtdcontext class defines an ordered list of tags (a context). ************************************************************************/ @@ -295,8 +296,6 @@ public: nsIParserNode* PopStyle(eHTMLTags aTag); nsIParserNode* RemoveStyle(eHTMLTags aTag); - nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler); - void RecycleNode(nsCParserNode *aNode); static void ReleaseGlobalObjects(void); CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue); @@ -304,9 +303,10 @@ public: void ResetCounters(void); void AllocateCounters(void); - PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult); + PRInt32 IncrementCounter(eHTMLTags aTag,nsIParserNode& aNode,nsString& aResult); void SetTokenAllocator(nsTokenAllocator* aTokenAllocator) { mTokenAllocator=aTokenAllocator; } + void SetNodeAllocator(nsNodeAllocator* aNodeAllocator) { mNodeAllocator=aNodeAllocator; } nsEntryStack mStack; //this will hold a list of tagentries... PRInt32 mResidualStyleCount; @@ -324,12 +324,10 @@ public: union { PRUint32 mAllBits; CFlags mFlags; - }; - - - static CNodeRecycler *gNodeRecycler; + }; nsTokenAllocator *mTokenAllocator; + nsNodeAllocator *mNodeAllocator; CTableState *mTableStates; PRInt32 *mCounters; nsDeque mEntities; diff --git a/mozilla/htmlparser/src/nsIParserNode.h b/mozilla/htmlparser/src/nsIParserNode.h index 8fe06fe980b..470695e16f1 100644 --- a/mozilla/htmlparser/src/nsIParserNode.h +++ b/mozilla/htmlparser/src/nsIParserNode.h @@ -46,7 +46,11 @@ #include "nsString.h" #include "nsDebug.h" -// class CToken; +//#define HEAP_ALLOCATED_NODES +//#define DEBUG_TRACK_NODES + + +class CToken; // 6e59f160-2717-11d2-9246-00805f8a7ab6 #define NS_IPARSER_NODE_IID \ @@ -133,6 +137,9 @@ class nsIParserNode : public nsISupports { */ virtual PRInt32 TranslateToUnicodeStr(nsString& aString) const = 0; + + virtual void AddAttribute(CToken* aToken)=0; + /** * This getter retrieves the line number from the input source where * the token occured. Lines are interpreted as occuring between \n characters. diff --git a/mozilla/htmlparser/src/nsLoggingSink.cpp b/mozilla/htmlparser/src/nsLoggingSink.cpp index 69eb8653029..7ea1600cc03 100644 --- a/mozilla/htmlparser/src/nsLoggingSink.cpp +++ b/mozilla/htmlparser/src/nsLoggingSink.cpp @@ -147,7 +147,7 @@ nsLoggingSink::WillBuildModel() { NS_IMETHODIMP nsLoggingSink::DidBuildModel(PRInt32 aQualityLevel) { - WriteTabs(mOutput,mLevel--); + WriteTabs(mOutput,--mLevel); PR_fprintf(mOutput, "\n"); //proxy the call to the real sink if you have one. @@ -342,11 +342,14 @@ nsLoggingSink::AddComment(const nsIParserNode& aNode){ NS_IMETHODIMP nsLoggingSink::SetTitle(const nsString& aValue) { - nsAutoString tmp; - QuoteText(aValue, tmp); - WriteTabs(mOutput,++mLevel); - PR_fprintf(mOutput, "\n", tmp.GetBuffer()); - --mLevel; + char* tmp; + GetNewCString(aValue, &tmp); + WriteTabs(mOutput,++mLevel); + if(tmp) { + PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp); + nsMemory::Free(tmp); + } + --mLevel; nsresult theResult=NS_OK; @@ -544,9 +547,12 @@ nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) { PR_fprintf(mOutput, "\"%s\"", tag); } else { - const nsAReadableString& theText = aNode.GetText(); - PR_fprintf(mOutput, "\"%s\"", theText); - + char* text; + GetNewCString(aNode.GetText(), &text); + if(text) { + PR_fprintf(mOutput, "\"%s\"", text); + nsMemory::Free(text); + } } if (WillWriteAttributes(aNode)) { @@ -571,18 +577,25 @@ nsLoggingSink::CloseNode(const char* aKind) { nsresult nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) { - nsAutoString tmp, tmp2; + + WriteTabs(mOutput,1+mLevel); + nsAutoString tmp; PRInt32 ac = aNode.GetAttributeCount(); for (PRInt32 i = 0; i < ac; i++) { + char* key=nsnull; + char* value=nsnull; const nsAReadableString& k = aNode.GetKeyAt(i); const nsString& v = aNode.GetValueAt(i); - PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", k); + GetNewCString(k, &key); + if(key) { + PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", key); + nsMemory::Free(key); + } tmp.Truncate(); tmp.Append(v); - - if(0<tmp.Length()) { + if(tmp.Length() > 0) { PRUnichar first = tmp.First(); if ((first == '"') || (first == '\'')) { if (tmp.Last() == first) { @@ -595,20 +608,26 @@ nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) { // Mismatched quotes - leave them in } } - } - QuoteText(tmp, tmp2); - PR_fprintf(mOutput, "%s\"/>\n", tmp2.GetBuffer()); - } + GetNewCString(tmp, &value); - if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) { - const nsString& content = aNode.GetSkippedContent(); - if (content.Length() > 0) { - QuoteText(content, tmp); - PR_fprintf(mOutput, " <content value=\""); - PR_fprintf(mOutput, "%s\"/>\n", tmp.GetBuffer()) ; + if(value) { + PR_fprintf(mOutput, "%s\"/>\n", value); + WriteTabs(mOutput,1+mLevel); + nsMemory::Free(value); + } } } + if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) { + char* content; + GetNewCString(aNode.GetSkippedContent(), &content); + if(content) { + PR_fprintf(mOutput, " <content value=\""); + PR_fprintf(mOutput, "%s\"/>\n", content) ; + nsMemory::Free(content); + } + } + WriteTabs(mOutput,1+mLevel); return NS_OK; } @@ -654,11 +673,15 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) else { PRInt32 pos; nsAutoString tmp; + char* str; switch (nodeType) { case eHTMLTag_whitespace: case eHTMLTag_text: - QuoteText(aNode.GetText(), tmp); - PR_fprintf(mOutput, "<text value=\"%s\"/>\n", tmp.GetBuffer()); + GetNewCString(aNode.GetText(), &str); + if(str) { + PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str); + nsMemory::Free(str); + } break; case eHTMLTag_newline: @@ -707,6 +730,28 @@ nsLoggingSink::QuoteText(const nsAReadableString& aValue, nsString& aResult) { return NS_OK; } +/** + * Use this method to convert nsString to char*. + * REMEMBER: Match this call with nsMemory::Free(aResult); + * + * @update 04/04/99 harishd + * @param aValue - The string value + * @param aResult - String coverted to char*. + */ +nsresult +nsLoggingSink::GetNewCString(const nsAReadableString& aValue, char** aResult) +{ + nsresult result=NS_OK; + nsAutoString temp; + result=QuoteText(aValue,temp); + if(NS_SUCCEEDED(result)) { + if(temp.Length()>0) { + *aResult=temp.ToNewCString(); + } + } + return result; +} + NS_IMETHODIMP nsLoggingSink::DoFragment(PRBool aFlag) { diff --git a/mozilla/htmlparser/src/nsLoggingSink.h b/mozilla/htmlparser/src/nsLoggingSink.h index 602f22e5891..d3931bf4a28 100644 --- a/mozilla/htmlparser/src/nsLoggingSink.h +++ b/mozilla/htmlparser/src/nsLoggingSink.h @@ -86,6 +86,7 @@ public: nsresult LeafNode(const nsIParserNode& aNode); nsresult WriteAttributes(const nsIParserNode& aNode); nsresult QuoteText(const nsAReadableString& aValue, nsString& aResult); + nsresult GetNewCString(const nsAReadableString& aValue, char** aResult); PRBool WillWriteAttributes(const nsIParserNode& aNode); protected: diff --git a/mozilla/htmlparser/src/nsParserModule.cpp b/mozilla/htmlparser/src/nsParserModule.cpp index 9a2939a40f1..b290cf1d5d7 100644 --- a/mozilla/htmlparser/src/nsParserModule.cpp +++ b/mozilla/htmlparser/src/nsParserModule.cpp @@ -136,7 +136,6 @@ nsParserService::IsBlock(PRInt32 aId, PRBool& aIsBlock) const //---------------------------------------------------------------------- static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); -static NS_DEFINE_CID(kParserNodeCID, NS_PARSER_NODE_IID); static NS_DEFINE_CID(kLoggingSinkCID, NS_LOGGING_SINK_CID); static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); @@ -154,7 +153,6 @@ struct Components { static Components gComponents[] = { { "Parser", &kParserCID }, - { "ParserNode", &kParserNodeCID }, { "Logging sink", &kLoggingSinkCID }, { "Well formed DTD", &kWellFormedDTDCID }, { "Navigator HTML DTD", &kNavDTDCID }, @@ -169,7 +167,6 @@ static Components gComponents[] = { #define NUM_COMPONENTS (sizeof(gComponents) / sizeof(gComponents[0])); NS_GENERIC_FACTORY_CONSTRUCTOR(nsParser) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsCParserNode) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLoggingSink) NS_GENERIC_FACTORY_CONSTRUCTOR(CWellFormedDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CNavDTD) @@ -277,13 +274,6 @@ nsParserModule::GetClassObject(nsIComponentManager *aCompMgr, } fact = mParserFactory; } - else if (aClass.Equals(kParserNodeCID)) { - if (!mParserNodeFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mParserNodeFactory), - &nsCParserNodeConstructor); - } - fact = mParserNodeFactory; - } else if (aClass.Equals(kLoggingSinkCID)) { if (!mLoggingSinkFactory) { rv = NS_NewGenericFactory(getter_AddRefs(mLoggingSinkFactory), diff --git a/mozilla/htmlparser/src/nsParserNode.cpp b/mozilla/htmlparser/src/nsParserNode.cpp index b098fa8e8c4..42deac4f10f 100644 --- a/mozilla/htmlparser/src/nsParserNode.cpp +++ b/mozilla/htmlparser/src/nsParserNode.cpp @@ -28,7 +28,6 @@ #include "nsITokenizer.h" #include "nsDTDUtils.h" - static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kClassIID, NS_PARSER_NODE_IID); static NS_DEFINE_IID(kIParserNodeIID, NS_IPARSER_NODE_IID); @@ -39,6 +38,7 @@ const nsString& GetEmptyString() { return gEmptyStr; } + /** * Default constructor * @@ -46,7 +46,7 @@ const nsString& GetEmptyString() { * @param aToken -- token to init internal token * @return */ -nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator): +nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator): nsIParserNode() { NS_INIT_REFCNT(); MOZ_COUNT_CTOR(nsCParserNode); @@ -61,15 +61,9 @@ nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator mUseCount=0; mSkippedContent=0; mGenericState=PR_FALSE; -} - -static void RecycleTokens(nsTokenAllocator* aTokenAllocator,nsDeque& aDeque) { - CToken* theToken=0; - if(aTokenAllocator) { - while((theToken=(CToken*)aDeque.Pop())){ - IF_FREE(theToken); - } - } +#ifdef HEAP_ALLOCATED_NODES + mNodeAllocator=aNodeAllocator; +#endif } /** @@ -83,6 +77,14 @@ static void RecycleTokens(nsTokenAllocator* aTokenAllocator,nsDeque& aDeque) { nsCParserNode::~nsCParserNode() { MOZ_COUNT_DTOR(nsCParserNode); ReleaseAll(); +#ifdef HEAP_ALLOCATED_NODES + if(mNodeAllocator) { + mNodeAllocator->Recycle(this); + } + mNodeAllocator=nsnull; +#endif + mTokenAllocator=0; + mLineNumber=0; } @@ -97,11 +99,15 @@ NS_IMPL_RELEASE(nsCParserNode) * @return */ -nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) { +nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator) { mLineNumber=aLineNumber; mTokenAllocator=aTokenAllocator; - if(mAttributes && (mAttributes->GetSize())) - RecycleTokens(mTokenAllocator,*mAttributes); + if(mAttributes && (mAttributes->GetSize())) { + CToken* theAttrToken=0; + while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) { + IF_FREE(theAttrToken); + } + } mToken=aToken; IF_HOLD(mToken); mGenericState=PR_FALSE; @@ -109,6 +115,9 @@ nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator if(mSkippedContent) { mSkippedContent->Truncate(); } +#ifdef HEAP_ALLOCATED_NODES + mNodeAllocator=aNodeAllocator; +#endif return NS_OK; } @@ -369,30 +378,18 @@ void nsCParserNode::GetSource(nsString& aString) { */ nsresult nsCParserNode::ReleaseAll() { if(mAttributes) { - - //fixed a bug that patrick found, where the attributes deque existed - //but was empty. In that case, the attributes deque itself was leaked. - //THANKS PATRICK! - // Umm...why is this a useful comment in the source? - - if(mTokenAllocator) { - RecycleTokens(mTokenAllocator,*mAttributes); - } - else { - CToken* theToken=(CToken*)mAttributes->Pop(); - while(theToken){ - IF_FREE(theToken); - theToken=(CToken*)mAttributes->Pop(); - } + CToken* theAttrToken=0; + while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) { + IF_FREE(theAttrToken); } delete mAttributes; mAttributes=0; } if(mSkippedContent) { delete mSkippedContent; + mSkippedContent=0; } IF_FREE(mToken); - mSkippedContent=0; return NS_OK; } diff --git a/mozilla/htmlparser/src/nsParserNode.h b/mozilla/htmlparser/src/nsParserNode.h index 540da833188..c8898cf560a 100644 --- a/mozilla/htmlparser/src/nsParserNode.h +++ b/mozilla/htmlparser/src/nsParserNode.h @@ -45,6 +45,7 @@ #include "nsString.h" #include "nsParserCIID.h" #include "nsDeque.h" +#include "nsDTDUtils.h" class nsTokenAllocator; @@ -54,12 +55,44 @@ class nsCParserNode : public nsIParserNode { NS_DECL_ISUPPORTS + +#ifdef HEAP_ALLOCATED_NODES + void* operator new(size_t aSize) { + return ::operator new(aSize); + } +#else + /** + * + * @update harishd 01/01/01 + * @param aSize - + * @param aArena - Allocate memory from this pool. + */ + static void * operator new (size_t aSize, nsFixedSizeAllocator& anArena) + { + return anArena.Alloc(aSize); + } +#endif + /** + * + * + * @update harishd 01/01/01 + * @param aPtr - The memory that should be recycled/freed. + * @param aSize - The size of memory that needs to be freed. + */ + static void operator delete (void* aPtr,size_t aSize) + { + // NodeAllocator would take care of heap allocated nodes.. +#ifndef HEAP_ALLOCATED_NODES + nsFixedSizeAllocator::Free(aPtr,aSize); +#endif + } + /** * Default constructor * @update gess5/11/98 * @param aToken is the token this node "refers" to */ - nsCParserNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); + nsCParserNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0,nsNodeAllocator* aNodeAllocator=0); /** * Destructor @@ -71,7 +104,7 @@ class nsCParserNode : public nsIParserNode { * Init * @update gess5/11/98 */ - virtual nsresult Init(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); + virtual nsresult Init(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0,nsNodeAllocator* aNodeAllocator=0); /** * Retrieve the name of the node @@ -212,6 +245,10 @@ class nsCParserNode : public nsIParserNode { nsCOMPtr<nsIAtom> mIDAttributeAtom; nsTokenAllocator* mTokenAllocator; +#ifdef HEAP_ALLOCATED_NODES + nsNodeAllocator* mNodeAllocator; // weak +#endif + }; #endif diff --git a/mozilla/htmlparser/src/nsViewSourceHTML.cpp b/mozilla/htmlparser/src/nsViewSourceHTML.cpp index e2d4cdaed49..3e7d89dbef6 100644 --- a/mozilla/htmlparser/src/nsViewSourceHTML.cpp +++ b/mozilla/htmlparser/src/nsViewSourceHTML.cpp @@ -1092,11 +1092,9 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { if((ePlainText!=mDocType) && mParser && (NS_OK==result)) { CObserverService* theService=mParser->GetObserverService(); if(theService) { - CParserContext* pc=mParser->PeekContext(); - void* theDocID=(pc)? pc->mKey:0; - eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); - - result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser); + eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); + const nsISupportsParserBundle* bundle=mParser->GetParserBundle(); + result=theService->Notify(theTag,theContext.mTokenNode,(void*)bundle, mMimeType, mParser); } } } diff --git a/mozilla/htmlparser/src/nsXIFDTD.cpp b/mozilla/htmlparser/src/nsXIFDTD.cpp index 539c81f95d8..16df385081d 100644 --- a/mozilla/htmlparser/src/nsXIFDTD.cpp +++ b/mozilla/htmlparser/src/nsXIFDTD.cpp @@ -652,7 +652,7 @@ nsresult nsXIFDTD::HandleStartToken(CToken* aToken) { } } - mNodeRecycler->RecycleNode(node); + NS_IF_RELEASE(node); return result; } @@ -1066,7 +1066,7 @@ nsresult nsXIFDTD::CloseContainer(const nsIParserNode& aNode) if(IsHTMLContainer(theTag) && theTag!=eHTMLTag_unknown) { result=mSink->CloseContainer(aNode); } - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(aNode); } return result; } @@ -1398,7 +1398,8 @@ nsresult nsXIFDTD::EndCSSStyleSheet(const nsIParserNode& aNode) ((nsCParserNode&)aNode).SetSkippedContent(mBuffer); result=mSink->AddLeaf(aNode); - mNodeRecycler->RecycleNode((nsCParserNode*)mXIFContext->Pop()); + nsIParserNode* node=mXIFContext->Pop(); + NS_IF_RELEASE(node); return result; } diff --git a/mozilla/htmlparser/tests/outsinks/Convert.cpp b/mozilla/htmlparser/tests/outsinks/Convert.cpp index 288a9e968e9..b5430f51b59 100644 --- a/mozilla/htmlparser/tests/outsinks/Convert.cpp +++ b/mozilla/htmlparser/tests/outsinks/Convert.cpp @@ -22,7 +22,6 @@ #include <ctype.h> // for isdigit() -#include "CNavDTD.h" #include "nsParserCIID.h" #include "nsIParser.h" #include "nsIHTMLContentSink.h" @@ -160,9 +159,11 @@ HTML2text(nsString& inString, nsString& inType, nsString& outType, #endif /* USE_SERIALIZER */ parser->SetContentSink(sink); - nsIDTD* dtd = nsnull; - if (inType.EqualsWithConversion("text/html")) - rv = NS_NewNavHTMLDTD(&dtd); + nsCOMPtr<nsIDTD> dtd; + if (inType.EqualsWithConversion("text/html")) { + static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); + rv=nsComponentManager::CreateInstance(kNavDTDCID,nsnull,NS_GET_IID(nsIDTD),getter_AddRefs(dtd)); + } else { printf("Don't know how to deal with non-html input!\n"); @@ -184,8 +185,6 @@ HTML2text(nsString& inString, nsString& inType, nsString& outType, printf("Parse() failed! 0x%x\n", rv); return rv; } - - NS_IF_RELEASE(dtd); NS_RELEASE(parser); if (compareAgainst.Length() > 0) diff --git a/mozilla/parser/htmlparser/src/CNavDTD.cpp b/mozilla/parser/htmlparser/src/CNavDTD.cpp index da6f31eae43..7ef008c72d2 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.cpp +++ b/mozilla/parser/htmlparser/src/CNavDTD.cpp @@ -138,8 +138,7 @@ NS_IMPL_RELEASE(CNavDTD) */ CNavDTD::CNavDTD() : nsIDTD(), mMisplacedContent(0), - mSkippedContent(0), - mSharedNodes(0) { + mSkippedContent(0) { NS_INIT_REFCNT(); mSink = 0; mParser=0; @@ -165,8 +164,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mHeadContext=new nsDTDContext(); mBodyContext=new nsDTDContext(); - mNodeRecycler=0; - #ifdef RICKG_DEBUG //DebugDumpContainmentRules2(*this,"c:/temp/DTDRules.new","New CNavDTD Containment Rules"); nsHTMLElement::DebugDumpContainment("c:/temp/contain.new","ElementTable Rules"); @@ -189,22 +186,10 @@ void CNavDTD::RecycleNodes(nsEntryStack *aNodeStack) { PRInt32 theIndex=0; for(theIndex=0;theIndex<theCount;theIndex++) { - nsCParserNode* theNode=(nsCParserNode*)aNodeStack->NodeAt(theIndex); - if(theNode) { - - theNode->mUseCount=0; - - IF_FREE(theNode->mToken); - - CToken* theToken=0; - while((theToken=(CToken*)theNode->PopAttributeToken())){ - IF_FREE(theToken); - } - - mNodeRecycler->RecycleNode(theNode); - } //if - } //while - } //if + nsIParserNode* node=aNodeStack->NodeAt(theIndex); + NS_IF_RELEASE(node); + } + } } /** @@ -282,9 +267,6 @@ CNavDTD::~CNavDTD(){ mTempContext=0; } - // delete mNodeRecycler; - - if(mSink) { nsLoggingSink *theLogSink=GetLoggingSink(); if(mSink==theLogSink) { @@ -498,8 +480,6 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke mTokenAllocator=mTokenizer->GetTokenAllocator(); - result=mBodyContext->GetNodeRecycler(mNodeRecycler); // Get a copy... - if(NS_FAILED(result)) return result; if(mSink) { @@ -609,14 +589,14 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse while(mBodyContext->GetCount() > 0) { nsEntryStack *theChildStyles=0; - nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles); - theNode->mUseCount=0; - mNodeRecycler->RecycleNode(theNode); - if(theChildStyles) { - delete theChildStyles; + nsIParserNode* theNode=mBodyContext->Pop(theChildStyles); + if(theNode) { + if(theChildStyles) { + delete theChildStyles; + } + NS_IF_RELEASE(theNode); } } - } STOP_TIMER(); @@ -891,7 +871,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ * @param aChildTag is the tag itself. * @return status */ -nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ +nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){ nsresult result=NS_OK; #if 0 @@ -983,10 +963,11 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ break; }//switch - //handle <empty/> tags by generating a close tag... - //added this to fix bug 48351, which contains XHTML and uses empty tags. - if(nsHTMLElement::IsContainer(aChildTag) && aNode.mToken) { //nullptr test fixes bug 56085 - CStartToken *theToken=NS_STATIC_CAST(CStartToken*,aNode.mToken); + //handle <empty/> tags by generating a close tag... + //added this to fix bug 48351, which contains XHTML and uses empty tags. + nsCParserNode* theNode=NS_STATIC_CAST(nsCParserNode*,&aNode); + if(nsHTMLElement::IsContainer(aChildTag) && theNode && theNode->mToken) { //nullptr test fixes bug 56085 + CStartToken *theToken=NS_STATIC_CAST(CStartToken*,theNode->mToken); if(theToken->IsEmpty()){ CToken *theEndToken=mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag); @@ -1295,7 +1276,7 @@ void WriteTokenToLog(CToken* aToken) { * @param aNode is the node (tag) with associated attributes. * @return TRUE if tag processing should continue; FALSE if the tag has been handled. */ -nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode& aNode){ +nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode& aNode) { nsresult result=NS_OK; PRInt32 theAttrCount = aNode.GetAttributeCount(); @@ -1580,8 +1561,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { //Begin by gathering up attributes... - nsCParserNode* theNode=mNodeRecycler->CreateNode(); - theNode->Init(aToken,mLineNumber,mTokenAllocator); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,mTokenAllocator); eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID(); PRInt16 attrCount=aToken->GetAttributeCount(); @@ -1697,7 +1677,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { result=NS_OK; } - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); return result; } @@ -2006,7 +1986,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) { nsEntryStack* theChildStyleStack=0; for(i=0; i<(theTagCount - theTopIndex); i++) { - mTempContext->Push((nsCParserNode*)mBodyContext->Pop(theChildStyleStack)); + nsIParserNode* node=mBodyContext->Pop(theChildStyleStack); + mTempContext->Push(node); + NS_IF_RELEASE(node); //release the popped node since push will addref for us. } // Now flush out all the bad contents. @@ -2047,7 +2029,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) { // Bad-contents were successfully processed. Now, itz time to get // back to the original body context state. for(PRInt32 k=0; k<(theTagCount - theTopIndex); k++) { - mBodyContext->Push((nsCParserNode*)mTempContext->Pop(theChildStyleStack)); + nsIParserNode* node=mTempContext->Pop(theChildStyleStack); + mBodyContext->Push(node); + NS_IF_RELEASE(node); } STOP_TIMER() @@ -2098,23 +2082,20 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) { eHTMLTags theParentTag=mBodyContext->Last(); - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute... if(CanOmit(theParentTag,eHTMLTag_entity,theParentContains)) { eHTMLTags theCurrTag=(eHTMLTags)aToken->GetTypeID(); result=HandleOmittedTag(aToken,theCurrTag,theParentTag,theNode); - mNodeRecycler->RecycleNode(theNode); - return result; } - - #ifdef RICKG_DEBUG - WriteTokenToLog(aToken); - #endif - - result=AddLeaf(theNode); - mNodeRecycler->RecycleNode(theNode); + else { +#ifdef RICKG_DEBUG + WriteTokenToLog(aToken); +#endif + result=AddLeaf(theNode); + } + NS_IF_RELEASE(theNode); } return result; } @@ -2138,9 +2119,8 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) { const nsAReadableString& theComment = theToken->GetStringValue(); mLineNumber += CountCharInReadable(theComment, PRUnichar(kNewLine)); - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); #ifdef RICKG_DEBUG WriteTokenToLog(aToken); @@ -2151,7 +2131,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) { result=(mSink) ? mSink->AddComment(*theNode) : NS_OK; - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this)); START_TIMER(); @@ -2215,9 +2195,8 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){ nsresult result=NS_OK; - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); #ifdef RICKG_DEBUG WriteTokenToLog(aToken); @@ -2228,7 +2207,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){ result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK; - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this)); START_TIMER(); @@ -2266,9 +2245,8 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ docTypeStr.Cut(0,2); // Now remove "<!" from the begining theToken->SetStringValue(docTypeStr); - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0); if(theNode) { - theNode->Init(aToken,mLineNumber,0); STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this)); @@ -2290,7 +2268,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ result = (mSink)? mSink->AddDocTypeDecl(*theNode,theMode):NS_OK; - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this)); START_TIMER(); @@ -2308,7 +2286,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ * @param aCount is the # of attributes you're expecting * @return error code (should be 0) */ -nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ +nsresult CNavDTD::CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ int attr=0; nsresult result=NS_OK; @@ -2319,7 +2297,8 @@ nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 for(attr=0;attr<aCount;attr++){ if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize()) theToken=NS_STATIC_CAST(CToken*,mSkippedContent.PopFront()); - else theToken=mTokenizer->PopToken(); + else + theToken=mTokenizer->PopToken(); if(theToken) { eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); if(theType!=eToken_attribute) { @@ -2359,7 +2338,7 @@ nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 * @param holds the number of skipped content elements encountered * @return Error condition. */ -nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) { +nsresult CNavDTD::CollectSkippedContent(nsIParserNode& aNode,PRInt32 &aCount) { eHTMLTags theNodeTag=(eHTMLTags)aNode.GetNodeType(); @@ -2371,54 +2350,58 @@ nsresult CNavDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32 &aCount) { PRBool aMustConvertLinebreaks = PR_FALSE; mScratch.Truncate(); - aNode.SetSkippedContent(mScratch); //this guarantees us some skipped content storage. + + nsCParserNode* theNode=NS_STATIC_CAST(nsCParserNode*,&aNode); + if(theNode) { + theNode->SetSkippedContent(mScratch); //this guarantees us some skipped content storage. - for(aIndex=0;aIndex<aMax;aIndex++){ - CHTMLToken* theNextToken=(CHTMLToken*)mSkippedContent.PopFront(); + for(aIndex=0;aIndex<aMax;aIndex++){ + CHTMLToken* theNextToken=(CHTMLToken*)mSkippedContent.PopFront(); - eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); + eHTMLTokenTypes theTokenType=(eHTMLTokenTypes)theNextToken->GetTokenType(); - // 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) && - ((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. - if(mScratch.Length()>0){ - aMustConvertLinebreaks |= (mScratch[0] == kCR); - aNode.mSkippedContent->Append(mScratch); + // 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) && + ((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. + if(mScratch.Length()>0){ + aMustConvertLinebreaks |= (mScratch[0] == kCR); + theNode->mSkippedContent->Append(mScratch); + } } - } - else theNextToken->AppendSource(*aNode.mSkippedContent); + else theNextToken->AppendSource(*theNode->mSkippedContent); + } + IF_FREE(theNextToken); } - IF_FREE(theNextToken); + + // if the string contained CRs (hence is either CR, or CRLF terminated) + // we need to convert line breaks + if (aMustConvertLinebreaks) + { + /* + PRInt32 offset; + while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound) + aNode.mSkippedContent.Cut(offset, 1); // remove the CR + + // now replace remaining CRs with LFs + aNode.mSkippedContent.ReplaceChar("\r", kNewLine); + */ + #if 1 + nsLinebreakConverter::ConvertStringLineBreaks(*theNode->mSkippedContent, + nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent); + #endif + } + + // Let's hope that this does not hamper the PERFORMANCE!! + mLineNumber += theNode->mSkippedContent->CountChar(kNewLine); } - - // if the string contained CRs (hence is either CR, or CRLF terminated) - // we need to convert line breaks - if (aMustConvertLinebreaks) - { - /* - PRInt32 offset; - while ((offset = aNode.mSkippedContent.Find("\r\n")) != kNotFound) - aNode.mSkippedContent.Cut(offset, 1); // remove the CR - - // now replace remaining CRs with LFs - aNode.mSkippedContent.ReplaceChar("\r", kNewLine); - */ -#if 1 - nsLinebreakConverter::ConvertStringLineBreaks(*aNode.mSkippedContent, - nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent); -#endif - } - - // Let's hope that this does not hamper the PERFORMANCE!! - mLineNumber += aNode.mSkippedContent->CountChar(kNewLine); return NS_OK; } @@ -2862,10 +2845,8 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){ } else { //if the node tag can't contain the child tag, then remove the child tag from the style stack - nsCParserNode* theRemovedNode=(nsCParserNode*)theStack->Remove(sindex,theNodeTag); - if(theRemovedNode) { - mNodeRecycler->RecycleNode(theRemovedNode); - } + nsIParserNode* node=theStack->Remove(sindex,theNodeTag); + NS_IF_RELEASE(node); theEntry--; //back up by one } } //if @@ -2932,10 +2913,8 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){ if(mStyleHandlingEnabled) { #ifdef ENABLE_RESIDUALSTYLE if(nsHTMLElement::IsResidualStyleTag(aTag)) { - nsCParserNode* theNode=(nsCParserNode*)mBodyContext->PopStyle(aTag); - if(theNode) { - mNodeRecycler->RecycleNode(theNode); - } + nsIParserNode* node=mBodyContext->PopStyle(aTag); + NS_IF_RELEASE(node); } #endif } //if @@ -3547,8 +3526,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC nsEntryStack *theChildStyleStack=0; eHTMLTags theTag=mBodyContext->Last(); - nsCParserNode *theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyleStack); -// eHTMLTags theParent=mBodyContext->Last(); + nsCParserNode *theNode=NS_STATIC_CAST(nsCParserNode*,mBodyContext->Pop(theChildStyleStack)); if(theNode) { result=CloseContainer(theNode,aTarget,aClosedByStartTag); @@ -3561,15 +3539,12 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC if(!theStyleDoesntLeakOut) { theStyleDoesntLeakOut = gHTMLElements[aTarget].HasSpecialProperty(kNoStyleLeaksOut); } - // (aClosedByStartTag) ? gHTMLElements[aTarget].HasSpecialProperty(kNoStyleLeaksOut) - // : gHTMLElements[theParent].HasSpecialProperty(kNoStyleLeaksOut); - - - /************************************************************* - I've added a check (mhasOpenNoXXX) below to prevent residual - style handling from getting invoked in these cases. - This fixes bug 25214. - *************************************************************/ + + /************************************************************* + I've added a check (mhasOpenNoXXX) below to prevent residual + style handling from getting invoked in these cases. + This fixes bug 25214. + *************************************************************/ if(theTagIsStyle && (0==mHasOpenNoXXX)) { @@ -3598,7 +3573,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC //here's a case we missed: <a><div>text<a>text</a></div> //The <div> pushes the 1st <a> onto the rs-stack, then the 2nd <a> //pops the 1st <a> from the rs-stack altogether. - mBodyContext->PopStyle(theTag); + nsIParserNode* node=mBodyContext->PopStyle(theTag); + NS_IF_RELEASE(node); } @@ -3643,7 +3619,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC // 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); + nsIParserNode* node=mBodyContext->PopStyle(theTag); + NS_IF_RELEASE(node); } mBodyContext->PushStyles(theChildStyleStack); } @@ -3667,7 +3644,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC //style tag that got onto that tag stack from a stylestack somewhere. //Pop it from the stylestack if the target is also a style tag. if(theTargetTagIsStyle) { - theNode=(nsCParserNode*)mBodyContext->PopStyle(theTag); + nsIParserNode* node=mBodyContext->PopStyle(theTag); + NS_IF_RELEASE(node); } } } @@ -3684,8 +3662,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC } } #endif - }//if anode - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); + }//if theNode } } //if @@ -3769,7 +3747,7 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ while(!done && NS_SUCCEEDED(result)) { CToken* theToken=mTokenizer->PeekToken(); if(theToken) { - nsCParserNode* theNode=mNodeRecycler->CreateNode(); + nsIParserNode* theNode=mNodeAllocator.CreateNode(theToken,mLineNumber,0); if(theNode) { theTag=(eHTMLTags)theToken->GetTypeID(); switch(theTag) { @@ -3778,7 +3756,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ case eHTMLTag_whitespace: { theToken=mTokenizer->PopToken(); - theNode->Init(theToken,mLineNumber,0); STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); @@ -3798,7 +3775,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ if((mHasOpenBody) && (!mHasOpenHead) && !(nsHTMLElement::IsWhitespaceTag(thePrevTag))) { theToken=mTokenizer->PopToken(); - theNode->Init(theToken,mLineNumber); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); STOP_TIMER(); @@ -3819,7 +3795,7 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ default: done=PR_TRUE; } //switch - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(theNode); } //if }//if else done=PR_TRUE; diff --git a/mozilla/parser/htmlparser/src/CNavDTD.h b/mozilla/parser/htmlparser/src/CNavDTD.h index e9cfd65f7c6..3915b6b4e6a 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.h +++ b/mozilla/parser/htmlparser/src/CNavDTD.h @@ -91,6 +91,7 @@ #include "nsDeque.h" #include "nsParserCIID.h" #include "nsTime.h" +#include "nsDTDUtils.h" #define NS_INAVHTML_DTD_IID \ {0x5c5cce40, 0xcfd6, 0x11d1, \ @@ -106,7 +107,6 @@ class nsEntryStack; class nsITokenizer; class nsCParserNode; class nsTokenAllocator; -class CNodeRecycler; /*************************************************************** Now the main event: CNavDTD. @@ -484,10 +484,10 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD { protected: - nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); - nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount); - nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode); - nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag); + nsresult CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); + nsresult CollectSkippedContent(nsIParserNode& aNode,PRInt32& aCount); + nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); + nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag); nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode); nsresult HandleSavedTokens(PRInt32 anIndex); nsresult HandleKeyGen(nsIParserNode *aNode); @@ -513,13 +513,12 @@ protected: nsParser* mParser; nsITokenizer* mTokenizer; nsTokenAllocator* mTokenAllocator; - CNodeRecycler* mNodeRecycler; + nsNodeAllocator mNodeAllocator; nsDeque mMisplacedContent; nsDeque mSkippedContent; PRBool mHasOpenScript; PRBool mSaveBadTokens; eHTMLTags mSkipTarget; - nsDeque mSharedNodes; nsresult mDTDState; nsDTDMode mDTDMode; eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors... diff --git a/mozilla/parser/htmlparser/src/COtherDTD.cpp b/mozilla/parser/htmlparser/src/COtherDTD.cpp index 9b2f7bcd696..716ae924aa8 100644 --- a/mozilla/parser/htmlparser/src/COtherDTD.cpp +++ b/mozilla/parser/htmlparser/src/COtherDTD.cpp @@ -129,7 +129,7 @@ NS_IMPL_RELEASE(COtherDTD) * @param * @return */ -COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { +COtherDTD::COtherDTD() : nsIDTD() { NS_INIT_REFCNT(); mSink = 0; mParser=0; @@ -149,6 +149,7 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { mHadBody=PR_FALSE; mHasOpenScript=PR_FALSE; mParserCommand=eViewNormal; + mNodeAllocator=new nsNodeAllocator(); mBodyContext=new nsDTDContext(); #if 1 //set this to 1 if you want strictDTD to be based on the environment setting. @@ -169,36 +170,8 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { nsHTMLElement::DebugDumpContainType("c:/temp/ctnrules.out"); #endif -#ifdef NS_DEBUG - gNodeCount=0; -#endif } -/** - * This method creates a new parser node. It tries to get one from - * the recycle list before allocating a new one. - * @update gess1/8/99 - * @param - * @return valid node* - */ -nsCParserNode* COtherDTD::CreateNode(void) { - - nsCParserNode* result=0; - if(0<mSharedNodes.GetSize()) { - result=(nsCParserNode*)mSharedNodes.Pop(); - } - else{ - result=new nsCParserNode(); -#ifdef NS_DEBUG -#if 1 - gNodeCount++; -#endif -#endif - } - return result; -} - - /** * * @update gess1/8/99 @@ -219,29 +192,12 @@ const nsIID& COtherDTD::GetMostDerivedIID(void)const { COtherDTD::~COtherDTD(){ delete mBodyContext; + if(mNodeAllocator) { + delete mNodeAllocator; + mNodeAllocator=nsnull; + } + NS_IF_RELEASE(mTokenizer); - - nsCParserNode* theNode=0; - -#ifdef NS_DEBUG -#if 0 - PRInt32 count=gNodeCount-mSharedNodes.GetSize(); - if(count) { - printf("%i of %i nodes leaked!\n",count,gNodeCount); - } -#endif -#endif - -#if 1 - while((theNode=(nsCParserNode*)mSharedNodes.Pop())){ - delete theNode; - } -#endif - -#ifdef NS_DEBUG - gNodeCount=0; -#endif - NS_IF_RELEASE(mSink); NS_IF_RELEASE(mDTDDebug); } @@ -455,6 +411,7 @@ nsresult COtherDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsITo mTokenAllocator=mTokenizer->GetTokenAllocator(); mBodyContext->SetTokenAllocator(mTokenAllocator); + mBodyContext->SetNodeAllocator(mNodeAllocator); if(mSink) { @@ -529,10 +486,10 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles); if(theNode) { theNode->mUseCount=0; - mBodyContext->RecycleNode(theNode); if(theChildStyles) { delete theChildStyles; } + NS_IF_RELEASE(theNode); } } } @@ -606,7 +563,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){ * @param aChildTag is the tag itself. * @return status */ -nsresult COtherDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ +nsresult COtherDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){ nsresult result=NS_OK; switch(aChildTag){ @@ -683,7 +640,7 @@ void WriteTokenToLog(CToken* aToken) { * @param aNode is the node (tag) with associated attributes. * @return TRUE if tag processing should continue; FALSE if the tag has been handled. */ -nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode& aNode){ +nsresult COtherDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode& aNode){ nsresult result=NS_OK; //first let's see if there's some skipped content to deal with... @@ -743,9 +700,8 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) { //Begin by gathering up attributes... nsresult result=NS_OK; - nsCParserNode* theNode=CreateNode(); + nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator); if(theNode) { - theNode->Init(aToken,mLineNumber,mTokenAllocator); eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID(); PRInt16 attrCount=aToken->GetAttributeCount(); @@ -786,7 +742,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) { } //if }//if - mBodyContext->RecycleNode(theNode); + NS_IF_RELEASE(theNode); } else result=NS_ERROR_OUT_OF_MEMORY; @@ -831,11 +787,10 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) { } CElement* theElement=gElementTable->mElements[theParent]; if(theElement) { - nsCParserNode* theNode=CreateNode(); + nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator); if(theNode) { - theNode->Init(aToken,mLineNumber,mTokenAllocator); result=theElement->HandleEndToken(theNode,theChildTag,mBodyContext,mSink); - mBodyContext->RecycleNode((nsCParserNode*)theNode); + NS_IF_RELEASE(theNode); } } break; @@ -853,7 +808,7 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) { * @param aCount is the # of attributes you're expecting * @return error code (should be 0) */ -nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ +nsresult COtherDTD::CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount){ int attr=0; nsresult result=NS_OK; diff --git a/mozilla/parser/htmlparser/src/COtherDTD.h b/mozilla/parser/htmlparser/src/COtherDTD.h index d2fd78f245e..1f2af7ba893 100644 --- a/mozilla/parser/htmlparser/src/COtherDTD.h +++ b/mozilla/parser/htmlparser/src/COtherDTD.h @@ -91,7 +91,6 @@ #include "nsDeque.h" #include "nsParserCIID.h" - #define NS_IOTHERHTML_DTD_IID \ {0x8a5e89c0, 0xd16d, 0x11d1, \ {0x80, 0x22, 0x00, 0x60, 0x8, 0x14, 0x98, 0x89}} @@ -103,8 +102,9 @@ class nsParser; class nsDTDContext; class nsEntryStack; class nsITokenizer; -class nsCParserNode; +class nsIParserNode; class nsTokenAllocator; +class nsNodeAllocator; /*************************************************************** Now the main event: COtherDTD. @@ -313,10 +313,10 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD { protected: - nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); - nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsCParserNode& aNode); - nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag); - nsCParserNode* CreateNode(void); + nsresult CollectAttributes(nsIParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); + nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); + nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag); + nsIParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); nsIHTMLContentSink* mSink; @@ -332,10 +332,10 @@ protected: PRInt32 mLineNumber; nsParser* mParser; nsITokenizer* mTokenizer; - nsTokenAllocator* mTokenAllocator; + nsTokenAllocator* mTokenAllocator; + nsNodeAllocator* mNodeAllocator; PRBool mHasOpenScript; eHTMLTags mSkipTarget; - nsDeque mSharedNodes; nsresult mDTDState; nsDTDMode mDTDMode; eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors... @@ -346,10 +346,6 @@ protected: eParserDocType mDocType; PRBool mEnableStrict; -#ifdef NS_DEBUG - PRInt32 gNodeCount; -#endif - }; extern NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult); diff --git a/mozilla/parser/htmlparser/src/COtherElements.h b/mozilla/parser/htmlparser/src/COtherElements.h index 6f261ba8817..2e5410f7094 100644 --- a/mozilla/parser/htmlparser/src/COtherElements.h +++ b/mozilla/parser/htmlparser/src/COtherElements.h @@ -323,8 +323,7 @@ public: CElement *theElement=(aTag==mTag) ? this : GetElement(aTag); result=theElement->NotifyClose(theNode,aTag,aContext,aSink); - aContext->RecycleNode((nsCParserNode*)theNode); - + NS_IF_RELEASE(aNode); return result; } @@ -808,9 +807,8 @@ public: if(aContext->mTableStates) { if(aContext->mTableStates->CanOpenTBody()) { - nsCParserNode* theNode=aContext->gNodeRecycler->CreateNode(); CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_tbody); - theNode->Init(theToken,0,0); //this will likely leak... + nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0); result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink); } @@ -1797,8 +1795,7 @@ public: //let's auto open the body CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body); - nsCParserNode* theNode=aContext->gNodeRecycler->CreateNode(); - theNode->Init(theToken,0,0); + nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0); result=theBody->HandleStartToken(theNode,eHTMLTag_body,aContext,aSink); diff --git a/mozilla/parser/htmlparser/src/nsDTDUtils.cpp b/mozilla/parser/htmlparser/src/nsDTDUtils.cpp index 3033f757597..5ca27e7bbcf 100644 --- a/mozilla/parser/htmlparser/src/nsDTDUtils.cpp +++ b/mozilla/parser/htmlparser/src/nsDTDUtils.cpp @@ -132,6 +132,9 @@ void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) { mEntries[mCount].mTag=(eHTMLTags)aNode->GetNodeType(); mEntries[mCount].mNode=(nsIParserNode*)aNode; + + NS_ADDREF(mEntries[mCount].mNode); + mEntries[mCount].mParent=aStyleStack; mEntries[mCount++].mStyles=0; } @@ -159,6 +162,9 @@ void nsEntryStack::PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStac mEntries[0].mTag=(eHTMLTags)aNode->GetNodeType(); mEntries[0].mNode=(nsIParserNode*)aNode; + + NS_ADDREF(mEntries[0].mNode); + mEntries[0].mParent=aStyleStack; mEntries[0].mStyles=0; mCount++; @@ -210,6 +216,7 @@ nsIParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) { for(theIndex=anIndex;theIndex<mCount;theIndex++){ mEntries[theIndex]=mEntries[theIndex+1]; } + mEntries[mCount].mNode=0; mEntries[mCount].mStyles=0; @@ -356,8 +363,6 @@ eHTMLTags nsEntryStack::Last() const { ***************************************************************/ -CNodeRecycler *nsDTDContext::gNodeRecycler=0; - /** * * @update gess 04.21.2000 @@ -370,6 +375,7 @@ nsDTDContext::nsDTDContext() : mStack(), mEntities(0){ mTableStates=0; mCounters=0; mTokenAllocator=0; + mNodeAllocator=0; mAllBits=0; #ifdef NS_DEBUG @@ -790,7 +796,7 @@ void nsDTDContext::ResetCounters(void) { returns the newly incremented value for the (determined) group. **********************************************************/ -PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult) { +PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsIParserNode& aNode,nsString& aResult) { PRInt32 result=0; @@ -1039,7 +1045,8 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){ // 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 - gNodeRecycler->RecycleNode((nsCParserNode*)aStyles->Pop()); + nsIParserNode* theNode=aStyles->Pop(); + NS_IF_RELEASE(theNode); delete aStyles; aStyles=0; } @@ -1118,51 +1125,12 @@ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){ return result; } -/** - * - * @update harishd 04/10/00 - */ -nsresult nsDTDContext::GetNodeRecycler(CNodeRecycler*& aNodeRecycler){ - nsresult result=NS_OK; - if(!gNodeRecycler) { - gNodeRecycler=new CNodeRecycler(); - if(gNodeRecycler==0) result=NS_ERROR_OUT_OF_MEMORY; - } - aNodeRecycler=gNodeRecycler; - return result; -} - -/** - * - * @update rickg 16June2000 - */ -void nsDTDContext::RecycleNode(nsCParserNode* aNode) { - nsresult result=NS_OK; - - if(aNode) { - if(!gNodeRecycler) - result=nsDTDContext::GetNodeRecycler(gNodeRecycler); - - if(NS_SUCCEEDED(result)) { - gNodeRecycler->RecycleNode(aNode); - } - else { - delete aNode; - } - } -} - - /** * This gets called when the parser module is getting unloaded * * @return nada */ void nsDTDContext::ReleaseGlobalObjects(){ - if(gNodeRecycler) { - delete gNodeRecycler; - gNodeRecycler=0; - } } @@ -1170,9 +1138,9 @@ void nsDTDContext::ReleaseGlobalObjects(){ Now define the nsTokenAllocator class... **************************************************************/ -static const size_t kBucketSizes[] ={sizeof(CStartToken),sizeof(CAttributeToken),sizeof(CCommentToken),sizeof(CEndToken)}; -static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t); -static const PRInt32 kInitialPoolSize = NS_SIZE_IN_HEAP(sizeof(CToken)) * 1536; +static const size_t kTokenBuckets[] ={sizeof(CStartToken),sizeof(CAttributeToken),sizeof(CCommentToken),sizeof(CEndToken)}; +static const PRInt32 kNumTokenBuckets = sizeof(kTokenBuckets) / sizeof(size_t); +static const PRInt32 kInitialTokenPoolSize = NS_SIZE_IN_HEAP(sizeof(CToken)) * 200; /** * @@ -1183,7 +1151,7 @@ nsTokenAllocator::nsTokenAllocator() { MOZ_COUNT_CTOR(nsTokenAllocator); - mArenaPool.Init("TheTokenPool", kBucketSizes, kNumBuckets, kInitialPoolSize); + mArenaPool.Init("TokenPool", kTokenBuckets, kNumTokenBuckets, kInitialTokenPoolSize); #ifdef NS_DEBUG int i=0; @@ -1295,7 +1263,6 @@ CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag return result; } -#define DEBUG_TRACK_NODES #ifdef DEBUG_TRACK_NODES static nsCParserNode* gAllNodes[100]; @@ -1329,69 +1296,72 @@ void RemoveNode(nsCParserNode *aNode) { #endif -CNodeRecycler::CNodeRecycler(): mSharedNodes(0) { - - MOZ_COUNT_CTOR(CNodeRecycler); +#ifdef HEAP_ALLOCATED_NODES +nsNodeAllocator::nsNodeAllocator():mSharedNodes(0){ +#ifdef DEBUG_TRACK_NODES + mCount=0; +#endif +#else + static const size_t kNodeBuckets[] ={sizeof(nsCParserNode)}; + static const PRInt32 kNumNodeBuckets = sizeof(kNodeBuckets) / sizeof(size_t); + static const PRInt32 kInitialNodePoolSize = NS_SIZE_IN_HEAP(sizeof(nsCParserNode)) * 50; +nsNodeAllocator::nsNodeAllocator() { + mNodePool.Init("NodePool", kNodeBuckets, kNumNodeBuckets, kInitialNodePoolSize); +#endif + MOZ_COUNT_CTOR(nsNodeAllocator); } + +nsNodeAllocator::~nsNodeAllocator() { + MOZ_COUNT_DTOR(nsNodeAllocator); -CNodeRecycler::~CNodeRecycler() { - - MOZ_COUNT_DTOR(CNodeRecycler); - +#ifdef HEAP_ALLOCATED_NODES nsCParserNode* theNode=0; while((theNode=(nsCParserNode*)mSharedNodes.Pop())){ -#ifdef DEBUG_TRACK_NODES +#ifdef DEBUG_TRACK_NODES RemoveNode(theNode); #endif - delete theNode; + ::operator delete(theNode); + theNode=nsnull; } - #ifdef DEBUG_TRACK_NODES - if(0<gAllNodeCount) { - printf("%i nodes leaked!\n",gAllNodeCount); + if(mCount) { + printf("**************************\n"); + printf("%i out of %i nodes leaked!\n",gAllNodeCount,mCount); + printf("**************************\n"); } #endif - +#endif } - -void CNodeRecycler::RecycleNode(nsCParserNode* aNode) { - if(aNode && (!aNode->mUseCount)) { - - IF_FREE(aNode->mToken); +nsIParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) { + nsCParserNode* result=0; - CToken* theToken=0; - while((theToken=(CToken*)aNode->PopAttributeToken())){ - IF_FREE(theToken); - } - mSharedNodes.Push(aNode); - } -} - -nsCParserNode* CNodeRecycler::CreateNode(void) { - -#ifdef DEBUG_TRACK_NODES +#ifdef HEAP_ALLOCATED_NODES #if 0 if(gAllNodeCount!=mSharedNodes.GetSize()) { int x=10; //this is very BAD! } -#endif #endif - nsCParserNode* result=0; - if(0<mSharedNodes.GetSize()) { - result=(nsCParserNode*)mSharedNodes.Pop(); + result=NS_STATIC_CAST(nsCParserNode*,mSharedNodes.Pop()); + if(result) { + result->Init(aToken,aLineNumber,aTokenAllocator,this); } else{ - result=new nsCParserNode(); + result=new nsCParserNode(aToken,aLineNumber,aTokenAllocator,this); #ifdef DEBUG_TRACK_NODES - AddNode(result); + mCount++; + AddNode(NS_STATIC_CAST(nsCParserNode*,result)); #endif - + NS_IF_ADDREF(result); } - return result; +#else + result=new(mNodePool) nsCParserNode(aToken,aLineNumber,aTokenAllocator); + NS_IF_ADDREF(result); +#endif + return NS_STATIC_CAST(nsIParserNode*,result); } void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) { diff --git a/mozilla/parser/htmlparser/src/nsDTDUtils.h b/mozilla/parser/htmlparser/src/nsDTDUtils.h index 603c9456850..7338250cd5d 100644 --- a/mozilla/parser/htmlparser/src/nsDTDUtils.h +++ b/mozilla/parser/htmlparser/src/nsDTDUtils.h @@ -46,11 +46,11 @@ #include "nsVoidArray.h" #define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); } -#define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr +#define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr class nsIParserNode; class nsCParserNode; -class CNodeRecycler; +class nsNodeAllocator; void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle); @@ -238,7 +238,6 @@ protected: #endif }; - /************************************************************************ CNodeRecycler class implementation. This class is used to recycle nodes. @@ -246,23 +245,25 @@ protected: that get created during the run of the system. ************************************************************************/ -class CNodeRecycler { +class nsNodeAllocator { public: - CNodeRecycler(); - virtual ~CNodeRecycler(); - virtual nsCParserNode* CreateNode(void); - virtual void RecycleNode(nsCParserNode* aNode); - + nsNodeAllocator(); + virtual ~nsNodeAllocator(); + virtual nsIParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); +#ifdef HEAP_ALLOCATED_NODES + void Recycle(nsIParserNode* aNode) { mSharedNodes.Push(NS_STATIC_CAST(void*,aNode)); } protected: - nsDeque mSharedNodes; - -#ifdef NS_DEBUG - PRInt32 gNodeCount; + nsDeque mSharedNodes; +#ifdef DEBUG_TRACK_NODES + PRInt32 mCount; +#endif +#else +protected: + nsFixedSizeAllocator mNodePool; #endif }; - /************************************************************************ The dtdcontext class defines an ordered list of tags (a context). ************************************************************************/ @@ -295,8 +296,6 @@ public: nsIParserNode* PopStyle(eHTMLTags aTag); nsIParserNode* RemoveStyle(eHTMLTags aTag); - nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler); - void RecycleNode(nsCParserNode *aNode); static void ReleaseGlobalObjects(void); CNamedEntity* RegisterEntity(const nsString& aName,const nsString& aValue); @@ -304,9 +303,10 @@ public: void ResetCounters(void); void AllocateCounters(void); - PRInt32 IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsString& aResult); + PRInt32 IncrementCounter(eHTMLTags aTag,nsIParserNode& aNode,nsString& aResult); void SetTokenAllocator(nsTokenAllocator* aTokenAllocator) { mTokenAllocator=aTokenAllocator; } + void SetNodeAllocator(nsNodeAllocator* aNodeAllocator) { mNodeAllocator=aNodeAllocator; } nsEntryStack mStack; //this will hold a list of tagentries... PRInt32 mResidualStyleCount; @@ -324,12 +324,10 @@ public: union { PRUint32 mAllBits; CFlags mFlags; - }; - - - static CNodeRecycler *gNodeRecycler; + }; nsTokenAllocator *mTokenAllocator; + nsNodeAllocator *mNodeAllocator; CTableState *mTableStates; PRInt32 *mCounters; nsDeque mEntities; diff --git a/mozilla/parser/htmlparser/src/nsIParserNode.h b/mozilla/parser/htmlparser/src/nsIParserNode.h index 8fe06fe980b..470695e16f1 100644 --- a/mozilla/parser/htmlparser/src/nsIParserNode.h +++ b/mozilla/parser/htmlparser/src/nsIParserNode.h @@ -46,7 +46,11 @@ #include "nsString.h" #include "nsDebug.h" -// class CToken; +//#define HEAP_ALLOCATED_NODES +//#define DEBUG_TRACK_NODES + + +class CToken; // 6e59f160-2717-11d2-9246-00805f8a7ab6 #define NS_IPARSER_NODE_IID \ @@ -133,6 +137,9 @@ class nsIParserNode : public nsISupports { */ virtual PRInt32 TranslateToUnicodeStr(nsString& aString) const = 0; + + virtual void AddAttribute(CToken* aToken)=0; + /** * This getter retrieves the line number from the input source where * the token occured. Lines are interpreted as occuring between \n characters. diff --git a/mozilla/parser/htmlparser/src/nsLoggingSink.cpp b/mozilla/parser/htmlparser/src/nsLoggingSink.cpp index 69eb8653029..7ea1600cc03 100644 --- a/mozilla/parser/htmlparser/src/nsLoggingSink.cpp +++ b/mozilla/parser/htmlparser/src/nsLoggingSink.cpp @@ -147,7 +147,7 @@ nsLoggingSink::WillBuildModel() { NS_IMETHODIMP nsLoggingSink::DidBuildModel(PRInt32 aQualityLevel) { - WriteTabs(mOutput,mLevel--); + WriteTabs(mOutput,--mLevel); PR_fprintf(mOutput, "</begin>\n"); //proxy the call to the real sink if you have one. @@ -342,11 +342,14 @@ nsLoggingSink::AddComment(const nsIParserNode& aNode){ NS_IMETHODIMP nsLoggingSink::SetTitle(const nsString& aValue) { - nsAutoString tmp; - QuoteText(aValue, tmp); - WriteTabs(mOutput,++mLevel); - PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp.GetBuffer()); - --mLevel; + char* tmp; + GetNewCString(aValue, &tmp); + WriteTabs(mOutput,++mLevel); + if(tmp) { + PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp); + nsMemory::Free(tmp); + } + --mLevel; nsresult theResult=NS_OK; @@ -544,9 +547,12 @@ nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) { PR_fprintf(mOutput, "\"%s\"", tag); } else { - const nsAReadableString& theText = aNode.GetText(); - PR_fprintf(mOutput, "\"%s\"", theText); - + char* text; + GetNewCString(aNode.GetText(), &text); + if(text) { + PR_fprintf(mOutput, "\"%s\"", text); + nsMemory::Free(text); + } } if (WillWriteAttributes(aNode)) { @@ -571,18 +577,25 @@ nsLoggingSink::CloseNode(const char* aKind) { nsresult nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) { - nsAutoString tmp, tmp2; + + WriteTabs(mOutput,1+mLevel); + nsAutoString tmp; PRInt32 ac = aNode.GetAttributeCount(); for (PRInt32 i = 0; i < ac; i++) { + char* key=nsnull; + char* value=nsnull; const nsAReadableString& k = aNode.GetKeyAt(i); const nsString& v = aNode.GetValueAt(i); - PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", k); + GetNewCString(k, &key); + if(key) { + PR_fprintf(mOutput, " <attr key=\"%s\" value=\"", key); + nsMemory::Free(key); + } tmp.Truncate(); tmp.Append(v); - - if(0<tmp.Length()) { + if(tmp.Length() > 0) { PRUnichar first = tmp.First(); if ((first == '"') || (first == '\'')) { if (tmp.Last() == first) { @@ -595,20 +608,26 @@ nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) { // Mismatched quotes - leave them in } } - } - QuoteText(tmp, tmp2); - PR_fprintf(mOutput, "%s\"/>\n", tmp2.GetBuffer()); - } + GetNewCString(tmp, &value); - if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) { - const nsString& content = aNode.GetSkippedContent(); - if (content.Length() > 0) { - QuoteText(content, tmp); - PR_fprintf(mOutput, " <content value=\""); - PR_fprintf(mOutput, "%s\"/>\n", tmp.GetBuffer()) ; + if(value) { + PR_fprintf(mOutput, "%s\"/>\n", value); + WriteTabs(mOutput,1+mLevel); + nsMemory::Free(value); + } } } + if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) { + char* content; + GetNewCString(aNode.GetSkippedContent(), &content); + if(content) { + PR_fprintf(mOutput, " <content value=\""); + PR_fprintf(mOutput, "%s\"/>\n", content) ; + nsMemory::Free(content); + } + } + WriteTabs(mOutput,1+mLevel); return NS_OK; } @@ -654,11 +673,15 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) else { PRInt32 pos; nsAutoString tmp; + char* str; switch (nodeType) { case eHTMLTag_whitespace: case eHTMLTag_text: - QuoteText(aNode.GetText(), tmp); - PR_fprintf(mOutput, "<text value=\"%s\"/>\n", tmp.GetBuffer()); + GetNewCString(aNode.GetText(), &str); + if(str) { + PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str); + nsMemory::Free(str); + } break; case eHTMLTag_newline: @@ -707,6 +730,28 @@ nsLoggingSink::QuoteText(const nsAReadableString& aValue, nsString& aResult) { return NS_OK; } +/** + * Use this method to convert nsString to char*. + * REMEMBER: Match this call with nsMemory::Free(aResult); + * + * @update 04/04/99 harishd + * @param aValue - The string value + * @param aResult - String coverted to char*. + */ +nsresult +nsLoggingSink::GetNewCString(const nsAReadableString& aValue, char** aResult) +{ + nsresult result=NS_OK; + nsAutoString temp; + result=QuoteText(aValue,temp); + if(NS_SUCCEEDED(result)) { + if(temp.Length()>0) { + *aResult=temp.ToNewCString(); + } + } + return result; +} + NS_IMETHODIMP nsLoggingSink::DoFragment(PRBool aFlag) { diff --git a/mozilla/parser/htmlparser/src/nsLoggingSink.h b/mozilla/parser/htmlparser/src/nsLoggingSink.h index 602f22e5891..d3931bf4a28 100644 --- a/mozilla/parser/htmlparser/src/nsLoggingSink.h +++ b/mozilla/parser/htmlparser/src/nsLoggingSink.h @@ -86,6 +86,7 @@ public: nsresult LeafNode(const nsIParserNode& aNode); nsresult WriteAttributes(const nsIParserNode& aNode); nsresult QuoteText(const nsAReadableString& aValue, nsString& aResult); + nsresult GetNewCString(const nsAReadableString& aValue, char** aResult); PRBool WillWriteAttributes(const nsIParserNode& aNode); protected: diff --git a/mozilla/parser/htmlparser/src/nsParserModule.cpp b/mozilla/parser/htmlparser/src/nsParserModule.cpp index 9a2939a40f1..b290cf1d5d7 100644 --- a/mozilla/parser/htmlparser/src/nsParserModule.cpp +++ b/mozilla/parser/htmlparser/src/nsParserModule.cpp @@ -136,7 +136,6 @@ nsParserService::IsBlock(PRInt32 aId, PRBool& aIsBlock) const //---------------------------------------------------------------------- static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); -static NS_DEFINE_CID(kParserNodeCID, NS_PARSER_NODE_IID); static NS_DEFINE_CID(kLoggingSinkCID, NS_LOGGING_SINK_CID); static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); @@ -154,7 +153,6 @@ struct Components { static Components gComponents[] = { { "Parser", &kParserCID }, - { "ParserNode", &kParserNodeCID }, { "Logging sink", &kLoggingSinkCID }, { "Well formed DTD", &kWellFormedDTDCID }, { "Navigator HTML DTD", &kNavDTDCID }, @@ -169,7 +167,6 @@ static Components gComponents[] = { #define NUM_COMPONENTS (sizeof(gComponents) / sizeof(gComponents[0])); NS_GENERIC_FACTORY_CONSTRUCTOR(nsParser) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsCParserNode) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLoggingSink) NS_GENERIC_FACTORY_CONSTRUCTOR(CWellFormedDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CNavDTD) @@ -277,13 +274,6 @@ nsParserModule::GetClassObject(nsIComponentManager *aCompMgr, } fact = mParserFactory; } - else if (aClass.Equals(kParserNodeCID)) { - if (!mParserNodeFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mParserNodeFactory), - &nsCParserNodeConstructor); - } - fact = mParserNodeFactory; - } else if (aClass.Equals(kLoggingSinkCID)) { if (!mLoggingSinkFactory) { rv = NS_NewGenericFactory(getter_AddRefs(mLoggingSinkFactory), diff --git a/mozilla/parser/htmlparser/src/nsParserNode.cpp b/mozilla/parser/htmlparser/src/nsParserNode.cpp index b098fa8e8c4..42deac4f10f 100644 --- a/mozilla/parser/htmlparser/src/nsParserNode.cpp +++ b/mozilla/parser/htmlparser/src/nsParserNode.cpp @@ -28,7 +28,6 @@ #include "nsITokenizer.h" #include "nsDTDUtils.h" - static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kClassIID, NS_PARSER_NODE_IID); static NS_DEFINE_IID(kIParserNodeIID, NS_IPARSER_NODE_IID); @@ -39,6 +38,7 @@ const nsString& GetEmptyString() { return gEmptyStr; } + /** * Default constructor * @@ -46,7 +46,7 @@ const nsString& GetEmptyString() { * @param aToken -- token to init internal token * @return */ -nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator): +nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator): nsIParserNode() { NS_INIT_REFCNT(); MOZ_COUNT_CTOR(nsCParserNode); @@ -61,15 +61,9 @@ nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator mUseCount=0; mSkippedContent=0; mGenericState=PR_FALSE; -} - -static void RecycleTokens(nsTokenAllocator* aTokenAllocator,nsDeque& aDeque) { - CToken* theToken=0; - if(aTokenAllocator) { - while((theToken=(CToken*)aDeque.Pop())){ - IF_FREE(theToken); - } - } +#ifdef HEAP_ALLOCATED_NODES + mNodeAllocator=aNodeAllocator; +#endif } /** @@ -83,6 +77,14 @@ static void RecycleTokens(nsTokenAllocator* aTokenAllocator,nsDeque& aDeque) { nsCParserNode::~nsCParserNode() { MOZ_COUNT_DTOR(nsCParserNode); ReleaseAll(); +#ifdef HEAP_ALLOCATED_NODES + if(mNodeAllocator) { + mNodeAllocator->Recycle(this); + } + mNodeAllocator=nsnull; +#endif + mTokenAllocator=0; + mLineNumber=0; } @@ -97,11 +99,15 @@ NS_IMPL_RELEASE(nsCParserNode) * @return */ -nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) { +nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator) { mLineNumber=aLineNumber; mTokenAllocator=aTokenAllocator; - if(mAttributes && (mAttributes->GetSize())) - RecycleTokens(mTokenAllocator,*mAttributes); + if(mAttributes && (mAttributes->GetSize())) { + CToken* theAttrToken=0; + while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) { + IF_FREE(theAttrToken); + } + } mToken=aToken; IF_HOLD(mToken); mGenericState=PR_FALSE; @@ -109,6 +115,9 @@ nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator if(mSkippedContent) { mSkippedContent->Truncate(); } +#ifdef HEAP_ALLOCATED_NODES + mNodeAllocator=aNodeAllocator; +#endif return NS_OK; } @@ -369,30 +378,18 @@ void nsCParserNode::GetSource(nsString& aString) { */ nsresult nsCParserNode::ReleaseAll() { if(mAttributes) { - - //fixed a bug that patrick found, where the attributes deque existed - //but was empty. In that case, the attributes deque itself was leaked. - //THANKS PATRICK! - // Umm...why is this a useful comment in the source? - - if(mTokenAllocator) { - RecycleTokens(mTokenAllocator,*mAttributes); - } - else { - CToken* theToken=(CToken*)mAttributes->Pop(); - while(theToken){ - IF_FREE(theToken); - theToken=(CToken*)mAttributes->Pop(); - } + CToken* theAttrToken=0; + while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) { + IF_FREE(theAttrToken); } delete mAttributes; mAttributes=0; } if(mSkippedContent) { delete mSkippedContent; + mSkippedContent=0; } IF_FREE(mToken); - mSkippedContent=0; return NS_OK; } diff --git a/mozilla/parser/htmlparser/src/nsParserNode.h b/mozilla/parser/htmlparser/src/nsParserNode.h index 540da833188..c8898cf560a 100644 --- a/mozilla/parser/htmlparser/src/nsParserNode.h +++ b/mozilla/parser/htmlparser/src/nsParserNode.h @@ -45,6 +45,7 @@ #include "nsString.h" #include "nsParserCIID.h" #include "nsDeque.h" +#include "nsDTDUtils.h" class nsTokenAllocator; @@ -54,12 +55,44 @@ class nsCParserNode : public nsIParserNode { NS_DECL_ISUPPORTS + +#ifdef HEAP_ALLOCATED_NODES + void* operator new(size_t aSize) { + return ::operator new(aSize); + } +#else + /** + * + * @update harishd 01/01/01 + * @param aSize - + * @param aArena - Allocate memory from this pool. + */ + static void * operator new (size_t aSize, nsFixedSizeAllocator& anArena) + { + return anArena.Alloc(aSize); + } +#endif + /** + * + * + * @update harishd 01/01/01 + * @param aPtr - The memory that should be recycled/freed. + * @param aSize - The size of memory that needs to be freed. + */ + static void operator delete (void* aPtr,size_t aSize) + { + // NodeAllocator would take care of heap allocated nodes.. +#ifndef HEAP_ALLOCATED_NODES + nsFixedSizeAllocator::Free(aPtr,aSize); +#endif + } + /** * Default constructor * @update gess5/11/98 * @param aToken is the token this node "refers" to */ - nsCParserNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); + nsCParserNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0,nsNodeAllocator* aNodeAllocator=0); /** * Destructor @@ -71,7 +104,7 @@ class nsCParserNode : public nsIParserNode { * Init * @update gess5/11/98 */ - virtual nsresult Init(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0); + virtual nsresult Init(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0,nsNodeAllocator* aNodeAllocator=0); /** * Retrieve the name of the node @@ -212,6 +245,10 @@ class nsCParserNode : public nsIParserNode { nsCOMPtr<nsIAtom> mIDAttributeAtom; nsTokenAllocator* mTokenAllocator; +#ifdef HEAP_ALLOCATED_NODES + nsNodeAllocator* mNodeAllocator; // weak +#endif + }; #endif diff --git a/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp b/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp index e2d4cdaed49..3e7d89dbef6 100644 --- a/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp +++ b/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp @@ -1092,11 +1092,9 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { if((ePlainText!=mDocType) && mParser && (NS_OK==result)) { CObserverService* theService=mParser->GetObserverService(); if(theService) { - CParserContext* pc=mParser->PeekContext(); - void* theDocID=(pc)? pc->mKey:0; - eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); - - result=theService->Notify(theTag,theContext.mTokenNode,theDocID, NS_ConvertToString(kViewSourceCommand), mParser); + eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); + const nsISupportsParserBundle* bundle=mParser->GetParserBundle(); + result=theService->Notify(theTag,theContext.mTokenNode,(void*)bundle, mMimeType, mParser); } } } diff --git a/mozilla/parser/htmlparser/src/nsXIFDTD.cpp b/mozilla/parser/htmlparser/src/nsXIFDTD.cpp index 539c81f95d8..16df385081d 100644 --- a/mozilla/parser/htmlparser/src/nsXIFDTD.cpp +++ b/mozilla/parser/htmlparser/src/nsXIFDTD.cpp @@ -652,7 +652,7 @@ nsresult nsXIFDTD::HandleStartToken(CToken* aToken) { } } - mNodeRecycler->RecycleNode(node); + NS_IF_RELEASE(node); return result; } @@ -1066,7 +1066,7 @@ nsresult nsXIFDTD::CloseContainer(const nsIParserNode& aNode) if(IsHTMLContainer(theTag) && theTag!=eHTMLTag_unknown) { result=mSink->CloseContainer(aNode); } - mNodeRecycler->RecycleNode(theNode); + NS_IF_RELEASE(aNode); } return result; } @@ -1398,7 +1398,8 @@ nsresult nsXIFDTD::EndCSSStyleSheet(const nsIParserNode& aNode) ((nsCParserNode&)aNode).SetSkippedContent(mBuffer); result=mSink->AddLeaf(aNode); - mNodeRecycler->RecycleNode((nsCParserNode*)mXIFContext->Pop()); + nsIParserNode* node=mXIFContext->Pop(); + NS_IF_RELEASE(node); return result; } diff --git a/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp b/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp index 288a9e968e9..b5430f51b59 100644 --- a/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp +++ b/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp @@ -22,7 +22,6 @@ #include <ctype.h> // for isdigit() -#include "CNavDTD.h" #include "nsParserCIID.h" #include "nsIParser.h" #include "nsIHTMLContentSink.h" @@ -160,9 +159,11 @@ HTML2text(nsString& inString, nsString& inType, nsString& outType, #endif /* USE_SERIALIZER */ parser->SetContentSink(sink); - nsIDTD* dtd = nsnull; - if (inType.EqualsWithConversion("text/html")) - rv = NS_NewNavHTMLDTD(&dtd); + nsCOMPtr<nsIDTD> dtd; + if (inType.EqualsWithConversion("text/html")) { + static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); + rv=nsComponentManager::CreateInstance(kNavDTDCID,nsnull,NS_GET_IID(nsIDTD),getter_AddRefs(dtd)); + } else { printf("Don't know how to deal with non-html input!\n"); @@ -184,8 +185,6 @@ HTML2text(nsString& inString, nsString& inType, nsString& outType, printf("Parse() failed! 0x%x\n", rv); return rv; } - - NS_IF_RELEASE(dtd); NS_RELEASE(parser); if (compareAgainst.Length() > 0)