зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
63e6e518f3
Коммит
bdd2e91772
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче