bug 272702: Remove skipped content. This simplifies the code handling <script>, <style> and related tags and makes the nsIHTMLContentSink interface just that much easier to implement. This also allows <object> tags to appear in the head with children. r=sicking sr=jst

This commit is contained in:
mrbkap%gmail.com 2005-09-09 18:03:47 +00:00
Родитель b8d0775c65
Коммит 973abde5a4
17 изменённых файлов: 449 добавлений и 989 удалений

Просмотреть файл

@ -304,43 +304,9 @@ mozSanitizingHTMLSerializer::OpenContainer(const nsIParserNode& aNode)
NS_IMETHODIMP NS_IMETHODIMP
mozSanitizingHTMLSerializer::CloseContainer(const nsHTMLTag aTag) mozSanitizingHTMLSerializer::CloseContainer(const nsHTMLTag aTag)
{ {
// XXX Why do we need this?
// mParserNode = NS_CONST_CAST(nsIParserNode*, &aNode);
return DoCloseContainer(aTag); return DoCloseContainer(aTag);
} }
NS_IMETHODIMP
mozSanitizingHTMLSerializer::AddHeadContent(const nsIParserNode& aNode)
{
nsresult rv = NS_OK;
eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
if (eHTMLTag_whitespace == type ||
eHTMLTag_newline == type ||
eHTMLTag_text == type ||
eHTMLTag_entity == type) {
rv = AddLeaf(aNode);
}
else if (eHTMLTag_title == type) {
NS_ASSERTION(mParser, "Only CNavDTD treats title this way.");
nsString skippedContent;
PRInt32 lineNo;
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_UNEXPECTED);
dtd->CollectSkippedContent(type, skippedContent, lineNo);
SetTitle(skippedContent);
}
else {
rv = OpenContainer(aNode);
NS_ENSURE_SUCCESS(rv, rv);
rv = CloseContainer(type);
}
return rv;
}
NS_IMETHODIMP NS_IMETHODIMP
mozSanitizingHTMLSerializer::AddLeaf(const nsIParserNode& aNode) mozSanitizingHTMLSerializer::AddLeaf(const nsIParserNode& aNode)
{ {
@ -403,6 +369,14 @@ mozSanitizingHTMLSerializer::OpenHead(const nsIParserNode& aNode)
return OpenContainer(aNode); return OpenContainer(aNode);
} }
NS_IMETHODIMP
mozSanitizingHTMLSerializer::OpenHead()
{
// XXX We don't have a parser node here, is it okay to ignore this?
// return OpenContainer(aNode);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
mozSanitizingHTMLSerializer::CloseHead() mozSanitizingHTMLSerializer::CloseHead()
{ {
@ -559,36 +533,6 @@ mozSanitizingHTMLSerializer::DoAddLeaf(PRInt32 aTag,
// using + operator here might give an infinitive loop, see above. // using + operator here might give an infinitive loop, see above.
// not adding ";", because Gecko delivers that as part of |aText| (freaky) // not adding ";", because Gecko delivers that as part of |aText| (freaky)
} }
else if (type == eHTMLTag_script ||
type == eHTMLTag_style ||
type == eHTMLTag_server)
{
// These special tags require some extra care. The parser gives them
// to us as leaves, but they're really containers. Their content is
// contained in the "skipped content" of the parser. This code is
// adapted from nsHTMLContentSink.cpp
nsString skippedContent;
PRInt32 lineNo;
NS_ASSERTION(mParser, "We are receiving containers as leaves with "
"no skipped content.");
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_UNEXPECTED);
// Note: we want to collect the skipped content no matter what. We
// may end up throwing it away anyway, but the DTD doesn't care
// about that.
dtd->CollectSkippedContent(type, skippedContent, lineNo);
DoOpenContainer(type);
if (IsAllowedTag(type))
{
Write(skippedContent);
}
DoCloseContainer(type);
}
else else
{ {
DoOpenContainer(type); DoOpenContainer(type);

Просмотреть файл

@ -93,14 +93,12 @@ public:
// nsIContentSink // nsIContentSink
NS_IMETHOD WillBuildModel(void) { return NS_OK; } NS_IMETHOD WillBuildModel(void) { return NS_OK; }
NS_IMETHOD DidBuildModel(void) NS_IMETHOD DidBuildModel(void) { return NS_OK; }
{ nsCOMPtr<nsIParser> temp(mParser); mParser = nsnull; return NS_OK; }
NS_IMETHOD WillInterrupt(void) { return NS_OK; } NS_IMETHOD WillInterrupt(void) { return NS_OK; }
NS_IMETHOD WillResume(void) { return NS_OK; } NS_IMETHOD WillResume(void) { return NS_OK; }
NS_IMETHOD SetParser(nsIParser* aParser) { mParser = aParser; return NS_OK; } NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; }
NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag); NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddHeadContent(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode) { return NS_OK; } NS_IMETHOD AddComment(const nsIParserNode& aNode) { return NS_OK; }
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode) NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode)
@ -114,6 +112,7 @@ public:
NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD OpenHTML(const nsIParserNode& aNode);
NS_IMETHOD CloseHTML(); NS_IMETHOD CloseHTML();
NS_IMETHOD OpenHead(const nsIParserNode& aNode); NS_IMETHOD OpenHead(const nsIParserNode& aNode);
NS_IMETHOD OpenHead();
NS_IMETHOD CloseHead(); NS_IMETHOD CloseHead();
NS_IMETHOD SetTitle(const nsString& aValue); NS_IMETHOD SetTitle(const nsString& aValue);
NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD OpenBody(const nsIParserNode& aNode);
@ -162,7 +161,6 @@ protected:
nsAString* mOutputString; nsAString* mOutputString;
nsIParserNode* mParserNode; nsIParserNode* mParserNode;
nsCOMPtr<nsIParserService> mParserService; nsCOMPtr<nsIParserService> mParserService;
nsCOMPtr<nsIParser> mParser;
}; };
nsresult nsresult

Просмотреть файл

@ -468,19 +468,6 @@ nsPlainTextSerializer::CloseContainer(const nsHTMLTag aTag)
return DoCloseContainer(aTag); return DoCloseContainer(aTag);
} }
NS_IMETHODIMP
nsPlainTextSerializer::AddHeadContent(const nsIParserNode& aNode)
{
if (eHTMLTag_title == aNode.GetNodeType()) {
// XXX collect the skipped content
return NS_OK;
}
OpenHead(aNode);
nsresult rv = AddLeaf(aNode);
CloseHead();
return rv;
}
NS_IMETHODIMP NS_IMETHODIMP
nsPlainTextSerializer::AddLeaf(const nsIParserNode& aNode) nsPlainTextSerializer::AddLeaf(const nsIParserNode& aNode)
{ {
@ -527,6 +514,13 @@ nsPlainTextSerializer::OpenHead(const nsIParserNode& aNode)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsPlainTextSerializer::OpenHead()
{
mInHead = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsPlainTextSerializer::CloseHead() nsPlainTextSerializer::CloseHead()
{ {

Просмотреть файл

@ -96,7 +96,6 @@ public:
NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; } NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; }
NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag); NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddHeadContent(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode) { return NS_OK; } NS_IMETHOD AddComment(const nsIParserNode& aNode) { return NS_OK; }
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode) { return NS_OK; } NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode) { return NS_OK; }
@ -106,10 +105,10 @@ public:
virtual nsISupports *GetTarget() { return nsnull; } virtual nsISupports *GetTarget() { return nsnull; }
// nsIHTMLContentSink // nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue) { return NS_OK; }
NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD OpenHTML(const nsIParserNode& aNode);
NS_IMETHOD CloseHTML(); NS_IMETHOD CloseHTML();
NS_IMETHOD OpenHead(const nsIParserNode& aNode); NS_IMETHOD OpenHead(const nsIParserNode& aNode);
NS_IMETHOD OpenHead();
NS_IMETHOD CloseHead(); NS_IMETHOD CloseHead();
NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD OpenBody(const nsIParserNode& aNode);
NS_IMETHOD CloseBody(); NS_IMETHOD CloseBody();

Просмотреть файл

@ -309,7 +309,7 @@ class nsHTMLScriptElement : public nsGenericHTMLElement,
public nsIScriptElement public nsIScriptElement
{ {
public: public:
nsHTMLScriptElement(nsINodeInfo *aNodeInfo); nsHTMLScriptElement(nsINodeInfo *aNodeInfo, PRBool aFromParser);
virtual ~nsHTMLScriptElement(); virtual ~nsHTMLScriptElement();
// nsISupports // nsISupports
@ -357,6 +357,8 @@ public:
virtual nsresult GetInnerHTML(nsAString& aInnerHTML); virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
virtual nsresult SetInnerHTML(const nsAString& aInnerHTML); virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
virtual void DoneAddingChildren();
virtual PRBool IsDoneAddingChildren();
protected: protected:
PRBool IsOnloadEventForWindow(); PRBool IsOnloadEventForWindow();
@ -364,6 +366,7 @@ protected:
PRUint32 mLineNumber; PRUint32 mLineNumber;
PRPackedBool mIsEvaluated; PRPackedBool mIsEvaluated;
PRPackedBool mEvaluating; PRPackedBool mEvaluating;
PRPackedBool mDoneAddingChildren;
// Pointer to the script handler helper object (OWNING reference) // Pointer to the script handler helper object (OWNING reference)
nsHTMLScriptEventHandler *mScriptEventHandler; nsHTMLScriptEventHandler *mScriptEventHandler;
@ -385,11 +388,13 @@ protected:
}; };
NS_IMPL_NS_NEW_HTML_ELEMENT(Script) NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script)
nsHTMLScriptElement::nsHTMLScriptElement(nsINodeInfo *aNodeInfo) nsHTMLScriptElement::nsHTMLScriptElement(nsINodeInfo *aNodeInfo,
: nsGenericHTMLElement(aNodeInfo) PRBool aFromParser)
: nsGenericHTMLElement(aNodeInfo),
mDoneAddingChildren(!aFromParser)
{ {
mLineNumber = 0; mLineNumber = 0;
mIsEvaluated = PR_FALSE; mIsEvaluated = PR_FALSE;
@ -484,7 +489,7 @@ nsHTMLScriptElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{ {
*aReturn = nsnull; *aReturn = nsnull;
nsHTMLScriptElement* it = new nsHTMLScriptElement(mNodeInfo); nsHTMLScriptElement* it = new nsHTMLScriptElement(mNodeInfo, PR_FALSE);
if (!it) { if (!it) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -538,6 +543,19 @@ nsHTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML)
return ReplaceContentsWithText(aInnerHTML, PR_TRUE); return ReplaceContentsWithText(aInnerHTML, PR_TRUE);
} }
void
nsHTMLScriptElement::DoneAddingChildren()
{
mDoneAddingChildren = PR_TRUE;
MaybeProcessScript();
}
PRBool
nsHTMLScriptElement::IsDoneAddingChildren()
{
return mDoneAddingChildren;
}
// variation of this code in nsSVGScriptElement - check if changes // variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying // need to be transfered when modifying
@ -646,7 +664,7 @@ nsHTMLScriptElement::GetScriptLineNumber()
void void
nsHTMLScriptElement::MaybeProcessScript() nsHTMLScriptElement::MaybeProcessScript()
{ {
if (mIsEvaluated || mEvaluating || !IsInDoc()) { if (mIsEvaluated || mEvaluating || !mDoneAddingChildren || !IsInDoc()) {
return; return;
} }

Просмотреть файл

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 et tw=78: */
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@ -235,7 +236,6 @@ public:
// nsIHTMLContentSink // nsIHTMLContentSink
NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag); NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddHeadContent(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode);
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
@ -247,10 +247,10 @@ public:
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode); NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode);
NS_IMETHOD BeginContext(PRInt32 aID); NS_IMETHOD BeginContext(PRInt32 aID);
NS_IMETHOD EndContext(PRInt32 aID); NS_IMETHOD EndContext(PRInt32 aID);
NS_IMETHOD SetTitle(const nsString& aValue);
NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD OpenHTML(const nsIParserNode& aNode);
NS_IMETHOD CloseHTML(); NS_IMETHOD CloseHTML();
NS_IMETHOD OpenHead(const nsIParserNode& aNode); NS_IMETHOD OpenHead(const nsIParserNode& aNode);
NS_IMETHOD OpenHead();
NS_IMETHOD CloseHead(); NS_IMETHOD CloseHead();
NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD OpenBody(const nsIParserNode& aNode);
NS_IMETHOD CloseBody(); NS_IMETHOD CloseBody();
@ -278,7 +278,7 @@ public:
protected: protected:
PRBool IsTimeToNotify(); PRBool IsTimeToNotify();
nsresult SetDocumentTitle(const nsAString& aTitle, const nsIParserNode* aNode); nsresult UpdateDocumentTitle();
// If aCheckIfPresent is true, will only set an attribute in cases // If aCheckIfPresent is true, will only set an attribute in cases
// when it's not already set. // when it's not already set.
nsresult AddAttributes(const nsIParserNode& aNode, nsIContent* aContent, nsresult AddAttributes(const nsIParserNode& aNode, nsIContent* aContent,
@ -337,14 +337,14 @@ protected:
nsGenericHTMLElement* mFrameset; nsGenericHTMLElement* mFrameset;
nsGenericHTMLElement* mHead; nsGenericHTMLElement* mHead;
nsString mSkippedContent;
// Do we notify based on time? // Do we notify based on time?
PRPackedBool mNotifyOnTimer; PRPackedBool mNotifyOnTimer;
PRPackedBool mLayoutStarted; PRPackedBool mLayoutStarted;
PRPackedBool mScrolledToRefAlready; PRPackedBool mScrolledToRefAlready;
PRPackedBool mInTitle;
nsString mTitleString;
PRInt32 mInNotification; PRInt32 mInNotification;
nsRefPtr<nsGenericHTMLElement> mCurrentForm; nsRefPtr<nsGenericHTMLElement> mCurrentForm;
nsCOMPtr<nsIContent> mCurrentMap; nsCOMPtr<nsIContent> mCurrentMap;
@ -407,8 +407,11 @@ protected:
nsresult ProcessLINKTag(const nsIParserNode& aNode); nsresult ProcessLINKTag(const nsIParserNode& aNode);
nsresult ProcessMAPTag(nsIContent* aContent); nsresult ProcessMAPTag(nsIContent* aContent);
nsresult ProcessMETATag(const nsIParserNode& aNode); nsresult ProcessMETATag(const nsIParserNode& aNode);
nsresult ProcessSCRIPTTag(const nsIParserNode& aNode);
nsresult ProcessSTYLETag(const nsIParserNode& aNode); // Routines for tags that require special handling when we reach their end
// tag.
nsresult ProcessSCRIPTEndTag(nsGenericHTMLElement* content);
nsresult ProcessSTYLEEndTag(nsGenericHTMLElement* content);
nsresult OpenHeadContext(); nsresult OpenHeadContext();
nsresult CloseHeadContext(); nsresult CloseHeadContext();
@ -466,7 +469,7 @@ public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
// nsIRequest // nsIRequest
NS_IMETHOD GetName(nsACString &result) NS_IMETHOD GetName(nsACString &result)
{ {
result.AssignLiteral("about:layout-dummy-request"); result.AssignLiteral("about:layout-dummy-request");
@ -523,7 +526,7 @@ public:
return NS_OK; return NS_OK;
} }
// nsIChannel // nsIChannel
NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI) NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI)
{ {
*aOriginalURI = gURI; *aOriginalURI = gURI;
@ -1167,6 +1170,25 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
mStack[mStackPos].mNumFlushed = 0; mStack[mStackPos].mNumFlushed = 0;
mStack[mStackPos].mInsertionPoint = -1; mStack[mStackPos].mInsertionPoint = -1;
// XXX Need to do this before we start adding attributes.
if (nodeType == eHTMLTag_style) {
nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(content);
NS_ASSERTION(ssle, "Style content isn't a style sheet?");
ssle->SetLineNumber(aNode.GetSourceLineNumber());
// Now disable updates so that every time we add an attribute or child
// text token, we don't try to update the style sheet.
if (!mSink->mInsideNoXXXTag) {
ssle->InitStyleLinkElement(mSink->mParser, PR_FALSE);
}
else {
// We're not going to be evaluating this style anyway.
ssle->InitStyleLinkElement(nsnull, PR_TRUE);
}
ssle->SetEnableUpdates(PR_FALSE);
}
// Make sure to add base tag info, if needed, before setting any other // Make sure to add base tag info, if needed, before setting any other
// attributes -- what URI attrs do will depend on the base URI. Only do this // attributes -- what URI attrs do will depend on the base URI. Only do this
// for elements that have useful URI attributes. // for elements that have useful URI attributes.
@ -1175,6 +1197,9 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
// Containers with "href=" // Containers with "href="
case eHTMLTag_a: case eHTMLTag_a:
case eHTMLTag_map: case eHTMLTag_map:
// Containers with "src="
case eHTMLTag_script:
// Containers with "action=" // Containers with "action="
case eHTMLTag_form: case eHTMLTag_form:
@ -1228,16 +1253,31 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
case eHTMLTag_noembed: case eHTMLTag_noembed:
case eHTMLTag_noframes: case eHTMLTag_noframes:
mSink->mInsideNoXXXTag++; mSink->mInsideNoXXXTag++;
break; break;
case eHTMLTag_map: case eHTMLTag_map:
mSink->ProcessMAPTag(content); mSink->ProcessMAPTag(content);
break; break;
case eHTMLTag_iframe: case eHTMLTag_iframe:
mSink->mNumOpenIFRAMES++; mSink->mNumOpenIFRAMES++;
break; break;
case eHTMLTag_script:
{
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
NS_ASSERTION(sele, "Script content isn't a script element?");
sele->SetScriptLineNumber(aNode.GetSourceLineNumber());
}
break;
case eHTMLTag_title:
if (mSink->mDocument->GetDocumentTitle().IsVoid()) {
// The first title wins.
mSink->mInTitle = PR_TRUE;
}
break;
default: default:
break; break;
} }
@ -1340,8 +1380,23 @@ SinkContext::CloseContainer(const nsHTMLTag aTag)
case eHTMLTag_object: case eHTMLTag_object:
case eHTMLTag_applet: case eHTMLTag_applet:
content->DoneAddingChildren(); content->DoneAddingChildren();
break; break;
case eHTMLTag_script:
result = mSink->ProcessSCRIPTEndTag(content);
break;
case eHTMLTag_style:
result = mSink->ProcessSTYLEEndTag(content);
break;
case eHTMLTag_title:
if (mSink->mInTitle) {
mSink->UpdateDocumentTitle();
mSink->mInTitle = PR_FALSE;
}
break;
default: default:
break; break;
} }
@ -1586,6 +1641,11 @@ SinkContext::AddText(const nsAString& aText)
if (addLen == 0) { if (addLen == 0) {
return NS_OK; return NS_OK;
} }
if (mSink->mInTitle) {
// Hang onto the title text specially.
mSink->mTitleString.Append(aText);
}
// Create buffer when we first need it // Create buffer when we first need it
if (mTextSize == 0) { if (mTextSize == 0) {
@ -2458,25 +2518,6 @@ HTMLContentSink::EndContext(PRInt32 aPosition)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
HTMLContentSink::SetTitle(const nsString& aValue)
{
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::SetTitle()\n"));
MOZ_TIMER_START(mWatch);
nsresult rv = OpenHeadContext();
if (NS_SUCCEEDED(rv)) {
rv = SetDocumentTitle(aValue, nsnull);
}
CloseHeadContext();
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::SetTitle()\n"));
MOZ_TIMER_STOP(mWatch);
return rv;
}
NS_IMETHODIMP NS_IMETHODIMP
HTMLContentSink::OpenHTML(const nsIParserNode& aNode) HTMLContentSink::OpenHTML(const nsIParserNode& aNode)
{ {
@ -2532,7 +2573,7 @@ HTMLContentSink::CloseHTML()
NS_IMETHODIMP NS_IMETHODIMP
HTMLContentSink::OpenHead(const nsIParserNode& aNode) HTMLContentSink::OpenHead(const nsIParserNode& aNode)
{ {
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::OpenHead()\n")); MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::OpenHead(nsIParserNode)\n"));
MOZ_TIMER_START(mWatch); MOZ_TIMER_START(mWatch);
SINK_TRACE_NODE(SINK_TRACE_CALLS, SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenHead", "HTMLContentSink::OpenHead",
@ -2540,7 +2581,7 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode)
nsresult rv = OpenHeadContext(); nsresult rv = OpenHeadContext();
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::OpenHead()\n")); MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::OpenHead(nsIParserNode)\n"));
MOZ_TIMER_STOP(mWatch); MOZ_TIMER_STOP(mWatch);
return rv; return rv;
} }
@ -2555,6 +2596,20 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode)
return rv; return rv;
} }
NS_IMETHODIMP
HTMLContentSink::OpenHead()
{
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::OpenHead()\n"));
MOZ_TIMER_START(mWatch);
nsresult rv = OpenHeadContext();
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::OpenHead()\n"));
MOZ_TIMER_STOP(mWatch);
return rv;
}
NS_IMETHODIMP NS_IMETHODIMP
HTMLContentSink::CloseHead() HTMLContentSink::CloseHead()
{ {
@ -2917,37 +2972,6 @@ HTMLContentSink::CloseContainer(const eHTMLTags aTag)
return rv; return rv;
} }
NS_IMETHODIMP
HTMLContentSink::AddHeadContent(const nsIParserNode& aNode)
{
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::AddHeadContent()\n"));
MOZ_TIMER_START(mWatch);
nsresult rv = OpenHeadContext();
if (NS_SUCCEEDED(rv)) {
nsHTMLTag type = nsHTMLTag(aNode.GetNodeType());
if (eHTMLTag_title == type) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
if (dtd) {
nsAutoString title;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(eHTMLTag_title, title, lineNo);
rv = SetDocumentTitle(title, &aNode);
}
}
else {
rv = AddLeaf(aNode);
}
CloseHeadContext();
}
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::AddHeadContent()\n"));
MOZ_TIMER_STOP(mWatch);
return rv;
}
NS_IMETHODIMP NS_IMETHODIMP
HTMLContentSink::AddLeaf(const nsIParserNode& aNode) HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
{ {
@ -2976,16 +3000,6 @@ HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
mCurrentContext->FlushTextAndRelease(); mCurrentContext->FlushTextAndRelease();
rv = ProcessMETATag(aNode); rv = ProcessMETATag(aNode);
break;
case eHTMLTag_style:
mCurrentContext->FlushTextAndRelease();
rv = ProcessSTYLETag(aNode);
break;
case eHTMLTag_script:
mCurrentContext->FlushTextAndRelease();
rv = ProcessSCRIPTTag(aNode);
break; break;
default: default:
rv = mCurrentContext->AddLeaf(aNode); rv = mCurrentContext->AddLeaf(aNode);
@ -3000,53 +3014,27 @@ HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
} }
nsresult nsresult
HTMLContentSink::SetDocumentTitle(const nsAString& aTitle, const nsIParserNode* aNode) HTMLContentSink::UpdateDocumentTitle()
{ {
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::SetDocumentTitle()\n")); MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::UpdateDocumentTitle()\n"));
MOZ_TIMER_START(mWatch); MOZ_TIMER_START(mWatch);
NS_ASSERTION(mCurrentContext == mHeadContext, "title not in head"); NS_ASSERTION(mCurrentContext == mHeadContext, "title not in head");
if (!mDocument->GetDocumentTitle().IsVoid()) { if (!mDocument->GetDocumentTitle().IsVoid()) {
// If the title was already set then don't try to overwrite it MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::UpdateDocumentTitle()\n"));
// when a new title is encountered - For backwards compatiblity
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::SetDocumentTitle()\n"));
MOZ_TIMER_STOP(mWatch); MOZ_TIMER_STOP(mWatch);
return NS_OK; return NS_OK;
} }
nsAutoString title(aTitle); // Use mTitleString.
title.CompressWhitespace(PR_TRUE, PR_TRUE); mTitleString.CompressWhitespace(PR_TRUE, PR_TRUE);
nsCOMPtr<nsIDOMNSDocument> domDoc(do_QueryInterface(mDocument)); nsCOMPtr<nsIDOMNSDocument> domDoc(do_QueryInterface(mDocument));
domDoc->SetTitle(title); domDoc->SetTitle(mTitleString);
nsCOMPtr<nsINodeInfo> nodeInfo; mTitleString.Truncate();
nsresult rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::title, nsnull,
kNameSpaceID_None,
getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsGenericHTMLElement> it = NS_NewHTMLTitleElement(nodeInfo); MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::UpdateDocumentTitle()\n"));
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (aNode) {
AddAttributes(*aNode, it);
}
nsCOMPtr<nsITextContent> text;
rv = NS_NewTextNode(getter_AddRefs(text));
NS_ENSURE_SUCCESS(rv, rv);
text->SetText(title, PR_TRUE);
it->AppendChildTo(text, PR_FALSE);
mHead->AppendChildTo(it, PR_FALSE);
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::SetDocumentTitle()\n"));
MOZ_TIMER_STOP(mWatch); MOZ_TIMER_STOP(mWatch);
return NS_OK; return NS_OK;
@ -4010,67 +3998,13 @@ HTMLContentSink::PostEvaluateScript()
} }
nsresult nsresult
HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) HTMLContentSink::ProcessSCRIPTEndTag(nsGenericHTMLElement *content)
{ {
nsresult rv = NS_OK; nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
NS_ASSERTION(sele, "Not really closing a script tag?");
// Create content object
NS_ASSERTION(mCurrentContext->mStackPos > 0, "leaf w/o container");
if (mCurrentContext->mStackPos <= 0) {
return NS_ERROR_FAILURE;
}
// Inserting the element into the document may execute a script.
// This can potentially make the parent go away. So, hold
// on to it till we are done.
nsRefPtr<nsGenericHTMLElement> parent = nsRefPtr<nsGenericHTMLElement> parent =
mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent; mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent;
nsCOMPtr<nsIContent> element;
nsCOMPtr<nsINodeInfo> nodeInfo;
mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::script, nsnull, kNameSpaceID_None,
getter_AddRefs(nodeInfo));
rv = NS_NewHTMLElement(getter_AddRefs(element), nodeInfo);
if (NS_FAILED(rv)) {
return rv;
}
element->SetContentID(mDocument->GetAndIncrementContentID());
// Add in the attributes and add the script content object to the
// head container.
AddBaseTagInfo(element);
rv = AddAttributes(aNode, element);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsCOMPtr<nsIScriptElement> sele(do_QueryInterface(element));
nsAutoString script;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(eHTMLTag_script, script, lineNo);
if (sele) {
sele->SetScriptLineNumber((PRUint32)lineNo);
}
// Create a text node holding the content. First, get the text
// content of the script tag
if (!script.IsEmpty()) {
nsCOMPtr<nsITextContent> text;
rv = NS_NewTextNode(getter_AddRefs(text));
NS_ENSURE_SUCCESS(rv, rv);
text->SetText(script, PR_TRUE);
element->AppendChildTo(text, PR_FALSE);
}
nsCOMPtr<nsIScriptLoader> loader; nsCOMPtr<nsIScriptLoader> loader;
if (mFrameset) { if (mFrameset) {
@ -4089,7 +4023,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
// Don't include script loading and evaluation in the stopwatch // Don't include script loading and evaluation in the stopwatch
// that is measuring content creation time // that is measuring content creation time
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::ProcessSCRIPTTag()\n")); MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::ProcessSCRIPTEndTag()\n"));
MOZ_TIMER_STOP(mWatch); MOZ_TIMER_STOP(mWatch);
// Assume that we're going to block the parser with a script load. // Assume that we're going to block the parser with a script load.
@ -4100,23 +4034,10 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
mScriptElements.AppendObject(sele); mScriptElements.AppendObject(sele);
} }
// Now flush out tags so that the script will actually be bound to a // Now tell the script that it's ready to go. This will execute the script
// document and will evaluate as soon as it's appended. // and call our ScriptAvailable method.
SINK_TRACE(SINK_TRACE_CALLS, content->DoneAddingChildren();
("HTMLContentSink::ProcessSCRIPTTag: flushing tags before "
"appending script"));
mCurrentContext->FlushTags(PR_FALSE);
// Insert the child into the content tree. This will evaluate the
// script as well.
if (mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mInsertionPoint != -1) {
parent->InsertChildAt(element,
mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mInsertionPoint++,
PR_FALSE);
} else {
parent->AppendChildTo(element, PR_FALSE);
}
// To prevent script evaluation in a frameset document, we suspended // To prevent script evaluation in a frameset document, we suspended
// the script loader. Now that the script content has been handled, // the script loader. Now that the script content has been handled,
// let's resume the script loader. // let's resume the script loader.
@ -4137,81 +4058,18 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
// XXX What does nav do if we have SRC= and some style data inline? // XXX What does nav do if we have SRC= and some style data inline?
nsresult nsresult
HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) HTMLContentSink::ProcessSTYLEEndTag(nsGenericHTMLElement* content)
{ {
nsresult rv = NS_OK; nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(content);
nsGenericHTMLElement* parent = nsnull;
if (mCurrentContext) {
parent = mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent;
}
if (!parent) {
return NS_OK;
}
// Create content object
nsCOMPtr<nsINodeInfo> nodeInfo;
mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::style, nsnull, kNameSpaceID_None,
getter_AddRefs(nodeInfo));
nsCOMPtr<nsIContent> element;
rv = NS_NewHTMLElement(getter_AddRefs(element), nodeInfo);
NS_ENSURE_SUCCESS(rv, rv);
element->SetContentID(mDocument->GetAndIncrementContentID());
nsCOMPtr<nsIStyleSheetLinkingElement> ssle = do_QueryInterface(element);
NS_ASSERTION(ssle, NS_ASSERTION(ssle,
"html:style doesn't implement nsIStyleSheetLinkingElement"); "html:style doesn't implement nsIStyleSheetLinkingElement");
if (ssle) { nsresult rv = NS_OK;
// XXX need prefs. check here.
if (!mInsideNoXXXTag) {
ssle->InitStyleLinkElement(mParser, PR_FALSE);
ssle->SetEnableUpdates(PR_FALSE);
} else {
ssle->InitStyleLinkElement(nsnull, PR_TRUE);
}
}
// Add in the attributes and add the style content object to the
// head container.
AddBaseTagInfo(element);
rv = AddAttributes(aNode, element);
if (NS_FAILED(rv)) {
return rv;
}
// The skipped content contains the inline style data
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsAutoString content;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(eHTMLTag_style, content, lineNo);
if (ssle) {
ssle->SetLineNumber(lineNo);
}
if (!content.IsEmpty()) {
// Create a text node holding the content
nsCOMPtr<nsITextContent> text;
rv = NS_NewTextNode(getter_AddRefs(text));
NS_ENSURE_SUCCESS(rv, rv);
text->SetText(content, PR_TRUE);
element->AppendChildTo(text, PR_FALSE);
}
parent->AppendChildTo(element, PR_FALSE);
if (ssle) { if (ssle) {
// Note: if we are inside a noXXX tag, then we init'ed this style element
// with mDontLoadStyle = PR_TRUE, so these two calls will have no effect.
ssle->SetEnableUpdates(PR_TRUE); ssle->SetEnableUpdates(PR_TRUE);
rv = ssle->UpdateStyleSheet(nsnull, nsnull); rv = ssle->UpdateStyleSheet(nsnull, nsnull);
} }

Просмотреть файл

@ -90,10 +90,10 @@ public:
// nsIHTMLContentSink // nsIHTMLContentSink
NS_IMETHOD BeginContext(PRInt32 aID); NS_IMETHOD BeginContext(PRInt32 aID);
NS_IMETHOD EndContext(PRInt32 aID); NS_IMETHOD EndContext(PRInt32 aID);
NS_IMETHOD SetTitle(const nsString& aValue);
NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD OpenHTML(const nsIParserNode& aNode);
NS_IMETHOD CloseHTML(); NS_IMETHOD CloseHTML();
NS_IMETHOD OpenHead(const nsIParserNode& aNode); NS_IMETHOD OpenHead(const nsIParserNode& aNode);
NS_IMETHOD OpenHead();
NS_IMETHOD CloseHead(); NS_IMETHOD CloseHead();
NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD OpenBody(const nsIParserNode& aNode);
NS_IMETHOD CloseBody(); NS_IMETHOD CloseBody();
@ -115,7 +115,6 @@ public:
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag); NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddHeadContent(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode);
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
@ -143,7 +142,6 @@ public:
void AddBaseTagInfo(nsIContent* aContent); void AddBaseTagInfo(nsIContent* aContent);
nsresult Init(); nsresult Init();
nsresult SetDocumentTitle(const nsAString& aString, const nsIParserNode* aNode);
PRPackedBool mAllContent; PRPackedBool mAllContent;
PRPackedBool mProcessing; PRPackedBool mProcessing;
@ -299,12 +297,6 @@ nsHTMLFragmentContentSink::EndContext(PRInt32 aID)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsHTMLFragmentContentSink::SetTitle(const nsString& aValue)
{
return SetDocumentTitle(aValue, nsnull);
}
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenHTML(const nsIParserNode& aNode) nsHTMLFragmentContentSink::OpenHTML(const nsIParserNode& aNode)
{ {
@ -323,6 +315,14 @@ nsHTMLFragmentContentSink::OpenHead(const nsIParserNode& aNode)
return OpenContainer(aNode); return OpenContainer(aNode);
} }
NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenHead()
{
// The DTD uses this function when the head is being forced open by a tag in
// the body. We can safely ignore it, for now.
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLFragmentContentSink::CloseHead() nsHTMLFragmentContentSink::CloseHead()
{ {
@ -338,9 +338,8 @@ nsHTMLFragmentContentSink::OpenBody(const nsIParserNode& aNode)
mSeenBody = PR_TRUE; mSeenBody = PR_TRUE;
return OpenContainer(aNode); return OpenContainer(aNode);
} }
else {
return NS_OK; return NS_OK;
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -410,36 +409,6 @@ nsHTMLFragmentContentSink::AddBaseTagInfo(nsIContent* aContent)
} }
} }
nsresult
nsHTMLFragmentContentSink::SetDocumentTitle(const nsAString& aString, const nsIParserNode* aNode)
{
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsINodeInfo> nodeInfo;
nsresult rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::title, nsnull,
kNameSpaceID_None,
getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsGenericHTMLElement> content = NS_NewHTMLTitleElement(nodeInfo);
NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY);
nsIContent *parent = GetCurrentContent();
if (!parent) {
parent = mRoot;
}
if (aNode) {
AddAttributes(*aNode, content);
}
rv = parent->AppendChildTo(content, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
return AddTextToContent(content, aString);
}
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode) nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
{ {
@ -520,28 +489,9 @@ nsHTMLFragmentContentSink::CloseContainer(const nsHTMLTag aTag)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsHTMLFragmentContentSink::AddHeadContent(const nsIParserNode& aNode)
{
return AddLeaf(aNode);
}
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode) nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode)
{ {
if (eHTMLTag_title == aNode.GetNodeType()) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsAutoString skippedContent;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(eHTMLTag_title, skippedContent, lineNo);
return SetDocumentTitle(skippedContent, &aNode);
}
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsresult result = NS_OK; nsresult result = NS_OK;
@ -594,22 +544,7 @@ nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode)
} }
} }
if(nodeType == eHTMLTag_script || if (nodeType == eHTMLTag_img || nodeType == eHTMLTag_frame
nodeType == eHTMLTag_style ||
nodeType == eHTMLTag_server) {
// Create a text node holding the content
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsAutoString skippedContent;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(nodeType, skippedContent, lineNo);
result=AddTextToContent(content, skippedContent);
}
else if (nodeType == eHTMLTag_img || nodeType == eHTMLTag_frame
|| nodeType == eHTMLTag_input) // elements with 'SRC=' || nodeType == eHTMLTag_input) // elements with 'SRC='
AddBaseTagInfo(content); AddBaseTagInfo(content);
else if (nodeType == eHTMLTag_base) else if (nodeType == eHTMLTag_base)

Просмотреть файл

@ -59,7 +59,9 @@
#include "nsITokenizer.h" #include "nsITokenizer.h"
#define NS_IDTD_IID \ #define NS_IDTD_IID \
{ 0xa6cf9053, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} { 0xab54d8ec, 0xc31c, 0x434b, \
{ 0xa7, 0x64, 0xb4, 0xe9, 0xcd, 0x60, 0xc5, 0xc1 } }
enum eAutoDetectResult { enum eAutoDetectResult {
eUnknownDetect, eUnknownDetect,
@ -200,8 +202,6 @@ public:
NS_IMETHOD_(void) Terminate() = 0; NS_IMETHOD_(void) Terminate() = 0;
NS_IMETHOD_(PRInt32) GetType() = 0; NS_IMETHOD_(PRInt32) GetType() = 0;
NS_IMETHOD CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLineNo) = 0;
}; };
#define NS_DECL_NSIDTD \ #define NS_DECL_NSIDTD \
@ -216,7 +216,6 @@ public:
NS_IMETHOD WillInterruptParse(nsIContentSink* aSink = 0);\ NS_IMETHOD WillInterruptParse(nsIContentSink* aSink = 0);\
NS_IMETHOD_(PRBool) CanContain(PRInt32 aParent,PRInt32 aChild) const;\ NS_IMETHOD_(PRBool) CanContain(PRInt32 aParent,PRInt32 aChild) const;\
NS_IMETHOD_(PRBool) IsContainer(PRInt32 aTag) const;\ NS_IMETHOD_(PRBool) IsContainer(PRInt32 aTag) const;\
NS_IMETHOD CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLineNo);\
NS_IMETHOD_(void) Terminate();\ NS_IMETHOD_(void) Terminate();\
NS_IMETHOD_(PRInt32) GetType(); NS_IMETHOD_(PRInt32) GetType();
#endif /* nsIDTD_h___ */ #endif /* nsIDTD_h___ */

