зеркало из https://github.com/mozilla/pjs.git
bug 88952: Remove trailing content. This checkin fixes a whole slew of textarea bugs. r=jst sr=rbs
This commit is contained in:
Родитель
a9b503e476
Коммит
f404ddb2db
|
@ -153,7 +153,6 @@ public:
|
|||
}
|
||||
|
||||
nsString mTextValue;
|
||||
nsString mTrailingContent;
|
||||
protected:
|
||||
eContainerInfo mContainerInfo;
|
||||
PRPackedBool mEmpty;
|
||||
|
@ -282,9 +281,6 @@ public:
|
|||
CTextToken();
|
||||
CTextToken(const nsAString& aString);
|
||||
virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode);
|
||||
nsresult ConsumeUntil(PRUnichar aChar, PRBool aIgnoreComments,
|
||||
nsScanner& aScanner, const nsAString& aEndTagName,
|
||||
PRInt32 aFlag, PRBool& aFlushTokens);
|
||||
virtual PRInt32 GetTokenType(void);
|
||||
virtual PRInt32 GetTextLength(void);
|
||||
virtual void CopyTo(nsAString& aStr);
|
||||
|
@ -293,6 +289,21 @@ public:
|
|||
nsScannerIterator& aEnd);
|
||||
virtual void Bind(const nsAString& aStr);
|
||||
|
||||
nsresult ConsumeCharacterData(PRUnichar aChar,
|
||||
PRBool aConservativeConsume,
|
||||
PRBool aIgnoreComments,
|
||||
nsScanner& aScanner,
|
||||
const nsAString& aEndTagName,
|
||||
PRInt32 aFlag,
|
||||
PRBool& aFlushTokens);
|
||||
|
||||
nsresult ConsumeParsedCharacterData(PRUnichar aChar,
|
||||
PRBool aConservativeConsume,
|
||||
nsScanner& aScanner,
|
||||
const nsAString& aEndTagName,
|
||||
PRInt32 aFlag,
|
||||
PRBool& aFound);
|
||||
|
||||
protected:
|
||||
nsScannerSubstring mTextValue;
|
||||
};
|
||||
|
|
|
@ -310,7 +310,8 @@ class nsIParser : public nsISupports {
|
|||
#define NS_ERROR_HTMLPARSER_STOPPARSING NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_HTMLPARSER,1015)
|
||||
#define NS_ERROR_HTMLPARSER_UNTERMINATEDSTRINGLITERAL NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_HTMLPARSER,1016)
|
||||
#define NS_ERROR_HTMLPARSER_HIERARCHYTOODEEP NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_HTMLPARSER,1017)
|
||||
|
||||
#define NS_ERROR_HTMLPARSER_FAKE_ENDTAG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_HTMLPARSER,1018)
|
||||
#define NS_ERROR_HTMLPARSER_INVALID_COMMENT NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_HTMLPARSER,1019)
|
||||
|
||||
#define NS_ERROR_HTMLPARSER_CONTINUE NS_OK
|
||||
|
||||
|
@ -325,6 +326,8 @@ const PRUint32 kInvalidParserContext = NS_ERROR_HTMLPARSER_INVALIDPARSERCONTEXT
|
|||
const PRUint32 kBlocked = NS_ERROR_HTMLPARSER_BLOCK;
|
||||
const PRUint32 kBadStringLiteral = NS_ERROR_HTMLPARSER_UNTERMINATEDSTRINGLITERAL;
|
||||
const PRUint32 kHierarchyTooDeep = NS_ERROR_HTMLPARSER_HIERARCHYTOODEEP;
|
||||
const PRUint32 kFakeEndTag = NS_ERROR_HTMLPARSER_FAKE_ENDTAG;
|
||||
const PRUint32 kNotAComment = NS_ERROR_HTMLPARSER_INVALID_COMMENT;
|
||||
|
||||
const PRUnichar kNewLine = '\n';
|
||||
const PRUnichar kCR = '\r';
|
||||
|
@ -381,9 +384,10 @@ const PRUnichar kNullCh = '\0';
|
|||
#define NS_IPARSER_FLAG_VIEW_NORMAL 0x00000020
|
||||
#define NS_IPARSER_FLAG_VIEW_SOURCE 0x00000040
|
||||
#define NS_IPARSER_FLAG_VIEW_ERRORS 0x00000080
|
||||
#define NS_IPARSER_FLAG_PRESERVE_CONTENT 0x00000100
|
||||
#define NS_IPARSER_FLAG_PLAIN_TEXT 0x00000200
|
||||
#define NS_IPARSER_FLAG_XML 0x00000400
|
||||
#define NS_IPARSER_FLAG_HTML 0x00000800
|
||||
#define NS_IPARSER_FLAG_PLAIN_TEXT 0x00000100
|
||||
#define NS_IPARSER_FLAG_XML 0x00000200
|
||||
#define NS_IPARSER_FLAG_HTML 0x00000400
|
||||
#define NS_IPARSER_FLAG_SCRIPT_ENABLED 0x00000800
|
||||
#define NS_IPARSER_FLAG_FRAMES_ENABLED 0x00001000
|
||||
|
||||
#endif
|
||||
|
|
|
@ -86,7 +86,6 @@ public:
|
|||
NS_IMETHOD_(PRInt32) GetCount(void)=0;
|
||||
NS_IMETHOD_(nsTokenAllocator*) GetTokenAllocator(void)=0;
|
||||
NS_IMETHOD_(void) PrependTokens(nsDeque& aDeque)=0;
|
||||
NS_IMETHOD CopyState(nsITokenizer* aTokenizer) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -101,8 +100,7 @@ public:
|
|||
NS_IMETHOD_(CToken*) GetTokenAt(PRInt32 anIndex);\
|
||||
NS_IMETHOD_(PRInt32) GetCount(void);\
|
||||
NS_IMETHOD_(nsTokenAllocator*) GetTokenAllocator(void);\
|
||||
NS_IMETHOD_(void) PrependTokens(nsDeque& aDeque);\
|
||||
NS_IMETHOD CopyState(nsITokenizer* aTokenizer);
|
||||
NS_IMETHOD_(void) PrependTokens(nsDeque& aDeque);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,12 +116,10 @@ static char gShowCRC;
|
|||
#define NS_DTD_FLAG_HAD_BODY 0x00000010
|
||||
#define NS_DTD_FLAG_HAD_FRAMESET 0x00000020
|
||||
#define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE 0x00000040
|
||||
#define NS_DTD_FLAG_SCRIPT_ENABLED 0x00000100
|
||||
#define NS_DTD_FLAG_FRAMES_ENABLED 0x00000200
|
||||
#define NS_DTD_FLAG_ALTERNATE_CONTENT 0x00000400 // NOFRAMES, NOSCRIPT
|
||||
#define NS_DTD_FLAG_MISPLACED_CONTENT 0x00000800
|
||||
#define NS_DTD_FLAG_IN_MISPLACED_CONTENT 0x00001000
|
||||
#define NS_DTD_FLAG_STOP_PARSING 0x00002000
|
||||
#define NS_DTD_FLAG_ALTERNATE_CONTENT 0x00000080 // NOFRAMES, NOSCRIPT
|
||||
#define NS_DTD_FLAG_MISPLACED_CONTENT 0x00000100
|
||||
#define NS_DTD_FLAG_IN_MISPLACED_CONTENT 0x00000200
|
||||
#define NS_DTD_FLAG_STOP_PARSING 0x00000400
|
||||
|
||||
/**
|
||||
* This method gets called as part of our COM-like interfaces.
|
||||
|
@ -384,15 +382,15 @@ nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext,
|
|||
#endif
|
||||
|
||||
if(mSink) {
|
||||
PRBool enabled;
|
||||
PRBool enabled = PR_TRUE;
|
||||
mSink->IsEnabled(eHTMLTag_frameset, &enabled);
|
||||
if(enabled) {
|
||||
mFlags |= NS_DTD_FLAG_FRAMES_ENABLED;
|
||||
mFlags |= NS_IPARSER_FLAG_FRAMES_ENABLED;
|
||||
}
|
||||
|
||||
mSink->IsEnabled(eHTMLTag_script, &enabled);
|
||||
if(enabled) {
|
||||
mFlags |= NS_DTD_FLAG_SCRIPT_ENABLED;
|
||||
mFlags |= NS_IPARSER_FLAG_SCRIPT_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,7 +437,7 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke
|
|||
}
|
||||
|
||||
// always open a body if frames are disabled....
|
||||
if(!(mFlags & NS_DTD_FLAG_FRAMES_ENABLED)) {
|
||||
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);
|
||||
}
|
||||
|
@ -522,37 +520,6 @@ CNavDTD::BuildNeglectedTarget(eHTMLTags aTarget,
|
|||
NS_ASSERTION(mTokenAllocator, "unable to create tokens without an allocator.");
|
||||
if (!mTokenizer || !mTokenAllocator)
|
||||
return NS_OK;
|
||||
if (eHTMLTag_unknown != mSkipTarget && eHTMLTag_title == aTarget) {
|
||||
PRInt32 size = mSkippedContent.GetSize();
|
||||
// Note: The first location of the skipped content
|
||||
// deque contains the opened-skip-target. Do not include
|
||||
// that when guessing title contents. The term "guessing"
|
||||
// is used because the document did not contain an end title
|
||||
// and hence it's almost impossible to know what markup
|
||||
// should belong in the title. The assumption used here is that
|
||||
// if the markup is anything other than "text", or "entity" or,
|
||||
// "whitespace" then it's least likely to belong in the title.
|
||||
PRInt32 index;
|
||||
for (index = 1; index < size; index++) {
|
||||
CHTMLToken* token =
|
||||
NS_REINTERPRET_CAST(CHTMLToken*, mSkippedContent.ObjectAt(index));
|
||||
NS_ASSERTION(token, "there is a null token in the skipped content list!");
|
||||
eHTMLTokenTypes type = eHTMLTokenTypes(token->GetTokenType());
|
||||
if (eToken_whitespace != type &&
|
||||
eToken_newline != type &&
|
||||
eToken_text != type &&
|
||||
eToken_entity != type &&
|
||||
eToken_attribute != type) {
|
||||
// Now pop the tokens that do not belong ( just a guess work )
|
||||
// in the title and push them into the tokens queue.
|
||||
while (size != index++) {
|
||||
token = NS_REINTERPRET_CAST(CHTMLToken*, mSkippedContent.Pop());
|
||||
mTokenizer->PushTokenFront(token);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CHTMLToken* target =
|
||||
NS_STATIC_CAST(CHTMLToken*, mTokenAllocator->CreateTokenOfType(aType, aTarget));
|
||||
mTokenizer->PushTokenFront(target);
|
||||
|
@ -846,30 +813,6 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
|
|||
return result;
|
||||
}
|
||||
}
|
||||
else if(mFlags & NS_DTD_FLAG_ALTERNATE_CONTENT) {
|
||||
if(theTag != mBodyContext->Last() || theType!=eToken_end) {
|
||||
// attribute source is a part of start token.
|
||||
if(theType!=eToken_attribute) {
|
||||
aToken->AppendSourceTo(mScratch);
|
||||
}
|
||||
IF_FREE(aToken, mTokenAllocator);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
// If you're here then we have either seen a /noscript,
|
||||
// or /noframes, or /iframe. After handling the text token
|
||||
// intentionally fall thro' to handle the current end token.
|
||||
CTextToken theTextToken(mScratch);
|
||||
result=HandleStartToken(&theTextToken);
|
||||
|
||||
if(NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mScratch.Truncate();
|
||||
mScratch.SetCapacity(0);
|
||||
}
|
||||
}
|
||||
else if(mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) {
|
||||
// Included TD & TH to fix Bug# 20797
|
||||
static eHTMLTags gLegalElements[]={eHTMLTag_table,eHTMLTag_thead,eHTMLTag_tbody,
|
||||
|
@ -949,7 +892,9 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
|
|||
}
|
||||
default:
|
||||
if(!gHTMLElements[eHTMLTag_html].SectionContains(theTag,PR_FALSE)) {
|
||||
if(!(mFlags & (NS_DTD_FLAG_HAD_BODY | NS_DTD_FLAG_HAD_FRAMESET))) {
|
||||
if(!(mFlags & (NS_DTD_FLAG_HAD_BODY |
|
||||
NS_DTD_FLAG_HAD_FRAMESET |
|
||||
NS_DTD_FLAG_ALTERNATE_CONTENT))) {
|
||||
|
||||
//For bug examples from this code, see bugs: 18928, 20989.
|
||||
|
||||
|
@ -1075,28 +1020,6 @@ nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){
|
|||
}//if
|
||||
}
|
||||
break;
|
||||
|
||||
case eHTMLTag_xmp:
|
||||
//grab the skipped content and dump it out as text...
|
||||
{
|
||||
STOP_TIMER()
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::DidHandleStartTag(), this=%p\n", this));
|
||||
nsAutoString theString;
|
||||
PRInt32 lineNo = 0;
|
||||
|
||||
result = CollectSkippedContent(aChildTag, theString, lineNo);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
if(0<theString.Length()) {
|
||||
CTextToken *theToken=NS_STATIC_CAST(CTextToken*,mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theString));
|
||||
nsCParserNode theNode(theToken, mTokenAllocator);
|
||||
result=mSink->AddLeaf(theNode); //when the node get's destructed, so does the new token
|
||||
}
|
||||
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::DidHandleStartTag(), this=%p\n", this));
|
||||
START_TIMER()
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef DEBUG
|
||||
case eHTMLTag_counter:
|
||||
{
|
||||
|
@ -2485,30 +2408,10 @@ CNavDTD::CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLine
|
|||
PRInt32 tagCount = mSkippedContent.GetSize();
|
||||
for (i = 0; i< tagCount; ++i){
|
||||
CHTMLToken* theNextToken = (CHTMLToken*)mSkippedContent.PopFront();
|
||||
|
||||
if (theNextToken) {
|
||||
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 == aTag) || (eHTMLTag_title == aTag))) {
|
||||
mScratch.Truncate();
|
||||
((CEntityToken*)theNextToken)->TranslateToUnicodeStr(mScratch);
|
||||
if (!mScratch.IsEmpty()){
|
||||
aContent.Append(mScratch);
|
||||
}
|
||||
else {
|
||||
// We thought it was an entity but it is not! - bug 79492
|
||||
aContent.Append(PRUnichar('&'));
|
||||
aContent.Append(theNextToken->GetStringValue());
|
||||
}
|
||||
}
|
||||
else theNextToken->AppendSourceTo(aContent);
|
||||
}
|
||||
theNextToken->AppendSourceTo(aContent);
|
||||
}
|
||||
|
||||
IF_FREE(theNextToken, mTokenAllocator);
|
||||
}
|
||||
|
||||
|
@ -3433,8 +3336,7 @@ CNavDTD::OpenContainer(const nsCParserNode *aNode,
|
|||
// If the script is disabled noscript should not be
|
||||
// in the content model until the layout can somehow
|
||||
// turn noscript's display property to block <-- bug 67899
|
||||
if(mFlags & NS_DTD_FLAG_SCRIPT_ENABLED) {
|
||||
mScratch.Truncate();
|
||||
if(mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED) {
|
||||
mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
|
||||
}
|
||||
break;
|
||||
|
@ -3442,8 +3344,7 @@ CNavDTD::OpenContainer(const nsCParserNode *aNode,
|
|||
case eHTMLTag_iframe: // Bug 84491
|
||||
case eHTMLTag_noframes:
|
||||
done=PR_FALSE;
|
||||
if(mFlags & NS_DTD_FLAG_FRAMES_ENABLED) {
|
||||
mScratch.Truncate();
|
||||
if(mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED) {
|
||||
mFlags |= NS_DTD_FLAG_ALTERNATE_CONTENT;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "CParserContext.h"
|
||||
#include "nsToken.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIHTMLContentSink.h"
|
||||
#include "nsHTMLTokenizer.h"
|
||||
#include "nsExpatDriver.h"
|
||||
|
||||
|
@ -169,16 +170,33 @@ void CParserContext::SetMimeType(const nsACString& aMimeType){
|
|||
}
|
||||
|
||||
nsresult
|
||||
CParserContext::GetTokenizer(PRInt32 aType, nsITokenizer*& aTokenizer) {
|
||||
CParserContext::GetTokenizer(PRInt32 aType,
|
||||
nsIContentSink* aSink,
|
||||
nsITokenizer*& aTokenizer) {
|
||||
nsresult result = NS_OK;
|
||||
|
||||
if(!mTokenizer) {
|
||||
if (aType == NS_IPARSER_FLAG_HTML || mParserCommand == eViewSource) {
|
||||
result = NS_NewHTMLTokenizer(&mTokenizer,mDTDMode,mDocType,mParserCommand);
|
||||
// Propagate tokenizer state so that information is preserved
|
||||
// between document.write. This fixes bug 99467
|
||||
if (mTokenizer && mPrevContext)
|
||||
mTokenizer->CopyState(mPrevContext->mTokenizer);
|
||||
nsCOMPtr<nsIHTMLContentSink> theSink = do_QueryInterface(aSink);
|
||||
PRUint16 theFlags = 0;
|
||||
|
||||
if (theSink) {
|
||||
// XXX This code is repeated both here and in CNavDTD. Can the two
|
||||
// callsites be combined?
|
||||
PRBool enabled;
|
||||
theSink->IsEnabled(eHTMLTag_frameset, &enabled);
|
||||
if(enabled) {
|
||||
theFlags |= NS_IPARSER_FLAG_FRAMES_ENABLED;
|
||||
}
|
||||
|
||||
theSink->IsEnabled(eHTMLTag_script, &enabled);
|
||||
if(enabled) {
|
||||
theFlags |= NS_IPARSER_FLAG_SCRIPT_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
result = NS_NewHTMLTokenizer(&mTokenizer,mDTDMode,mDocType,
|
||||
mParserCommand,theFlags);
|
||||
}
|
||||
else if (aType == NS_IPARSER_FLAG_XML)
|
||||
{
|
||||
|
|
|
@ -76,7 +76,9 @@ public:
|
|||
CParserContext( const CParserContext& aContext);
|
||||
~CParserContext();
|
||||
|
||||
nsresult GetTokenizer(PRInt32 aType, nsITokenizer*& aTokenizer);
|
||||
nsresult GetTokenizer(PRInt32 aType,
|
||||
nsIContentSink* aSink,
|
||||
nsITokenizer*& aTokenizer);
|
||||
void SetMimeType(const nsACString& aMimeType);
|
||||
|
||||
nsCOMPtr<nsIRequest> mRequest; // provided by necko to differnciate different input streams
|
||||
|
|
|
@ -1228,9 +1228,9 @@ void InitializeElementTable(void) {
|
|||
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
|
||||
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
|
||||
/*autoclose starttags and endtags*/ 0,0,0,0,
|
||||
/*parent,incl,exclgroups*/ kInlineEntity|kPreformatted, kNone, kNone,
|
||||
/*parent,incl,exclgroups*/ kInlineEntity|kPreformatted, kCDATA, kNone,
|
||||
/*special props, prop-range*/ kNone,kDefaultPropRange,
|
||||
/*special parents,kids,skip*/ 0,0,eHTMLTag_xmp);
|
||||
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
|
||||
|
||||
Initialize(
|
||||
/*tag*/ eHTMLTag_text,
|
||||
|
@ -2270,7 +2270,8 @@ PRBool nsHTMLElement::CanContain(eHTMLTags aChild,nsDTDMode aMode) const{
|
|||
}
|
||||
|
||||
if(nsHTMLElement::IsTextTag(aChild)) {
|
||||
if(nsHTMLElement::IsInlineParent(mTagID)){
|
||||
// Allow <xmp> to contain text.
|
||||
if(nsHTMLElement::IsInlineParent(mTagID) || CanContainType(kCDATA)){
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1168,12 +1168,6 @@ nsExpatDriver::PrependTokens(nsDeque& aDeque)
|
|||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpatDriver::CopyState(nsITokenizer* aTokenizer)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExpatDriver::HandleToken(CToken* aToken,nsIParser* aParser)
|
||||
{
|
||||
|
|
|
@ -103,13 +103,14 @@ nsresult nsHTMLTokenizer::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|||
nsresult NS_NewHTMLTokenizer(nsITokenizer** aInstancePtrResult,
|
||||
PRInt32 aFlag,
|
||||
eParserDocType aDocType,
|
||||
eParserCommands aCommand)
|
||||
eParserCommands aCommand,
|
||||
PRInt32 aFlags)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsHTMLTokenizer* it = new nsHTMLTokenizer(aFlag,aDocType,aCommand);
|
||||
nsHTMLTokenizer* it = new nsHTMLTokenizer(aFlag,aDocType,aCommand,aFlags);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -128,23 +129,24 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
|
|||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsHTMLTokenizer::nsHTMLTokenizer(PRInt32 aParseMode,
|
||||
eParserDocType aDocType,
|
||||
eParserCommands aCommand) :
|
||||
nsITokenizer(), mTokenDeque(0)
|
||||
nsHTMLTokenizer::nsHTMLTokenizer(PRInt32 aParseMode,
|
||||
eParserDocType aDocType,
|
||||
eParserCommands aCommand,
|
||||
PRUint16 aFlags) :
|
||||
nsITokenizer(), mTokenDeque(0), mFlags(aFlags)
|
||||
{
|
||||
if (aParseMode==eDTDMode_full_standards ||
|
||||
aParseMode==eDTDMode_almost_standards) {
|
||||
mFlags = NS_IPARSER_FLAG_STRICT_MODE;
|
||||
mFlags |= NS_IPARSER_FLAG_STRICT_MODE;
|
||||
}
|
||||
else if (aParseMode==eDTDMode_quirks) {
|
||||
mFlags = NS_IPARSER_FLAG_QUIRKS_MODE;
|
||||
mFlags |= NS_IPARSER_FLAG_QUIRKS_MODE;
|
||||
}
|
||||
else if (aParseMode==eDTDMode_autodetect) {
|
||||
mFlags = NS_IPARSER_FLAG_AUTO_DETECT_MODE;
|
||||
mFlags |= NS_IPARSER_FLAG_AUTO_DETECT_MODE;
|
||||
}
|
||||
else {
|
||||
mFlags = NS_IPARSER_FLAG_UNKNOWN_MODE;
|
||||
mFlags |= NS_IPARSER_FLAG_UNKNOWN_MODE;
|
||||
}
|
||||
|
||||
if (aDocType==ePlainText) {
|
||||
|
@ -167,7 +169,6 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
|
|||
|
||||
mTokenAllocator = nsnull;
|
||||
mTokenScanPos = 0;
|
||||
mPreserveTarget = eHTMLTag_unknown;
|
||||
}
|
||||
|
||||
|
||||
|
@ -311,19 +312,6 @@ void nsHTMLTokenizer::PrependTokens(nsDeque& aDeque){
|
|||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTokenizer::CopyState(nsITokenizer* aTokenizer)
|
||||
{
|
||||
if (aTokenizer) {
|
||||
mFlags &= ~NS_IPARSER_FLAG_PRESERVE_CONTENT;
|
||||
mPreserveTarget =
|
||||
NS_STATIC_CAST(nsHTMLTokenizer*, aTokenizer)->mPreserveTarget;
|
||||
if (mPreserveTarget != eHTMLTag_unknown)
|
||||
mFlags |= NS_IPARSER_FLAG_PRESERVE_CONTENT;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utilty method for ScanDocStructure, which finds a given
|
||||
* tag in the stack.
|
||||
|
@ -649,10 +637,11 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,
|
|||
const nsSubstring& key=theToken->GetKey();
|
||||
const nsAString& text=theToken->GetValue();
|
||||
|
||||
// support XML like syntax to fix bugs like 44186
|
||||
if(!key.IsEmpty() && kForwardSlash==key.First() && text.IsEmpty()) {
|
||||
isUsableAttr = PRBool(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE); // Fix bug 103095
|
||||
aToken->SetEmpty(isUsableAttr);
|
||||
if(!(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
// We only care about these in view-source.
|
||||
isUsableAttr = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if(isUsableAttr) {
|
||||
++theAttrCount;
|
||||
|
@ -721,10 +710,6 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
|
|||
aToken=theAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown);
|
||||
|
||||
if(aToken) {
|
||||
// Save the position after '<' for use in recording traling contents. Ref: Bug. 15204.
|
||||
nsScannerIterator origin;
|
||||
aScanner.CurrentPosition(origin);
|
||||
|
||||
result= aToken->Consume(aChar,aScanner,mFlags); //tell new token to finish consuming text...
|
||||
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
|
@ -757,68 +742,81 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
|
|||
*/
|
||||
if(NS_SUCCEEDED(result) && !(mFlags & NS_IPARSER_FLAG_XML)) {
|
||||
CStartToken* theStartToken = NS_STATIC_CAST(CStartToken*,aToken);
|
||||
//XXX - Find a better soution to record content
|
||||
if(!(mFlags & NS_IPARSER_FLAG_PRESERVE_CONTENT) &&
|
||||
(theTag == eHTMLTag_textarea ||
|
||||
theTag == eHTMLTag_xmp ||
|
||||
theTag == eHTMLTag_noscript ||
|
||||
theTag == eHTMLTag_noframes)) {
|
||||
NS_ASSERTION(mPreserveTarget == eHTMLTag_unknown,
|
||||
"mPreserveTarget set but not preserving content?");
|
||||
mPreserveTarget = theTag;
|
||||
mFlags |= NS_IPARSER_FLAG_PRESERVE_CONTENT;
|
||||
|
||||
PRBool isCDATA = gHTMLElements[theTag].CanContainType(kCDATA);
|
||||
PRBool isPCDATA = eHTMLTag_textarea == theTag ||
|
||||
eHTMLTag_title == theTag;
|
||||
|
||||
if ((eHTMLTag_iframe == theTag && (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) ||
|
||||
(eHTMLTag_noframes == theTag && (mFlags & NS_IPARSER_FLAG_FRAMES_ENABLED)) ||
|
||||
(eHTMLTag_noscript == theTag && (mFlags & NS_IPARSER_FLAG_SCRIPT_ENABLED))) {
|
||||
isCDATA = PR_TRUE;
|
||||
}
|
||||
|
||||
if (mFlags & NS_IPARSER_FLAG_PRESERVE_CONTENT)
|
||||
PreserveToken(theStartToken, aScanner, origin);
|
||||
|
||||
//if((eHTMLTag_style==theTag) || (eHTMLTag_script==theTag)) {
|
||||
if(gHTMLElements[theTag].CanContainType(kCDATA)) {
|
||||
if (isCDATA || isPCDATA) {
|
||||
PRBool done = PR_FALSE;
|
||||
nsDependentString endTagName(nsHTMLTags::GetStringValue(theTag));
|
||||
|
||||
CToken* text=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text);
|
||||
CTextToken* textToken=NS_STATIC_CAST(CTextToken*,text);
|
||||
CToken* text =
|
||||
theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text);
|
||||
CTextToken* textToken = NS_STATIC_CAST(CTextToken*,text);
|
||||
|
||||
//tell new token to finish consuming text...
|
||||
result=textToken->ConsumeUntil(0,theTag!=eHTMLTag_script,
|
||||
aScanner,
|
||||
endTagName,
|
||||
mFlags,
|
||||
aFlushTokens);
|
||||
if (isCDATA) {
|
||||
// The only tags that consume conservatively are <script> and
|
||||
// <style>, the rest all consume until the end of the document.
|
||||
result = textToken->ConsumeCharacterData(0,
|
||||
theTag==eHTMLTag_script ||
|
||||
theTag==eHTMLTag_style,
|
||||
theTag!=eHTMLTag_script,
|
||||
aScanner,
|
||||
endTagName,
|
||||
mFlags,
|
||||
done);
|
||||
aFlushTokens = done;
|
||||
}
|
||||
else if (isPCDATA) {
|
||||
// Title is consumed conservatively in order to not regress
|
||||
// bug 42945
|
||||
result = textToken->ConsumeParsedCharacterData(0,
|
||||
theTag==eHTMLTag_title,
|
||||
aScanner,
|
||||
endTagName,
|
||||
mFlags,
|
||||
done);
|
||||
|
||||
// Fix bug 44186
|
||||
// Support XML like syntax, i.e., <script src="external.js"/> == <script src="external.js"></script>
|
||||
// Note: if aFlushTokens is TRUE then we have seen an </script>
|
||||
// We do NOT want to output the end token if we didn't see a
|
||||
// </script> and have a preserve target. If that happens, then we'd
|
||||
// be messing up the text inside the <textarea> or <xmp> or whatever
|
||||
// it is.
|
||||
if((!(mFlags & NS_IPARSER_FLAG_PRESERVE_CONTENT) &&
|
||||
!theStartToken->IsEmpty()) || aFlushTokens) {
|
||||
// Setting this would make cases like <script/>d.w("text");</script> work.
|
||||
theStartToken->SetEmpty(PR_FALSE);
|
||||
// do this up here so we can just add the end token later on
|
||||
AddToken(text,result,&mTokenDeque,theAllocator);
|
||||
// Note: we *don't* set aFlushTokens here.
|
||||
}
|
||||
|
||||
CToken* endToken=nsnull;
|
||||
// We want to do this unless result is kEOF, in which case we will
|
||||
// simply unwind our stack and wait for more data anyway.
|
||||
if (kEOF != result) {
|
||||
AddToken(text,NS_OK,&mTokenDeque,theAllocator);
|
||||
CToken* endToken = nsnull;
|
||||
|
||||
if (NS_SUCCEEDED(result) && aFlushTokens) {
|
||||
if (NS_SUCCEEDED(result) && done) {
|
||||
PRUnichar theChar;
|
||||
// Get the <
|
||||
result = aScanner.GetChar(theChar);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result) && theChar == kLessThan,
|
||||
"CTextToken::ConsumeUntil is broken!");
|
||||
"CTextToken::Consume*Data is broken!");
|
||||
#ifdef DEBUG
|
||||
// Ensure we have a /
|
||||
PRUnichar tempChar; // Don't change non-debug vars in debug-only code
|
||||
result = aScanner.Peek(tempChar);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result) && tempChar == kForwardSlash,
|
||||
"CTextToken::ConsumeUntil is broken!");
|
||||
"CTextToken::Consume*Data is broken!");
|
||||
#endif
|
||||
result = ConsumeEndTag(PRUnichar('/'),endToken,aScanner);
|
||||
} else if (!(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
} else if (result == kFakeEndTag &&
|
||||
!(mFlags & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
result = NS_OK;
|
||||
endToken=theAllocator->CreateTokenOfType(eToken_end,theTag,endTagName);
|
||||
AddToken(endToken,result,&mTokenDeque,theAllocator);
|
||||
} else if (result == kFakeEndTag) {
|
||||
// If we are here, we are both faking having seen the end tag
|
||||
// and are in view-source.
|
||||
result = NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -879,15 +877,6 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne
|
|||
aScanner.GetChar(aChar);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
eHTMLTags theTag = (eHTMLTags)aToken->GetTypeID();
|
||||
if (mPreserveTarget == theTag) {
|
||||
// Target reached. Stop preserving content.
|
||||
mPreserveTarget = eHTMLTag_unknown;
|
||||
mFlags &= ~NS_IPARSER_FLAG_PRESERVE_CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the same thing as we do in ConsumeStartTag. Basically, if we've run
|
||||
// out of room in this *section* of the document, pop all of the tokens
|
||||
// we've consumed this round and wait for more data.
|
||||
|
@ -984,6 +973,12 @@ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScann
|
|||
result=aToken->Consume(aChar,aScanner,mFlags);
|
||||
AddToken(aToken,result,&mTokenDeque,theAllocator);
|
||||
}
|
||||
|
||||
if (kNotAComment == result) {
|
||||
// AddToken has IF_FREE()'d our token, so...
|
||||
return ConsumeText(aToken, aScanner);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1109,33 +1104,3 @@ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*&
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method keeps a copy of contents within the start token.
|
||||
* The stored content could later be used in displaying TEXTAREA,
|
||||
* and also in view source.
|
||||
*
|
||||
* @update harishd 11/09/99
|
||||
* @param aStartToken: The token whose trailing contents are to be recorded
|
||||
* @param aScanner: see nsScanner.h
|
||||
*
|
||||
*/
|
||||
|
||||
void nsHTMLTokenizer::PreserveToken(CStartToken* aStartToken,
|
||||
nsScanner& aScanner,
|
||||
nsScannerIterator aOrigin) {
|
||||
if(aStartToken) {
|
||||
nsScannerIterator theCurrentPosition;
|
||||
aScanner.CurrentPosition(theCurrentPosition);
|
||||
|
||||
nsString& trailingContent = aStartToken->mTrailingContent;
|
||||
PRUint32 oldLength = trailingContent.Length();
|
||||
trailingContent.SetLength(oldLength + Distance(aOrigin, theCurrentPosition));
|
||||
|
||||
nsWritingIterator<PRUnichar> beginWriting;
|
||||
trailingContent.BeginWriting(beginWriting);
|
||||
beginWriting.advance(oldLength);
|
||||
|
||||
copy_string( aOrigin, theCurrentPosition, beginWriting );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
{0xe4238ddd, 0x9eb6, 0x11d2, \
|
||||
{0xba, 0xa5, 0x0, 0x10, 0x4b, 0x98, 0x3f, 0xd4 }}
|
||||
|
||||
|
||||
/***************************************************************
|
||||
Notes:
|
||||
***************************************************************/
|
||||
|
@ -74,7 +73,8 @@ public:
|
|||
NS_DECL_NSITOKENIZER
|
||||
nsHTMLTokenizer(PRInt32 aParseMode = eDTDMode_quirks,
|
||||
eParserDocType aDocType = eHTML3_Quirks,
|
||||
eParserCommands aCommand = eViewNormal);
|
||||
eParserCommands aCommand = eViewNormal,
|
||||
PRUint16 aPrefs = 0);
|
||||
virtual ~nsHTMLTokenizer();
|
||||
|
||||
protected:
|
||||
|
@ -93,8 +93,6 @@ protected:
|
|||
|
||||
nsresult ScanDocStructure(PRBool aIsFinalChunk);
|
||||
|
||||
virtual void PreserveToken(CStartToken* aStartToken, nsScanner& aScanner, nsScannerIterator aOrigin);
|
||||
|
||||
static void AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,nsTokenAllocator* aTokenAllocator);
|
||||
|
||||
nsDeque mTokenDeque;
|
||||
|
@ -102,12 +100,11 @@ protected:
|
|||
nsTokenAllocator* mTokenAllocator;
|
||||
PRInt32 mTokenScanPos;
|
||||
PRUint32 mFlags;
|
||||
eHTMLTags mPreserveTarget; // Tag whose content is preserved
|
||||
};
|
||||
|
||||
extern nsresult NS_NewHTMLTokenizer(nsITokenizer** aInstancePtrResult,
|
||||
PRInt32 aMode,eParserDocType aDocType,
|
||||
eParserCommands aCommand);
|
||||
eParserCommands aCommand, PRInt32 aFlags);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -62,6 +62,138 @@ static const PRUnichar kAttributeTerminalChars[] = {
|
|||
PRUnichar(0)
|
||||
};
|
||||
|
||||
static void AppendNCR(nsSubstring& aString, PRInt32 aNCRValue);
|
||||
/*
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @param aFlag -- If NS_IPARSER_FLAG_VIEW_SOURCE do not reduce entities...
|
||||
* @return error result
|
||||
*
|
||||
*/
|
||||
static
|
||||
nsresult ConsumeEntity(nsScannerSharedSubstring& aString,
|
||||
nsScanner& aScanner,
|
||||
PRInt32 aFlag)
|
||||
{
|
||||
nsresult result=NS_OK;
|
||||
|
||||
PRUnichar ch;
|
||||
result=aScanner.Peek(ch, 1);
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
PRUnichar amp=0;
|
||||
PRInt32 theNCRValue=0;
|
||||
nsAutoString entity;
|
||||
|
||||
if (nsCRT::IsAsciiAlpha(ch) && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
theNCRValue = nsHTMLEntities::EntityToUnicode(entity);
|
||||
PRUnichar theTermChar=entity.Last();
|
||||
// If an entity value is greater than 255 then:
|
||||
// Nav 4.x does not treat it as an entity,
|
||||
// IE treats it as an entity if terminated with a semicolon.
|
||||
// Resembling IE!!
|
||||
|
||||
nsSubstring &writable = aString.writable();
|
||||
if(theNCRValue < 0 || (theNCRValue > 255 && theTermChar != ';')) {
|
||||
// Looks like we're not dealing with an entity
|
||||
writable.Append(kAmpersand);
|
||||
writable.Append(entity);
|
||||
}
|
||||
else {
|
||||
// A valid entity so reduce it.
|
||||
writable.Append(PRUnichar(theNCRValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ch==kHashsign && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsSubstring &writable = aString.writable();
|
||||
if (result == NS_HTMLTOKENS_NOT_AN_ENTITY) {
|
||||
// Looked like an entity but it's not
|
||||
aScanner.GetChar(amp);
|
||||
writable.Append(amp);
|
||||
result = NS_OK; // just being safe..
|
||||
}
|
||||
else {
|
||||
PRInt32 err;
|
||||
theNCRValue=entity.ToInteger(&err,kAutoDetect);
|
||||
AppendNCR(writable, theNCRValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// What we thought as entity is not really an entity...
|
||||
aScanner.GetChar(amp);
|
||||
aString.writable().Append(amp);
|
||||
}//if
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This general purpose method is used when you want to
|
||||
* consume attributed text value.
|
||||
* Note: It also reduces entities.
|
||||
*
|
||||
* @param aNewlineCount -- the newline count to increment when hitting newlines
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @param aTerminalChars -- characters that stop consuming attribute.
|
||||
* @param aAllowNewlines -- whether to allow newlines in the value.
|
||||
* XXX it would be nice to roll this info into
|
||||
* aTerminalChars somehow....
|
||||
* @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
|
||||
* @return error result
|
||||
*/
|
||||
static
|
||||
nsresult ConsumeUntil(nsScannerSharedSubstring& aString,
|
||||
PRInt32& aNewlineCount,
|
||||
nsScanner& aScanner,
|
||||
const nsReadEndCondition& aEndCondition,
|
||||
PRBool aAllowNewlines,
|
||||
PRInt32 aFlag)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
PRBool done = PR_FALSE;
|
||||
|
||||
do {
|
||||
result = aScanner.ReadUntil(aString,aEndCondition,PR_FALSE);
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
PRUnichar ch;
|
||||
aScanner.Peek(ch);
|
||||
if(ch == kAmpersand) {
|
||||
result = ConsumeEntity(aString,aScanner,aFlag);
|
||||
}
|
||||
else if(ch == kCR && aAllowNewlines) {
|
||||
aScanner.GetChar(ch);
|
||||
result = aScanner.Peek(ch);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsSubstring &writable = aString.writable();
|
||||
if(ch == kNewLine) {
|
||||
writable.AppendLiteral("\r\n");
|
||||
aScanner.GetChar(ch);
|
||||
}
|
||||
else {
|
||||
writable.Append(PRUnichar('\r'));
|
||||
}
|
||||
++aNewlineCount;
|
||||
}
|
||||
}
|
||||
else if(ch == kNewLine && aAllowNewlines) {
|
||||
aScanner.GetChar(ch);
|
||||
aString.writable().Append(PRUnichar('\n'));
|
||||
++aNewlineCount;
|
||||
}
|
||||
else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} while (NS_SUCCEEDED(result) && !done);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
And now for the token classes...
|
||||
|
@ -244,15 +376,12 @@ void CStartToken::AppendSourceTo(nsAString& anOutputString){
|
|||
/*
|
||||
* Watch out for Bug 15204
|
||||
*/
|
||||
if(!mTrailingContent.IsEmpty())
|
||||
anOutputString.Append(mTrailingContent);
|
||||
else {
|
||||
if(!mTextValue.IsEmpty())
|
||||
anOutputString.Append(mTextValue);
|
||||
else
|
||||
anOutputString.Append(GetTagName(mTypeID));
|
||||
anOutputString.Append(PRUnichar('>'));
|
||||
}
|
||||
if(!mTextValue.IsEmpty())
|
||||
anOutputString.Append(mTextValue);
|
||||
else
|
||||
anOutputString.Append(GetTagName(mTypeID));
|
||||
|
||||
anOutputString.Append(PRUnichar('>'));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -294,7 +423,7 @@ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag)
|
|||
// Save the original tag string if this is user-defined or if we
|
||||
// are viewing source
|
||||
if(eHTMLTag_userdefined==mTypeID ||
|
||||
(aFlag & (NS_IPARSER_FLAG_VIEW_SOURCE | NS_IPARSER_FLAG_PRESERVE_CONTENT))) {
|
||||
(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
mTextValue = tagIdent.str();
|
||||
}
|
||||
}
|
||||
|
@ -388,6 +517,7 @@ void CEndToken::AppendSourceTo(nsAString& anOutputString){
|
|||
anOutputString.Append(mTextValue);
|
||||
else
|
||||
anOutputString.Append(GetTagName(mTypeID));
|
||||
|
||||
anOutputString.Append(PRUnichar('>'));
|
||||
}
|
||||
|
||||
|
@ -498,14 +628,24 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aFlag)
|
|||
* Consume as much clear text from scanner as possible.
|
||||
* The scanner is left on the < of the perceived end tag.
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
* @param aChar -- last char consumed from stream
|
||||
* @param aConservativeConsume -- controls our handling of content with no
|
||||
* terminating string.
|
||||
* @param aIgnoreComments -- whether or not we should take comments into
|
||||
* account in looking for the end tag.
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @param aEndTagname -- the terminal tag name.
|
||||
* @param aFlag -- dtd modes and such.
|
||||
* @param aFlushTokens -- PR_TRUE if we found the terminal tag.
|
||||
* @return error result
|
||||
*/
|
||||
nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner,
|
||||
const nsAString& aEndTagName,PRInt32 aFlag,
|
||||
PRBool& aFlushTokens){
|
||||
nsresult CTextToken::ConsumeCharacterData(PRUnichar aChar,
|
||||
PRBool aConservativeConsume,
|
||||
PRBool aIgnoreComments,
|
||||
nsScanner& aScanner,
|
||||
const nsAString& aEndTagName,
|
||||
PRInt32 aFlag,
|
||||
PRBool& aFlushTokens) {
|
||||
nsresult result=NS_OK;
|
||||
nsScannerIterator theStartOffset, theCurrOffset, theTermStrPos, theStartCommentPos, theAltTermStrPos, endPos;
|
||||
PRBool done=PR_FALSE;
|
||||
|
@ -532,7 +672,9 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
// 4. Amen...If you found a terminal string and '-->'. Otherwise goto step 1.
|
||||
// 5. If the end of the document is reached and if we still don't have the condition in step 4. then
|
||||
// assume that the prematured terminal string is the actual terminal string and goto step 1. This
|
||||
// will be our last iteration.
|
||||
// will be our last iteration. If there is no premature terminal string and we're being
|
||||
// conservative in our consumption (aConservativeConsume), then don't consume anything
|
||||
// from the scanner. Otherwise, we consume all the way until the end (for <xmp>).
|
||||
|
||||
NS_NAMED_LITERAL_STRING(ltslash, "</");
|
||||
const nsString theTerminalString = ltslash + aEndTagName;
|
||||
|
@ -609,20 +751,171 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann
|
|||
// a) when the buffer runs out ot data.
|
||||
// b) when the terminal string is not found.
|
||||
if(!aScanner.IsIncremental()) {
|
||||
if(theAltTermStrPos != endPos) {
|
||||
if(theAltTermStrPos != endPos && aConservativeConsume) {
|
||||
// If you're here it means..we hit the rock bottom and therefore switch to plan B.
|
||||
theCurrOffset = theAltTermStrPos;
|
||||
theLastIteration = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
else if (!aConservativeConsume) {
|
||||
done = PR_TRUE; // Do this to fix Bug. 35456
|
||||
result = kFakeEndTag;
|
||||
aScanner.BindSubstring(mTextValue, theStartOffset, endPos.advance(-1));
|
||||
aScanner.SetPosition(endPos.advance(1));
|
||||
}
|
||||
else {
|
||||
done = PR_TRUE;
|
||||
result = kFakeEndTag;
|
||||
// We need to bind our value to a non-empty string.
|
||||
aScanner.BindSubstring(mTextValue, theStartOffset, theStartOffset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result=kEOF;
|
||||
result=kEOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consume as much clear text from scanner as possible. Reducing entities.
|
||||
* The scanner is left on the < of the perceived end tag.
|
||||
*
|
||||
* @param aChar -- last char consumed from stream
|
||||
* @param aConservativeConsume -- controls our handling of content with no
|
||||
* terminating string.
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @param aEndTagname -- the terminal tag name.
|
||||
* @param aFlag -- dtd modes and such.
|
||||
* @param aFlushTokens -- PR_TRUE if we found the terminal tag.
|
||||
* @return error result
|
||||
*/
|
||||
nsresult CTextToken::ConsumeParsedCharacterData(PRUnichar aChar,
|
||||
PRBool aConservativeConsume,
|
||||
nsScanner& aScanner,
|
||||
const nsAString& aEndTagName,
|
||||
PRInt32 aFlag,
|
||||
PRBool& aFound)
|
||||
{
|
||||
// This function is fairly straightforward except if there is no terminating
|
||||
// string. If there is, we simply loop through all of the entities, reducing
|
||||
// them as necessary and skipping over non-terminal strings starting with <.
|
||||
// If there is *no* terminal string, then we examine aConservativeConsume.
|
||||
// If we want to be conservative, we backtrack to the first place in the
|
||||
// document that looked like the end of PCDATA (i.e., the first tag). This
|
||||
// is for compatibility and so we don't regress bug 42945. If we are not
|
||||
// conservative, then we consume everything, all the way up to the end of
|
||||
// the document.
|
||||
|
||||
static const PRUnichar terminalChars[] = {
|
||||
PRUnichar('&'), PRUnichar('<'),
|
||||
PRUnichar(0)
|
||||
};
|
||||
static const nsReadEndCondition theEndCondition(terminalChars);
|
||||
|
||||
nsScannerIterator currPos,endPos,altEndPos;
|
||||
PRUint32 truncPos = 0;
|
||||
aScanner.CurrentPosition(currPos);
|
||||
aScanner.EndReading(endPos);
|
||||
|
||||
altEndPos = endPos;
|
||||
|
||||
nsScannerSharedSubstring theContent;
|
||||
PRUnichar ch = 0;
|
||||
|
||||
NS_NAMED_LITERAL_STRING(commentStart, "<!--");
|
||||
NS_NAMED_LITERAL_STRING(ltslash, "</");
|
||||
const nsString theTerminalString = ltslash + aEndTagName;
|
||||
PRUint32 termStrLen = theTerminalString.Length();
|
||||
PRUint32 commentStartLen = commentStart.Length();
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
while (currPos != endPos) {
|
||||
result = ConsumeUntil(theContent, mNewlineCount, aScanner,
|
||||
theEndCondition, PR_TRUE, aFlag);
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (kEOF == result && !aScanner.IsIncremental()) {
|
||||
aFound = PR_TRUE; // this is as good as it gets.
|
||||
result = kFakeEndTag;
|
||||
|
||||
if (aConservativeConsume && altEndPos != endPos) {
|
||||
// We ran out of room looking for a </title>. Go back to the first
|
||||
// place that looked like a tag and use that as our stopping point.
|
||||
theContent.writable().Truncate(truncPos);
|
||||
aScanner.SetPosition(altEndPos);
|
||||
}
|
||||
// else we take everything we consumed.
|
||||
mTextValue.Rebind(theContent.str());
|
||||
}
|
||||
else {
|
||||
aFound = PR_FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
aScanner.CurrentPosition(currPos);
|
||||
aScanner.GetChar(ch); // this character must be '&' or '<'
|
||||
|
||||
if (ch == kLessThan && altEndPos == endPos) {
|
||||
// Keep this position in case we need it for later.
|
||||
altEndPos = currPos;
|
||||
truncPos = theContent.str().Length();
|
||||
}
|
||||
|
||||
if (Distance(currPos, endPos) >= termStrLen) {
|
||||
nsScannerIterator start(currPos), end(currPos);
|
||||
end.advance(termStrLen);
|
||||
|
||||
if (CaseInsensitiveFindInReadable(theTerminalString,start,end)) {
|
||||
if (end != endPos && (*end == '>' || *end == ' ' ||
|
||||
*end == '\t' || *end == '\n' ||
|
||||
*end == '\r' || *end == '\b')) {
|
||||
aFound = PR_TRUE;
|
||||
mTextValue.Rebind(theContent.str());
|
||||
aScanner.SetPosition(currPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// IE only consumes <!-- --> as comments in PCDATA. We'll accept a bit
|
||||
// more in quirks mode, but lets ensure that this really is a comment
|
||||
// start to maintain the illusion of compatability.
|
||||
if (Distance(currPos, endPos) >= commentStartLen) {
|
||||
nsScannerIterator start(currPos), end(currPos);
|
||||
end.advance(commentStartLen);
|
||||
|
||||
if (CaseInsensitiveFindInReadable(commentStart,start,end)) {
|
||||
CCommentToken consumer; // stack allocated.
|
||||
|
||||
// CCommentToken expects us to be on the '-'
|
||||
aScanner.SetPosition(currPos.advance(2));
|
||||
result = consumer.Consume(*currPos, aScanner, aFlag);
|
||||
if (kEOF == result) {
|
||||
return kEOF; // this can only happen if we're really out of space.
|
||||
}
|
||||
else if (kNotAComment == result) {
|
||||
// Fall through and consume this as text.
|
||||
aScanner.CurrentPosition(currPos);
|
||||
aScanner.SetPosition(currPos.advance(1));
|
||||
}
|
||||
else {
|
||||
consumer.AppendSourceTo(theContent.writable());
|
||||
mNewlineCount += consumer.GetNewlineCount();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = kEOF;
|
||||
// We did not find the terminal string yet so
|
||||
// include the character that stopped consumption.
|
||||
theContent.writable().Append(ch);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1036,10 +1329,9 @@ nsresult CCommentToken::ConsumeStrictComment(nsScanner& aScanner)
|
|||
return kEOF; // not really an nsresult, but...
|
||||
}
|
||||
|
||||
// XXX We should return kNotAComment, parse comment open as text, and parse
|
||||
// the rest of the document normally. Now we ALMOST do that: <! is
|
||||
// missing from the content model.
|
||||
return NS_OK;
|
||||
// There was no terminating string, parse this comment as text.
|
||||
aScanner.SetPosition(lt);
|
||||
return kNotAComment;
|
||||
}
|
||||
|
||||
nsresult CCommentToken::ConsumeQuirksComment(nsScanner& aScanner)
|
||||
|
@ -1435,140 +1727,6 @@ void CAttributeToken::AppendSourceTo(nsAString& anOutputString){
|
|||
// anOutputString.AppendLiteral(";");
|
||||
}
|
||||
|
||||
static void AppendNCR(nsSubstring& aString, PRInt32 aNCRValue);
|
||||
/*
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @param aFlag -- If NS_IPARSER_FLAG_VIEW_SOURCE do not reduce entities...
|
||||
* @return error result
|
||||
*
|
||||
*/
|
||||
static
|
||||
nsresult ConsumeAttributeEntity(nsScannerSharedSubstring& aString,
|
||||
nsScanner& aScanner,
|
||||
PRInt32 aFlag)
|
||||
{
|
||||
|
||||
nsresult result=NS_OK;
|
||||
|
||||
PRUnichar ch;
|
||||
result=aScanner.Peek(ch, 1);
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
PRUnichar amp=0;
|
||||
PRInt32 theNCRValue=0;
|
||||
nsAutoString entity;
|
||||
|
||||
if (nsCRT::IsAsciiAlpha(ch) && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
theNCRValue = nsHTMLEntities::EntityToUnicode(entity);
|
||||
PRUnichar theTermChar=entity.Last();
|
||||
// If an entity value is greater than 255 then:
|
||||
// Nav 4.x does not treat it as an entity,
|
||||
// IE treats it as an entity if terminated with a semicolon.
|
||||
// Resembling IE!!
|
||||
|
||||
nsSubstring &writable = aString.writable();
|
||||
if(theNCRValue < 0 || (theNCRValue > 255 && theTermChar != ';')) {
|
||||
// Looks like we're not dealing with an entity
|
||||
writable.Append(kAmpersand);
|
||||
writable.Append(entity);
|
||||
}
|
||||
else {
|
||||
// A valid entity so reduce it.
|
||||
writable.Append(PRUnichar(theNCRValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ch==kHashsign && !(aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
result=CEntityToken::ConsumeEntity(ch,entity,aScanner);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsSubstring &writable = aString.writable();
|
||||
if (result == NS_HTMLTOKENS_NOT_AN_ENTITY) {
|
||||
// Looked like an entity but it's not
|
||||
aScanner.GetChar(amp);
|
||||
writable.Append(amp);
|
||||
result = NS_OK; // just being safe..
|
||||
}
|
||||
else {
|
||||
PRInt32 err;
|
||||
theNCRValue=entity.ToInteger(&err,kAutoDetect);
|
||||
AppendNCR(writable, theNCRValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// What we thought as entity is not really an entity...
|
||||
aScanner.GetChar(amp);
|
||||
aString.writable().Append(amp);
|
||||
}//if
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This general purpose method is used when you want to
|
||||
* consume attributed text value.
|
||||
* Note: It also reduces entities within attributes.
|
||||
*
|
||||
* @param aNewlineCount -- the newline count to increment when hitting newlines
|
||||
* @param aScanner -- controller of underlying input source
|
||||
* @param aTerminalChars -- characters that stop consuming attribute.
|
||||
* @param aAllowNewlines -- whether to allow newlines in the value.
|
||||
* XXX it would be nice to roll this info into
|
||||
* aTerminalChars somehow....
|
||||
* @param aFlag - contains information such as |dtd mode|view mode|doctype|etc...
|
||||
* @return error result
|
||||
*/
|
||||
static
|
||||
nsresult ConsumeAttributeValueText(nsScannerSharedSubstring& aString,
|
||||
PRInt32& aNewlineCount,
|
||||
nsScanner& aScanner,
|
||||
const nsReadEndCondition& aEndCondition,
|
||||
PRBool aAllowNewlines,
|
||||
PRInt32 aFlag)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
PRBool done = PR_FALSE;
|
||||
|
||||
do {
|
||||
result = aScanner.ReadUntil(aString,aEndCondition,PR_FALSE);
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
PRUnichar ch;
|
||||
aScanner.Peek(ch);
|
||||
if(ch == kAmpersand) {
|
||||
result = ConsumeAttributeEntity(aString,aScanner,aFlag);
|
||||
}
|
||||
else if(ch == kCR && aAllowNewlines) {
|
||||
aScanner.GetChar(ch);
|
||||
result = aScanner.Peek(ch);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsSubstring &writable = aString.writable();
|
||||
if(ch == kNewLine) {
|
||||
writable.AppendLiteral("\r\n");
|
||||
aScanner.GetChar(ch);
|
||||
}
|
||||
else {
|
||||
writable.Append(PRUnichar('\r'));
|
||||
}
|
||||
++aNewlineCount;
|
||||
}
|
||||
}
|
||||
else if(ch == kNewLine && aAllowNewlines) {
|
||||
aScanner.GetChar(ch);
|
||||
aString.writable().Append(PRUnichar('\n'));
|
||||
++aNewlineCount;
|
||||
}
|
||||
else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} while (NS_SUCCEEDED(result) && !done);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This general purpose method is used when you want to
|
||||
* consume a known quoted string.
|
||||
|
@ -1609,8 +1767,8 @@ nsresult ConsumeQuotedString(PRUnichar aChar,
|
|||
nsScannerIterator theOffset;
|
||||
aScanner.CurrentPosition(theOffset);
|
||||
|
||||
result=ConsumeAttributeValueText(aString,aNewlineCount,aScanner,
|
||||
*terminateCondition,PR_TRUE,aFlag);
|
||||
result=ConsumeUntil(aString,aNewlineCount,aScanner,
|
||||
*terminateCondition,PR_TRUE,aFlag);
|
||||
|
||||
if(NS_SUCCEEDED(result)) {
|
||||
result = aScanner.GetChar(aChar); // aChar should be " or '
|
||||
|
@ -1625,8 +1783,8 @@ nsresult ConsumeQuotedString(PRUnichar aChar,
|
|||
theAttributeTerminator(kAttributeTerminalChars);
|
||||
aString.writable().Truncate(origLen);
|
||||
aScanner.SetPosition(theOffset, PR_FALSE, PR_TRUE);
|
||||
result=ConsumeAttributeValueText(aString,aNewlineCount,aScanner,
|
||||
theAttributeTerminator,PR_FALSE,aFlag);
|
||||
result=ConsumeUntil(aString,aNewlineCount,aScanner,
|
||||
theAttributeTerminator,PR_FALSE,aFlag);
|
||||
if (NS_SUCCEEDED(result) && (aFlag & NS_IPARSER_FLAG_VIEW_SOURCE)) {
|
||||
// Remember that this string literal was unterminated.
|
||||
result = NS_ERROR_HTMLPARSER_UNTERMINATEDSTRINGLITERAL;
|
||||
|
@ -1770,12 +1928,12 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a
|
|||
else {
|
||||
static const nsReadEndCondition
|
||||
theAttributeTerminator(kAttributeTerminalChars);
|
||||
result=ConsumeAttributeValueText(mTextValue,
|
||||
mNewlineCount,
|
||||
aScanner,
|
||||
theAttributeTerminator,
|
||||
PR_FALSE,
|
||||
aFlag);
|
||||
result=ConsumeUntil(mTextValue,
|
||||
mNewlineCount,
|
||||
aScanner,
|
||||
theAttributeTerminator,
|
||||
PR_FALSE,
|
||||
aFlag);
|
||||
}
|
||||
}//if
|
||||
if (NS_OK==result) {
|
||||
|
|
|
@ -90,7 +90,9 @@ public:
|
|||
NS_IMETHOD CloseMap();
|
||||
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
||||
NS_IMETHOD CloseFrameset();
|
||||
NS_IMETHOD IsEnabled(PRInt32 aTag, PRBool* aReturn) { return NS_OK; }
|
||||
NS_IMETHOD IsEnabled(PRInt32 aTag, PRBool* aReturn)
|
||||
/* Take the largest possible feature set. */
|
||||
{ NS_ENSURE_ARG_POINTER(aReturn); *aReturn = PR_TRUE; return NS_OK; }
|
||||
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
|
||||
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
|
||||
|
||||
|
|
|
@ -1294,7 +1294,7 @@ nsParser::WillBuildModel(nsString& aFilename)
|
|||
return rv;
|
||||
|
||||
nsITokenizer* tokenizer;
|
||||
mParserContext->GetTokenizer(mParserContext->mDTD->GetType(), tokenizer);
|
||||
mParserContext->GetTokenizer(mParserContext->mDTD->GetType(), mSink, tokenizer);
|
||||
return mParserContext->mDTD->WillBuildModel(*mParserContext, tokenizer, mSink);
|
||||
}
|
||||
|
||||
|
@ -1355,10 +1355,6 @@ CParserContext* nsParser::PopContext()
|
|||
if (mParserContext->mStreamListenerState != eOnStop) {
|
||||
mParserContext->mStreamListenerState = oldContext->mStreamListenerState;
|
||||
}
|
||||
// Preserve tokenizer state so that information is not lost
|
||||
// between document.write. This fixes bug 99467
|
||||
if (mParserContext->mTokenizer)
|
||||
mParserContext->mTokenizer->CopyState(oldContext->mTokenizer);
|
||||
}
|
||||
}
|
||||
return oldContext;
|
||||
|
@ -1644,7 +1640,6 @@ nsParser::Parse(nsIInputStream* aStream,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this method if all you want to do is parse 1 string full of HTML text.
|
||||
* In particular, this method should be called by the DOM when it has an HTML
|
||||
|
@ -1718,7 +1713,8 @@ nsParser::Parse(const nsAString& aSourceBuffer,
|
|||
}
|
||||
}
|
||||
|
||||
pc = new CParserContext(theScanner, aKey, mCommand, 0, theDTD, theStatus, aLastCall);
|
||||
pc = new CParserContext(theScanner, aKey, mCommand,
|
||||
0, theDTD, theStatus, aLastCall);
|
||||
NS_ENSURE_TRUE(pc, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PushContext(*pc);
|
||||
|
@ -2010,7 +2006,7 @@ nsresult nsParser::BuildModel() {
|
|||
nsresult result = NS_OK;
|
||||
if (mParserContext) {
|
||||
PRInt32 type = mParserContext->mDTD ? mParserContext->mDTD->GetType() : NS_IPARSER_FLAG_HTML;
|
||||
mParserContext->GetTokenizer(type, theTokenizer);
|
||||
mParserContext->GetTokenizer(type, mSink, theTokenizer);
|
||||
}
|
||||
|
||||
if (theTokenizer) {
|
||||
|
@ -2047,7 +2043,7 @@ nsresult nsParser::GetTokenizer(nsITokenizer*& aTokenizer) {
|
|||
aTokenizer = nsnull;
|
||||
if(mParserContext) {
|
||||
PRInt32 type = mParserContext->mDTD ? mParserContext->mDTD->GetType() : NS_IPARSER_FLAG_HTML;
|
||||
result = mParserContext->GetTokenizer(type, aTokenizer);
|
||||
result = mParserContext->GetTokenizer(type, mSink, aTokenizer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2658,7 +2654,7 @@ PRBool nsParser::WillTokenize(PRBool aIsFinalChunk){
|
|||
nsresult result = NS_OK;
|
||||
if (mParserContext) {
|
||||
PRInt32 type = mParserContext->mDTD ? mParserContext->mDTD->GetType() : NS_IPARSER_FLAG_HTML;
|
||||
mParserContext->GetTokenizer(type, theTokenizer);
|
||||
mParserContext->GetTokenizer(type, mSink, theTokenizer);
|
||||
}
|
||||
|
||||
if (theTokenizer) {
|
||||
|
@ -2684,7 +2680,7 @@ nsresult nsParser::Tokenize(PRBool aIsFinalChunk){
|
|||
|
||||
if (mParserContext) {
|
||||
PRInt32 type = mParserContext->mDTD ? mParserContext->mDTD->GetType() : NS_IPARSER_FLAG_HTML;
|
||||
mParserContext->GetTokenizer(type, theTokenizer);
|
||||
mParserContext->GetTokenizer(type, mSink, theTokenizer);
|
||||
}
|
||||
|
||||
if (theTokenizer) {
|
||||
|
@ -2755,7 +2751,7 @@ PRBool nsParser::DidTokenize(PRBool aIsFinalChunk){
|
|||
nsresult rv = NS_OK;
|
||||
if (mParserContext) {
|
||||
PRInt32 type = mParserContext->mDTD ? mParserContext->mDTD->GetType() : NS_IPARSER_FLAG_HTML;
|
||||
mParserContext->GetTokenizer(type, theTokenizer);
|
||||
mParserContext->GetTokenizer(type, mSink, theTokenizer);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && theTokenizer) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче