diff --git a/htmlparser/src/CParserContext.cpp b/htmlparser/src/CParserContext.cpp index 8b58ff42934f..a52566816794 100644 --- a/htmlparser/src/CParserContext.cpp +++ b/htmlparser/src/CParserContext.cpp @@ -25,6 +25,7 @@ #include "nsToken.h" MOZ_DECL_CTOR_COUNTER(CParserContext); + /** * Your friendly little constructor. Ok, it's not the friendly, but the only guy * using it is the parser. @@ -33,27 +34,68 @@ MOZ_DECL_CTOR_COUNTER(CParserContext); * @param aKey * @param aListener */ -CParserContext::CParserContext(nsScanner* aScanner,void* aKey,nsIStreamObserver* aListener,PRBool aCopyUnused) : - mSourceType() +CParserContext::CParserContext(nsScanner* aScanner, + void *aKey, + nsIStreamObserver* aListener, + nsIDTD *aDTD, + eAutoDetectResult aStatus, + PRBool aCopyUnused) : + mSourceType() + //,mTokenDeque(gTokenDeallocator) +{ + MOZ_COUNT_CTOR(CParserContext); + + mScanner=aScanner; + mKey=aKey; + mPrevContext=0; + mListener=aListener; + NS_IF_ADDREF(mListener); + mParseMode=eParseMode_unknown; + mAutoDetectStatus=aStatus; + mTransferBuffer=0; + mDTD=aDTD; + NS_IF_ADDREF(mDTD); + mTransferBufferSize=eTransferBufferSize; + mParserEnabled=PR_TRUE; + mStreamListenerState=eNone; + mMultipart=PR_TRUE; + mContextType=eCTNone; + mCopyUnused=aCopyUnused; +} + +/** + * Your friendly little constructor. Ok, it's not the friendly, but the only guy + * using it is the parser. + * @update gess7/23/98 + * @param aScanner + * @param aKey + * @param aListener + */ +CParserContext::CParserContext(const CParserContext &aContext) : + mSourceType(aContext.mSourceType) //,mTokenDeque(gTokenDeallocator) { MOZ_COUNT_CTOR(CParserContext); - mScanner=aScanner; - mKey=aKey; + mScanner=aContext.mScanner; + mKey=aContext.mKey; mPrevContext=0; - mListener=aListener; + mListener=aContext.mListener; NS_IF_ADDREF(mListener); - mParseMode=eParseMode_unknown; - mAutoDetectStatus=eUnknownDetect; - mTransferBuffer=0; - mDTD=0; + + mParseMode=aContext.mParseMode; + mAutoDetectStatus=aContext.mAutoDetectStatus; + mTransferBuffer=aContext.mTransferBuffer; + mDTD=aContext.mDTD; + NS_IF_ADDREF(mDTD); + mTransferBufferSize=eTransferBufferSize; - mParserEnabled=PR_TRUE; - mStreamListenerState=eNone; - mMultipart=PR_TRUE; - mContextType=eCTNone; - mCopyUnused=aCopyUnused; + mParserEnabled=aContext.mParserEnabled; + mStreamListenerState=aContext.mStreamListenerState; + mMultipart=aContext.mMultipart; + mContextType=aContext.mContextType; + mCopyUnused; + mRefCount=2; } @@ -66,11 +108,14 @@ CParserContext::~CParserContext(){ MOZ_COUNT_DTOR(CParserContext); - if(mScanner) - delete mScanner; + mRefCount--; + if(0==mRefCount) { + if(mScanner) + delete mScanner; - if(mTransferBuffer) - delete [] mTransferBuffer; + if(mTransferBuffer) + delete [] mTransferBuffer; + } NS_IF_RELEASE(mDTD); diff --git a/htmlparser/src/CParserContext.h b/htmlparser/src/CParserContext.h index a54f68f9a6ad..45fc701b4894 100644 --- a/htmlparser/src/CParserContext.h +++ b/htmlparser/src/CParserContext.h @@ -49,10 +49,14 @@ public: enum {eTransferBufferSize=4096}; enum eContextType {eCTNone,eCTURL,eCTString,eCTStream}; - CParserContext( nsScanner* aScanner, - void* aKey=0, - nsIStreamObserver* aListener=0, - PRBool aCopyUnused=PR_FALSE); + CParserContext( nsScanner* aScanner, + void* aKey=0, + nsIStreamObserver* aListener=0, + nsIDTD *aDTD=0, + eAutoDetectResult aStatus=eUnknownDetect, + PRBool aCopyUnused=PR_FALSE); + + CParserContext( const CParserContext& aContext); ~CParserContext(); @@ -64,6 +68,7 @@ public: PRBool mMultipart; eContextType mContextType; eAutoDetectResult mAutoDetectStatus; + PRInt32 mRefCount; nsString mSourceType; diff --git a/htmlparser/src/nsParser.cpp b/htmlparser/src/nsParser.cpp index c14a1e1aa151..4987bff547d0 100644 --- a/htmlparser/src/nsParser.cpp +++ b/htmlparser/src/nsParser.cpp @@ -810,6 +810,9 @@ nsresult nsParser::EnableParser(PRBool aState){ if(mParserContext) { mParserContext->mParserEnabled=aState; if(aState) { + + //printf(" Re-enable parser\n"); + result=ResumeParse(); if(result!=NS_OK) result=mInternalState; @@ -926,61 +929,75 @@ nsresult nsParser::Parse(nsIInputStream& aStream,PRBool aVerifyEnabled, void* aK * @param aContentType tells us what type of content to expect in the given string * @return error code -- 0 if ok, non-zero if error. */ -nsresult nsParser::Parse(const nsString& aSourceBuffer,void* aKey,const nsString& aContentType,PRBool aVerifyEnabled,PRBool aLastCall,eParseMode aMode){ - +nsresult nsParser::Parse(const nsString& aSourceBuffer,void* aKey,const nsString& +aContentType,PRBool aVerifyEnabled,PRBool aLastCall,eParseMode aMode){ + //NOTE: Make sure that updates to this method don't cause - // bug #2361 to break again! + // bug #2361 to break again! -#if 0 - //this is only for debug purposes - aSourceBuffer.DebugDump(); +#if 0 + //this is only for debug purposes + aSourceBuffer.DebugDump(); #endif - nsresult result=NS_OK; - nsParser* me = this; - // Maintain a reference to ourselves so we don't go away - // till we're completely done. - NS_ADDREF(me); - if(aSourceBuffer.Length() || mUnusedInput.Length()) { - mDTDVerification=aVerifyEnabled; + nsresult result=NS_OK; + nsParser* me = this; + // Maintain a reference to ourselves so we don't go away + // till we're completely done. + NS_ADDREF(me); + + if(aSourceBuffer.Length() || mUnusedInput.Length()) { + mDTDVerification=aVerifyEnabled; CParserContext* pc=0; - if((!mParserContext) || (mParserContext->mKey!=aKey)) { - //only make a new context if we dont have one, OR if we do, but has a different context key... - - nsScanner* theScanner=new nsScanner(mUnusedInput,mCharset,mCharsetSource); - pc=new CParserContext(theScanner,aKey, 0, aLastCall); - if(pc && theScanner) { - PushContext(*pc); + if((!mParserContext) || (mParserContext->mKey!=aKey)) { + //only make a new context if we dont have one, OR if we do, but has a different context key... + + nsScanner* theScanner=new nsScanner(mUnusedInput,mCharset,mCharsetSource); + nsIDTD *theDTD=0; + eAutoDetectResult theStatus=eUnknownDetect; - pc->mMultipart=!aLastCall; //by default - if (pc->mPrevContext) { - pc->mMultipart |= pc->mPrevContext->mMultipart; //if available - } + if(mParserContext && (mParserContext->mSourceType==aContentType)) { + theDTD=mParserContext->mDTD; + theStatus=mParserContext->mAutoDetectStatus; - pc->mStreamListenerState = (pc->mMultipart) ? eOnDataAvail : eOnStop; - pc->mContextType=CParserContext::eCTString; - pc->mSourceType=aContentType; - mUnusedInput.Truncate(0); + //added this to fix bug 32022. } - else { - NS_RELEASE(me); - return NS_ERROR_OUT_OF_MEMORY; - } - } - else { - pc=mParserContext; - pc->mScanner->Append(mUnusedInput); - } - pc->mScanner->Append(aSourceBuffer); + pc=new CParserContext(theScanner,aKey, 0,theDTD,theStatus,aLastCall); + - result=ResumeParse(PR_FALSE); + if(pc && theScanner) { + PushContext(*pc); - }//if - NS_RELEASE(me); - return result; -} + pc->mMultipart=!aLastCall; //by default + if (pc->mPrevContext) { + pc->mMultipart |= pc->mPrevContext->mMultipart; //if available + } + + pc->mStreamListenerState = (pc->mMultipart) ? eOnDataAvail : eOnStop; + pc->mContextType=CParserContext::eCTString; + pc->mSourceType=aContentType; + mUnusedInput.Truncate(0); + + //printf("Parse(string) iterate: %i",PR_FALSE); + pc->mScanner->Append(aSourceBuffer); + result=ResumeParse(PR_FALSE); + + } + else { + NS_RELEASE(me); + return NS_ERROR_OUT_OF_MEMORY; + } + + } + else { + mParserContext->mScanner->Append(aSourceBuffer); + } + }//if + NS_RELEASE(me); + return result; +} /** @@ -1118,7 +1135,10 @@ nsresult nsParser::ParseFragment(const nsString& aSourceBuffer,void* aKey,nsITag * @return error code -- 0 if ok, non-zero if error. */ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { + + //printf(" Resume %i, prev-context: %p\n",allowIteration,mParserContext->mPrevContext); + nsresult result=NS_OK; if(mParserContext->mParserEnabled && mInternalState!=NS_ERROR_HTMLPARSER_STOPPARSING) { @@ -1131,10 +1151,11 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { if(mParserContext->mDTD) { mParserContext->mDTD->WillResumeParse(); - PRBool theIterationIsOk=(allowIteration||(!mParserContext->mPrevContext)); + PRBool theFirstTime=PR_TRUE; + PRBool theIterationIsOk=(allowIteration || (!mParserContext->mPrevContext)); - while((result==NS_OK) && (theIterationIsOk)) { - + while((result==NS_OK) && (theFirstTime || theIterationIsOk)) { + theFirstTime=PR_FALSE; if(mUnusedInput.Length()>0) { if(mParserContext->mScanner) { // -- Ref: Bug# 22485 -- diff --git a/parser/htmlparser/src/CParserContext.cpp b/parser/htmlparser/src/CParserContext.cpp index 8b58ff42934f..a52566816794 100644 --- a/parser/htmlparser/src/CParserContext.cpp +++ b/parser/htmlparser/src/CParserContext.cpp @@ -25,6 +25,7 @@ #include "nsToken.h" MOZ_DECL_CTOR_COUNTER(CParserContext); + /** * Your friendly little constructor. Ok, it's not the friendly, but the only guy * using it is the parser. @@ -33,27 +34,68 @@ MOZ_DECL_CTOR_COUNTER(CParserContext); * @param aKey * @param aListener */ -CParserContext::CParserContext(nsScanner* aScanner,void* aKey,nsIStreamObserver* aListener,PRBool aCopyUnused) : - mSourceType() +CParserContext::CParserContext(nsScanner* aScanner, + void *aKey, + nsIStreamObserver* aListener, + nsIDTD *aDTD, + eAutoDetectResult aStatus, + PRBool aCopyUnused) : + mSourceType() + //,mTokenDeque(gTokenDeallocator) +{ + MOZ_COUNT_CTOR(CParserContext); + + mScanner=aScanner; + mKey=aKey; + mPrevContext=0; + mListener=aListener; + NS_IF_ADDREF(mListener); + mParseMode=eParseMode_unknown; + mAutoDetectStatus=aStatus; + mTransferBuffer=0; + mDTD=aDTD; + NS_IF_ADDREF(mDTD); + mTransferBufferSize=eTransferBufferSize; + mParserEnabled=PR_TRUE; + mStreamListenerState=eNone; + mMultipart=PR_TRUE; + mContextType=eCTNone; + mCopyUnused=aCopyUnused; +} + +/** + * Your friendly little constructor. Ok, it's not the friendly, but the only guy + * using it is the parser. + * @update gess7/23/98 + * @param aScanner + * @param aKey + * @param aListener + */ +CParserContext::CParserContext(const CParserContext &aContext) : + mSourceType(aContext.mSourceType) //,mTokenDeque(gTokenDeallocator) { MOZ_COUNT_CTOR(CParserContext); - mScanner=aScanner; - mKey=aKey; + mScanner=aContext.mScanner; + mKey=aContext.mKey; mPrevContext=0; - mListener=aListener; + mListener=aContext.mListener; NS_IF_ADDREF(mListener); - mParseMode=eParseMode_unknown; - mAutoDetectStatus=eUnknownDetect; - mTransferBuffer=0; - mDTD=0; + + mParseMode=aContext.mParseMode; + mAutoDetectStatus=aContext.mAutoDetectStatus; + mTransferBuffer=aContext.mTransferBuffer; + mDTD=aContext.mDTD; + NS_IF_ADDREF(mDTD); + mTransferBufferSize=eTransferBufferSize; - mParserEnabled=PR_TRUE; - mStreamListenerState=eNone; - mMultipart=PR_TRUE; - mContextType=eCTNone; - mCopyUnused=aCopyUnused; + mParserEnabled=aContext.mParserEnabled; + mStreamListenerState=aContext.mStreamListenerState; + mMultipart=aContext.mMultipart; + mContextType=aContext.mContextType; + mCopyUnused; + mRefCount=2; } @@ -66,11 +108,14 @@ CParserContext::~CParserContext(){ MOZ_COUNT_DTOR(CParserContext); - if(mScanner) - delete mScanner; + mRefCount--; + if(0==mRefCount) { + if(mScanner) + delete mScanner; - if(mTransferBuffer) - delete [] mTransferBuffer; + if(mTransferBuffer) + delete [] mTransferBuffer; + } NS_IF_RELEASE(mDTD); diff --git a/parser/htmlparser/src/CParserContext.h b/parser/htmlparser/src/CParserContext.h index a54f68f9a6ad..45fc701b4894 100644 --- a/parser/htmlparser/src/CParserContext.h +++ b/parser/htmlparser/src/CParserContext.h @@ -49,10 +49,14 @@ public: enum {eTransferBufferSize=4096}; enum eContextType {eCTNone,eCTURL,eCTString,eCTStream}; - CParserContext( nsScanner* aScanner, - void* aKey=0, - nsIStreamObserver* aListener=0, - PRBool aCopyUnused=PR_FALSE); + CParserContext( nsScanner* aScanner, + void* aKey=0, + nsIStreamObserver* aListener=0, + nsIDTD *aDTD=0, + eAutoDetectResult aStatus=eUnknownDetect, + PRBool aCopyUnused=PR_FALSE); + + CParserContext( const CParserContext& aContext); ~CParserContext(); @@ -64,6 +68,7 @@ public: PRBool mMultipart; eContextType mContextType; eAutoDetectResult mAutoDetectStatus; + PRInt32 mRefCount; nsString mSourceType; diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp index c14a1e1aa151..4987bff547d0 100644 --- a/parser/htmlparser/src/nsParser.cpp +++ b/parser/htmlparser/src/nsParser.cpp @@ -810,6 +810,9 @@ nsresult nsParser::EnableParser(PRBool aState){ if(mParserContext) { mParserContext->mParserEnabled=aState; if(aState) { + + //printf(" Re-enable parser\n"); + result=ResumeParse(); if(result!=NS_OK) result=mInternalState; @@ -926,61 +929,75 @@ nsresult nsParser::Parse(nsIInputStream& aStream,PRBool aVerifyEnabled, void* aK * @param aContentType tells us what type of content to expect in the given string * @return error code -- 0 if ok, non-zero if error. */ -nsresult nsParser::Parse(const nsString& aSourceBuffer,void* aKey,const nsString& aContentType,PRBool aVerifyEnabled,PRBool aLastCall,eParseMode aMode){ - +nsresult nsParser::Parse(const nsString& aSourceBuffer,void* aKey,const nsString& +aContentType,PRBool aVerifyEnabled,PRBool aLastCall,eParseMode aMode){ + //NOTE: Make sure that updates to this method don't cause - // bug #2361 to break again! + // bug #2361 to break again! -#if 0 - //this is only for debug purposes - aSourceBuffer.DebugDump(); +#if 0 + //this is only for debug purposes + aSourceBuffer.DebugDump(); #endif - nsresult result=NS_OK; - nsParser* me = this; - // Maintain a reference to ourselves so we don't go away - // till we're completely done. - NS_ADDREF(me); - if(aSourceBuffer.Length() || mUnusedInput.Length()) { - mDTDVerification=aVerifyEnabled; + nsresult result=NS_OK; + nsParser* me = this; + // Maintain a reference to ourselves so we don't go away + // till we're completely done. + NS_ADDREF(me); + + if(aSourceBuffer.Length() || mUnusedInput.Length()) { + mDTDVerification=aVerifyEnabled; CParserContext* pc=0; - if((!mParserContext) || (mParserContext->mKey!=aKey)) { - //only make a new context if we dont have one, OR if we do, but has a different context key... - - nsScanner* theScanner=new nsScanner(mUnusedInput,mCharset,mCharsetSource); - pc=new CParserContext(theScanner,aKey, 0, aLastCall); - if(pc && theScanner) { - PushContext(*pc); + if((!mParserContext) || (mParserContext->mKey!=aKey)) { + //only make a new context if we dont have one, OR if we do, but has a different context key... + + nsScanner* theScanner=new nsScanner(mUnusedInput,mCharset,mCharsetSource); + nsIDTD *theDTD=0; + eAutoDetectResult theStatus=eUnknownDetect; - pc->mMultipart=!aLastCall; //by default - if (pc->mPrevContext) { - pc->mMultipart |= pc->mPrevContext->mMultipart; //if available - } + if(mParserContext && (mParserContext->mSourceType==aContentType)) { + theDTD=mParserContext->mDTD; + theStatus=mParserContext->mAutoDetectStatus; - pc->mStreamListenerState = (pc->mMultipart) ? eOnDataAvail : eOnStop; - pc->mContextType=CParserContext::eCTString; - pc->mSourceType=aContentType; - mUnusedInput.Truncate(0); + //added this to fix bug 32022. } - else { - NS_RELEASE(me); - return NS_ERROR_OUT_OF_MEMORY; - } - } - else { - pc=mParserContext; - pc->mScanner->Append(mUnusedInput); - } - pc->mScanner->Append(aSourceBuffer); + pc=new CParserContext(theScanner,aKey, 0,theDTD,theStatus,aLastCall); + - result=ResumeParse(PR_FALSE); + if(pc && theScanner) { + PushContext(*pc); - }//if - NS_RELEASE(me); - return result; -} + pc->mMultipart=!aLastCall; //by default + if (pc->mPrevContext) { + pc->mMultipart |= pc->mPrevContext->mMultipart; //if available + } + + pc->mStreamListenerState = (pc->mMultipart) ? eOnDataAvail : eOnStop; + pc->mContextType=CParserContext::eCTString; + pc->mSourceType=aContentType; + mUnusedInput.Truncate(0); + + //printf("Parse(string) iterate: %i",PR_FALSE); + pc->mScanner->Append(aSourceBuffer); + result=ResumeParse(PR_FALSE); + + } + else { + NS_RELEASE(me); + return NS_ERROR_OUT_OF_MEMORY; + } + + } + else { + mParserContext->mScanner->Append(aSourceBuffer); + } + }//if + NS_RELEASE(me); + return result; +} /** @@ -1118,7 +1135,10 @@ nsresult nsParser::ParseFragment(const nsString& aSourceBuffer,void* aKey,nsITag * @return error code -- 0 if ok, non-zero if error. */ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { + + //printf(" Resume %i, prev-context: %p\n",allowIteration,mParserContext->mPrevContext); + nsresult result=NS_OK; if(mParserContext->mParserEnabled && mInternalState!=NS_ERROR_HTMLPARSER_STOPPARSING) { @@ -1131,10 +1151,11 @@ nsresult nsParser::ResumeParse(PRBool allowIteration, PRBool aIsFinalChunk) { if(mParserContext->mDTD) { mParserContext->mDTD->WillResumeParse(); - PRBool theIterationIsOk=(allowIteration||(!mParserContext->mPrevContext)); + PRBool theFirstTime=PR_TRUE; + PRBool theIterationIsOk=(allowIteration || (!mParserContext->mPrevContext)); - while((result==NS_OK) && (theIterationIsOk)) { - + while((result==NS_OK) && (theFirstTime || theIterationIsOk)) { + theFirstTime=PR_FALSE; if(mUnusedInput.Length()>0) { if(mParserContext->mScanner) { // -- Ref: Bug# 22485 --