From 6cb66fa5cbd6397f522284e84eeacab5f0e007cd Mon Sep 17 00:00:00 2001 From: "harishd%netscape.com" Date: Tue, 6 Feb 2001 23:35:29 +0000 Subject: [PATCH] 63423 - Unblock parser before evaluating external js content. 63661 - Do not create an end token automatically if the tag did not contain '>' 33051 - Handle residual style before closing a tag. 58992 - Leaf content should go thro' the normal HandleToken path. 61462 - Release parser bundle only when the parser is about to shutdown r=jst sr=vidur git-svn-id: svn://10.0.0.236/trunk@86373 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/htmlparser/src/CNavDTD.cpp | 71 ++------------- mozilla/htmlparser/src/CParserContext.cpp | 2 - mozilla/htmlparser/src/CParserContext.h | 1 - mozilla/htmlparser/src/nsHTMLTokenizer.cpp | 5 -- mozilla/htmlparser/src/nsIParser.h | 16 +++- mozilla/htmlparser/src/nsParser.cpp | 88 +++++++++++-------- mozilla/htmlparser/src/nsParser.h | 6 +- mozilla/parser/htmlparser/src/CNavDTD.cpp | 71 ++------------- .../parser/htmlparser/src/CParserContext.cpp | 2 - .../parser/htmlparser/src/CParserContext.h | 1 - .../parser/htmlparser/src/nsHTMLTokenizer.cpp | 5 -- mozilla/parser/htmlparser/src/nsIParser.h | 16 +++- mozilla/parser/htmlparser/src/nsParser.cpp | 88 +++++++++++-------- mozilla/parser/htmlparser/src/nsParser.h | 6 +- 14 files changed, 152 insertions(+), 226 deletions(-) diff --git a/mozilla/htmlparser/src/CNavDTD.cpp b/mozilla/htmlparser/src/CNavDTD.cpp index d7764e52e58..5dc39b27e34 100644 --- a/mozilla/htmlparser/src/CNavDTD.cpp +++ b/mozilla/htmlparser/src/CNavDTD.cpp @@ -730,7 +730,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ eHTMLTags theParentTag=mBodyContext->Last(); theTag=(eHTMLTags)theToken->GetTypeID(); if((FindTagInSet(theTag,gLegalElements,sizeof(gLegalElements)/sizeof(theTag))) || - (gHTMLElements[theParentTag].CanContain(theTag))) { + (gHTMLElements[theParentTag].CanContain(theTag)) && (theTag!=eHTMLTag_comment)) { // Added comment -> bug 40855 mDTDState=NS_OK; // reset the state since all the misplaced tokens are about to get handled. result=HandleSavedTokens(mBodyContext->mContextTopIndex); @@ -1928,6 +1928,12 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { if(result==NS_OK) { eHTMLTags theTarget=FindAutoCloseTargetForEndTag(theChildTag,*mBodyContext); if(eHTMLTag_unknown!=theTarget) { + if (nsHTMLElement::IsResidualStyleTag(theChildTag)) { + result=OpenTransientStyles(theChildTag); + if(NS_FAILED(result)) { + return result; + } + } result=CloseContainersTo(theTarget,PR_FALSE); } } @@ -3739,69 +3745,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); result=mSink->AddLeaf(*aNode); - - if(NS_SUCCEEDED(result)) { - PRBool done=PR_FALSE; - eHTMLTags thePrevTag=theTag; - //nsCParserNode theNode; - - while(!done && NS_SUCCEEDED(result)) { - CToken* theToken=mTokenizer->PeekToken(); - if(theToken) { - nsIParserNode* theNode=mNodeAllocator.CreateNode(theToken,mLineNumber,0); - if(theNode) { - theTag=(eHTMLTags)theToken->GetTypeID(); - switch(theTag) { - case eHTMLTag_newline: - mLineNumber++; - case eHTMLTag_whitespace: - { - theToken=mTokenizer->PopToken(); - - STOP_TIMER(); - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - - result=mSink->AddLeaf(*theNode); - - if((NS_SUCCEEDED(result))||(NS_ERROR_HTMLPARSER_BLOCK==result)) { - IF_FREE(theToken); - } - - MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - START_TIMER(); - thePrevTag=theTag; - } - break; - case eHTMLTag_text: - if((mHasOpenBody) && (!mHasOpenHead) && - !(nsHTMLElement::IsWhitespaceTag(thePrevTag))) { - theToken=mTokenizer->PopToken(); - - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - STOP_TIMER(); - - mLineNumber += theToken->mNewlineCount; - result=mSink->AddLeaf(*theNode); - - if((NS_SUCCEEDED(result))||(NS_ERROR_HTMLPARSER_BLOCK==result)) { - IF_FREE(theToken); - } - - MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - START_TIMER(); - } - else done=PR_TRUE; - break; - - default: - done=PR_TRUE; - } //switch - NS_IF_RELEASE(theNode); - } //if - }//if - else done=PR_TRUE; - } //while - } //if MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); START_TIMER(); diff --git a/mozilla/htmlparser/src/CParserContext.cpp b/mozilla/htmlparser/src/CParserContext.cpp index f2760f3149c..c3bbaaacf78 100644 --- a/mozilla/htmlparser/src/CParserContext.cpp +++ b/mozilla/htmlparser/src/CParserContext.cpp @@ -56,7 +56,6 @@ CParserContext::CParserContext(nsScanner* aScanner, mDTD=aDTD; NS_IF_ADDREF(mDTD); mTransferBufferSize=eTransferBufferSize; - mParserEnabled=PR_TRUE; mStreamListenerState=eNone; mMultipart=PR_TRUE; mContextType=eCTNone; @@ -90,7 +89,6 @@ CParserContext::CParserContext(const CParserContext &aContext) : mMimeType() { NS_IF_ADDREF(mDTD); mTransferBufferSize=eTransferBufferSize; - mParserEnabled=aContext.mParserEnabled; mStreamListenerState=aContext.mStreamListenerState; mMultipart=aContext.mMultipart; mContextType=aContext.mContextType; diff --git a/mozilla/htmlparser/src/CParserContext.h b/mozilla/htmlparser/src/CParserContext.h index 7b458f1041e..9e282589875 100644 --- a/mozilla/htmlparser/src/CParserContext.h +++ b/mozilla/htmlparser/src/CParserContext.h @@ -83,7 +83,6 @@ public: void* mKey; PRUint32 mTransferBufferSize; - PRBool mParserEnabled; PRBool mCopyUnused; }; diff --git a/mozilla/htmlparser/src/nsHTMLTokenizer.cpp b/mozilla/htmlparser/src/nsHTMLTokenizer.cpp index e56490dafaf..3e8a207f89e 100644 --- a/mozilla/htmlparser/src/nsHTMLTokenizer.cpp +++ b/mozilla/htmlparser/src/nsHTMLTokenizer.cpp @@ -606,11 +606,6 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, done=PR_TRUE; } else if(aChar==kLessThan) { - eHTMLTags theEndTag = (eHTMLTags)aToken->GetTypeID(); - if(result==NS_OK&&(gHTMLElements[theEndTag].mSkipTarget)){ - CToken* theEndToken=theAllocator->CreateTokenOfType(eToken_end,theEndTag); - AddToken(theEndToken,NS_OK,&mTokenDeque,theAllocator); - } done=PR_TRUE; } }//if diff --git a/mozilla/htmlparser/src/nsIParser.h b/mozilla/htmlparser/src/nsIParser.h index dc6cc4ad23a..8f1a91df521 100644 --- a/mozilla/htmlparser/src/nsIParser.h +++ b/mozilla/htmlparser/src/nsIParser.h @@ -219,8 +219,20 @@ class nsIParser : public nsISupports { * until you wind up being emitted to the given contentsink (which may or may not * be a proxy for the NGLayout content model). ******************************************************************************************/ - virtual nsresult EnableParser(PRBool aState) = 0; - virtual PRBool IsParserEnabled() = 0; + + // This method enables the parser ( by calling UnblockParser() ) and resumes parsing. + virtual nsresult ResumeParsing() =0; + + // Stops parsing temporarily. + virtual void BlockParser() =0; + + // Open up the parser for tokenization, building up content + // model..etc. However, this method does not resume parsing + // automatically. It's the callers' responsibility to restart + // the parsing engine. + virtual void UnblockParser() =0; + + virtual PRBool IsParserEnabled() =0; virtual nsresult Parse(nsIURI* aURL,nsIStreamObserver* aListener = nsnull,PRBool aEnableVerify=PR_FALSE, void* aKey=0,nsDTDMode aMode=eDTDMode_autodetect) = 0; virtual nsresult Parse(nsIInputStream& aStream, const nsString& aMimeType,PRBool aEnableVerify=PR_FALSE, void* aKey=0,nsDTDMode aMode=eDTDMode_autodetect) = 0; diff --git a/mozilla/htmlparser/src/nsParser.cpp b/mozilla/htmlparser/src/nsParser.cpp index 8730b8837f2..2b36aafe988 100644 --- a/mozilla/htmlparser/src/nsParser.cpp +++ b/mozilla/htmlparser/src/nsParser.cpp @@ -237,6 +237,7 @@ nsParser::nsParser(nsITokenObserver* anObserver) { mInternalState=NS_OK; mObserversEnabled=PR_TRUE; mCommand=eViewNormal; + mParserEnabled=PR_TRUE; mBundle=nsnull; MOZ_TIMER_DEBUGLOG(("Reset: Parse Time: nsParser::nsParser(), this=%p\n", this)); @@ -1413,10 +1414,12 @@ nsresult nsParser::DidBuildModel(nsresult anErrorCode) { //One last thing...close any open containers. nsresult result=anErrorCode; - if((mParserContext) && mParserContext->mParserEnabled) { - if((!mParserContext->mPrevContext) && (mParserContext->mDTD)) { + if(mParserEnabled && mParserContext && !mParserContext->mPrevContext) { + if(mParserContext->mDTD) { result=mParserContext->mDTD->DidBuildModel(anErrorCode,PRBool(0==mParserContext->mPrevContext),this,mSink); } + //Ref. to bug 61462. + NS_IF_RELEASE(mBundle); }//if return result; @@ -1432,9 +1435,6 @@ nsresult nsParser::DidBuildModel(nsresult anErrorCode) { */ void nsParser::PushContext(CParserContext& aContext) { aContext.mPrevContext=mParserContext; - if (mParserContext) { - aContext.mParserEnabled = mParserContext->mParserEnabled; - } mParserContext=&aContext; } @@ -1453,7 +1453,6 @@ CParserContext* nsParser::PopContext() { // back to the new one. Also, propagate the stream listener state // but don't override onStop state to guarantee the call to DidBuildModel(). if (mParserContext) { - mParserContext->mParserEnabled = oldContext->mParserEnabled; if(mParserContext->mStreamListenerState!=eOnStop) { mParserContext->mStreamListenerState = oldContext->mStreamListenerState; } @@ -1499,49 +1498,64 @@ nsresult nsParser::Terminate(void){ return mInternalState; } + /** - * Call this when you want control whether or not the parser will parse - * and tokenize input (TRUE), or whether it just caches input to be - * parsed later (FALSE). + * Call this when you want to toggle from the blocked state and resume parsing * * @update gess 1/29/99 * @param aState determines whether we parse/tokenize or just cache. * @return current state */ -nsresult nsParser::EnableParser(PRBool aState){ - +nsresult nsParser::ResumeParsing(){ + // If the stream has already finished, there's a good chance // that we might start closing things down when the parser // is reenabled. To make sure that we're not deleted across // the reenabling process, hold a reference to ourselves. nsresult result=NS_OK; - nsIParser* me = this; - NS_ADDREF(me); + nsCOMPtr kungFuDeathGrip(this); - // If we're reenabling the parser - if(mParserContext) { - mParserContext->mParserEnabled=aState; - if(aState) { + // Enable the parser + UnblockParser(); - //printf(" Re-enable parser\n"); - PRBool isFinalChunk=(mParserContext->mStreamListenerState==eOnStop)? PR_TRUE:PR_FALSE; - - result=ResumeParse(PR_TRUE,isFinalChunk); // Ref. bug 57999 - - if(result!=NS_OK) - result=mInternalState; - } - else { - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: nsParser::EnableParser(), this=%p\n", this)); - MOZ_TIMER_STOP(mParseTime); - } - } + PRBool isFinalChunk=(mParserContext && mParserContext->mStreamListenerState==eOnStop)? PR_TRUE:PR_FALSE; + + result=ResumeParse(PR_TRUE,isFinalChunk); // Ref. bug 57999 + + if(result!=NS_OK) + result=mInternalState; - // Release reference if we added one at the top of this routine - NS_IF_RELEASE(me); return result; } +/** + * Stops parsing temporarily. That's it will prevent the + * parser from building up content model. + * + * @update + * @return + */ +void nsParser::BlockParser() { + mParserEnabled=PR_FALSE; + MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: nsParser::BlockParser(), this=%p\n", this)); + MOZ_TIMER_STOP(mParseTime); +} + +/** + * Open up the parser for tokenization, building up content + * model..etc. However, this method does not resume parsing + * automatically. It's the callers' responsibility to restart + * the parsing engine. + * + * @update + * @return + */ +void nsParser::UnblockParser() { + mParserEnabled=PR_TRUE; + MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::UnblockParser(), this=%p\n", this)); + MOZ_TIMER_START(mParseTime); +} + /** * Call this to query whether the parser is enabled or not. * @@ -1549,7 +1563,7 @@ nsresult nsParser::EnableParser(PRBool aState){ * @return current state */ PRBool nsParser::IsParserEnabled() { - return mParserContext->mParserEnabled; + return mParserEnabled; } @@ -1863,7 +1877,7 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { nsresult result=NS_OK; - if(mParserContext->mParserEnabled && mInternalState!=NS_ERROR_HTMLPARSER_STOPPARSING) { + if(mParserEnabled && mInternalState!=NS_ERROR_HTMLPARSER_STOPPARSING) { MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::ResumeParse(), this=%p\n", this)); @@ -1904,8 +1918,8 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { if(NS_ERROR_HTMLPARSER_BLOCK==result) { //BLOCK == 2152596464 mParserContext->mDTD->WillInterruptParse(); - result=EnableParser(PR_FALSE); - return result; + BlockParser(); + return NS_OK; } else if (NS_ERROR_HTMLPARSER_STOPPARSING==result) { @@ -2392,7 +2406,7 @@ nsresult nsParser::OnStopRequest(nsIChannel* channel, nsISupports* aContext, gOutFile=0; } #endif - NS_IF_RELEASE(mBundle); + return result; } diff --git a/mozilla/htmlparser/src/nsParser.h b/mozilla/htmlparser/src/nsParser.h index ae72d064538..2a89af5b537 100644 --- a/mozilla/htmlparser/src/nsParser.h +++ b/mozilla/htmlparser/src/nsParser.h @@ -213,7 +213,9 @@ class nsParser : public nsIParser, * @param aState determines whether we parse/tokenize or just cache. * @return current state */ - virtual nsresult EnableParser(PRBool aState); + virtual nsresult ResumeParsing(); + virtual void BlockParser(); + virtual void UnblockParser(); virtual nsresult Terminate(void); /** @@ -407,7 +409,7 @@ protected: CObserverService mObserverService; PRBool mObserversEnabled; nsString mCommandStr; - + PRBool mParserEnabled; nsParserBundle* mBundle; nsTokenAllocator mTokenAllocator; diff --git a/mozilla/parser/htmlparser/src/CNavDTD.cpp b/mozilla/parser/htmlparser/src/CNavDTD.cpp index d7764e52e58..5dc39b27e34 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.cpp +++ b/mozilla/parser/htmlparser/src/CNavDTD.cpp @@ -730,7 +730,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ eHTMLTags theParentTag=mBodyContext->Last(); theTag=(eHTMLTags)theToken->GetTypeID(); if((FindTagInSet(theTag,gLegalElements,sizeof(gLegalElements)/sizeof(theTag))) || - (gHTMLElements[theParentTag].CanContain(theTag))) { + (gHTMLElements[theParentTag].CanContain(theTag)) && (theTag!=eHTMLTag_comment)) { // Added comment -> bug 40855 mDTDState=NS_OK; // reset the state since all the misplaced tokens are about to get handled. result=HandleSavedTokens(mBodyContext->mContextTopIndex); @@ -1928,6 +1928,12 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { if(result==NS_OK) { eHTMLTags theTarget=FindAutoCloseTargetForEndTag(theChildTag,*mBodyContext); if(eHTMLTag_unknown!=theTarget) { + if (nsHTMLElement::IsResidualStyleTag(theChildTag)) { + result=OpenTransientStyles(theChildTag); + if(NS_FAILED(result)) { + return result; + } + } result=CloseContainersTo(theTarget,PR_FALSE); } } @@ -3739,69 +3745,6 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); result=mSink->AddLeaf(*aNode); - - if(NS_SUCCEEDED(result)) { - PRBool done=PR_FALSE; - eHTMLTags thePrevTag=theTag; - //nsCParserNode theNode; - - while(!done && NS_SUCCEEDED(result)) { - CToken* theToken=mTokenizer->PeekToken(); - if(theToken) { - nsIParserNode* theNode=mNodeAllocator.CreateNode(theToken,mLineNumber,0); - if(theNode) { - theTag=(eHTMLTags)theToken->GetTypeID(); - switch(theTag) { - case eHTMLTag_newline: - mLineNumber++; - case eHTMLTag_whitespace: - { - theToken=mTokenizer->PopToken(); - - STOP_TIMER(); - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - - result=mSink->AddLeaf(*theNode); - - if((NS_SUCCEEDED(result))||(NS_ERROR_HTMLPARSER_BLOCK==result)) { - IF_FREE(theToken); - } - - MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - START_TIMER(); - thePrevTag=theTag; - } - break; - case eHTMLTag_text: - if((mHasOpenBody) && (!mHasOpenHead) && - !(nsHTMLElement::IsWhitespaceTag(thePrevTag))) { - theToken=mTokenizer->PopToken(); - - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - STOP_TIMER(); - - mLineNumber += theToken->mNewlineCount; - result=mSink->AddLeaf(*theNode); - - if((NS_SUCCEEDED(result))||(NS_ERROR_HTMLPARSER_BLOCK==result)) { - IF_FREE(theToken); - } - - MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); - START_TIMER(); - } - else done=PR_TRUE; - break; - - default: - done=PR_TRUE; - } //switch - NS_IF_RELEASE(theNode); - } //if - }//if - else done=PR_TRUE; - } //while - } //if MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddLeaf(), this=%p\n", this)); START_TIMER(); diff --git a/mozilla/parser/htmlparser/src/CParserContext.cpp b/mozilla/parser/htmlparser/src/CParserContext.cpp index f2760f3149c..c3bbaaacf78 100644 --- a/mozilla/parser/htmlparser/src/CParserContext.cpp +++ b/mozilla/parser/htmlparser/src/CParserContext.cpp @@ -56,7 +56,6 @@ CParserContext::CParserContext(nsScanner* aScanner, mDTD=aDTD; NS_IF_ADDREF(mDTD); mTransferBufferSize=eTransferBufferSize; - mParserEnabled=PR_TRUE; mStreamListenerState=eNone; mMultipart=PR_TRUE; mContextType=eCTNone; @@ -90,7 +89,6 @@ CParserContext::CParserContext(const CParserContext &aContext) : mMimeType() { NS_IF_ADDREF(mDTD); mTransferBufferSize=eTransferBufferSize; - mParserEnabled=aContext.mParserEnabled; mStreamListenerState=aContext.mStreamListenerState; mMultipart=aContext.mMultipart; mContextType=aContext.mContextType; diff --git a/mozilla/parser/htmlparser/src/CParserContext.h b/mozilla/parser/htmlparser/src/CParserContext.h index 7b458f1041e..9e282589875 100644 --- a/mozilla/parser/htmlparser/src/CParserContext.h +++ b/mozilla/parser/htmlparser/src/CParserContext.h @@ -83,7 +83,6 @@ public: void* mKey; PRUint32 mTransferBufferSize; - PRBool mParserEnabled; PRBool mCopyUnused; }; diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp index e56490dafaf..3e8a207f89e 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp @@ -606,11 +606,6 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, done=PR_TRUE; } else if(aChar==kLessThan) { - eHTMLTags theEndTag = (eHTMLTags)aToken->GetTypeID(); - if(result==NS_OK&&(gHTMLElements[theEndTag].mSkipTarget)){ - CToken* theEndToken=theAllocator->CreateTokenOfType(eToken_end,theEndTag); - AddToken(theEndToken,NS_OK,&mTokenDeque,theAllocator); - } done=PR_TRUE; } }//if diff --git a/mozilla/parser/htmlparser/src/nsIParser.h b/mozilla/parser/htmlparser/src/nsIParser.h index dc6cc4ad23a..8f1a91df521 100644 --- a/mozilla/parser/htmlparser/src/nsIParser.h +++ b/mozilla/parser/htmlparser/src/nsIParser.h @@ -219,8 +219,20 @@ class nsIParser : public nsISupports { * until you wind up being emitted to the given contentsink (which may or may not * be a proxy for the NGLayout content model). ******************************************************************************************/ - virtual nsresult EnableParser(PRBool aState) = 0; - virtual PRBool IsParserEnabled() = 0; + + // This method enables the parser ( by calling UnblockParser() ) and resumes parsing. + virtual nsresult ResumeParsing() =0; + + // Stops parsing temporarily. + virtual void BlockParser() =0; + + // Open up the parser for tokenization, building up content + // model..etc. However, this method does not resume parsing + // automatically. It's the callers' responsibility to restart + // the parsing engine. + virtual void UnblockParser() =0; + + virtual PRBool IsParserEnabled() =0; virtual nsresult Parse(nsIURI* aURL,nsIStreamObserver* aListener = nsnull,PRBool aEnableVerify=PR_FALSE, void* aKey=0,nsDTDMode aMode=eDTDMode_autodetect) = 0; virtual nsresult Parse(nsIInputStream& aStream, const nsString& aMimeType,PRBool aEnableVerify=PR_FALSE, void* aKey=0,nsDTDMode aMode=eDTDMode_autodetect) = 0; diff --git a/mozilla/parser/htmlparser/src/nsParser.cpp b/mozilla/parser/htmlparser/src/nsParser.cpp index 8730b8837f2..2b36aafe988 100644 --- a/mozilla/parser/htmlparser/src/nsParser.cpp +++ b/mozilla/parser/htmlparser/src/nsParser.cpp @@ -237,6 +237,7 @@ nsParser::nsParser(nsITokenObserver* anObserver) { mInternalState=NS_OK; mObserversEnabled=PR_TRUE; mCommand=eViewNormal; + mParserEnabled=PR_TRUE; mBundle=nsnull; MOZ_TIMER_DEBUGLOG(("Reset: Parse Time: nsParser::nsParser(), this=%p\n", this)); @@ -1413,10 +1414,12 @@ nsresult nsParser::DidBuildModel(nsresult anErrorCode) { //One last thing...close any open containers. nsresult result=anErrorCode; - if((mParserContext) && mParserContext->mParserEnabled) { - if((!mParserContext->mPrevContext) && (mParserContext->mDTD)) { + if(mParserEnabled && mParserContext && !mParserContext->mPrevContext) { + if(mParserContext->mDTD) { result=mParserContext->mDTD->DidBuildModel(anErrorCode,PRBool(0==mParserContext->mPrevContext),this,mSink); } + //Ref. to bug 61462. + NS_IF_RELEASE(mBundle); }//if return result; @@ -1432,9 +1435,6 @@ nsresult nsParser::DidBuildModel(nsresult anErrorCode) { */ void nsParser::PushContext(CParserContext& aContext) { aContext.mPrevContext=mParserContext; - if (mParserContext) { - aContext.mParserEnabled = mParserContext->mParserEnabled; - } mParserContext=&aContext; } @@ -1453,7 +1453,6 @@ CParserContext* nsParser::PopContext() { // back to the new one. Also, propagate the stream listener state // but don't override onStop state to guarantee the call to DidBuildModel(). if (mParserContext) { - mParserContext->mParserEnabled = oldContext->mParserEnabled; if(mParserContext->mStreamListenerState!=eOnStop) { mParserContext->mStreamListenerState = oldContext->mStreamListenerState; } @@ -1499,49 +1498,64 @@ nsresult nsParser::Terminate(void){ return mInternalState; } + /** - * Call this when you want control whether or not the parser will parse - * and tokenize input (TRUE), or whether it just caches input to be - * parsed later (FALSE). + * Call this when you want to toggle from the blocked state and resume parsing * * @update gess 1/29/99 * @param aState determines whether we parse/tokenize or just cache. * @return current state */ -nsresult nsParser::EnableParser(PRBool aState){ - +nsresult nsParser::ResumeParsing(){ + // If the stream has already finished, there's a good chance // that we might start closing things down when the parser // is reenabled. To make sure that we're not deleted across // the reenabling process, hold a reference to ourselves. nsresult result=NS_OK; - nsIParser* me = this; - NS_ADDREF(me); + nsCOMPtr kungFuDeathGrip(this); - // If we're reenabling the parser - if(mParserContext) { - mParserContext->mParserEnabled=aState; - if(aState) { + // Enable the parser + UnblockParser(); - //printf(" Re-enable parser\n"); - PRBool isFinalChunk=(mParserContext->mStreamListenerState==eOnStop)? PR_TRUE:PR_FALSE; - - result=ResumeParse(PR_TRUE,isFinalChunk); // Ref. bug 57999 - - if(result!=NS_OK) - result=mInternalState; - } - else { - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: nsParser::EnableParser(), this=%p\n", this)); - MOZ_TIMER_STOP(mParseTime); - } - } + PRBool isFinalChunk=(mParserContext && mParserContext->mStreamListenerState==eOnStop)? PR_TRUE:PR_FALSE; + + result=ResumeParse(PR_TRUE,isFinalChunk); // Ref. bug 57999 + + if(result!=NS_OK) + result=mInternalState; - // Release reference if we added one at the top of this routine - NS_IF_RELEASE(me); return result; } +/** + * Stops parsing temporarily. That's it will prevent the + * parser from building up content model. + * + * @update + * @return + */ +void nsParser::BlockParser() { + mParserEnabled=PR_FALSE; + MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: nsParser::BlockParser(), this=%p\n", this)); + MOZ_TIMER_STOP(mParseTime); +} + +/** + * Open up the parser for tokenization, building up content + * model..etc. However, this method does not resume parsing + * automatically. It's the callers' responsibility to restart + * the parsing engine. + * + * @update + * @return + */ +void nsParser::UnblockParser() { + mParserEnabled=PR_TRUE; + MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::UnblockParser(), this=%p\n", this)); + MOZ_TIMER_START(mParseTime); +} + /** * Call this to query whether the parser is enabled or not. * @@ -1549,7 +1563,7 @@ nsresult nsParser::EnableParser(PRBool aState){ * @return current state */ PRBool nsParser::IsParserEnabled() { - return mParserContext->mParserEnabled; + return mParserEnabled; } @@ -1863,7 +1877,7 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { nsresult result=NS_OK; - if(mParserContext->mParserEnabled && mInternalState!=NS_ERROR_HTMLPARSER_STOPPARSING) { + if(mParserEnabled && mInternalState!=NS_ERROR_HTMLPARSER_STOPPARSING) { MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::ResumeParse(), this=%p\n", this)); @@ -1904,8 +1918,8 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { if(NS_ERROR_HTMLPARSER_BLOCK==result) { //BLOCK == 2152596464 mParserContext->mDTD->WillInterruptParse(); - result=EnableParser(PR_FALSE); - return result; + BlockParser(); + return NS_OK; } else if (NS_ERROR_HTMLPARSER_STOPPARSING==result) { @@ -2392,7 +2406,7 @@ nsresult nsParser::OnStopRequest(nsIChannel* channel, nsISupports* aContext, gOutFile=0; } #endif - NS_IF_RELEASE(mBundle); + return result; } diff --git a/mozilla/parser/htmlparser/src/nsParser.h b/mozilla/parser/htmlparser/src/nsParser.h index ae72d064538..2a89af5b537 100644 --- a/mozilla/parser/htmlparser/src/nsParser.h +++ b/mozilla/parser/htmlparser/src/nsParser.h @@ -213,7 +213,9 @@ class nsParser : public nsIParser, * @param aState determines whether we parse/tokenize or just cache. * @return current state */ - virtual nsresult EnableParser(PRBool aState); + virtual nsresult ResumeParsing(); + virtual void BlockParser(); + virtual void UnblockParser(); virtual nsresult Terminate(void); /** @@ -407,7 +409,7 @@ protected: CObserverService mObserverService; PRBool mObserversEnabled; nsString mCommandStr; - + PRBool mParserEnabled; nsParserBundle* mBundle; nsTokenAllocator mTokenAllocator;