From f08d3b747dc8657ccb618962badba77c33343b87 Mon Sep 17 00:00:00 2001 From: "mrbkap%gmail.com" Date: Thu, 24 Nov 2005 00:14:25 +0000 Subject: [PATCH] bug 316582: Clean up style nitpicks in CNavDTD. rs=jst git-svn-id: svn://10.0.0.236/trunk@185233 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/parser/htmlparser/src/CNavDTD.cpp | 3465 ++++++++++----------- mozilla/parser/htmlparser/src/CNavDTD.h | 296 +- 2 files changed, 1803 insertions(+), 1958 deletions(-) diff --git a/mozilla/parser/htmlparser/src/CNavDTD.cpp b/mozilla/parser/htmlparser/src/CNavDTD.cpp index dca93296ca8..1d4a42eabd7 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.cpp +++ b/mozilla/parser/htmlparser/src/CNavDTD.cpp @@ -38,20 +38,17 @@ //#define ALLOW_TR_AS_CHILD_OF_TABLE //by setting this to true, TR is allowable directly in TABLE. -#define ENABLE_RESIDUALSTYLE - - #include "nsDebug.h" #include "nsIAtom.h" -#include "CNavDTD.h" +#include "CNavDTD.h" #include "nsHTMLTokens.h" #include "nsCRT.h" #include "nsParser.h" #include "nsIParser.h" -#include "nsIHTMLContentSink.h" +#include "nsIHTMLContentSink.h" #include "nsScanner.h" -#include "prenv.h" //this is here for debug reasons... -#include "prtypes.h" //this is here for debug reasons... +#include "prenv.h" +#include "prtypes.h" #include "prio.h" #include "plstr.h" #include "nsDTDUtils.h" @@ -74,16 +71,11 @@ /* * Ignore kFontStyle and kPhrase tags when the stack is deep, bug 58917. */ -#define FONTSTYLE_IGNORE_DEPTH (MAX_REFLOW_DEPTH*80/100) -#define PHRASE_IGNORE_DEPTH (MAX_REFLOW_DEPTH*90/100) - +#define FONTSTYLE_IGNORE_DEPTH (MAX_REFLOW_DEPTH * 80 / 100) +#define PHRASE_IGNORE_DEPTH (MAX_REFLOW_DEPTH * 90 / 100) -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID); -static NS_DEFINE_IID(kClassIID, NS_INAVHTML_DTD_IID); +static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID); -static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID); - #ifdef DEBUG static const char kNullToken[] = "Error: Null token given"; static const char kInvalidTagStackPos[] = "Error: invalid tag stack position"; @@ -93,22 +85,18 @@ static const char kInvalidTagStackPos[] = "Error: invalid tag stack position"; #ifdef MOZ_PERF_METRICS # define START_TIMER() \ - if(mParser) MOZ_TIMER_START(mParser->mParseTime); \ - if(mParser) MOZ_TIMER_START(mParser->mDTDTime); + if (mParser) MOZ_TIMER_START(mParser->mParseTime); \ + if (mParser) MOZ_TIMER_START(mParser->mDTDTime); # define STOP_TIMER() \ - if(mParser) MOZ_TIMER_STOP(mParser->mParseTime); \ - if(mParser) MOZ_TIMER_STOP(mParser->mDTDTime); + if (mParser) MOZ_TIMER_STOP(mParser->mParseTime); \ + if (mParser) MOZ_TIMER_STOP(mParser->mDTDTime); #else # define STOP_TIMER() # define START_TIMER() #endif -/************************************************************************ - And now for the main class -- CNavDTD... - ************************************************************************/ - - +// Some flags for use by the DTD. #define NS_DTD_FLAG_NONE 0x00000000 #define NS_DTD_FLAG_HAS_OPEN_HEAD 0x00000001 #define NS_DTD_FLAG_HAS_OPEN_BODY 0x00000002 @@ -125,55 +113,15 @@ static const char kInvalidTagStackPos[] = "Error: invalid tag stack position"; #define NS_DTD_FLAG_HAS_MAIN_CONTAINER (NS_DTD_FLAG_HAD_BODY | \ NS_DTD_FLAG_HAD_FRAMESET) -/** - * This method gets called as part of our COM-like interfaces. - * Its purpose is to create an interface to parser object - * of some type. - * - * @update gess 4/8/98 - * @param nsIID id of object to discover - * @param aInstancePtr ptr to newly discovered interface - * @return NS_xxx result code - */ -nsresult CNavDTD::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } +NS_IMPL_ISUPPORTS2(CNavDTD, nsIDTD, CNavDTD); - if(aIID.Equals(kISupportsIID)) { //do IUnknown... - *aInstancePtr = (nsIDTD*)(this); - } - else if(aIID.Equals(kIDTDIID)) { //do IParser base class... - *aInstancePtr = (nsIDTD*)(this); - } - else if(aIID.Equals(kClassIID)) { //do this class... - *aInstancePtr = (CNavDTD*)(this); - } - else { - *aInstancePtr=0; - return NS_NOINTERFACE; - } - NS_ADDREF_THIS(); - return NS_OK; -} - -NS_IMPL_ADDREF(CNavDTD) -NS_IMPL_RELEASE(CNavDTD) - -/** - * Default constructor - * - * @update gess 4/9/98 - * @param - * @return - */ -CNavDTD::CNavDTD() : nsIDTD(), - mMisplacedContent(0), +CNavDTD::CNavDTD() + : mMisplacedContent(0), mSink(0), mTokenAllocator(0), + mBodyContext(new nsDTDContext()), mTempContext(0), - mParser(0), + mParser(0), mTokenizer(0), mDTDMode(eDTDMode_quirks), mDocType(eHTML3_Quirks), // why not eHTML_Quirks? @@ -183,54 +131,44 @@ CNavDTD::CNavDTD() : nsIDTD(), mHeadContainerPosition(-1), mFlags(NS_DTD_FLAG_NONE) { - mBodyContext=new nsDTDContext(); } -/** - * - * @update gess1/8/99 - * @param - * @return - */ -const nsIID& CNavDTD::GetMostDerivedIID(void)const { +const nsIID& +CNavDTD::GetMostDerivedIID() const +{ + static nsIID kClassIID = NS_GET_IID(CNavDTD); return kClassIID; } #ifdef NS_DEBUG -nsLoggingSink* GetLoggingSink() { +static nsLoggingSink* +GetLoggingSink() +{ + // This returns a content sink that is useful for following what calls the DTD + // makes to the content sink. - //these are used when you want to generate a log file for contentsink construction... + static PRBool checkForPath = PR_TRUE; + static nsLoggingSink *theSink = nsnull; + static const char* gLogPath = nsnull; - static PRBool checkForPath=PR_TRUE; - static nsLoggingSink *theSink=0; - static const char* gLogPath=0; - - if(checkForPath) { - - // we're only going to check the environment once per session. - - gLogPath = /* "c:/temp/parse.log"; */ PR_GetEnv("PARSE_LOGFILE"); - checkForPath=PR_FALSE; + if (checkForPath) { + // Only check once per run. + gLogPath = PR_GetEnv("PARSE_LOGFILE"); + checkForPath = PR_FALSE; } - if(gLogPath && (!theSink)) { - static nsLoggingSink gLoggingSink; + if (gLogPath && !theSink) { + static nsLoggingSink gLoggingSink; - PRIntn theFlags = 0; + PRIntn theFlags = PR_CREATE_FILE | PR_RDWR; - // create the file exists, only open for read/write - // otherwise, create it - if(PR_Access(gLogPath,PR_ACCESS_EXISTS) != PR_SUCCESS) - theFlags = PR_CREATE_FILE; - theFlags |= PR_RDWR; - - // open the record file - PRFileDesc *theLogFile = PR_Open(gLogPath,theFlags,0); - gLoggingSink.SetOutputStream(theLogFile,PR_TRUE); - theSink=&gLoggingSink; + // Open the record file. + PRFileDesc *theLogFile = PR_Open(gLogPath, theFlags, 0); + gLoggingSink.SetOutputStream(theLogFile, PR_TRUE); + theSink = &gLoggingSink; } return theSink; @@ -238,29 +176,15 @@ nsLoggingSink* GetLoggingSink() { #endif -/** - * Default destructor - * - * @update gess 4/9/98 - * @param - * @return - */ -CNavDTD::~CNavDTD(){ - if(mBodyContext) { - delete mBodyContext; - mBodyContext=0; - } +CNavDTD::~CNavDTD() +{ + delete mBodyContext; + delete mTempContext; - if(mTempContext) { - delete mTempContext; - mTempContext=0; - } - - #ifdef NS_DEBUG - if(mSink) { - nsLoggingSink *theLogSink=GetLoggingSink(); - if(mSink==theLogSink) { + if (mSink) { + nsLoggingSink *theLogSink = GetLoggingSink(); + if (mSink == theLogSink) { theLogSink->ReleaseProxySink(); } } @@ -268,16 +192,9 @@ CNavDTD::~CNavDTD(){ NS_IF_RELEASE(mSink); } - -/** - * Call this method if you want the DTD to construct a fresh - * instance of itself. - * @update gess 25May2000 - * @param - * @return - */ -nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult) +nsresult +CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult) { nsresult result = NS_NewNavHTMLDTD(aInstancePtrResult); NS_ENSURE_SUCCESS(result, result); @@ -291,17 +208,6 @@ nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult) return result; } -/** - * This method is called to determine if the given DTD can parse - * a document in a given source-type. - * NOTE: Parsing always assumes that the end result will involve - * storing the result in the main content model. - * @param aParserContext -- the context for this document (knows - * the content type, document type, parser command, etc). - * @return eUnknownDetect if you don't know how to parse it, - * eValidDetect if you do, but someone may have a better idea, - * ePrimaryDetect if you think you know best - */ NS_IMETHODIMP_(eAutoDetectResult) CNavDTD::CanParse(CParserContext& aParserContext) { @@ -322,22 +228,15 @@ CNavDTD::CanParse(CParserContext& aParserContext) return eUnknownDetect; } -/** - * The parser uses a code sandwich to wrap the parsing process. Before - * the process begins, WillBuildModel() is called. Afterwards the parser - * calls DidBuildModel(). - * @update rickg 03.20.2000 - * @param aParserContext - * @param aSink - * @return error code (almost always 0) - */ -nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext, - nsITokenizer* aTokenizer, - nsIContentSink* aSink) { - nsresult result=NS_OK; +nsresult +CNavDTD::WillBuildModel(const CParserContext& aParserContext, + nsITokenizer* aTokenizer, + nsIContentSink* aSink) +{ + nsresult result = NS_OK; - mFilename=aParserContext.mScanner->GetFilename(); - mFlags = NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE; // residual style is always on. This will also reset the flags + mFilename = aParserContext.mScanner->GetFilename(); + mFlags = NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE; mLineNumber = 1; mDTDMode = aParserContext.mDTDMode; mParserCommand = aParserContext.mParserCommand; @@ -346,8 +245,7 @@ nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext, mTokenizer = aTokenizer; mBodyContext->SetNodeAllocator(&mNodeAllocator); - if(!aParserContext.mPrevContext && aSink) { - + if (!aParserContext.mPrevContext && aSink) { STOP_TIMER(); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::WillBuildModel(), this=%p\n", this)); @@ -364,26 +262,26 @@ nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext, } } - //let's see if the environment is set up for us to write output to - //a logging sink. If so, then we'll create one, and make it the - //proxy for the real sink we're given from the parser. + // Let's see if the environment is set up for us to write output to + // a logging sink. If so, then we'll create one, and make it the + // proxy for the real sink we're given from the parser. #ifdef NS_DEBUG - nsLoggingSink *theLogSink=GetLoggingSink(); - if(theLogSink) { + nsLoggingSink *theLogSink = GetLoggingSink(); + if (theLogSink) { theLogSink->SetProxySink(mSink); - mSink=theLogSink; + mSink = theLogSink; } #endif - if(mSink) { + if (mSink) { PRBool enabled = PR_TRUE; mSink->IsEnabled(eHTMLTag_frameset, &enabled); - if(enabled) { + if (enabled) { mFlags |= NS_IPARSER_FLAG_FRAMES_ENABLED; } mSink->IsEnabled(eHTMLTag_script, &enabled); - if(enabled) { + if (enabled) { mFlags |= NS_IPARSER_FLAG_SCRIPT_ENABLED; } } @@ -392,114 +290,117 @@ nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext, return result; } - -/** - * This is called when it's time to read as many tokens from the tokenizer - * as you can. Not all tokens may make sense, so you may not be able to - * read them all (until more come in later). - * - * @update gess5/18/98 - * @param aParser is the parser object that's driving this process - * @return error code (almost always NS_OK) - */ -nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsITokenObserver* anObserver,nsIContentSink* aSink) { - NS_PRECONDITION(mBodyContext!=nsnull,"Create a context before calling build model"); +nsresult +CNavDTD::BuildModel(nsIParser* aParser, + nsITokenizer* aTokenizer, + nsITokenObserver* anObserver, + nsIContentSink* aSink) +{ + NS_PRECONDITION(mBodyContext != nsnull, + "Create a context before calling build model"); nsresult result = NS_OK; - if (aTokenizer && aParser) { - nsITokenizer* oldTokenizer = mTokenizer; + if (!aTokenizer || !aParser) { + return NS_OK; + } - mTokenizer = aTokenizer; - mParser = (nsParser*)aParser; - mTokenAllocator = mTokenizer->GetTokenAllocator(); - - if (mSink) { - if (mBodyContext->GetCount() == 0) { - CStartToken* theToken=nsnull; - if(ePlainText==mDocType) { - //we do this little trick for text files, in both normal and viewsource mode... - theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_pre)); - if(theToken) { - mTokenizer->PushTokenFront(theToken); - } - } + nsITokenizer* oldTokenizer = mTokenizer; - // always open a body if frames are disabled.... - if(!(mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) { - theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_LITERAL_STRING("body"))); - mTokenizer->PushTokenFront(theToken); - } - //if the content model is empty, then begin by opening ... - theToken = (CStartToken*)mTokenizer->GetTokenAt(0); - if (theToken) { - eHTMLTags theTag = (eHTMLTags)theToken->GetTypeID(); - eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType()); - if (theTag != eHTMLTag_html || theType != eToken_start) { - theToken = NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_LITERAL_STRING("html"))); - if (theToken) { - mTokenizer->PushTokenFront(theToken); //this token should get pushed on the context stack. - } - } - } - else { - theToken = NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_LITERAL_STRING("html"))); - if (theToken) { - mTokenizer->PushTokenFront(theToken); //this token should get pushed on the context stack. - } + mTokenizer = aTokenizer; + mParser = (nsParser*)aParser; + mTokenAllocator = mTokenizer->GetTokenAllocator(); + + if (!mSink) { + return (mFlags & NS_DTD_FLAG_STOP_PARSING) + ? NS_ERROR_HTMLPARSER_STOPPARSING + : result; + } + + if (mBodyContext->GetCount() == 0) { + CToken* tempToken; + if (ePlainText == mDocType) { + tempToken = + mTokenAllocator->CreateTokenOfType(eToken_start, eHTMLTag_pre); + if (tempToken) { + mTokenizer->PushTokenFront(tempToken); + } + } + + // Always open a body if frames are disabled. + if (!(mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) { + tempToken = + mTokenAllocator->CreateTokenOfType(eToken_start, + eHTMLTag_body, + NS_LITERAL_STRING("body")); + if (tempToken) { + mTokenizer->PushTokenFront(tempToken); + } + } + + // If the content model is empty, then begin by opening . + CStartToken* theToken = (CStartToken*)mTokenizer->GetTokenAt(0); + if (theToken) { + eHTMLTags theTag = (eHTMLTags)theToken->GetTypeID(); + eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType()); + if (theTag != eHTMLTag_html || theType != eToken_start) { + tempToken = + mTokenAllocator->CreateTokenOfType(eToken_start, + eHTMLTag_html, + NS_LITERAL_STRING("html")); + if (tempToken) { + mTokenizer->PushTokenFront(tempToken); } } - - mSink->WillProcessTokens(); - - while (NS_SUCCEEDED(result)) { - if (!(mFlags & NS_DTD_FLAG_STOP_PARSING)) { - CToken* theToken = mTokenizer->PopToken(); - if (theToken) { - result = HandleToken(theToken,aParser); - } - else break; - } - else { - result = NS_ERROR_HTMLPARSER_STOPPARSING; - break; - } - - if ((NS_ERROR_HTMLPARSER_INTERRUPTED == mSink->DidProcessAToken())) { - // The content sink has requested that DTD interrupt processing tokens - // So we need to make sure the parser is in a state where it can be - // interrupted. - // The mParser->CanInterrupt will return TRUE if BuildModel was called - // from a place in the parser where it prepared to handle a return value of - // NS_ERROR_HTMLPARSER_INTERRUPTED. - // If the parser is processing a script's document.write we should not - // allow it to be interrupted. - // We also need to make sure that an interruption does not override - // a request to block the parser. - if (mParser->CanInterrupt() && - !IsParserInDocWrite() && - NS_SUCCEEDED(result)) { - result = NS_ERROR_HTMLPARSER_INTERRUPTED; - break; - } - } - }//while - mTokenizer = oldTokenizer; - } - else { - result = mFlags & NS_DTD_FLAG_STOP_PARSING ? NS_ERROR_HTMLPARSER_STOPPARSING : result; + } else { + tempToken = + mTokenAllocator->CreateTokenOfType(eToken_start, + eHTMLTag_html, + NS_LITERAL_STRING("html")); + if (tempToken) { + mTokenizer->PushTokenFront(tempToken); + } } } + mSink->WillProcessTokens(); + + while (NS_SUCCEEDED(result)) { + if (!(mFlags & NS_DTD_FLAG_STOP_PARSING)) { + CToken* theToken = mTokenizer->PopToken(); + if (!theToken) { + break; + } + result = HandleToken(theToken, aParser); + } else { + result = NS_ERROR_HTMLPARSER_STOPPARSING; + break; + } + + if (NS_ERROR_HTMLPARSER_INTERRUPTED == mSink->DidProcessAToken()) { + // The content sink has requested that DTD interrupt processing tokens + // So we need to make sure the parser is in a state where it can be + // interrupted. + // The mParser->CanInterrupt will return TRUE if BuildModel was called + // from a place in the parser where it prepared to handle a return value of + // NS_ERROR_HTMLPARSER_INTERRUPTED. + // If the parser is processing a script's document.write we should not + // allow it to be interrupted. + // We also need to make sure that an interruption does not override + // a request to block the parser. + if (mParser->CanInterrupt() && + !IsParserInDocWrite() && + NS_SUCCEEDED(result)) { + result = NS_ERROR_HTMLPARSER_INTERRUPTED; + break; + } + } + } + + mTokenizer = oldTokenizer; return result; } -/** - * @param aTarget - Tag that was neglected in the document. - * @param aType - Specifies the type of the target. Ex. start, end, text, etc. - * @param aParser - Parser to drive this process - * @param aSink - HTML Content sink - */ nsresult CNavDTD::BuildNeglectedTarget(eHTMLTags aTarget, eHTMLTokenTypes aType, @@ -508,35 +409,35 @@ CNavDTD::BuildNeglectedTarget(eHTMLTags aTarget, { NS_ASSERTION(mTokenizer, "tokenizer is null! unable to build target."); NS_ASSERTION(mTokenAllocator, "unable to create tokens without an allocator."); - if (!mTokenizer || !mTokenAllocator) + if (!mTokenizer || !mTokenAllocator) { return NS_OK; - CHTMLToken* target = - NS_STATIC_CAST(CHTMLToken*, mTokenAllocator->CreateTokenOfType(aType, aTarget)); + } + + CToken* target = mTokenAllocator->CreateTokenOfType(aType, aTarget); mTokenizer->PushTokenFront(target); return BuildModel(aParser, mTokenizer, 0, aSink); } -/** - * - * @update gess5/18/98 - * @param - * @return - */ -nsresult CNavDTD::DidBuildModel(nsresult anErrorCode, - PRBool aNotifySink, - nsIParser* aParser, - nsIContentSink* aSink) +nsresult +CNavDTD::DidBuildModel(nsresult anErrorCode, + PRBool aNotifySink, + nsIParser* aParser, + nsIContentSink* aSink) { - if (!aSink) + if (!aSink) { return NS_OK; + } + nsresult result = NS_OK; - if (aParser && aNotifySink) { + if (aParser && aNotifySink) { if (NS_OK == anErrorCode) { if (!(mFlags & NS_DTD_FLAG_HAS_MAIN_CONTAINER)) { // This document is not a frameset document, however, it did not contain // a body tag either. So, make one!. Note: Body tag is optional per spec.. - result = BuildNeglectedTarget(eHTMLTag_body, eToken_start, aParser, aSink); - NS_ENSURE_SUCCESS(result , result); + // Also note: We ignore the return value of BuildNeglectedTarget, we + // can't reasonably respond to errors (or requests to block) at this + // point in the parsing process. + BuildNeglectedTarget(eHTMLTag_body, eToken_start, aParser, aSink); } if (mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) { // Looks like the misplaced contents are not processed yet. @@ -562,8 +463,10 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode, } while (mFlags & NS_DTD_FLAG_MISPLACED_CONTENT); mBodyContext->mContextTopIndex = -1; - } - //now let's disable style handling to save time when closing remaining stack members... + } + + // Now let's disable style handling to save time when closing remaining + // stack members. mFlags &= ~NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE; while (mBodyContext->GetCount() > 0) { result = CloseContainersTo(mBodyContext->Last(), PR_FALSE); @@ -573,28 +476,27 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode, return result; } } - } - else { - //If you're here, then an error occured, but we still have nodes on the stack. - //At a minimum, we should grab the nodes and recycle them. - //Just to be correct, we'll also recycle the nodes. + } else { + // If you're here, then an error occured, but we still have nodes on the stack. + // At a minimum, we should grab the nodes and recycle them. + // Just to be correct, we'll also recycle the nodes. while (mBodyContext->GetCount() > 0) { nsEntryStack* theChildStyles = 0; nsCParserNode* theNode = mBodyContext->Pop(theChildStyles); - IF_DELETE(theChildStyles,&mNodeAllocator); + IF_DELETE(theChildStyles, &mNodeAllocator); IF_FREE(theNode, &mNodeAllocator); } } - //Now make sure the misplaced content list is empty, - //by forcefully recycling any tokens we might find there. + // Now make sure the misplaced content list is empty, + // by forcefully recycling any tokens we might find there. CToken* theToken = 0; while ((theToken = (CToken*)mMisplacedContent.Pop())) { IF_FREE(theToken, mTokenAllocator); } - } //if aparser + } - //No matter what, you need to call did build model. + // No matter what, you need to call did build model. return aSink->DidBuildModel(); } @@ -612,38 +514,41 @@ CNavDTD::GetType() } /** - * --- Backwards compatibility --- - * Use this method to determine if the tag in question needs a BODY. - * --- + * Text and some tags require a body when they're added, this function returns + * true for those tags. + * + * @param aToken The current token that we care about. + * @param aTokenizer A tokenizer that we can get the tags attributes off of. + * @return PR_TRUE if aToken does indeed force the body to open. */ -static -PRBool DoesRequireBody(CToken* aToken,nsITokenizer* aTokenizer) { +static PRBool +DoesRequireBody(CToken* aToken, nsITokenizer* aTokenizer) +{ + PRBool result = PR_FALSE; - PRBool result=PR_FALSE; - - if(aToken) { - eHTMLTags theTag=(eHTMLTags)aToken->GetTypeID(); - if(gHTMLElements[theTag].HasSpecialProperty(kRequiresBody)) { - if(theTag==eHTMLTag_input) { + if (aToken) { + eHTMLTags theTag = (eHTMLTags)aToken->GetTypeID(); + if (gHTMLElements[theTag].HasSpecialProperty(kRequiresBody)) { + if (theTag == eHTMLTag_input) { // IE & Nav4x opens up a body for type=text - Bug 66985 - PRInt32 ac=aToken->GetAttributeCount(); - for(PRInt32 i=0; iGetTokenAt(i)); - const nsSubstring& name=attr->GetKey(); - const nsAString& value=attr->GetValue(); + PRInt32 ac = aToken->GetAttributeCount(); + for(PRInt32 i = 0; i < ac; ++i) { + CAttributeToken* attr = NS_STATIC_CAST(CAttributeToken*, + aTokenizer->GetTokenAt(i)); + const nsSubstring& name = attr->GetKey(); + const nsAString& value = attr->GetValue(); - if((name.EqualsLiteral("type") || - name.EqualsLiteral("TYPE")) - && - !(value.EqualsLiteral("hidden") || - value.EqualsLiteral("HIDDEN"))) { - result=PR_TRUE; + if ((name.EqualsLiteral("type") || + name.EqualsLiteral("TYPE")) + && + !(value.EqualsLiteral("hidden") || + value.EqualsLiteral("HIDDEN"))) { + result = PR_TRUE; break; } - }//for - } - else { - result=PR_TRUE; + } + } else { + result = PR_TRUE; } } } @@ -654,8 +559,9 @@ PRBool DoesRequireBody(CToken* aToken,nsITokenizer* aTokenizer) { /** * Returns whether or not there is a tag of type aType open on aContext. */ -static -PRBool HasOpenTagOfType(PRInt32 aType, const nsDTDContext& aContext) { +static PRBool +HasOpenTagOfType(PRInt32 aType, const nsDTDContext& aContext) +{ PRInt32 count = aContext.GetCount(); while (--count >= 0) { @@ -667,342 +573,312 @@ PRBool HasOpenTagOfType(PRInt32 aType, const nsDTDContext& aContext) { return PR_FALSE; } -/** - * This big dispatch method is used to route token handler calls to the right place. - * What's wrong with it? This table, and the dispatch methods themselves need to be - * moved over to the delegate. Ah, so much to do... - * - * @update gess 12/1/99 - * @param aToken - * @param aParser - * @return - */ -nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ - nsresult result=NS_OK; +nsresult +CNavDTD::HandleToken(CToken* aToken, nsIParser* aParser) +{ + if (!aToken) { + return NS_OK; + } - if(aToken) { - CHTMLToken* theToken= NS_STATIC_CAST(CHTMLToken*, aToken); - eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); - eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); + nsresult result = NS_OK; + CHTMLToken* theToken = NS_STATIC_CAST(CHTMLToken*, aToken); + eHTMLTokenTypes theType = eHTMLTokenTypes(theToken->GetTokenType()); + eHTMLTags theTag = (eHTMLTags)theToken->GetTypeID(); - aToken->SetLineNumber(mLineNumber); + aToken->SetLineNumber(mLineNumber); - if (!IsParserInDocWrite()) { - mLineNumber += aToken->GetNewlineCount(); + if (!IsParserInDocWrite()) { + mLineNumber += aToken->GetNewlineCount(); + } + + if (mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) { + // Included TD & TH to fix Bug# 20797 + static eHTMLTags gLegalElements[] = { + eHTMLTag_table, eHTMLTag_thead, eHTMLTag_tbody, + eHTMLTag_tr, eHTMLTag_td, eHTMLTag_th, eHTMLTag_tfoot + }; + // Don't even try processing misplaced tokens if we're already + // handling misplaced content. See bug 269095 + if (mFlags & NS_DTD_FLAG_IN_MISPLACED_CONTENT) { + PushIntoMisplacedStack(theToken); + return NS_OK; } - - if(mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) { - // Included TD & TH to fix Bug# 20797 - static eHTMLTags gLegalElements[]={eHTMLTag_table,eHTMLTag_thead,eHTMLTag_tbody, - eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th,eHTMLTag_tfoot}; - if(theToken) { - // Don't even try processing misplaced tokens if we're already - // handling misplaced content. See bug 269095 - if (mFlags & NS_DTD_FLAG_IN_MISPLACED_CONTENT) { - PushIntoMisplacedStack(theToken); - return result; - } - eHTMLTags theParentTag=mBodyContext->Last(); - theTag=(eHTMLTags)theToken->GetTypeID(); - if(FindTagInSet(theTag, gLegalElements, - NS_ARRAY_LENGTH(gLegalElements)) || - (gHTMLElements[theParentTag].CanContain(theTag,mDTDMode) && - // Here's a problem. If theTag is legal in here, we don't move it - // out. So if we're moving stuff out of here, the parent of theTag - // gets closed at this point. But some things are legal - // _everywhere_ and hence would effectively close out misplaced - // content in tables. This is undesirable, so treat them as - // illegal here so they'll be shipped out with their parents and - // siblings. See bug 40855 for an explanation (that bug was for - // comments, but the same issues arise with whitespace, newlines, - // noscript, etc). Script is special, though. Shipping it out - // breaks document.write stuff. See bug 243064. - (!gHTMLElements[theTag].HasSpecialProperty(kLegalOpen) || - theTag == eHTMLTag_script))) { - - mFlags &= ~NS_DTD_FLAG_MISPLACED_CONTENT; // reset the state since all the misplaced tokens are about to get handled. + eHTMLTags theParentTag = mBodyContext->Last(); + theTag = (eHTMLTags)theToken->GetTypeID(); + if (FindTagInSet(theTag, gLegalElements, + NS_ARRAY_LENGTH(gLegalElements)) || + (gHTMLElements[theParentTag].CanContain(theTag, mDTDMode) && + // Here's a problem. If theTag is legal in here, we don't move it + // out. So if we're moving stuff out of here, the parent of theTag + // gets closed at this point. But some things are legal + // _everywhere_ and hence would effectively close out misplaced + // content in tables. This is undesirable, so treat them as + // illegal here so they'll be shipped out with their parents and + // siblings. See bug 40855 for an explanation (that bug was for + // comments, but the same issues arise with whitespace, newlines, + // noscript, etc). Script is special, though. Shipping it out + // breaks document.write stuff. See bug 243064. + (!gHTMLElements[theTag].HasSpecialProperty(kLegalOpen) || + theTag == eHTMLTag_script))) { + // Reset the state since all the misplaced tokens are about to get + // handled. + mFlags &= ~NS_DTD_FLAG_MISPLACED_CONTENT; - result = HandleSavedTokens(mBodyContext->mContextTopIndex); - NS_ENSURE_SUCCESS(result, result); + result = HandleSavedTokens(mBodyContext->mContextTopIndex); + NS_ENSURE_SUCCESS(result, result); - mBodyContext->mContextTopIndex = -1; - } - else { - PushIntoMisplacedStack(theToken); - return result; + mBodyContext->mContextTopIndex = -1; + } else { + PushIntoMisplacedStack(theToken); + return result; + } + } + + /* + * This section of code is used to "move" misplaced content from one location + * in our document model to another. (Consider what would happen if we found a + *

