fix for 159842: parser has no mechanism to allow parsing of incomplete html fragments. sr's from heikki, kin, bz

This commit is contained in:
jfrancis%netscape.com 2002-08-29 08:17:41 +00:00
Родитель 63e6e518f3
Коммит bdd2e91772
14 изменённых файлов: 255 добавлений и 202 удалений

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

@ -228,6 +228,10 @@
#define NS_PLAINTEXTSERIALIZER_CID \
{ 0x6030f7ef, 0x32ed, 0x46a7, { 0x9a, 0x63, 0x6a, 0x5d, 0x3f, 0x90, 0x44, 0x5f } }
// {d4f2b600-b5c1-11d6-b483-cc97c63e567c}
#define NS_HTMLFRAGMENTSINK_CID \
{ 0xd4f2b600, 0xb5c1, 0x11d6, { 0xb4, 0x83, 0xcc, 0x97, 0xc6, 0x3e, 0x56, 0x7c } }
// {3986B301-097C-11d3-BF87-00105A1B0627}
#define NS_XULPOPUPLISTENER_CID \
{ 0x3986b301, 0x97c, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }

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

@ -228,6 +228,10 @@
#define NS_PLAINTEXTSERIALIZER_CID \
{ 0x6030f7ef, 0x32ed, 0x46a7, { 0x9a, 0x63, 0x6a, 0x5d, 0x3f, 0x90, 0x44, 0x5f } }
// {d4f2b600-b5c1-11d6-b483-cc97c63e567c}
#define NS_HTMLFRAGMENTSINK_CID \
{ 0xd4f2b600, 0xb5c1, 0x11d6, { 0xb4, 0x83, 0xcc, 0x97, 0xc6, 0x3e, 0x56, 0x7c } }
// {3986B301-097C-11d3-BF87-00105A1B0627}
#define NS_XULPOPUPLISTENER_CID \
{ 0x3986b301, 0x97c, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }

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

@ -82,6 +82,7 @@
#include "nsHTMLAttributes.h"
#include "nsIHTMLCSSStyleSheet.h"
#include "nsIHTMLContent.h"
#include "nsIHTMLFragmentContentSink.h"
#include "nsIHTMLStyleSheet.h"
#include "nsIHTMLToTextSink.h"
#include "nsILayoutDebugger.h"
@ -352,6 +353,7 @@ MAKE_CTOR(CreateHTMLCopyTextEncoder, nsIDocumentEncoder, NS_NewHTM
MAKE_CTOR(CreateXMLContentSerializer, nsIContentSerializer, NS_NewXMLContentSerializer)
MAKE_CTOR(CreateHTMLContentSerializer, nsIContentSerializer, NS_NewHTMLContentSerializer)
MAKE_CTOR(CreatePlainTextSerializer, nsIContentSerializer, NS_NewPlainTextSerializer)
MAKE_CTOR(CreateHTMLFragmentSink, nsIHTMLFragmentContentSink, NS_NewHTMLFragmentContentSink)
MAKE_CTOR(CreateSanitizingHTMLSerializer, nsIContentSerializer, NS_NewSanitizingHTMLSerializer)
MAKE_CTOR(CreateXBLService, nsIXBLService, NS_NewXBLService)
MAKE_CTOR(CreateBindingManager, nsIBindingManager, NS_NewBindingManager)
@ -731,6 +733,11 @@ static const nsModuleComponentInfo gComponents[] = {
NS_PLAINTEXTSINK_CONTRACTID,
CreatePlainTextSerializer },
{ "html fragment sink",
NS_HTMLFRAGMENTSINK_CID,
NS_HTMLFRAGMENTSINK_CONTRACTID,
CreateHTMLFragmentSink },
{ "HTML sanitizing content serializer",
MOZ_SANITIZINGHTMLSERIALIZER_CID,
MOZ_SANITIZINGHTMLSERIALIZER_CONTRACTID,

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

@ -249,6 +249,12 @@ nsHTMLFragmentContentSink::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIContentSink))) {
nsIContentSink* tmp = this;
*aInstancePtr = (void*) tmp;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) ((nsISupports*)this);
NS_ADDREF_THIS();

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

@ -74,7 +74,8 @@ enum nsDTDMode {
eDTDMode_quirks, //pre 4.0 versions
eDTDMode_almost_standards,
eDTDMode_full_standards,
eDTDMode_autodetect
eDTDMode_autodetect,
eDTDMode_fragment
};

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

@ -40,6 +40,8 @@
#include "nsIHTMLContentSink.h"
#define NS_HTMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;1"
class nsIDOMDocumentFragment;
#define NS_IHTML_FRAGMENT_CONTENT_SINK_IID \

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

@ -73,6 +73,7 @@ class nsIChannel;
enum eParserCommands {
eViewNormal,
eViewSource,
eViewFragment,
eViewErrors
};
@ -353,6 +354,7 @@ const PRUnichar kNullCh = '\0';
#define kXIFTextContentType "text/xif"
#define kPlainTextContentType "text/plain"
#define kViewSourceCommand "view-source"
#define kViewFragmentCommand "view-fragment"
#define kTextCSSContentType "text/css"
#define kApplicationJSContentType "application/x-javascript"
#define kTextJSContentType "text/javascript"

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

@ -1223,124 +1223,129 @@ nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsC
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
PRBool theChildAgrees=PR_TRUE;
PRInt32 theIndex=mBodyContext->GetCount();
PRBool theChildIsContainer=nsHTMLElement::IsContainer(aChildTag);
PRBool theParentContains=-1;
do {
eHTMLTags theParentTag=mBodyContext->TagAt(--theIndex);
theParentContains=CanContain(theParentTag,aChildTag); //precompute containment, and pass it to CanOmit()...
if(CanOmit(theParentTag,aChildTag,theParentContains)) {
result=HandleOmittedTag(aToken,aChildTag,theParentTag,aNode);
return result;
}
// client of parser is spefically trying to parse a fragment that
// may lack required context. Suspend containment rules if so.
if (mParserCommand != eViewFragment)
{
PRBool theChildAgrees=PR_TRUE;
PRInt32 theIndex=mBodyContext->GetCount();
PRBool theParentContains=-1;
do {
eHTMLTags theParentTag=mBodyContext->TagAt(--theIndex);
theParentContains=CanContain(theParentTag,aChildTag); //precompute containment, and pass it to CanOmit()...
eProcessRule theRule=eNormalOp;
if(CanOmit(theParentTag,aChildTag,theParentContains)) {
result=HandleOmittedTag(aToken,aChildTag,theParentTag,aNode);
return result;
}
if((!theParentContains) &&
(IsBlockElement(aChildTag,theParentTag) &&
IsInlineElement(theParentTag,theParentTag))) { //broaden this to fix <inline><block></block></inline>
eProcessRule theRule=eNormalOp;
if(eHTMLTag_li!=aChildTag) { //remove test for table to fix 57554
nsCParserNode* theParentNode= NS_STATIC_CAST(nsCParserNode*, mBodyContext->PeekNode());
if(theParentNode->mToken->IsWellFormed()) {
theRule=eLetInlineContainBlock;
if((!theParentContains) &&
(IsBlockElement(aChildTag,theParentTag) &&
IsInlineElement(theParentTag,theParentTag))) { //broaden this to fix <inline><block></block></inline>
if(eHTMLTag_li!=aChildTag) { //remove test for table to fix 57554
nsCParserNode* theParentNode= NS_STATIC_CAST(nsCParserNode*, mBodyContext->PeekNode());
if(theParentNode->mToken->IsWellFormed()) {
theRule=eLetInlineContainBlock;
}
}
}
}
switch(theRule){
switch(theRule){
case eNormalOp:
case eNormalOp:
theChildAgrees=PR_TRUE;
if(theParentContains) {
theChildAgrees=PR_TRUE;
if(theParentContains) {
eHTMLTags theAncestor=gHTMLElements[aChildTag].mRequiredAncestor;
if(eHTMLTag_unknown!=theAncestor){
theChildAgrees=HasOpenContainer(theAncestor);
}
if(theChildAgrees && theChildIsContainer) {
if(theParentTag!=aChildTag) {
// Double check the power structure a
// Note: The bit is currently set on <A> and <LI>.
if(gHTMLElements[aChildTag].ShouldVerifyHierarchy()){
PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
eHTMLTags theAncestor=gHTMLElements[aChildTag].mRequiredAncestor;
if(eHTMLTag_unknown!=theAncestor){
theChildAgrees=HasOpenContainer(theAncestor);
}
if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
/*-------------------------------------------------------------------------------------
1 Here's a tricky case from bug 22596: <h5><li><h5>
How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
(Afterall, the <h5> is a legal child of the <LI>).
The way you know is that there is no root between the two, so the <h5> binds more
tightly to the 1st <h5> than to the <LI>.
2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
From this case we learned not to execute this logic if the parent is a block.
3. Fix for 26583
Ex. <A href=foo.html><B>foo<A href-bar.html>bar</A></B></A> <-- A legal HTML
In the above example clicking on "foo" or "bar" should link to
foo.html or bar.html respectively. That is, the inner <A> should be informed
about the presence of an open <A> above <B>..so that the inner <A> can close out
the outer <A>. The following code does it for us.
if(theChildAgrees && theChildIsContainer) {
if(theParentTag!=aChildTag) {
// Double check the power structure a
// Note: The bit is currently set on <A> and <LI>.
if(gHTMLElements[aChildTag].ShouldVerifyHierarchy()){
PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
4. Fix for 27865 [ similer to 22596 ]. Ex: <DL><DD><LI>one<DD><LI>two
-------------------------------------------------------------------------------------*/
theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
} //if
}//if
/*-------------------------------------------------------------------------------------
1 Here's a tricky case from bug 22596: <h5><li><h5>
How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
(Afterall, the <h5> is a legal child of the <LI>).
The way you know is that there is no root between the two, so the <h5> binds more
tightly to the 1st <h5> than to the <LI>.
2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
From this case we learned not to execute this logic if the parent is a block.
3. Fix for 26583
Ex. <A href=foo.html><B>foo<A href-bar.html>bar</A></B></A> <-- A legal HTML
In the above example clicking on "foo" or "bar" should link to
foo.html or bar.html respectively. That is, the inner <A> should be informed
about the presence of an open <A> above <B>..so that the inner <A> can close out
the outer <A>. The following code does it for us.
4. Fix for 27865 [ similer to 22596 ]. Ex: <DL><DD><LI>one<DD><LI>two
-------------------------------------------------------------------------------------*/
theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
} //if
}//if
} //if
} //if
} //if
} //if parentcontains
} //if parentcontains
if(!(theParentContains && theChildAgrees)) {
if (!CanPropagate(theParentTag,aChildTag,theParentContains)) {
if(theChildIsContainer || (!theParentContains)){
if(!theChildAgrees && !gHTMLElements[aChildTag].CanAutoCloseTag(*mBodyContext,aChildTag)) {
// Closing the tags above might cause non-compatible results.
// Ex. <TABLE><TR><TD><TBODY>Text</TD></TR></TABLE>.
// In the example above <TBODY> is badly misplaced, but
// we should not attempt to close the tags above it,
// The safest thing to do is to discard this tag.
return result;
}
else if (mBodyContext->mContextTopIndex > 0 && theIndex <= mBodyContext->mContextTopIndex) {
// Looks like the parent tag does not want to contain the current tag ( aChildTag ).
// However, we have to force the containment, when handling misplaced content, to avoid data loss.
// Ref. bug 138577.
theParentContains = PR_TRUE;
}
else {
CloseContainersTo(theIndex,aChildTag,PR_TRUE);
}
if(!(theParentContains && theChildAgrees)) {
if (!CanPropagate(theParentTag,aChildTag,theParentContains)) {
if(theChildIsContainer || (!theParentContains)){
if(!theChildAgrees && !gHTMLElements[aChildTag].CanAutoCloseTag(*mBodyContext,aChildTag)) {
// Closing the tags above might cause non-compatible results.
// Ex. <TABLE><TR><TD><TBODY>Text</TD></TR></TABLE>.
// In the example above <TBODY> is badly misplaced, but
// we should not attempt to close the tags above it,
// The safest thing to do is to discard this tag.
return result;
}
else if (mBodyContext->mContextTopIndex > 0 && theIndex <= mBodyContext->mContextTopIndex) {
// Looks like the parent tag does not want to contain the current tag ( aChildTag ).
// However, we have to force the containment, when handling misplaced content, to avoid data loss.
// Ref. bug 138577.
theParentContains = PR_TRUE;
}
else {
CloseContainersTo(theIndex,aChildTag,PR_TRUE);
}
}//if
else break;
}//if
else break;
else {
CreateContextStackFor(aChildTag);
theIndex=mBodyContext->GetCount();
}
}//if
else {
CreateContextStackFor(aChildTag);
theIndex=mBodyContext->GetCount();
}
}//if
break;
break;
case eLetInlineContainBlock:
theParentContains=theChildAgrees=PR_TRUE; //cause us to fall out of loop and open the block.
break;
case eLetInlineContainBlock:
theParentContains=theChildAgrees=PR_TRUE; //cause us to fall out of loop and open the block.
break;
default:
break;
}//switch
} while(!(theParentContains && theChildAgrees));
default:
break;
}//switch
} while(!(theParentContains && theChildAgrees));
}
if(theChildIsContainer){
result=OpenContainer(aNode,aChildTag,PR_TRUE);
}
@ -2502,8 +2507,8 @@ CNavDTD::CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLine
* @param aChild -- tag enum of child container
* @return PR_TRUE if parent can contain child
*/
PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) const {
PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) const
{
PRBool result=gHTMLElements[aParent].CanContain((eHTMLTags)aChild);
#ifdef ALLOW_TR_AS_CHILD_OF_TABLE

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

@ -469,6 +469,8 @@ void nsParser::SetCommand(const char* aCommand){
nsCAutoString theCommand(aCommand);
if(theCommand.Equals(kViewSourceCommand))
mCommand=eViewSource;
else if(theCommand.Equals(kViewFragmentCommand))
mCommand=eViewFragment;
else mCommand=eViewNormal;
mCommandStr.AssignWithConversion(aCommand);
}
@ -1560,6 +1562,10 @@ nsresult nsParser::Parse(const nsAString& aSourceBuffer, void* aKey,
return result;
}
// hack to pass on to the dtd the caller's desire to
// parse a fragment without worrying about containment rules
if (aMode == eDTDMode_fragment)
mCommand = eViewFragment;
// Maintain a reference to ourselves so we don't go away
// till we're completely done.

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

@ -74,7 +74,8 @@ enum nsDTDMode {
eDTDMode_quirks, //pre 4.0 versions
eDTDMode_almost_standards,
eDTDMode_full_standards,
eDTDMode_autodetect
eDTDMode_autodetect,
eDTDMode_fragment
};

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

@ -40,6 +40,8 @@
#include "nsIHTMLContentSink.h"
#define NS_HTMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;1"
class nsIDOMDocumentFragment;
#define NS_IHTML_FRAGMENT_CONTENT_SINK_IID \

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

@ -73,6 +73,7 @@ class nsIChannel;
enum eParserCommands {
eViewNormal,
eViewSource,
eViewFragment,
eViewErrors
};
@ -353,6 +354,7 @@ const PRUnichar kNullCh = '\0';
#define kXIFTextContentType "text/xif"
#define kPlainTextContentType "text/plain"
#define kViewSourceCommand "view-source"
#define kViewFragmentCommand "view-fragment"
#define kTextCSSContentType "text/css"
#define kApplicationJSContentType "application/x-javascript"
#define kTextJSContentType "text/javascript"

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

@ -1223,124 +1223,129 @@ nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsC
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
PRBool theChildAgrees=PR_TRUE;
PRInt32 theIndex=mBodyContext->GetCount();
PRBool theChildIsContainer=nsHTMLElement::IsContainer(aChildTag);
PRBool theParentContains=-1;
do {
eHTMLTags theParentTag=mBodyContext->TagAt(--theIndex);
theParentContains=CanContain(theParentTag,aChildTag); //precompute containment, and pass it to CanOmit()...
if(CanOmit(theParentTag,aChildTag,theParentContains)) {
result=HandleOmittedTag(aToken,aChildTag,theParentTag,aNode);
return result;
}
// client of parser is spefically trying to parse a fragment that
// may lack required context. Suspend containment rules if so.
if (mParserCommand != eViewFragment)
{
PRBool theChildAgrees=PR_TRUE;
PRInt32 theIndex=mBodyContext->GetCount();
PRBool theParentContains=-1;
do {
eHTMLTags theParentTag=mBodyContext->TagAt(--theIndex);
theParentContains=CanContain(theParentTag,aChildTag); //precompute containment, and pass it to CanOmit()...
eProcessRule theRule=eNormalOp;
if(CanOmit(theParentTag,aChildTag,theParentContains)) {
result=HandleOmittedTag(aToken,aChildTag,theParentTag,aNode);
return result;
}
if((!theParentContains) &&
(IsBlockElement(aChildTag,theParentTag) &&
IsInlineElement(theParentTag,theParentTag))) { //broaden this to fix <inline><block></block></inline>
eProcessRule theRule=eNormalOp;
if(eHTMLTag_li!=aChildTag) { //remove test for table to fix 57554
nsCParserNode* theParentNode= NS_STATIC_CAST(nsCParserNode*, mBodyContext->PeekNode());
if(theParentNode->mToken->IsWellFormed()) {
theRule=eLetInlineContainBlock;
if((!theParentContains) &&
(IsBlockElement(aChildTag,theParentTag) &&
IsInlineElement(theParentTag,theParentTag))) { //broaden this to fix <inline><block></block></inline>
if(eHTMLTag_li!=aChildTag) { //remove test for table to fix 57554
nsCParserNode* theParentNode= NS_STATIC_CAST(nsCParserNode*, mBodyContext->PeekNode());
if(theParentNode->mToken->IsWellFormed()) {
theRule=eLetInlineContainBlock;
}
}
}
}
switch(theRule){
switch(theRule){
case eNormalOp:
case eNormalOp:
theChildAgrees=PR_TRUE;
if(theParentContains) {
theChildAgrees=PR_TRUE;
if(theParentContains) {
eHTMLTags theAncestor=gHTMLElements[aChildTag].mRequiredAncestor;
if(eHTMLTag_unknown!=theAncestor){
theChildAgrees=HasOpenContainer(theAncestor);
}
if(theChildAgrees && theChildIsContainer) {
if(theParentTag!=aChildTag) {
// Double check the power structure a
// Note: The bit is currently set on <A> and <LI>.
if(gHTMLElements[aChildTag].ShouldVerifyHierarchy()){
PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
eHTMLTags theAncestor=gHTMLElements[aChildTag].mRequiredAncestor;
if(eHTMLTag_unknown!=theAncestor){
theChildAgrees=HasOpenContainer(theAncestor);
}
if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
/*-------------------------------------------------------------------------------------
1 Here's a tricky case from bug 22596: <h5><li><h5>
How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
(Afterall, the <h5> is a legal child of the <LI>).
The way you know is that there is no root between the two, so the <h5> binds more
tightly to the 1st <h5> than to the <LI>.
2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
From this case we learned not to execute this logic if the parent is a block.
3. Fix for 26583
Ex. <A href=foo.html><B>foo<A href-bar.html>bar</A></B></A> <-- A legal HTML
In the above example clicking on "foo" or "bar" should link to
foo.html or bar.html respectively. That is, the inner <A> should be informed
about the presence of an open <A> above <B>..so that the inner <A> can close out
the outer <A>. The following code does it for us.
if(theChildAgrees && theChildIsContainer) {
if(theParentTag!=aChildTag) {
// Double check the power structure a
// Note: The bit is currently set on <A> and <LI>.
if(gHTMLElements[aChildTag].ShouldVerifyHierarchy()){
PRInt32 theChildIndex=GetIndexOfChildOrSynonym(*mBodyContext,aChildTag);
if((kNotFound<theChildIndex) && (theChildIndex<theIndex)) {
4. Fix for 27865 [ similer to 22596 ]. Ex: <DL><DD><LI>one<DD><LI>two
-------------------------------------------------------------------------------------*/
theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
} //if
}//if
/*-------------------------------------------------------------------------------------
1 Here's a tricky case from bug 22596: <h5><li><h5>
How do we know that the 2nd <h5> should close the <LI> rather than nest inside the <LI>?
(Afterall, the <h5> is a legal child of the <LI>).
The way you know is that there is no root between the two, so the <h5> binds more
tightly to the 1st <h5> than to the <LI>.
2. Also, bug 6148 shows this case: <SPAN><DIV><SPAN>
From this case we learned not to execute this logic if the parent is a block.
3. Fix for 26583
Ex. <A href=foo.html><B>foo<A href-bar.html>bar</A></B></A> <-- A legal HTML
In the above example clicking on "foo" or "bar" should link to
foo.html or bar.html respectively. That is, the inner <A> should be informed
about the presence of an open <A> above <B>..so that the inner <A> can close out
the outer <A>. The following code does it for us.
4. Fix for 27865 [ similer to 22596 ]. Ex: <DL><DD><LI>one<DD><LI>two
-------------------------------------------------------------------------------------*/
theChildAgrees=CanBeContained(aChildTag,*mBodyContext);
} //if
}//if
} //if
} //if
} //if
} //if parentcontains
} //if parentcontains
if(!(theParentContains && theChildAgrees)) {
if (!CanPropagate(theParentTag,aChildTag,theParentContains)) {
if(theChildIsContainer || (!theParentContains)){
if(!theChildAgrees && !gHTMLElements[aChildTag].CanAutoCloseTag(*mBodyContext,aChildTag)) {
// Closing the tags above might cause non-compatible results.
// Ex. <TABLE><TR><TD><TBODY>Text</TD></TR></TABLE>.
// In the example above <TBODY> is badly misplaced, but
// we should not attempt to close the tags above it,
// The safest thing to do is to discard this tag.
return result;
}
else if (mBodyContext->mContextTopIndex > 0 && theIndex <= mBodyContext->mContextTopIndex) {
// Looks like the parent tag does not want to contain the current tag ( aChildTag ).
// However, we have to force the containment, when handling misplaced content, to avoid data loss.
// Ref. bug 138577.
theParentContains = PR_TRUE;
}
else {
CloseContainersTo(theIndex,aChildTag,PR_TRUE);
}
if(!(theParentContains && theChildAgrees)) {
if (!CanPropagate(theParentTag,aChildTag,theParentContains)) {
if(theChildIsContainer || (!theParentContains)){
if(!theChildAgrees && !gHTMLElements[aChildTag].CanAutoCloseTag(*mBodyContext,aChildTag)) {
// Closing the tags above might cause non-compatible results.
// Ex. <TABLE><TR><TD><TBODY>Text</TD></TR></TABLE>.
// In the example above <TBODY> is badly misplaced, but
// we should not attempt to close the tags above it,
// The safest thing to do is to discard this tag.
return result;
}
else if (mBodyContext->mContextTopIndex > 0 && theIndex <= mBodyContext->mContextTopIndex) {
// Looks like the parent tag does not want to contain the current tag ( aChildTag ).
// However, we have to force the containment, when handling misplaced content, to avoid data loss.
// Ref. bug 138577.
theParentContains = PR_TRUE;
}
else {
CloseContainersTo(theIndex,aChildTag,PR_TRUE);
}
}//if
else break;
}//if
else break;
else {
CreateContextStackFor(aChildTag);
theIndex=mBodyContext->GetCount();
}
}//if
else {
CreateContextStackFor(aChildTag);
theIndex=mBodyContext->GetCount();
}
}//if
break;
break;
case eLetInlineContainBlock:
theParentContains=theChildAgrees=PR_TRUE; //cause us to fall out of loop and open the block.
break;
case eLetInlineContainBlock:
theParentContains=theChildAgrees=PR_TRUE; //cause us to fall out of loop and open the block.
break;
default:
break;
}//switch
} while(!(theParentContains && theChildAgrees));
default:
break;
}//switch
} while(!(theParentContains && theChildAgrees));
}
if(theChildIsContainer){
result=OpenContainer(aNode,aChildTag,PR_TRUE);
}
@ -2502,8 +2507,8 @@ CNavDTD::CollectSkippedContent(PRInt32 aTag, nsAString& aContent, PRInt32 &aLine
* @param aChild -- tag enum of child container
* @return PR_TRUE if parent can contain child
*/
PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) const {
PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) const
{
PRBool result=gHTMLElements[aParent].CanContain((eHTMLTags)aChild);
#ifdef ALLOW_TR_AS_CHILD_OF_TABLE

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

@ -469,6 +469,8 @@ void nsParser::SetCommand(const char* aCommand){
nsCAutoString theCommand(aCommand);
if(theCommand.Equals(kViewSourceCommand))
mCommand=eViewSource;
else if(theCommand.Equals(kViewFragmentCommand))
mCommand=eViewFragment;
else mCommand=eViewNormal;
mCommandStr.AssignWithConversion(aCommand);
}
@ -1560,6 +1562,10 @@ nsresult nsParser::Parse(const nsAString& aSourceBuffer, void* aKey,
return result;
}
// hack to pass on to the dtd the caller's desire to
// parse a fragment without worrying about containment rules
if (aMode == eDTDMode_fragment)
mCommand = eViewFragment;
// Maintain a reference to ourselves so we don't go away
// till we're completely done.