Просмотреть файл

@ -38,9 +38,6 @@
#define nsIHTMLContentSink_h___ #define nsIHTMLContentSink_h___
/** /**
* MODULE NOTES:
* @update gess 4/1/98
*
* This file declares the concrete HTMLContentSink class. * This file declares the concrete HTMLContentSink class.
* This class is used during the parsing process as the * This class is used during the parsing process as the
* primary interface between the parser and the content * primary interface between the parser and the content
@ -86,7 +83,9 @@
#include "nsHTMLTags.h" #include "nsHTMLTags.h"
#define NS_IHTML_CONTENT_SINK_IID \ #define NS_IHTML_CONTENT_SINK_IID \
{ 0x59929de5, 0xe60b, 0x48b1,{0x81, 0x69, 0x48, 0x47, 0xb5, 0xc9, 0x44, 0x29}} { 0x73b5a072, 0x0f87, 0x4d07, \
{ 0xa8, 0x16, 0xe6, 0xac, 0x73, 0xa7, 0x04, 0x3c } }
#if defined(XP_MAC) || defined(WINCE) #if defined(XP_MAC) || defined(WINCE)
#define MAX_REFLOW_DEPTH 75 //setting to 75 to prevent layout from crashing on mac. Bug 55095. #define MAX_REFLOW_DEPTH 75 //setting to 75 to prevent layout from crashing on mac. Bug 55095.
@ -102,15 +101,6 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID) NS_DEFINE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID)
/**
* This method gets called by the parser when it encounters
* a title tag and wants to set the document title in the sink.
*
* @update 4/1/98 gess
* @param nsString reference to new title value
*/
NS_IMETHOD SetTitle(const nsString& aValue) = 0;
/** /**
* This method is used to open the outer HTML container. * This method is used to open the outer HTML container.
* *
@ -133,6 +123,13 @@ public:
*/ */
NS_IMETHOD OpenHead(const nsIParserNode& aNode) = 0; NS_IMETHOD OpenHead(const nsIParserNode& aNode) = 0;
/**
* This method is used to open the HEAD container. It is useful if a tag
* is forcing us to open the head (probably again), like if we find a <meta>
* tag in the body.
*/
NS_IMETHOD OpenHead() = 0;
/** /**
* This method is used to close the only HEAD container. * This method is used to close the only HEAD container.
*/ */
@ -262,13 +259,6 @@ public:
*/ */
NS_IMETHOD CloseContainer(const nsHTMLTag aTag) = 0; NS_IMETHOD CloseContainer(const nsHTMLTag aTag) = 0;
/**
* This gets called by the parser to contents to
* the head container
*
*/
NS_IMETHOD AddHeadContent(const nsIParserNode& aNode) = 0;
/** /**
* This gets called by the parser when you want to add * This gets called by the parser when you want to add
* a leaf node to the current container in the content * a leaf node to the current container in the content
@ -303,7 +293,7 @@ public:
* This method is called by the parser when it encounters * This method is called by the parser when it encounters
* a document type declaration. * a document type declaration.
* *
* XXX Should the parser also part the internal subset? * XXX Should the parser also parse the internal subset?
* *
* @param nsIParserNode reference to parser node interface * @param nsIParserNode reference to parser node interface
*/ */