tag in the head.) To move content, we throw it onto the + * misplacedcontent deque until we can deal with it. + */ + switch(theTag) { + case eHTMLTag_html: + case eHTMLTag_noframes: + case eHTMLTag_noscript: + case eHTMLTag_script: + case eHTMLTag_doctypeDecl: + case eHTMLTag_instruction: + break; + + default: + if (!gHTMLElements[eHTMLTag_html].SectionContains(theTag, PR_FALSE)) { + if (!(mFlags & (NS_DTD_FLAG_HAS_MAIN_CONTAINER | + NS_DTD_FLAG_ALTERNATE_CONTENT))) { + // For bug examples from this code, see bugs: 18928, 20989. + // At this point we know the body/frameset aren't open. + // If the child belongs in the head, then handle it (which may open the head); + // otherwise, push it onto the misplaced stack. + + PRBool isExclusive = PR_FALSE; + PRBool theChildBelongsInHead = + gHTMLElements[eHTMLTag_head].IsChildOfHead(theTag, isExclusive); + if (theChildBelongsInHead && !isExclusive) { + if (mMisplacedContent.GetSize() == 0) { + // This tag can either be in the body or the head. Since + // there is no indication that the body should be open, + // put this token in the head. + break; + } + + // Otherwise, we have received some indication that the body is + // "open", so push this token onto the misplaced content stack. + theChildBelongsInHead = PR_FALSE; + } + + if (!theChildBelongsInHead) { + eHTMLTags top = mBodyContext->Last(); + NS_ASSERTION(top != eHTMLTag_userdefined, + "Userdefined tags should act as leaves in the head"); + if (top != eHTMLTag_html && + gHTMLElements[top].CanContain(theTag, mDTDMode)) { + // Some tags (such as and