diff --git a/mozilla/content/base/src/mozSanitizingSerializer.cpp b/mozilla/content/base/src/mozSanitizingSerializer.cpp index a69b159ed29..97e84a3bd20 100644 --- a/mozilla/content/base/src/mozSanitizingSerializer.cpp +++ b/mozilla/content/base/src/mozSanitizingSerializer.cpp @@ -304,43 +304,9 @@ mozSanitizingHTMLSerializer::OpenContainer(const nsIParserNode& aNode) NS_IMETHODIMP mozSanitizingHTMLSerializer::CloseContainer(const nsHTMLTag aTag) { - // XXX Why do we need this? - // mParserNode = NS_CONST_CAST(nsIParserNode*, &aNode); 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 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 mozSanitizingHTMLSerializer::AddLeaf(const nsIParserNode& aNode) { @@ -403,6 +369,14 @@ mozSanitizingHTMLSerializer::OpenHead(const nsIParserNode& 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 mozSanitizingHTMLSerializer::CloseHead() { @@ -559,36 +533,6 @@ mozSanitizingHTMLSerializer::DoAddLeaf(PRInt32 aTag, // using + operator here might give an infinitive loop, see above. // 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 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 { DoOpenContainer(type); diff --git a/mozilla/content/base/src/mozSanitizingSerializer.h b/mozilla/content/base/src/mozSanitizingSerializer.h index dea21c726ce..4d61821763f 100644 --- a/mozilla/content/base/src/mozSanitizingSerializer.h +++ b/mozilla/content/base/src/mozSanitizingSerializer.h @@ -93,14 +93,12 @@ public: // nsIContentSink NS_IMETHOD WillBuildModel(void) { return NS_OK; } - NS_IMETHOD DidBuildModel(void) - { nsCOMPtr temp(mParser); mParser = nsnull; return NS_OK; } + NS_IMETHOD DidBuildModel(void) { return NS_OK; } NS_IMETHOD WillInterrupt(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 CloseContainer(const nsHTMLTag aTag); - NS_IMETHOD AddHeadContent(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode) { return NS_OK; } NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode) @@ -114,6 +112,7 @@ public: NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD CloseHTML(); NS_IMETHOD OpenHead(const nsIParserNode& aNode); + NS_IMETHOD OpenHead(); NS_IMETHOD CloseHead(); NS_IMETHOD SetTitle(const nsString& aValue); NS_IMETHOD OpenBody(const nsIParserNode& aNode); @@ -162,7 +161,6 @@ protected: nsAString* mOutputString; nsIParserNode* mParserNode; nsCOMPtr mParserService; - nsCOMPtr mParser; }; nsresult diff --git a/mozilla/content/base/src/nsPlainTextSerializer.cpp b/mozilla/content/base/src/nsPlainTextSerializer.cpp index 3d8f0e9cbbb..2f550515f89 100644 --- a/mozilla/content/base/src/nsPlainTextSerializer.cpp +++ b/mozilla/content/base/src/nsPlainTextSerializer.cpp @@ -468,19 +468,6 @@ nsPlainTextSerializer::CloseContainer(const nsHTMLTag 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 nsPlainTextSerializer::AddLeaf(const nsIParserNode& aNode) { @@ -527,6 +514,13 @@ nsPlainTextSerializer::OpenHead(const nsIParserNode& aNode) return NS_OK; } +NS_IMETHODIMP +nsPlainTextSerializer::OpenHead() +{ + mInHead = PR_TRUE; + return NS_OK; +} + NS_IMETHODIMP nsPlainTextSerializer::CloseHead() { diff --git a/mozilla/content/base/src/nsPlainTextSerializer.h b/mozilla/content/base/src/nsPlainTextSerializer.h index e8b1a7fb138..06ae5940c23 100644 --- a/mozilla/content/base/src/nsPlainTextSerializer.h +++ b/mozilla/content/base/src/nsPlainTextSerializer.h @@ -96,7 +96,6 @@ public: NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; } NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); - NS_IMETHOD AddHeadContent(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddComment(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; } // nsIHTMLContentSink - NS_IMETHOD SetTitle(const nsString& aValue) { return NS_OK; } NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD CloseHTML(); NS_IMETHOD OpenHead(const nsIParserNode& aNode); + NS_IMETHOD OpenHead(); NS_IMETHOD CloseHead(); NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD CloseBody(); diff --git a/mozilla/content/html/content/src/nsHTMLScriptElement.cpp b/mozilla/content/html/content/src/nsHTMLScriptElement.cpp index 173b6ffb043..9a4eab18260 100644 --- a/mozilla/content/html/content/src/nsHTMLScriptElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLScriptElement.cpp @@ -309,7 +309,7 @@ class nsHTMLScriptElement : public nsGenericHTMLElement, public nsIScriptElement { public: - nsHTMLScriptElement(nsINodeInfo *aNodeInfo); + nsHTMLScriptElement(nsINodeInfo *aNodeInfo, PRBool aFromParser); virtual ~nsHTMLScriptElement(); // nsISupports @@ -357,6 +357,8 @@ public: virtual nsresult GetInnerHTML(nsAString& aInnerHTML); virtual nsresult SetInnerHTML(const nsAString& aInnerHTML); + virtual void DoneAddingChildren(); + virtual PRBool IsDoneAddingChildren(); protected: PRBool IsOnloadEventForWindow(); @@ -364,6 +366,7 @@ protected: PRUint32 mLineNumber; PRPackedBool mIsEvaluated; PRPackedBool mEvaluating; + PRPackedBool mDoneAddingChildren; // Pointer to the script handler helper object (OWNING reference) 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) - : nsGenericHTMLElement(aNodeInfo) +nsHTMLScriptElement::nsHTMLScriptElement(nsINodeInfo *aNodeInfo, + PRBool aFromParser) + : nsGenericHTMLElement(aNodeInfo), + mDoneAddingChildren(!aFromParser) { mLineNumber = 0; mIsEvaluated = PR_FALSE; @@ -484,7 +489,7 @@ nsHTMLScriptElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { *aReturn = nsnull; - nsHTMLScriptElement* it = new nsHTMLScriptElement(mNodeInfo); + nsHTMLScriptElement* it = new nsHTMLScriptElement(mNodeInfo, PR_FALSE); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -538,6 +543,19 @@ nsHTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML) 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 // need to be transfered when modifying @@ -646,7 +664,7 @@ nsHTMLScriptElement::GetScriptLineNumber() void nsHTMLScriptElement::MaybeProcessScript() { - if (mIsEvaluated || mEvaluating || !IsInDoc()) { + if (mIsEvaluated || mEvaluating || !mDoneAddingChildren || !IsInDoc()) { return; } diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index f6795dbf058..3126184ed62 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -1,4 +1,5 @@ /* -*- 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 ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -235,7 +236,6 @@ public: // nsIHTMLContentSink NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); - NS_IMETHOD AddHeadContent(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode); NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); @@ -247,10 +247,10 @@ public: NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode); NS_IMETHOD BeginContext(PRInt32 aID); NS_IMETHOD EndContext(PRInt32 aID); - NS_IMETHOD SetTitle(const nsString& aValue); NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD CloseHTML(); NS_IMETHOD OpenHead(const nsIParserNode& aNode); + NS_IMETHOD OpenHead(); NS_IMETHOD CloseHead(); NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD CloseBody(); @@ -278,7 +278,7 @@ public: protected: PRBool IsTimeToNotify(); - nsresult SetDocumentTitle(const nsAString& aTitle, const nsIParserNode* aNode); + nsresult UpdateDocumentTitle(); // If aCheckIfPresent is true, will only set an attribute in cases // when it's not already set. nsresult AddAttributes(const nsIParserNode& aNode, nsIContent* aContent, @@ -337,14 +337,14 @@ protected: nsGenericHTMLElement* mFrameset; nsGenericHTMLElement* mHead; - nsString mSkippedContent; - // Do we notify based on time? PRPackedBool mNotifyOnTimer; PRPackedBool mLayoutStarted; PRPackedBool mScrolledToRefAlready; + PRPackedBool mInTitle; + nsString mTitleString; PRInt32 mInNotification; nsRefPtr mCurrentForm; nsCOMPtr mCurrentMap; @@ -407,8 +407,11 @@ protected: nsresult ProcessLINKTag(const nsIParserNode& aNode); nsresult ProcessMAPTag(nsIContent* aContent); 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 CloseHeadContext(); @@ -466,7 +469,7 @@ public: NS_DECL_ISUPPORTS - // nsIRequest + // nsIRequest NS_IMETHOD GetName(nsACString &result) { result.AssignLiteral("about:layout-dummy-request"); @@ -523,7 +526,7 @@ public: return NS_OK; } - // nsIChannel + // nsIChannel NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI) { *aOriginalURI = gURI; @@ -1167,6 +1170,25 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) mStack[mStackPos].mNumFlushed = 0; mStack[mStackPos].mInsertionPoint = -1; + // XXX Need to do this before we start adding attributes. + if (nodeType == eHTMLTag_style) { + nsCOMPtr 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 // attributes -- what URI attrs do will depend on the base URI. Only do this // for elements that have useful URI attributes. @@ -1175,6 +1197,9 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) // Containers with "href=" case eHTMLTag_a: case eHTMLTag_map: + + // Containers with "src=" + case eHTMLTag_script: // Containers with "action=" case eHTMLTag_form: @@ -1228,16 +1253,31 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) case eHTMLTag_noembed: case eHTMLTag_noframes: mSink->mInsideNoXXXTag++; - break; case eHTMLTag_map: mSink->ProcessMAPTag(content); break; + case eHTMLTag_iframe: mSink->mNumOpenIFRAMES++; - break; + + case eHTMLTag_script: + { + nsCOMPtr 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: break; } @@ -1340,8 +1380,23 @@ SinkContext::CloseContainer(const nsHTMLTag aTag) case eHTMLTag_object: case eHTMLTag_applet: content->DoneAddingChildren(); - 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: break; } @@ -1586,6 +1641,11 @@ SinkContext::AddText(const nsAString& aText) if (addLen == 0) { return NS_OK; } + + if (mSink->mInTitle) { + // Hang onto the title text specially. + mSink->mTitleString.Append(aText); + } // Create buffer when we first need it if (mTextSize == 0) { @@ -2458,25 +2518,6 @@ HTMLContentSink::EndContext(PRInt32 aPosition) 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 HTMLContentSink::OpenHTML(const nsIParserNode& aNode) { @@ -2532,7 +2573,7 @@ HTMLContentSink::CloseHTML() NS_IMETHODIMP HTMLContentSink::OpenHead(const nsIParserNode& aNode) { - MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::OpenHead()\n")); + MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::OpenHead(nsIParserNode)\n")); MOZ_TIMER_START(mWatch); SINK_TRACE_NODE(SINK_TRACE_CALLS, "HTMLContentSink::OpenHead", @@ -2540,7 +2581,7 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode) nsresult rv = OpenHeadContext(); if (NS_FAILED(rv)) { - MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::OpenHead()\n")); + MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::OpenHead(nsIParserNode)\n")); MOZ_TIMER_STOP(mWatch); return rv; } @@ -2555,6 +2596,20 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode) 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 HTMLContentSink::CloseHead() { @@ -2917,37 +2972,6 @@ HTMLContentSink::CloseContainer(const eHTMLTags aTag) 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 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 HTMLContentSink::AddLeaf(const nsIParserNode& aNode) { @@ -2976,16 +3000,6 @@ HTMLContentSink::AddLeaf(const nsIParserNode& aNode) mCurrentContext->FlushTextAndRelease(); rv = ProcessMETATag(aNode); - break; - case eHTMLTag_style: - mCurrentContext->FlushTextAndRelease(); - rv = ProcessSTYLETag(aNode); - - break; - case eHTMLTag_script: - mCurrentContext->FlushTextAndRelease(); - rv = ProcessSCRIPTTag(aNode); - break; default: rv = mCurrentContext->AddLeaf(aNode); @@ -3000,53 +3014,27 @@ HTMLContentSink::AddLeaf(const nsIParserNode& aNode) } 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); NS_ASSERTION(mCurrentContext == mHeadContext, "title not in head"); if (!mDocument->GetDocumentTitle().IsVoid()) { - // If the title was already set then don't try to overwrite it - // when a new title is encountered - For backwards compatiblity - MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::SetDocumentTitle()\n")); + MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::UpdateDocumentTitle()\n")); MOZ_TIMER_STOP(mWatch); - return NS_OK; } - nsAutoString title(aTitle); - title.CompressWhitespace(PR_TRUE, PR_TRUE); + // Use mTitleString. + mTitleString.CompressWhitespace(PR_TRUE, PR_TRUE); nsCOMPtr domDoc(do_QueryInterface(mDocument)); - domDoc->SetTitle(title); + domDoc->SetTitle(mTitleString); - nsCOMPtr nodeInfo; - nsresult rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::title, nsnull, - kNameSpaceID_None, - getter_AddRefs(nodeInfo)); - NS_ENSURE_SUCCESS(rv, rv); + mTitleString.Truncate(); - nsRefPtr it = NS_NewHTMLTitleElement(nodeInfo); - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } - - if (aNode) { - AddAttributes(*aNode, it); - } - - nsCOMPtr 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_DEBUGLOG(("Stop: nsHTMLContentSink::UpdateDocumentTitle()\n")); MOZ_TIMER_STOP(mWatch); return NS_OK; @@ -4010,67 +3998,13 @@ HTMLContentSink::PostEvaluateScript() } nsresult -HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) +HTMLContentSink::ProcessSCRIPTEndTag(nsGenericHTMLElement *content) { - nsresult rv = NS_OK; + nsCOMPtr 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 parent = mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent; - nsCOMPtr element; - nsCOMPtr 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 dtd; - mParser->GetDTD(getter_AddRefs(dtd)); - NS_ENSURE_TRUE(dtd, NS_ERROR_FAILURE); - - nsCOMPtr 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 text; - rv = NS_NewTextNode(getter_AddRefs(text)); - NS_ENSURE_SUCCESS(rv, rv); - - text->SetText(script, PR_TRUE); - - element->AppendChildTo(text, PR_FALSE); - } nsCOMPtr loader; if (mFrameset) { @@ -4089,7 +4023,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) // Don't include script loading and evaluation in the stopwatch // that is measuring content creation time - MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::ProcessSCRIPTTag()\n")); + MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::ProcessSCRIPTEndTag()\n")); MOZ_TIMER_STOP(mWatch); // 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); } - // Now flush out tags so that the script will actually be bound to a - // document and will evaluate as soon as it's appended. - SINK_TRACE(SINK_TRACE_CALLS, - ("HTMLContentSink::ProcessSCRIPTTag: flushing tags before " - "appending script")); - mCurrentContext->FlushTags(PR_FALSE); + // Now tell the script that it's ready to go. This will execute the script + // and call our ScriptAvailable method. + content->DoneAddingChildren(); - // 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 // the script loader. Now that the script content has been handled, // 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? nsresult -HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode) +HTMLContentSink::ProcessSTYLEEndTag(nsGenericHTMLElement* content) { - nsresult rv = NS_OK; - nsGenericHTMLElement* parent = nsnull; - - if (mCurrentContext) { - parent = mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent; - } - - if (!parent) { - return NS_OK; - } - - // Create content object - nsCOMPtr nodeInfo; - mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::style, nsnull, kNameSpaceID_None, - getter_AddRefs(nodeInfo)); - - nsCOMPtr element; - rv = NS_NewHTMLElement(getter_AddRefs(element), nodeInfo); - NS_ENSURE_SUCCESS(rv, rv); - - element->SetContentID(mDocument->GetAndIncrementContentID()); - - nsCOMPtr ssle = do_QueryInterface(element); + nsCOMPtr ssle = do_QueryInterface(content); NS_ASSERTION(ssle, "html:style doesn't implement nsIStyleSheetLinkingElement"); - if (ssle) { - // 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 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 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); + nsresult rv = NS_OK; 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); rv = ssle->UpdateStyleSheet(nsnull, nsnull); } diff --git a/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp b/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp index 29dd643d58f..c6abc305d8b 100644 --- a/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLFragmentContentSink.cpp @@ -90,10 +90,10 @@ public: // nsIHTMLContentSink NS_IMETHOD BeginContext(PRInt32 aID); NS_IMETHOD EndContext(PRInt32 aID); - NS_IMETHOD SetTitle(const nsString& aValue); NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD CloseHTML(); NS_IMETHOD OpenHead(const nsIParserNode& aNode); + NS_IMETHOD OpenHead(); NS_IMETHOD CloseHead(); NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD CloseBody(); @@ -115,7 +115,6 @@ public: NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; } NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); - NS_IMETHOD AddHeadContent(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode); NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); @@ -143,7 +142,6 @@ public: void AddBaseTagInfo(nsIContent* aContent); nsresult Init(); - nsresult SetDocumentTitle(const nsAString& aString, const nsIParserNode* aNode); PRPackedBool mAllContent; PRPackedBool mProcessing; @@ -299,12 +297,6 @@ nsHTMLFragmentContentSink::EndContext(PRInt32 aID) return NS_OK; } -NS_IMETHODIMP -nsHTMLFragmentContentSink::SetTitle(const nsString& aValue) -{ - return SetDocumentTitle(aValue, nsnull); -} - NS_IMETHODIMP nsHTMLFragmentContentSink::OpenHTML(const nsIParserNode& aNode) { @@ -323,6 +315,14 @@ nsHTMLFragmentContentSink::OpenHead(const nsIParserNode& 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 nsHTMLFragmentContentSink::CloseHead() { @@ -338,9 +338,8 @@ nsHTMLFragmentContentSink::OpenBody(const nsIParserNode& aNode) mSeenBody = PR_TRUE; return OpenContainer(aNode); } - else { - return NS_OK; - } + + return NS_OK; } 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 nodeInfo; - nsresult rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::title, nsnull, - kNameSpaceID_None, - getter_AddRefs(nodeInfo)); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr 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 nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode) { @@ -520,28 +489,9 @@ nsHTMLFragmentContentSink::CloseContainer(const nsHTMLTag aTag) return NS_OK; } -NS_IMETHODIMP -nsHTMLFragmentContentSink::AddHeadContent(const nsIParserNode& aNode) -{ - return AddLeaf(aNode); -} - NS_IMETHODIMP nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode) { - if (eHTMLTag_title == aNode.GetNodeType()) { - nsCOMPtr 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); nsresult result = NS_OK; @@ -594,22 +544,7 @@ nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode) } } - if(nodeType == eHTMLTag_script || - nodeType == eHTMLTag_style || - nodeType == eHTMLTag_server) { - - // Create a text node holding the content - nsCOMPtr 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 + if (nodeType == eHTMLTag_img || nodeType == eHTMLTag_frame || nodeType == eHTMLTag_input) // elements with 'SRC=' AddBaseTagInfo(content); else if (nodeType == eHTMLTag_base) diff --git a/mozilla/parser/htmlparser/public/nsIDTD.h b/mozilla/parser/htmlparser/public/nsIDTD.h index b620488bb17..dedd13cda50 100644 --- a/mozilla/parser/htmlparser/public/nsIDTD.h +++ b/mozilla/parser/htmlparser/public/nsIDTD.h @@ -59,7 +59,9 @@ #include "nsITokenizer.h" #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 { eUnknownDetect, @@ -200,8 +202,6 @@ public: NS_IMETHOD_(void) Terminate() = 0; NS_IMETHOD_(PRInt32) GetType() = 0; - - NS_IMETHOD CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLineNo) = 0; }; #define NS_DECL_NSIDTD \ @@ -216,7 +216,6 @@ public: NS_IMETHOD WillInterruptParse(nsIContentSink* aSink = 0);\ NS_IMETHOD_(PRBool) CanContain(PRInt32 aParent,PRInt32 aChild) const;\ NS_IMETHOD_(PRBool) IsContainer(PRInt32 aTag) const;\ - NS_IMETHOD CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLineNo);\ NS_IMETHOD_(void) Terminate();\ NS_IMETHOD_(PRInt32) GetType(); #endif /* nsIDTD_h___ */ diff --git a/mozilla/parser/htmlparser/public/nsIHTMLContentSink.h b/mozilla/parser/htmlparser/public/nsIHTMLContentSink.h index d36252f679f..a95b09e1cb4 100644 --- a/mozilla/parser/htmlparser/public/nsIHTMLContentSink.h +++ b/mozilla/parser/htmlparser/public/nsIHTMLContentSink.h @@ -38,9 +38,6 @@ #define nsIHTMLContentSink_h___ /** - * MODULE NOTES: - * @update gess 4/1/98 - * * This file declares the concrete HTMLContentSink class. * This class is used during the parsing process as the * primary interface between the parser and the content @@ -86,7 +83,9 @@ #include "nsHTMLTags.h" #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) #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) - /** - * 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. * @@ -133,6 +123,13 @@ public: */ 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 + * tag in the body. + */ + NS_IMETHOD OpenHead() = 0; + /** * This method is used to close the only HEAD container. */ @@ -262,13 +259,6 @@ public: */ 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 * 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 * 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 */ diff --git a/mozilla/parser/htmlparser/src/CNavDTD.cpp b/mozilla/parser/htmlparser/src/CNavDTD.cpp index 319769965e1..347bfa0efe9 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.cpp +++ b/mozilla/parser/htmlparser/src/CNavDTD.cpp @@ -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_BODY 0x00000002 #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_FRAMESET 0x00000020 #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_IN_MISPLACED_CONTENT 0x00000200 #define NS_DTD_FLAG_STOP_PARSING 0x00000400 @@ -167,7 +167,6 @@ NS_IMPL_RELEASE(CNavDTD) */ CNavDTD::CNavDTD() : nsIDTD(), mMisplacedContent(0), - mSkippedContent(0), mSink(0), mTokenAllocator(0), mTempContext(0), @@ -176,9 +175,9 @@ CNavDTD::CNavDTD() : nsIDTD(), mDTDMode(eDTDMode_quirks), mDocType(eHTML3_Quirks), // why not eHTML_Quirks? mParserCommand(eViewNormal), - mSkipTarget(eHTMLTag_unknown), mLineNumber(1), mOpenMapCount(0), + mHeadContainerPosition(-1), mFlags(NS_DTD_FLAG_NONE) { mBodyContext=new nsDTDContext(); @@ -341,7 +340,6 @@ nsresult CNavDTD::WillBuildModel(const CParserContext& aParserContext, mParserCommand = aParserContext.mParserCommand; mMimeType = aParserContext.mMimeType; mDocType = aParserContext.mDocType; - mSkipTarget = eHTMLTag_unknown; mTokenizer = aTokenizer; 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. // We also need to make sure that an interruption does not override // a request to block the parser. - if ((mParser->CanInterrupt()) && - (nsnull == mParser->PeekContext()->mPrevContext) && - (eHTMLTag_unknown==mSkipTarget) && - NS_SUCCEEDED(result)) { + if (mParser->CanInterrupt() && + !mParser->PeekContext()->mPrevContext && + NS_SUCCEEDED(result)) { result = NS_ERROR_HTMLPARSER_INTERRUPTED; break; } @@ -532,12 +529,6 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode, nsresult result = NS_OK; if (aParser && aNotifySink) { if (NS_OK == anErrorCode) { - if (eHTMLTag_unknown != mSkipTarget) { - // Looks like there is an open target ( ex. ). - // 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))) { // 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.. @@ -673,81 +664,6 @@ PRBool HasOpenTagOfType(PRInt32 aType, const nsDTDContext& aContext) { 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. * 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); eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); - PRBool execSkipContent=PR_FALSE; aToken->SetLineNumber(mLineNumber); mLineNumber += aToken->GetNewlineCount(); - /* --------------------------------------------------------------------------------- - 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) { + if(mFlags & NS_DTD_FLAG_MISPLACED_CONTENT) { // Included TD & TH to fix Bug# 20797 static eHTMLTags gLegalElements[]={eHTMLTag_table,eHTMLTag_thead,eHTMLTag_tbody, eHTMLTag_tr,eHTMLTag_td,eHTMLTag_th,eHTMLTag_tfoot}; @@ -831,12 +722,6 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ NS_ENSURE_SUCCESS(result, result); mBodyContext->mContextTopIndex = -1; - - if (mSkipTarget) { - mSkippedContent.Push(theToken); - return result; - } - // Fall through if the skipped content collection is |not| in progress - bug 124788 } else { PushIntoMisplacedStack(theToken); @@ -853,145 +738,135 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ 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) { - case eHTMLTag_html: - case eHTMLTag_noframes: - case eHTMLTag_noscript: - case eHTMLTag_script: - case eHTMLTag_doctypeDecl: - case eHTMLTag_instruction: - break; + default: + if(!gHTMLElements[eHTMLTag_html].SectionContains(theTag,PR_FALSE)) { + if(!(mFlags & (NS_DTD_FLAG_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) { + 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: - if(!gHTMLElements[eHTMLTag_html].SectionContains(theTag,PR_FALSE)) { - 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 + break; }//switch - } //if - - if(theToken){ - //Before dealing with the token normally, we need to deal with skip targets - CStartToken* theStartToken=NS_STATIC_CAST(CStartToken*,aToken); - if((!execSkipContent) && - (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); + + 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 { - - 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; - } + return NS_OK; } } + } - }//if 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)); 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; } @@ -1439,17 +1298,6 @@ nsresult CNavDTD::HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags // If the token is attributed then save those attributes too. 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 }//if }//if @@ -1597,6 +1445,8 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { } break; case eHTMLTag_head: + mFlags |= NS_DTD_FLAG_HAS_EXPLICIT_HEAD; + if(mFlags & (NS_DTD_FLAG_HAD_BODY | NS_DTD_FLAG_HAD_FRAMESET)) { result=HandleOmittedTag(aToken,theChildTag,theParent,theNode); isTokenHandled=PR_TRUE; @@ -1610,7 +1460,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { PRBool isExclusive=PR_FALSE; theHeadIsParent=nsHTMLElement::IsChildOfHead(theChildTag,isExclusive); - switch(theChildTag) { + switch(theChildTag) { case eHTMLTag_area: 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 // into the body. isExclusive = !(mFlags & NS_DTD_FLAG_HAD_BODY); - mFlags |= NS_DTD_FLAG_HAS_OPEN_SCRIPT; + break; - default: - break; + default:; }//switch if(!isTokenHandled) { @@ -1657,12 +1506,12 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) { theHeadIsParent = theHeadIsParent && (isExclusive || (prefersBody - ? (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) + ? (mFlags & NS_DTD_FLAG_HAS_EXPLICIT_HEAD) : !(mFlags & NS_DTD_FLAG_HAD_BODY))); if(theHeadIsParent) { // These tokens prefer to be in the head. - result = AddHeadLeaf(theNode); + result = AddHeadContent(theNode); } else { result = HandleDefaultStartToken(aToken,theChildTag,theNode); @@ -1842,13 +1691,8 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { CollectAttributes(nsnull,theChildTag,attrCount); switch(theChildTag) { - - case eHTMLTag_script: - mFlags &= ~NS_DTD_FLAG_HAS_OPEN_SCRIPT; - case eHTMLTag_style: case eHTMLTag_link: case eHTMLTag_meta: - case eHTMLTag_title: break; case eHTMLTag_head: @@ -1877,6 +1721,23 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { StripWSFollowingTag(theChildTag,mTokenizer,mTokenAllocator,mLineNumber); 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: { //now check to see if this token should be omitted, or @@ -2012,7 +1873,7 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) { theToken=(CToken*)mMisplacedContent.PopFront(); if(theToken) { 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 for(PRInt32 j=0;j<attrCount; ++j){ CToken* theAttrToken = (CToken*)mMisplacedContent.PopFront(); @@ -2156,31 +2017,6 @@ nsresult CNavDTD::HandleAttributeToken(CToken* aToken) { 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 * encountered in the parse process. @@ -2266,15 +2102,11 @@ nsresult CNavDTD::CollectAttributes(nsIParserNode *aNode,eHTMLTags aTag,PRInt32 int attr=0; nsresult result=NS_OK; - int theAvailTokenCount=mTokenizer->GetCount() + mSkippedContent.GetSize(); + int theAvailTokenCount=mTokenizer->GetCount(); if(aCount<=theAvailTokenCount) { CToken* theToken=0; - eHTMLTags theSkipTarget=gHTMLElements[aTag].mSkipTarget; for(attr=0;attr<aCount;++attr){ - if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize()) - theToken=NS_STATIC_CAST(CToken*,mSkippedContent.PopFront()); - else - theToken=mTokenizer->PopToken(); + theToken=mTokenizer->PopToken(); if(theToken) { eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); if(theType!=eToken_attribute) { @@ -2313,55 +2145,6 @@ nsresult CNavDTD::CollectAttributes(nsIParserNode *aNode,eHTMLTags aTag,PRInt32 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 * 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)) { 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)); @@ -2965,6 +2753,10 @@ nsresult CNavDTD::OpenBody(const nsCParserNode *aNode) STOP_TIMER(); 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; MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::OpenBody(), this=%p\n", this)); @@ -3205,10 +2997,6 @@ CNavDTD::OpenContainer(const nsCParserNode *aNode, } break; - case eHTMLTag_style: - case eHTMLTag_title: - break; - case eHTMLTag_map: result = OpenMap(aNode); break; @@ -3221,10 +3009,6 @@ CNavDTD::OpenContainer(const nsCParserNode *aNode, result = OpenFrameset(aNode); break; - case eHTMLTag_script: - result = HandleScriptToken(aNode); - break; - case eHTMLTag_noembed: // <noembed> is unconditionally alternate content. done = PR_FALSE; @@ -3292,9 +3076,6 @@ CNavDTD::CloseContainer(const eHTMLTags aTag, eHTMLTags aTarget,PRBool aClosedBy case eHTMLTag_html: result=CloseHTML(); break; - case eHTMLTag_style: - break; - case eHTMLTag_head: result=CloseHead(); break; @@ -3322,12 +3103,22 @@ CNavDTD::CloseContainer(const eHTMLTags aTag, eHTMLTags aTarget,PRBool aClosedBy // switch from alternate content state to regular state mFlags &= ~NS_DTD_FLAG_ALTERNATE_CONTENT; // falling thro' intentionally.... - case eHTMLTag_title: default: STOP_TIMER(); 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)); START_TIMER(); @@ -3586,7 +3377,7 @@ nsresult CNavDTD::AddLeaf(const nsIParserNode *aNode){ * @param aNode -- next node to be added to model * @return error code; 0 means OK */ -nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ +nsresult CNavDTD::AddHeadContent(nsIParserNode *aNode){ nsresult result=NS_OK; static eHTMLTags gNoXTags[] = {eHTMLTag_noembed,eHTMLTag_noframes}; @@ -3604,11 +3395,35 @@ nsresult CNavDTD::AddHeadLeaf(nsIParserNode *aNode){ if (mSink) { STOP_TIMER(); - MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddHeadLeaf(), this=%p\n", this)); - - result = mSink->AddHeadContent(*aNode); - - MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::AddHeadLeaf(), this=%p\n", this)); + MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::AddHeadContent(), this=%p\n", this)); + + // Make sure the head is opened. This might just be a no-op. + result = OpenHead(nsnull); + + // 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(); } return result; diff --git a/mozilla/parser/htmlparser/src/CNavDTD.h b/mozilla/parser/htmlparser/src/CNavDTD.h index e8ce0910490..dfbb6e6e5aa 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.h +++ b/mozilla/parser/htmlparser/src/CNavDTD.h @@ -1,4 +1,5 @@ /* -*- 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 ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -271,7 +272,6 @@ public: nsresult HandleEntityToken(CToken* aToken); nsresult HandleCommentToken(CToken* aToken); nsresult HandleAttributeToken(CToken* aToken); - nsresult HandleScriptToken(const nsIParserNode *aNode); nsresult HandleProcessingInstructionToken(CToken* aToken); nsresult HandleDocTypeDeclToken(CToken* aToken); nsresult BuildNeglectedTarget(eHTMLTags aTarget, eHTMLTokenTypes aType, @@ -337,7 +337,7 @@ public: * @return error code - 0 if all went well. */ 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 @@ -365,7 +365,6 @@ public: protected: nsresult CollectAttributes(nsIParserNode* aNode,eHTMLTags aTag,PRInt32 aCount); - nsresult CollectSkippedContent(nsIParserNode& aNode,PRInt32& aCount); nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag); nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode); @@ -376,7 +375,6 @@ protected: PRBool IsInlineElement(PRInt32 aTagID, PRInt32 aParentID) const; nsDeque mMisplacedContent; - nsDeque mSkippedContent; nsIHTMLContentSink* mSink; nsTokenAllocator* mTokenAllocator; @@ -394,9 +392,9 @@ protected: eParserDocType mDocType; eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors... - eHTMLTags mSkipTarget; PRInt32 mLineNumber; PRInt32 mOpenMapCount; + PRInt32 mHeadContainerPosition; PRUint16 mFlags; }; diff --git a/mozilla/parser/htmlparser/src/nsDTDUtils.cpp b/mozilla/parser/htmlparser/src/nsDTDUtils.cpp index 38f2b32132d..91f2eb56d95 100644 --- a/mozilla/parser/htmlparser/src/nsDTDUtils.cpp +++ b/mozilla/parser/htmlparser/src/nsDTDUtils.cpp @@ -291,6 +291,9 @@ nsCParserNode* nsEntryStack::Pop(void) // XXX If this NS_ENSURE_TRUE fails, it means that the style stack was // empty before we were removed. +#ifdef DEBUG_mrbkap + NS_ASSERTION(scount != 0, "preventing a potential crash."); +#endif NS_ENSURE_TRUE(scount != 0, result); PRUint32 sindex = 0; diff --git a/mozilla/parser/htmlparser/src/nsElementTable.cpp b/mozilla/parser/htmlparser/src/nsElementTable.cpp index f99a93a33fd..2be8259e41a 100644 --- a/mozilla/parser/htmlparser/src/nsElementTable.cpp +++ b/mozilla/parser/htmlparser/src/nsElementTable.cpp @@ -194,12 +194,6 @@ const nsHTMLElement gHTMLElements[] = { /*contain-func*/ 0 }, { - /************************************************* - Note: I changed A to contain flow elements - since it's such a popular (but illegal) - idiom. - *************************************************/ - /*tag*/ eHTMLTag_a, /*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown, /*rootnodes,endrootnodes*/ &gRootTags,&gRootTags, @@ -905,7 +899,7 @@ const nsHTMLElement gHTMLElements[] = { /*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown, /*rootnodes,endrootnodes*/ &gRootTags,&gRootTags, /*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 parents,kids,skip*/ 0,&gContainsParam,eHTMLTag_unknown, /*contain-func*/ 0 @@ -1017,7 +1011,7 @@ const nsHTMLElement gHTMLElements[] = { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ (kSpecial|kHeadContent), kCDATA, kNone, // note: this is kHeadContent since shipping this breaks things. /*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 }, { @@ -1037,7 +1031,7 @@ const nsHTMLElement gHTMLElements[] = { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ (kSpecial|kHeadMisc), kCDATA, kNone, /*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 }, { @@ -1115,8 +1109,8 @@ const nsHTMLElement gHTMLElements[] = { /*rootnodes,endrootnodes*/ &gInHead,&gInHead, /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ kHeadContent, kCDATA, kNone, - /*special props, prop-range*/ kNoStyleLeaksIn|kNonContainer, kNoPropRange, - /*special parents,kids,skip*/ &gInHead,0,eHTMLTag_style, + /*special props, prop-range*/ kNoStyleLeaksIn, kNoPropRange, + /*special parents,kids,skip*/ &gInHead,0,eHTMLTag_unknown, /*contain-func*/ 0 }, { @@ -1217,7 +1211,7 @@ const nsHTMLElement gHTMLElements[] = { /*autoclose starttags and endtags*/ 0,0,0,0, /*parent,incl,exclgroups*/ kHeadContent,kPCDATA, kNone, /*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 }, { diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp index 99e184df46e..5b158f09a84 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp @@ -1155,13 +1155,6 @@ nsExpatDriver::GetType() /*************************** Unused methods **********************************/ -NS_IMETHODIMP -nsExpatDriver::CollectSkippedContent(PRInt32 aTag, nsAString& aContent, - PRInt32 &aLineNo) -{ - return NS_OK; -} - NS_IMETHODIMP_(CToken*) nsExpatDriver::PushTokenFront(CToken* aToken) { diff --git a/mozilla/parser/htmlparser/src/nsLoggingSink.cpp b/mozilla/parser/htmlparser/src/nsLoggingSink.cpp index a610e78ef7b..4b3ba0e4726 100644 --- a/mozilla/parser/htmlparser/src/nsLoggingSink.cpp +++ b/mozilla/parser/htmlparser/src/nsLoggingSink.cpp @@ -1,4 +1,5 @@ /* -*- 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 ***** * 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(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 NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult) { @@ -73,7 +64,7 @@ NS_NewHTMLLoggingSink(nsIContentSink** aInstancePtrResult) nsLoggingSink::nsLoggingSink() { mOutput = 0; - mLevel=-1; + mLevel=-1; mSink=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 nsLoggingSink::AddLeaf(const nsIParserNode& 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 nsLoggingSink::OpenHTML(const nsIParserNode& aNode) { OpenNode("html", aNode); @@ -434,6 +370,21 @@ nsLoggingSink::OpenHead(const nsIParserNode& aNode) { 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 nsLoggingSink::CloseHead() { 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); return NS_OK; } @@ -673,43 +607,31 @@ nsLoggingSink::WillWriteAttributes(const nsIParserNode& aNode) if (0 != ac) { 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; } nsresult nsLoggingSink::LeafNode(const nsIParserNode& aNode) { - WriteTabs(mOutput,1+mLevel); - nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); + WriteTabs(mOutput,1+mLevel); + nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType()); if ((nodeType >= eHTMLTag_unknown) && (nodeType <= nsHTMLTag(NS_HTML_TAG_MAX))) { const PRUnichar* tag = nsHTMLTags::GetStringValue(nodeType); - if(tag) + if(tag) 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)) { - PR_fprintf(mOutput, ">\n"); + PR_fprintf(mOutput, ">\n"); WriteAttributes(aNode); - PR_fprintf(mOutput, "</leaf>\n"); + PR_fprintf(mOutput, "</leaf>\n"); } else { - PR_fprintf(mOutput, "/>\n"); + PR_fprintf(mOutput, "/>\n"); } } else { @@ -717,32 +639,32 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) nsAutoString tmp; char* str = nsnull; switch (nodeType) { - case eHTMLTag_whitespace: - case eHTMLTag_text: - GetNewCString(aNode.GetText(), &str); - if(str) { - PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str); - nsMemory::Free(str); - } - break; + case eHTMLTag_whitespace: + case eHTMLTag_text: + GetNewCString(aNode.GetText(), &str); + if(str) { + PR_fprintf(mOutput, "<text value=\"%s\"/>\n", str); + nsMemory::Free(str); + } + break; - case eHTMLTag_newline: - PR_fprintf(mOutput, "<newline/>\n"); - break; + case eHTMLTag_newline: + PR_fprintf(mOutput, "<newline/>\n"); + break; - case eHTMLTag_entity: - tmp.Append(aNode.GetText()); - tmp.Cut(0, 1); - pos = tmp.Length() - 1; - if (pos >= 0) { - tmp.Cut(pos, 1); - } - PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", NS_LossyConvertUCS2toASCII(tmp).get()); - break; + case eHTMLTag_entity: + tmp.Append(aNode.GetText()); + tmp.Cut(0, 1); + pos = tmp.Length() - 1; + if (pos >= 0) { + tmp.Cut(pos, 1); + } + PR_fprintf(mOutput, "<entity value=\"%s\"/>\n", NS_LossyConvertUCS2toASCII(tmp).get()); + break; - default: - NS_NOTREACHED("unsupported leaf node type"); - }//switch + default: + NS_NOTREACHED("unsupported leaf node type"); + }//switch } return NS_OK; } diff --git a/mozilla/parser/htmlparser/src/nsLoggingSink.h b/mozilla/parser/htmlparser/src/nsLoggingSink.h index 969ae8a8af7..c252da699c0 100644 --- a/mozilla/parser/htmlparser/src/nsLoggingSink.h +++ b/mozilla/parser/htmlparser/src/nsLoggingSink.h @@ -67,7 +67,6 @@ public: NS_IMETHOD SetParser(nsIParser* aParser); NS_IMETHOD OpenContainer(const nsIParserNode& aNode); NS_IMETHOD CloseContainer(const nsHTMLTag aTag); - NS_IMETHOD AddHeadContent(const nsIParserNode& aNode); NS_IMETHOD AddLeaf(const nsIParserNode& aNode); NS_IMETHOD AddComment(const nsIParserNode& aNode); NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); @@ -77,10 +76,10 @@ public: virtual nsISupports *GetTarget() { return nsnull; } // nsIHTMLContentSink - NS_IMETHOD SetTitle(const nsString& aValue); NS_IMETHOD OpenHTML(const nsIParserNode& aNode); NS_IMETHOD CloseHTML(); NS_IMETHOD OpenHead(const nsIParserNode& aNode); + NS_IMETHOD OpenHead(); NS_IMETHOD CloseHead(); NS_IMETHOD OpenBody(const nsIParserNode& aNode); NS_IMETHOD CloseBody(); @@ -116,10 +115,10 @@ public: protected: PRFileDesc *mOutput; - int mLevel; + int mLevel; nsIHTMLContentSink *mSink; - PRBool mAutoDeleteOutput; - nsIParser* mParser; + PRBool mAutoDeleteOutput; + nsIParser* mParser; }; #endif diff --git a/mozilla/parser/htmlparser/tests/html/TestParser.cpp b/mozilla/parser/htmlparser/tests/html/TestParser.cpp index a849222eb1a..1620c9eb547 100644 --- a/mozilla/parser/htmlparser/tests/html/TestParser.cpp +++ b/mozilla/parser/htmlparser/tests/html/TestParser.cpp @@ -74,13 +74,14 @@ nsresult ParseData(char* anInputStream,char* anOutputStream) { return result; } - PRFileDesc* in = PR_Open(anInputStream, PR_RDONLY, 777); + PRFileDesc* in = PR_Open(anInputStream, PR_RDONLY, 0777); if (!in) { printf("\nUnable to open input file - %s\n", anInputStream); 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) { printf("\nUnable to open output file - %s\n", anOutputStream); return result;