Просмотреть файл

@ -113,11 +113,11 @@ static const char kInvalidTagStackPos[] = "Error: invalid tag stack position";
#define NS_DTD_FLAG_HAS_OPEN_HEAD 0x00000001 #define NS_DTD_FLAG_HAS_OPEN_HEAD 0x00000001
#define NS_DTD_FLAG_HAS_OPEN_BODY 0x00000002 #define NS_DTD_FLAG_HAS_OPEN_BODY 0x00000002
#define NS_DTD_FLAG_HAS_OPEN_FORM 0x00000004 #define NS_DTD_FLAG_HAS_OPEN_FORM 0x00000004
#define NS_DTD_FLAG_HAS_OPEN_SCRIPT 0x00000008 #define NS_DTD_FLAG_HAS_EXPLICIT_HEAD 0x00000008
#define NS_DTD_FLAG_HAD_BODY 0x00000010 #define NS_DTD_FLAG_HAD_BODY 0x00000010
#define NS_DTD_FLAG_HAD_FRAMESET 0x00000020 #define NS_DTD_FLAG_HAD_FRAMESET 0x00000020
#define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE 0x00000040 #define NS_DTD_FLAG_ENABLE_RESIDUAL_STYLE 0x00000040
#define NS_DTD_FLAG_ALTERNATE_CONTENT 0x00000080 // NOFRAMES, NOSCRIPT #define NS_DTD_FLAG_ALTERNATE_CONTENT 0x00000080 // NOFRAMES, NOSCRIPT
#define NS_DTD_FLAG_MISPLACED_CONTENT 0x00000100 #define NS_DTD_FLAG_MISPLACED_CONTENT 0x00000100
#define NS_DTD_FLAG_IN_MISPLACED_CONTENT 0x00000200 #define NS_DTD_FLAG_IN_MISPLACED_CONTENT 0x00000200
#define NS_DTD_FLAG_STOP_PARSING 0x00000400 #define NS_DTD_FLAG_STOP_PARSING 0x00000400
@ -167,7 +167,6 @@ NS_IMPL_RELEASE(CNavDTD)
*/ */
CNavDTD::CNavDTD() : nsIDTD(), CNavDTD::CNavDTD() : nsIDTD(),
mMisplacedContent(0), mMisplacedContent(0),
mSkippedContent(0),
mSink(0), mSink(0),
mTokenAllocator(0), mTokenAllocator(0),
mTempContext(0), mTempContext(0),
@ -176,9 +175,9 @@ CNavDTD::CNavDTD() : nsIDTD(),
mDTDMode(eDTDMode_quirks), mDTDMode(eDTDMode_quirks),
mDocType(eHTML3_Quirks), // why not eHTML_Quirks? mDocType(eHTML3_Quirks), // why not eHTML_Quirks?
mParserCommand(eViewNormal), mParserCommand(eViewNormal),
mSkipTarget(eHTMLTag_unknown),
mLineNumber(1), mLineNumber(1),
mOpenMapCount(0), mOpenMapCount(0),
mHeadContainerPosition(-1),
mFlags(NS_DTD_FLAG_NONE) mFlags(NS_DTD_FLAG_NONE)
{ {
mBodyContext=new nsDTDContext(); mBodyContext=new nsDTDContext();
@ -341,7 +340,6 @@ nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext,
mParserCommand = aParserContext.mParserCommand; mParserCommand = aParserContext.mParserCommand;
mMimeType = aParserContext.mMimeType; mMimeType = aParserContext.mMimeType;
mDocType = aParserContext.mDocType; mDocType = aParserContext.mDocType;
mSkipTarget = eHTMLTag_unknown;
mTokenizer = aTokenizer; mTokenizer = aTokenizer;
mBodyContext->SetNodeAllocator(&mNodeAllocator); mBodyContext->SetNodeAllocator(&mNodeAllocator);
@ -475,10 +473,9 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke
// Script so we should not allow it to be interrupted. // Script so we should not allow it to be interrupted.
// We also need to make sure that an interruption does not override // We also need to make sure that an interruption does not override
// a request to block the parser. // a request to block the parser.
if ((mParser->CanInterrupt()) && if (mParser->CanInterrupt() &&
(nsnull == mParser->PeekContext()->mPrevContext) && !mParser->PeekContext()->mPrevContext &&
(eHTMLTag_unknown==mSkipTarget) && NS_SUCCEEDED(result)) {
NS_SUCCEEDED(result)) {
result = NS_ERROR_HTMLPARSER_INTERRUPTED; result = NS_ERROR_HTMLPARSER_INTERRUPTED;
break; break;
} }
@ -532,12 +529,6 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,
nsresult result = NS_OK; nsresult result = NS_OK;
if (aParser && aNotifySink) { if (aParser && aNotifySink) {
if (NS_OK == anErrorCode) { if (NS_OK == anErrorCode) {
if (eHTMLTag_unknown != mSkipTarget) {
// Looks like there is an open target ( ex. <title> ).
// Create a matching target to handle the unclosed target.
result = BuildNeglectedTarget(mSkipTarget, eToken_end, aParser, aSink);
NS_ENSURE_SUCCESS(result , result);
}
if (!(mFlags & (NS_DTD_FLAG_HAD_FRAMESET | NS_DTD_FLAG_HAD_BODY))) { if (!(mFlags & (NS_DTD_FLAG_HAD_FRAMESET | NS_DTD_FLAG_HAD_BODY))) {
// This document is not a frameset document, however, it did not contain // 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.. // a body tag either. So, make one!. Note: Body tag is optional per spec..
@ -673,81 +664,6 @@ PRBool HasOpenTagOfType(PRInt32 aType, const nsDTDContext& aContext) {
return PR_FALSE; return PR_FALSE;
} }
static void
InPlaceConvertLineEndings( nsAString& aString )
{
// go from '\r\n' or '\r' to '\n'
nsAString::iterator iter;
aString.BeginWriting(iter);
PRUnichar* S = iter.get();
size_t N = iter.size_forward();
// this fragment must be the entire string because
// (a) no multi-fragment string is writable, so only an illegal cast could give us one, and
// (b) else we would have to do more work (watching for |to| to fall off the end)
NS_ASSERTION(aString.Length() == N, "You cheated... multi-fragment strings are never writable!");
// we scan/convert in two phases (but only one pass over the string)
// until we have to skip a character, we only need to touch end-of-line chars
// after that, we'll have to start moving every character we want to keep
// use array indexing instead of pointers, because compilers optimize that better
// this first loop just converts line endings... no characters get moved
size_t i = 0;
PRBool just_saw_cr = PR_FALSE;
for ( ; i < N; ++i )
{
// if it's something we need to convert...
if ( S[i] == '\r' )
{
S[i] = '\n';
just_saw_cr = PR_TRUE;
}
else
{
// else, if it's something we need to skip...
// i.e., a '\n' immediately following a '\r',
// then we need to start moving any character we want to keep
// and we have a second loop for that, so get out of this one
if ( S[i] == '\n' && just_saw_cr )
break;
just_saw_cr = PR_FALSE;
}
}
// this second loop handles the rest of the buffer, moving characters down
// _and_ converting line-endings as it goes
// start the loop at |from = i| so that that |just_saw_cr| gets cleared automatically
size_t to = i;
for ( size_t from = i; from < N; ++from )
{
// if it's something we need to convert...
if ( S[from] == '\r' )
{
S[to++] = '\n';
just_saw_cr = PR_TRUE;
}
else
{
// else, if it's something we need to copy...
// i.e., NOT a '\n' immediately following a '\r'
if ( S[from] != '\n' || !just_saw_cr )
S[to++] = S[from];
just_saw_cr = PR_FALSE;
}
}
// if we chopped characters out of the string, we need to shorten it logically
if ( to < N )
aString.SetLength(to);
}
/** /**
* This big dispatch method is used to route token handler calls to the right place. * 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 * What's wrong with it? This table, and the dispatch methods themselves need to be
@ -765,37 +681,12 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
CHTMLToken* theToken= NS_STATIC_CAST(CHTMLToken*, aToken); CHTMLToken* theToken= NS_STATIC_CAST(CHTMLToken*, aToken);
eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType());
eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID();
PRBool execSkipContent=PR_FALSE;
aToken->SetLineNumber(mLineNumber); aToken->SetLineNumber(mLineNumber);
mLineNumber += aToken->GetNewlineCount(); mLineNumber += aToken->GetNewlineCount();
/* --------------------------------------------------------------------------------- if(mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) {
To understand this little piece of code, you need to look below too.
In essence, this code caches "skipped content" until we find a given skiptarget.
Once we find the skiptarget, we take all skipped content up to that point and
coallate it. Then we push those tokens back onto the tokenizer deque.
---------------------------------------------------------------------------------
*/
// printf("token: %p\n",aToken);
if(mSkipTarget){ //handle a preexisting target...
if((theTag==mSkipTarget) && (eToken_end==theType)){
mSkipTarget=eHTMLTag_unknown; //stop skipping.
//mTokenizer->PushTokenFront(aToken); //push the end token...
execSkipContent=PR_TRUE;
IF_FREE(aToken, mTokenAllocator);
theToken=(CHTMLToken*)mSkippedContent.PopFront();
theType=eToken_start;
}
else {
mSkippedContent.Push(theToken);
return result;
}
}
else if(mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) {
// Included TD & TH to fix Bug# 20797 // Included TD & TH to fix Bug# 20797
static eHTMLTags gLegalElements[]={eHTMLTag_table,eHTMLTag_thead,eHTMLTag_tbody, static eHTMLTags gLegalElements[]={eHTMLTag_table,eHTMLTag_thead,eHTMLTag_tbody,
eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th,eHTMLTag_tfoot}; eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th,eHTMLTag_tfoot};
@ -831,12 +722,6 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
NS_ENSURE_SUCCESS(result, result); NS_ENSURE_SUCCESS(result, result);
mBodyContext->mContextTopIndex = -1; mBodyContext->mContextTopIndex = -1;
if (mSkipTarget) {
mSkippedContent.Push(theToken);
return result;
}
// Fall through if the skipped content collection is |not| in progress - bug 124788
} }
else { else {
PushIntoMisplacedStack(theToken); PushIntoMisplacedStack(theToken);
@ -853,145 +738,135 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
deque until we can deal with it. deque until we can deal with it.
--------------------------------------------------------------------------------- ---------------------------------------------------------------------------------
*/ */
if(!execSkipContent) { switch(theTag) {
case eHTMLTag_html:
case eHTMLTag_noframes:
case eHTMLTag_noscript:
case eHTMLTag_script:
case eHTMLTag_doctypeDecl:
case eHTMLTag_instruction:
break;
switch(theTag) { default:
case eHTMLTag_html: if(!gHTMLElements[eHTMLTag_html].SectionContains(theTag,PR_FALSE)) {
case eHTMLTag_noframes: if(!(mFlags & (NS_DTD_FLAG_HAD_BODY |
case eHTMLTag_noscript: NS_DTD_FLAG_HAD_FRAMESET |
case eHTMLTag_script: NS_DTD_FLAG_ALTERNATE_CONTENT))) {
case eHTMLTag_doctypeDecl:
case eHTMLTag_instruction: //For bug examples from this code, see bugs: 18928, 20989.
break; //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_head &&
gHTMLElements[top].CanContain(theTag, mDTDMode)) {
// Some tags (such as <object> and <script>) are opened in the
// head and allow other non-head content to be children.
// Note: Userdefined tags in the head act like leaves.
break;
}
//If you're here then we found a child of the body that was out of place.
//We're going to move it to the body by storing it temporarily on the misplaced stack.
//However, in quirks mode, a few tags request, ambiguosly, for a BODY. - Bugs 18928, 24204.-
PushIntoMisplacedStack(aToken);
if (IsAlternateTag(theTag)) {
// These tags' contents are consumed as CDATA. If we simply
// pushed them on the misplaced content stack, the CDATA
// contents would force us to open a body, which could be
// wrong. So we collect the whole tag as misplaced in one
// gulp. Note that the tokenizer guarantees that there will
// be an end tag.
CToken *current = aToken;
while (current->GetTokenType() != eToken_end ||
current->GetTypeID() != theTag) {
current = NS_STATIC_CAST(CToken *, mTokenizer->PopToken());
NS_ASSERTION(current, "The tokenizer is not creating good "
"alternate tags");
PushIntoMisplacedStack(current);
}
// XXX Add code to also collect incorrect attributes on the
// end tag.
}
if(DoesRequireBody(aToken,mTokenizer)) {
CToken* theBodyToken=NS_STATIC_CAST(CToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_LITERAL_STRING("body")));
result=HandleToken(theBodyToken,aParser);
}
return result;
}
} //if
} //if
}//switch
if(theToken){
mParser=(nsParser*)aParser;
switch(theType) {
case eToken_text:
case eToken_start:
case eToken_whitespace:
case eToken_newline:
result=HandleStartToken(theToken); break;
case eToken_end:
result=HandleEndToken(theToken); break;
case eToken_cdatasection:
case eToken_comment:
case eToken_markupDecl:
result=HandleCommentToken(theToken); break;
case eToken_entity:
result=HandleEntityToken(theToken); break;
case eToken_attribute:
result=HandleAttributeToken(theToken); break;
case eToken_instruction:
result=HandleProcessingInstructionToken(theToken); break;
case eToken_doctypeDecl:
result=HandleDocTypeDeclToken(theToken); break;
default: default:
if(!gHTMLElements[eHTMLTag_html].SectionContains(theTag,PR_FALSE)) { break;
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.
//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) {
//If you're here then we found a child of the body that was out of place.
//We're going to move it to the body by storing it temporarily on the misplaced stack.
//However, in quirks mode, a few tags request, ambiguosly, for a BODY. - Bugs 18928, 24204.-
PushIntoMisplacedStack(aToken);
if (IsAlternateTag(theTag)) {
// These tags' contents are consumed as CDATA. If we simply
// pushed them on the misplaced content stack, the CDATA
// contents would force us to open a body, which could be
// wrong. So we collect the whole tag as misplaced in one
// gulp. Note that the tokenizer guarantees that there will
// be an end tag.
CToken *current = aToken;
while (current->GetTokenType() != eToken_end ||
current->GetTypeID() != theTag) {
current = NS_STATIC_CAST(CToken *, mTokenizer->PopToken());
NS_ASSERTION(current, "The tokenizer is not creating good "
"alternate tags");
PushIntoMisplacedStack(current);
}
// XXX Add code to also collect incorrect attributes on the
// end tag.
}
if(DoesRequireBody(aToken,mTokenizer)) {
CToken* theBodyToken=NS_STATIC_CAST(CToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_LITERAL_STRING("body")));
result=HandleToken(theBodyToken,aParser);
}
return result;
}
} //if
} //if
}//switch }//switch
} //if
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
if(theToken){ IF_FREE(theToken, mTokenAllocator);
//Before dealing with the token normally, we need to deal with skip targets }
CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken); else if(result==NS_ERROR_HTMLPARSER_STOPPARSING) {
if((!execSkipContent) && mFlags |= NS_DTD_FLAG_STOP_PARSING;
(theType!=eToken_end) &&
(eHTMLTag_unknown==mSkipTarget) &&
(gHTMLElements[theTag].mSkipTarget) &&
(!theStartToken->IsEmpty())) { // added empty token check for bug 44186
//create a new target
NS_ASSERTION(mSkippedContent.GetSize() == 0, "all the skipped content tokens did not get handled");
mSkippedContent.Empty();
mSkipTarget=gHTMLElements[theTag].mSkipTarget;
mSkippedContent.Push(theToken);
} }
else { else {
return NS_OK;
mParser=(nsParser*)aParser;
switch(theType) {
case eToken_text:
case eToken_start:
case eToken_whitespace:
case eToken_newline:
result=HandleStartToken(theToken); break;
case eToken_end:
result=HandleEndToken(theToken); break;
case eToken_cdatasection:
case eToken_comment:
case eToken_markupDecl:
result=HandleCommentToken(theToken); break;
case eToken_entity:
result=HandleEntityToken(theToken); break;
case eToken_attribute:
result=HandleAttributeToken(theToken); break;
case eToken_instruction:
result=HandleProcessingInstructionToken(theToken); break;
case eToken_doctypeDecl:
result=HandleDocTypeDeclToken(theToken); break;
default:
break;
}//switch
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken, mTokenAllocator);
}
else if(result==NS_ERROR_HTMLPARSER_STOPPARSING) {
mFlags |= NS_DTD_FLAG_STOP_PARSING;
}
else {
return NS_OK;
}
} }
} }
}
}//if
return result; return result;
} }
@ -1357,22 +1232,6 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::WillHandleStartTag(), this=%p\n", this));
START_TIMER() START_TIMER()
if(NS_SUCCEEDED(result)) {
// This code is here to make sure the head is closed before we deal
// with any tags that don't belong in the head. If the tag is not exclusive
// then we do not have enough information, and we have to trust the logic
// in HandleToken() to not hand us non-exclusive tokens
PRBool isExclusive = PR_FALSE;
PRBool isChildOfHead =
gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag, isExclusive);
if (NS_SUCCEEDED(result) && ((mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) &&
isExclusive &&
!isChildOfHead)) {
result = CloseHead();
}
}
return result; return result;
} }
@ -1439,17 +1298,6 @@ nsresult CNavDTD::HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags
// If the token is attributed then save those attributes too. // If the token is attributed then save those attributes too.
if(attrCount > 0) PushMisplacedAttributes(*aNode,mMisplacedContent,attrCount); if(attrCount > 0) PushMisplacedAttributes(*aNode,mMisplacedContent,attrCount);
if(gHTMLElements[aChildTag].mSkipTarget) {
nsAutoString theString;
PRInt32 lineNo = 0;
result = CollectSkippedContent(aChildTag, theString, lineNo);
NS_ENSURE_SUCCESS(result, result);
PushIntoMisplacedStack(mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theString));
PushIntoMisplacedStack(mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag));
}
mFlags |= NS_DTD_FLAG_MISPLACED_CONTENT; // This state would help us in gathering all the misplaced elements mFlags |= NS_DTD_FLAG_MISPLACED_CONTENT; // This state would help us in gathering all the misplaced elements
}//if }//if
}//if }//if
@ -1597,6 +1445,8 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
} }
break; break;
case eHTMLTag_head: case eHTMLTag_head:
mFlags |= NS_DTD_FLAG_HAS_EXPLICIT_HEAD;
if(mFlags & (NS_DTD_FLAG_HAD_BODY | NS_DTD_FLAG_HAD_FRAMESET)) { if(mFlags & (NS_DTD_FLAG_HAD_BODY | NS_DTD_FLAG_HAD_FRAMESET)) {
result=HandleOmittedTag(aToken,theChildTag,theParent,theNode); result=HandleOmittedTag(aToken,theChildTag,theParent,theNode);
isTokenHandled=PR_TRUE; isTokenHandled=PR_TRUE;
@ -1610,7 +1460,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
PRBool isExclusive=PR_FALSE; PRBool isExclusive=PR_FALSE;
theHeadIsParent=nsHTMLElement::IsChildOfHead(theChildTag,isExclusive); theHeadIsParent=nsHTMLElement::IsChildOfHead(theChildTag,isExclusive);
switch(theChildTag) { switch(theChildTag) {
case eHTMLTag_area: case eHTMLTag_area:
if(!mOpenMapCount) isTokenHandled=PR_TRUE; if(!mOpenMapCount) isTokenHandled=PR_TRUE;
@ -1640,10 +1490,9 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
// as such to make sure that we don't pull scripts outside the head // as such to make sure that we don't pull scripts outside the head
// into the body. // into the body.
isExclusive = !(mFlags & NS_DTD_FLAG_HAD_BODY); isExclusive = !(mFlags & NS_DTD_FLAG_HAD_BODY);
mFlags |= NS_DTD_FLAG_HAS_OPEN_SCRIPT; break;
default: default:;
break;
}//switch }//switch
if(!isTokenHandled) { if(!isTokenHandled) {
@ -1657,12 +1506,12 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
theHeadIsParent = theHeadIsParent && theHeadIsParent = theHeadIsParent &&
(isExclusive || (isExclusive ||
(prefersBody (prefersBody
? (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) ? (mFlags & NS_DTD_FLAG_HAS_EXPLICIT_HEAD)
: !(mFlags & NS_DTD_FLAG_HAD_BODY))); : !(mFlags & NS_DTD_FLAG_HAD_BODY)));
if(theHeadIsParent) { if(theHeadIsParent) {
// These tokens prefer to be in the head. // These tokens prefer to be in the head.
result = AddHeadLeaf(theNode); result = AddHeadContent(theNode);
} }
else { else {
result = HandleDefaultStartToken(aToken,theChildTag,theNode); result = HandleDefaultStartToken(aToken,theChildTag,theNode);
@ -1842,13 +1691,8 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) {
CollectAttributes(nsnull,theChildTag,attrCount); CollectAttributes(nsnull,theChildTag,attrCount);
switch(theChildTag) { switch(theChildTag) {
case eHTMLTag_script:
mFlags &= ~NS_DTD_FLAG_HAS_OPEN_SCRIPT;
case eHTMLTag_style:
case eHTMLTag_link: case eHTMLTag_link:
case eHTMLTag_meta: case eHTMLTag_meta:
case eHTMLTag_title:
break; break;
case eHTMLTag_head: case eHTMLTag_head:
@ -1877,6 +1721,23 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) {
StripWSFollowingTag(theChildTag,mTokenizer,mTokenAllocator,mLineNumber); StripWSFollowingTag(theChildTag,mTokenizer,mTokenAllocator,mLineNumber);
break; break;
case eHTMLTag_script:
// Note: we don't fall through to the default case because
// CloseContainersTo() has the bad habit of closing tags that are opened
// by document.write(). Fortunately, the tokenizer guarantees that no
// actual tags appear between <script> and </script> so we won't be
// closing the wrong tag.
if (mBodyContext->Last() != eHTMLTag_script) {
// Except if we're here, then there's probably a stray script tag.
NS_ASSERTION(mBodyContext->LastOf(eHTMLTag_script) == kNotFound,
"Mishandling scripts in CNavDTD");
break;
}
mBodyContext->Pop();
result = CloseContainer(eHTMLTag_script, theChildTag, PR_FALSE);
break;
default: default:
{ {
//now check to see if this token should be omitted, or //now check to see if this token should be omitted, or
@ -2012,7 +1873,7 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
theToken=(CToken*)mMisplacedContent.PopFront(); theToken=(CToken*)mMisplacedContent.PopFront();
if(theToken) { if(theToken) {
theTag = (eHTMLTags)theToken->GetTypeID(); theTag = (eHTMLTags)theToken->GetTypeID();
attrCount = (gHTMLElements[theTag].mSkipTarget)? 0:theToken->GetAttributeCount(); attrCount = theToken->GetAttributeCount();
// Put back attributes, which once got popped out, into the tokenizer // Put back attributes, which once got popped out, into the tokenizer
for(PRInt32 j=0;j<attrCount; ++j){ for(PRInt32 j=0;j<attrCount; ++j){
CToken* theAttrToken = (CToken*)mMisplacedContent.PopFront(); CToken* theAttrToken = (CToken*)mMisplacedContent.PopFront();
@ -2156,31 +2017,6 @@ nsresult CNavDTD::HandleAttributeToken(CToken* aToken) {
return NS_OK; return NS_OK;
} }
/**
* This method gets called when a script token has been
* encountered in the parse process. n
*
* @update gess 3/25/98
* @param aToken -- next (start) token to be handled
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult CNavDTD::HandleScriptToken(const nsIParserNode *aNode) {
// PRInt32 attrCount=aNode.GetAttributeCount(PR_TRUE);
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleScriptToken(), this=%p\n", this));
nsresult result=AddLeaf(aNode);
mParser->SetCanInterrupt(PR_FALSE);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleScriptToken(), this=%p\n", this));
START_TIMER();
return result;
}
/** /**
* This method gets called when an "instruction" token has been * This method gets called when an "instruction" token has been
* encountered in the parse process. * encountered in the parse process.
@ -2266,15 +2102,11 @@ nsresult CNavDTD::CollectAttributes(nsIParserNode *aNode,eHTMLTags aTag,PRInt32
int attr=0; int attr=0;
nsresult result=NS_OK; nsresult result=NS_OK;
int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize(); int theAvailTokenCount=mTokenizer->GetCount();
if(aCount<=theAvailTokenCount) { if(aCount<=theAvailTokenCount) {
CToken* theToken=0; CToken* theToken=0;
eHTMLTags theSkipTarget=gHTMLElements[aTag].mSkipTarget;
for(attr=0;attr<aCount;++attr){ for(attr=0;attr<aCount;++attr){
if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize()) theToken=mTokenizer->PopToken();
theToken=NS_STATIC_CAST(CToken*,mSkippedContent.PopFront());
else
theToken=mTokenizer->PopToken();
if(theToken) { if(theToken) {
eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType());
if(theType!=eToken_attribute) { if(theType!=eToken_attribute) {
@ -2313,55 +2145,6 @@ nsresult CNavDTD::CollectAttributes(nsIParserNode *aNode,eHTMLTags aTag,PRInt32
return result; return result;
} }
/**
* Causes the next skipped-content token (if any) to
* be consumed by this node.
*
* @update gess 4Sep2000
* @param node to consume skipped-content
* @param holds the number of skipped content elements encountered
* @return Error condition.
*/
NS_IMETHODIMP
CNavDTD::CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLineNo) {
NS_ASSERTION(aTag >= eHTMLTag_unknown && aTag <= NS_HTML_TAG_MAX, "tag array out of bounds");
aContent.Truncate();
NS_ASSERTION(eHTMLTag_unknown != gHTMLElements[aTag].mSkipTarget, "cannot collect content for this tag");
if (eHTMLTag_unknown == gHTMLElements[aTag].mSkipTarget) {
// This tag doesn't support skipped content.
aLineNo = -1;
return NS_OK;
}
aLineNo = mLineNumber;
mScratch.Truncate();
PRInt32 i = 0;
PRInt32 tagCount = mSkippedContent.GetSize();
for (i = 0; i< tagCount; ++i){
CHTMLToken* theNextToken = (CHTMLToken*)mSkippedContent.PopFront();
if (theNextToken) {
theNextToken->AppendSourceTo(aContent);
}
IF_FREE(theNextToken, mTokenAllocator);
}
InPlaceConvertLineEndings(aContent);
// Note: TITLE content is PCDATA and hence the newlines are already accounted for.
mLineNumber += (aTag != eHTMLTag_title) ? aContent.CountChar(kNewLine) : 0;
return NS_OK;
}
/***********************************************************************************
The preceeding tables determine the set of elements each tag can contain...
***********************************************************************************/
/** /**
* This method is called to determine whether or not a tag * This method is called to determine whether or not a tag
* of one type can contain a tag of another type. * of one type can contain a tag of another type.
@ -2908,7 +2691,12 @@ nsresult CNavDTD::OpenHead(const nsIParserNode *aNode)
if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) { if (!(mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD)) {
mFlags |= NS_DTD_FLAG_HAS_OPEN_HEAD; mFlags |= NS_DTD_FLAG_HAS_OPEN_HEAD;
result = mSink ? mSink->OpenHead(*aNode) : NS_OK; if (mSink && aNode) {
result = mSink->OpenHead(*aNode);
}
else if (mSink) {
result = mSink->OpenHead();
}
} }
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenHead(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenHead(), this=%p\n", this));
@ -2965,6 +2753,10 @@ nsresult CNavDTD::OpenBody(const nsCParserNode *aNode)
STOP_TIMER(); STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenBody(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenBody(), this=%p\n", this));
// Make sure the head is closed by the time the body is opened.
CloseHead();
// Now we can open the body.
result = (mSink) ? mSink->OpenBody(*aNode) : NS_OK; result = (mSink) ? mSink->OpenBody(*aNode) : NS_OK;
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenBody(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenBody(), this=%p\n", this));
@ -3205,10 +2997,6 @@ CNavDTD::OpenContainer(const nsCParserNode *aNode,
} }
break; break;
case eHTMLTag_style:
case eHTMLTag_title:
break;
case eHTMLTag_map: case eHTMLTag_map:
result = OpenMap(aNode); result = OpenMap(aNode);
break; break;
@ -3221,10 +3009,6 @@ CNavDTD::OpenContainer(const nsCParserNode *aNode,
result = OpenFrameset(aNode); result = OpenFrameset(aNode);
break; break;
case eHTMLTag_script:
result = HandleScriptToken(aNode);
break;
case eHTMLTag_noembed: case eHTMLTag_noembed:
// <noembed> is unconditionally alternate content. // <noembed> is unconditionally alternate content.
done = PR_FALSE; done = PR_FALSE;
@ -3292,9 +3076,6 @@ CNavDTD::CloseContainer(const eHTMLTags aTag, eHTMLTags aTarget,PRBool aClosedBy
case eHTMLTag_html: case eHTMLTag_html:
result=CloseHTML(); break; result=CloseHTML(); break;
case eHTMLTag_style:
break;
case eHTMLTag_head: case eHTMLTag_head:
result=CloseHead(); result=CloseHead();
break; break;
@ -3322,12 +3103,22 @@ CNavDTD::CloseContainer(const eHTMLTags aTag, eHTMLTags aTarget,PRBool aClosedBy
// switch from alternate content state to regular state // switch from alternate content state to regular state
mFlags &= ~NS_DTD_FLAG_ALTERNATE_CONTENT; mFlags &= ~NS_DTD_FLAG_ALTERNATE_CONTENT;
// falling thro' intentionally.... // falling thro' intentionally....
case eHTMLTag_title:
default: default:
STOP_TIMER(); STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseContainer(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::CloseContainer(), this=%p\n", this));
result=(mSink) ? mSink->CloseContainer(aTag) : NS_OK; result = mSink
? mSink->CloseContainer(aTag)
: NS_OK; // XXX Can this case really happen?
// If we were dealing with a head container in the body, make sure to
// close the head context now, so that body content doesn't get sucked
// into the head.
if ((mFlags & NS_DTD_FLAG_HAD_BODY) &&
mBodyContext->GetCount() == mHeadContainerPosition) {
result = CloseHead();
mHeadContainerPosition = -1;
}
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseContainer(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::CloseContainer(), this=%p\n", this));
START_TIMER(); START_TIMER();
@ -3586,7 +3377,7 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model * @param aNode -- next node to be added to model
* @return error code; 0 means OK * @return error code; 0 means OK
*/ */
nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ nsresult CNavDTD::AddHeadContent(nsIParserNode *aNode){
nsresult result=NS_OK; nsresult result=NS_OK;
static eHTMLTags gNoXTags[] = {eHTMLTag_noembed,eHTMLTag_noframes}; static eHTMLTags gNoXTags[] = {eHTMLTag_noembed,eHTMLTag_noframes};
@ -3604,11 +3395,35 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){
if (mSink) { if (mSink) {
STOP_TIMER(); STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddHeadLeaf(), this=%p\n", this)); MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddHeadContent(), this=%p\n", this));
result = mSink->AddHeadContent(*aNode); // Make sure the head is opened. This might just be a no-op.
result = OpenHead(nsnull);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddHeadLeaf(), this=%p\n", this));
// Note: userdefined tags in the head are treated as leaves.
if (!nsHTMLElement::IsContainer(theTag) || theTag == eHTMLTag_userdefined) {
result = mSink->AddLeaf(*aNode);
if (mFlags & NS_DTD_FLAG_HAD_BODY) {
// Close the head now so that body content doesn't get sucked into it.
CloseHead();
}
}
else {
if ((mFlags & NS_DTD_FLAG_HAD_BODY) && mHeadContainerPosition == -1) {
// Keep track of this so that we know when to close the head, when
// this tag is done with.
mHeadContainerPosition = mBodyContext->GetCount();
}
mBodyContext->Push(NS_STATIC_CAST(nsCParserNode*, aNode), nsnull,
PR_FALSE);
// Note: The head context is already opened.
result = mSink->OpenContainer(*aNode);
}
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddHeadContent(), this=%p\n", this));
START_TIMER(); START_TIMER();
} }
return result; return result;

Просмотреть файл

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=2 ts=2 et tw=78: */
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@ -271,7 +272,6 @@ public:
nsresult HandleEntityToken(CToken* aToken); nsresult HandleEntityToken(CToken* aToken);
nsresult HandleCommentToken(CToken* aToken); nsresult HandleCommentToken(CToken* aToken);
nsresult HandleAttributeToken(CToken* aToken); nsresult HandleAttributeToken(CToken* aToken);
nsresult HandleScriptToken(const nsIParserNode *aNode);
nsresult HandleProcessingInstructionToken(CToken* aToken); nsresult HandleProcessingInstructionToken(CToken* aToken);
nsresult HandleDocTypeDeclToken(CToken* aToken); nsresult HandleDocTypeDeclToken(CToken* aToken);
nsresult BuildNeglectedTarget(eHTMLTags aTarget, eHTMLTokenTypes aType, nsresult BuildNeglectedTarget(eHTMLTags aTarget, eHTMLTokenTypes aType,
@ -337,7 +337,7 @@ public:
* @return error code - 0 if all went well. * @return error code - 0 if all went well.
*/ */
nsresult AddLeaf(const nsIParserNode *aNode); nsresult AddLeaf(const nsIParserNode *aNode);
nsresult AddHeadLeaf(nsIParserNode *aNode); nsresult AddHeadContent(nsIParserNode *aNode);
/** /**
* This set of methods is used to create and manage the set of * This set of methods is used to create and manage the set of
@ -365,7 +365,6 @@ public:
protected: protected:
nsresult CollectAttributes(nsIParserNode* aNode,eHTMLTags aTag,PRInt32 aCount); nsresult CollectAttributes(nsIParserNode* aNode,eHTMLTags aTag,PRInt32 aCount);
nsresult CollectSkippedContent(nsIParserNode& aNode,PRInt32& aCount);
nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode);
nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag); nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag);
nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode); nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode);
@ -376,7 +375,6 @@ protected:
PRBool IsInlineElement(PRInt32 aTagID, PRInt32 aParentID) const; PRBool IsInlineElement(PRInt32 aTagID, PRInt32 aParentID) const;
nsDeque mMisplacedContent; nsDeque mMisplacedContent;
nsDeque mSkippedContent;
nsIHTMLContentSink* mSink; nsIHTMLContentSink* mSink;
nsTokenAllocator* mTokenAllocator; nsTokenAllocator* mTokenAllocator;
@ -394,9 +392,9 @@ protected:
eParserDocType mDocType; eParserDocType mDocType;
eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors... eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors...
eHTMLTags mSkipTarget;
PRInt32 mLineNumber; PRInt32 mLineNumber;
PRInt32 mOpenMapCount; PRInt32 mOpenMapCount;
PRInt32 mHeadContainerPosition;
PRUint16 mFlags; PRUint16 mFlags;
}; };

Просмотреть файл

@ -291,6 +291,9 @@ nsCParserNode* nsEntryStack::Pop(void)
// XXX If this NS_ENSURE_TRUE fails, it means that the style stack was // XXX If this NS_ENSURE_TRUE fails, it means that the style stack was
// empty before we were removed. // empty before we were removed.
#ifdef DEBUG_mrbkap
NS_ASSERTION(scount != 0, "preventing a potential crash.");
#endif
NS_ENSURE_TRUE(scount != 0, result); NS_ENSURE_TRUE(scount != 0, result);
PRUint32 sindex = 0; PRUint32 sindex = 0;

Просмотреть файл

@ -194,12 +194,6 @@ const nsHTMLElement gHTMLElements[] = {
/*contain-func*/ 0 /*contain-func*/ 0
}, },
{ {
/*************************************************
Note: I changed A to contain flow elements
since it's such a popular (but illegal)
idiom.
*************************************************/
/*tag*/ eHTMLTag_a, /*tag*/ eHTMLTag_a,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown, /*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags, /*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
@ -905,7 +899,7 @@ const nsHTMLElement gHTMLElements[] = {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown, /*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags, /*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0, /*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kSpecial, (kFlowEntity|kInlineEntity|kSelf), kNone, // XXX should have a kHeadMisc parent too /*parent,incl,exclgroups*/ kSpecial|kHeadMisc, (kFlowEntity|kSelf), kNone,
/*special props, prop-range*/ kNoStyleLeaksOut,kDefaultPropRange, /*special props, prop-range*/ kNoStyleLeaksOut,kDefaultPropRange,
/*special parents,kids,skip*/ 0,&gContainsParam,eHTMLTag_unknown, /*special parents,kids,skip*/ 0,&gContainsParam,eHTMLTag_unknown,
/*contain-func*/ 0 /*contain-func*/ 0
@ -1017,7 +1011,7 @@ const nsHTMLElement gHTMLElements[] = {
/*autoclose starttags and endtags*/ 0,0,0,0, /*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ (kSpecial|kHeadContent), kCDATA, kNone, // note: this is kHeadContent since shipping this breaks things. /*parent,incl,exclgroups*/ (kSpecial|kHeadContent), kCDATA, kNone, // note: this is kHeadContent since shipping this breaks things.
/*special props, prop-range*/ kNoStyleLeaksIn|kLegalOpen, kNoPropRange, /*special props, prop-range*/ kNoStyleLeaksIn|kLegalOpen, kNoPropRange,
/*special parents,kids,skip*/ 0,&gContainsText,eHTMLTag_script, /*special parents,kids,skip*/ 0,&gContainsText,eHTMLTag_unknown,
/*contain-func*/ 0 /*contain-func*/ 0
}, },
{ {
@ -1037,7 +1031,7 @@ const nsHTMLElement gHTMLElements[] = {
/*autoclose starttags and endtags*/ 0,0,0,0, /*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ (kSpecial|kHeadMisc), kCDATA, kNone, /*parent,incl,exclgroups*/ (kSpecial|kHeadMisc), kCDATA, kNone,
/*special props, prop-range*/ (kNoStyleLeaksIn|kLegalOpen), kNoPropRange, /*special props, prop-range*/ (kNoStyleLeaksIn|kLegalOpen), kNoPropRange,
/*special parents,kids,skip*/ 0,&gContainsText,eHTMLTag_server, /*special parents,kids,skip*/ 0,&gContainsText,eHTMLTag_unknown,
/*contain-func*/ 0 /*contain-func*/ 0
}, },
{ {
@ -1115,8 +1109,8 @@ const nsHTMLElement gHTMLElements[] = {
/*rootnodes,endrootnodes*/ &gInHead,&gInHead, /*rootnodes,endrootnodes*/ &gInHead,&gInHead,
/*autoclose starttags and endtags*/ 0,0,0,0, /*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadContent, kCDATA, kNone, /*parent,incl,exclgroups*/ kHeadContent, kCDATA, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn|kNonContainer, kNoPropRange, /*special props, prop-range*/ kNoStyleLeaksIn, kNoPropRange,
/*special parents,kids,skip*/ &gInHead,0,eHTMLTag_style, /*special parents,kids,skip*/ &gInHead,0,eHTMLTag_unknown,
/*contain-func*/ 0 /*contain-func*/ 0
}, },
{ {
@ -1217,7 +1211,7 @@ const nsHTMLElement gHTMLElements[] = {
/*autoclose starttags and endtags*/ 0,0,0,0, /*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadContent,kPCDATA, kNone, /*parent,incl,exclgroups*/ kHeadContent,kPCDATA, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn, kNoPropRange, /*special props, prop-range*/ kNoStyleLeaksIn, kNoPropRange,
/*special parents,kids,skip*/ &gInHead,&gContainsText,eHTMLTag_title, /*special parents,kids,skip*/ &gInHead,&gContainsText,eHTMLTag_unknown,
/*contain-func*/ 0 /*contain-func*/ 0
}, },
{ {

Просмотреть файл

@ -1155,13 +1155,6 @@ nsExpatDriver::GetType()
/*************************** Unused methods **********************************/ /*************************** Unused methods **********************************/
NS_IMETHODIMP
nsExpatDriver::CollectSkippedContent(PRInt32 aTag, nsAString& aContent,
PRInt32 &aLineNo)
{
return NS_OK;
}
NS_IMETHODIMP_(CToken*) NS_IMETHODIMP_(CToken*)
nsExpatDriver::PushTokenFront(CToken* aToken) nsExpatDriver::PushTokenFront(CToken* aToken)
{ {

Просмотреть файл

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 et tw=78: */
/* ***** BEGIN LICENSE BLOCK ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@ -47,16 +48,6 @@ static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kILoggingSinkIID, NS_ILOGGING_SINK_IID); static NS_DEFINE_IID(kILoggingSinkIID, NS_ILOGGING_SINK_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
// list of tags that have skipped content
static const char gSkippedContentTags[] = {
eHTMLTag_style,
eHTMLTag_script,
eHTMLTag_server,
eHTMLTag_title,
0
};
nsresult nsresult
NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult) NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult)
{ {
@ -73,7 +64,7 @@ NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult)
nsLoggingSink::nsLoggingSink() { nsLoggingSink::nsLoggingSink() {
mOutput = 0; mOutput = 0;
mLevel=-1; mLevel=-1;
mSink=0; mSink=0;
mParser=0; mParser=0;
} }
@ -244,36 +235,6 @@ nsLoggingSink::CloseContainer(const nsHTMLTag aTag) {
} }
NS_IMETHODIMP
nsLoggingSink::AddHeadContent(const nsIParserNode& aNode) {
eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
if (type == eHTMLTag_title) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsString theString;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(type, theString, lineNo);
SetTitle(theString);
}
else {
LeafNode(aNode);
}
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->AddHeadContent(aNode);
}
return theResult;
}
NS_IMETHODIMP NS_IMETHODIMP
nsLoggingSink::AddLeaf(const nsIParserNode& aNode) { nsLoggingSink::AddLeaf(const nsIParserNode& aNode) {
LeafNode(aNode); LeafNode(aNode);
@ -365,31 +326,6 @@ nsLoggingSink::AddComment(const nsIParserNode& aNode){
} }
NS_IMETHODIMP
nsLoggingSink::SetTitle(const nsString& aValue) {
char* tmp = nsnull;
GetNewCString(aValue, &tmp);
WriteTabs(mOutput,++mLevel);
if(tmp) {
PR_fprintf(mOutput, "<title value=\"%s\"/>\n", tmp);
nsMemory::Free(tmp);
}
--mLevel;
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->SetTitle(aValue);
}
return theResult;
}
NS_IMETHODIMP NS_IMETHODIMP
nsLoggingSink::OpenHTML(const nsIParserNode& aNode) { nsLoggingSink::OpenHTML(const nsIParserNode& aNode) {
OpenNode("html", aNode); OpenNode("html", aNode);
@ -434,6 +370,21 @@ nsLoggingSink::OpenHead(const nsIParserNode& aNode) {
return theResult; return theResult;
} }
NS_IMETHODIMP
nsLoggingSink::OpenHead() {
WriteTabs(mOutput,++mLevel);
PR_fprintf(mOutput,"<open container=head>\n");
nsresult theResult=NS_OK;
//then proxy the call to the real sink if you have one.
if(mSink) {
theResult=mSink->OpenHead();
}
return theResult;
}
NS_IMETHODIMP NS_IMETHODIMP
nsLoggingSink::CloseHead() { nsLoggingSink::CloseHead() {
CloseNode("head"); CloseNode("head");
@ -645,23 +596,6 @@ nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) {
} }
} }
if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsString theString;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(aNode.GetNodeType(), theString, lineNo);
char* content = nsnull;
GetNewCString(theString, &content);
if(content) {
PR_fprintf(mOutput, " <content value=\"");
PR_fprintf(mOutput, "%s\"/>\n", content) ;
nsMemory::Free(content);
}
}
WriteTabs(mOutput,1+mLevel); WriteTabs(mOutput,1+mLevel);
return NS_OK; return NS_OK;
} }
@ -673,43 +607,31 @@ nsLoggingSink::WillWriteAttributes(const nsIParserNode& aNode)
if (0 != ac) { if (0 != ac) {
return PR_TRUE; return PR_TRUE;
} }
if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE);
nsString content;
PRInt32 lineNo = 0;
dtd->CollectSkippedContent(aNode.GetNodeType(), content, lineNo);
if (!content.IsEmpty()) {
return PR_TRUE;
}
}
return PR_FALSE; return PR_FALSE;
} }
nsresult nsresult
nsLoggingSink::LeafNode(const nsIParserNode& aNode) nsLoggingSink::LeafNode(const nsIParserNode& aNode)
{ {
WriteTabs(mOutput,1+mLevel); WriteTabs(mOutput,1+mLevel);
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if ((nodeType >= eHTMLTag_unknown) && if ((nodeType >= eHTMLTag_unknown) &&
(nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) { (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) {
const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType); const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType);
if(tag) if(tag)
PR_fprintf(mOutput, "<leaf tag=\"%s\"", NS_ConvertUCS2toUTF8(tag).get()); PR_fprintf(mOutput, "<leaf tag=\"%s\"", NS_ConvertUCS2toUTF8(tag).get());
else PR_fprintf(mOutput, "<leaf tag=\"???\""); else
PR_fprintf(mOutput, "<leaf tag=\"???\"");
if (WillWriteAttributes(aNode)) { if (WillWriteAttributes(aNode)) {
PR_fprintf(mOutput, ">\n"); PR_fprintf(mOutput, ">\n");
WriteAttributes(aNode); WriteAttributes(aNode);
PR_fprintf(mOutput, "</leaf>\n"); PR_fprintf(mOutput, "</leaf>\n");
} }
else { else {
PR_fprintf(mOutput, "/>\n"); PR_fprintf(mOutput, "/>\n");
} }
} }
else { else {
@ -717,32 +639,32 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode)
nsAutoString tmp; nsAutoString tmp;
char* str = nsnull; char* str = nsnull;
switch (nodeType) { switch (nodeType) {
case eHTMLTag_whitespace: case eHTMLTag_whitespace:
case eHTMLTag_text: case eHTMLTag_text:
GetNewCString(aNode.GetText(), &str); GetNewCString(aNode.GetText(), &str);
if(str) { if(str) {
PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str); PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str);
nsMemory::Free(str); nsMemory::Free(str);
} }
break; break;
case eHTMLTag_newline: case eHTMLTag_newline:
PR_fprintf(mOutput, "<newline/>\n"); PR_fprintf(mOutput, "<newline/>\n");
break; break;
case eHTMLTag_entity: case eHTMLTag_entity:
tmp.Append(aNode.GetText()); tmp.Append(aNode.GetText());
tmp.Cut(0, 1); tmp.Cut(0, 1);
pos = tmp.Length() - 1; pos = tmp.Length() - 1;
if (pos >= 0) { if (pos >= 0) {
tmp.Cut(pos, 1); tmp.Cut(pos, 1);
} }
PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", NS_LossyConvertUCS2toASCII(tmp).get()); PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", NS_LossyConvertUCS2toASCII(tmp).get());
break; break;
default: default:
NS_NOTREACHED("unsupported leaf node type"); NS_NOTREACHED("unsupported leaf node type");
}//switch }//switch
} }
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -67,7 +67,6 @@ public:
NS_IMETHOD SetParser(nsIParser* aParser); NS_IMETHOD SetParser(nsIParser* aParser);
NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag); NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddHeadContent(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode);
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
@ -77,10 +76,10 @@ public:
virtual nsISupports *GetTarget() { return nsnull; } virtual nsISupports *GetTarget() { return nsnull; }
// nsIHTMLContentSink // nsIHTMLContentSink
NS_IMETHOD SetTitle(const nsString& aValue);
NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD OpenHTML(const nsIParserNode& aNode);
NS_IMETHOD CloseHTML(); NS_IMETHOD CloseHTML();
NS_IMETHOD OpenHead(const nsIParserNode& aNode); NS_IMETHOD OpenHead(const nsIParserNode& aNode);
NS_IMETHOD OpenHead();
NS_IMETHOD CloseHead(); NS_IMETHOD CloseHead();
NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD OpenBody(const nsIParserNode& aNode);
NS_IMETHOD CloseBody(); NS_IMETHOD CloseBody();
@ -116,10 +115,10 @@ public:
protected: protected:
PRFileDesc *mOutput; PRFileDesc *mOutput;
int mLevel; int mLevel;
nsIHTMLContentSink *mSink; nsIHTMLContentSink *mSink;
PRBool mAutoDeleteOutput; PRBool mAutoDeleteOutput;
nsIParser* mParser; nsIParser* mParser;
}; };
#endif #endif

Просмотреть файл

@ -74,13 +74,14 @@ nsresult ParseData(char* anInputStream,char* anOutputStream) {
return result; return result;
} }
PRFileDesc* in = PR_Open(anInputStream, PR_RDONLY, 777); PRFileDesc* in = PR_Open(anInputStream, PR_RDONLY, 0777);
if (!in) { if (!in) {
printf("\nUnable to open input file - %s\n", anInputStream); printf("\nUnable to open input file - %s\n", anInputStream);
return result; return result;
} }
PRFileDesc* out = PR_Open(anOutputStream, PR_CREATE_FILE|PR_WRONLY, 777); PRFileDesc* out = PR_Open(anOutputStream,
PR_CREATE_FILE|PR_TRUNCATE|PR_RDWR, 0777);
if (!out) { if (!out) {
printf("\nUnable to open output file - %s\n", anOutputStream); printf("\nUnable to open output file - %s\n", anOutputStream);
return result; return result;