bug 285250: Give tags the ability to request to be either in the head OR the body. They follow the same rules that userdefined, whitespace, and newline tags used to follow. r=bzbarsky sr=jst

This commit is contained in:
mrbkap%gmail.com 2005-03-17 23:28:35 +00:00
parent c1615c1d7b
commit bef46d35d1
3 changed files with 96 additions and 83 deletions

View File

@ -476,10 +476,12 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke
// NS_ERROR_HTMLPARSER_INTERRUPTED.
// If the parser has mPrevContext then it may be processing
// 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)) {
(eHTMLTag_unknown==mSkipTarget) &&
NS_SUCCEEDED(result)) {
result = NS_ERROR_HTMLPARSER_INTERRUPTED;
break;
}
@ -837,15 +839,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
case eHTMLTag_doctypeDecl:
case eHTMLTag_instruction:
break;
case eHTMLTag_comment:
case eHTMLTag_newline:
case eHTMLTag_whitespace:
case eHTMLTag_userdefined:
if (mMisplacedContent.GetSize() == 0) {
// simply pass these through to token handler without further ado...
// fix for bugs 17017,18308,23765,24275,69331
break;
}
default:
if(!gHTMLElements[eHTMLTag_html].SectionContains(theTag,PR_FALSE)) {
if(!(mFlags & (NS_DTD_FLAG_HAD_BODY |
@ -853,13 +847,25 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
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 theExclusive=PR_FALSE;
PRBool theChildBelongsInHead=gHTMLElements[eHTMLTag_head].IsChildOfHead(theTag,theExclusive);
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.
@ -1363,18 +1369,21 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsIParserNode
result=gHTMLElements[aTag].HasSpecialProperty(kDiscardTag) ? 1 : NS_OK;
}
//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 (NS_SUCCEEDED(result) && (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD &&
eHTMLTag_newline != aTag &&
eHTMLTag_whitespace != aTag &&
eHTMLTag_userdefined != aTag)) {
PRBool theExclusive = PR_FALSE;
if (!gHTMLElements[eHTMLTag_head].IsChildOfHead(aTag, theExclusive)) {
result = CloseHead();
}
// 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;
}
@ -1596,8 +1605,8 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
}
}
PRBool theExclusive=PR_FALSE;
theHeadIsParent=nsHTMLElement::IsChildOfHead(theChildTag,theExclusive);
PRBool isExclusive=PR_FALSE;
theHeadIsParent=nsHTMLElement::IsChildOfHead(theChildTag,isExclusive);
switch(theChildTag) {
case eHTMLTag_area:
@ -1625,7 +1634,10 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
break;
case eHTMLTag_script:
theHeadIsParent = !(mFlags & NS_DTD_FLAG_HAS_OPEN_BODY);
// Script isn't really exclusively in the head. However, we treat it
// 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;
default:
@ -1633,14 +1645,14 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
}//switch
if(!isTokenHandled) {
if(theHeadIsParent || ((mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD) &&
(eHTMLTag_newline == theChildTag ||
eHTMLTag_whitespace == theChildTag ||
eHTMLTag_userdefined == theChildTag))) {
result = AddHeadLeaf(theNode);
if(theHeadIsParent &&
(isExclusive || (mFlags & NS_DTD_FLAG_HAS_OPEN_HEAD))) {
// These tokens prefer to be in the head.
result = AddHeadLeaf(theNode);
}
else
else {
result = HandleDefaultStartToken(aToken,theChildTag,theNode);
}
}
//now do any post processing necessary on the tag...

View File

@ -113,7 +113,6 @@ DECL_TAG_LIST(gFormKids,{eHTMLTag_keygen})
DECL_TAG_LIST(gFramesetKids,{eHTMLTag_frame COMMA eHTMLTag_frameset COMMA eHTMLTag_noframes})
DECL_TAG_LIST(gHtmlKids,{eHTMLTag_body COMMA eHTMLTag_frameset COMMA eHTMLTag_head COMMA eHTMLTag_map COMMA eHTMLTag_noscript COMMA eHTMLTag_noframes COMMA eHTMLTag_script COMMA eHTMLTag_newline COMMA eHTMLTag_whitespace})
DECL_TAG_LIST(gHeadKids,{eHTMLTag_base COMMA eHTMLTag_bgsound COMMA eHTMLTag_link COMMA eHTMLTag_meta COMMA eHTMLTag_script COMMA eHTMLTag_style COMMA eHTMLTag_title COMMA eHTMLTag_noembed})
DECL_TAG_LIST(gLabelKids,{eHTMLTag_span})
DECL_TAG_LIST(gLIKids,{eHTMLTag_ol COMMA eHTMLTag_ul})
@ -316,7 +315,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInHead, &gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kNone, kNone, kNone,
/*parent,incl,exclgroups*/ kHeadContent, kNone, kNone,
/*special props, prop-range*/ kNonContainer, kNoPropRange,
/*special parents,kids,skip*/ &gInHead,0,eHTMLTag_unknown);
@ -652,7 +651,7 @@ void InitializeElementTable(void) {
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHTMLContent, (kHeadContent|kHeadMisc), kNone,
/*special props, prop-range*/ kNoStyleLeaksIn, kDefaultPropRange,
/*special parents,kids,skip*/ &gInHTML,&gHeadKids,eHTMLTag_unknown);
/*special parents,kids,skip*/ &gInHTML,0,eHTMLTag_unknown);
Initialize(
/*tag*/ eHTMLTag_hr,
@ -731,7 +730,7 @@ void InitializeElementTable(void) {
/*requiredAncestor*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ (kBlock|kHeadContent), kFlowEntity, kNone,
/*parent,incl,exclgroups*/ kBlock, kFlowEntity, kNone,
/*special props, prop-range*/ kNonContainer,kDefaultPropRange,
/*special parents,kids,skip*/ &gInBody,0,eHTMLTag_unknown);
@ -787,7 +786,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInHead,&gInHead,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadMisc, kNone, kNone,
/*parent,incl,exclgroups*/ kHeadContent, kNone, kNone,
/*special props, prop-range*/ kNonContainer,kDefaultPropRange,
/*special parents,kids,skip*/ &gInHead,0,eHTMLTag_unknown);
@ -832,7 +831,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInHead, &gInHead,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadMisc, kNone, kNone,
/*parent,incl,exclgroups*/ kHeadContent, kNone, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn|kNonContainer, kDefaultPropRange,
/*special parents,kids,skip*/ &gInHead,0,eHTMLTag_unknown);
@ -976,7 +975,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ (kSpecial|kHeadMisc), kCDATA, kNone,
/*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);
@ -1013,7 +1012,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ (kFlowEntity|kHeadContent), kNone, kNone, // Added kFlowEntity|kHeadContent & kNonContainer in
/*parent,incl,exclgroups*/ (kFlowEntity|kHeadMisc), kNone, kNone, // Added kFlowEntity|kHeadMisc & kNonContainer in
/*special props, prop-range*/ kNonContainer,kDefaultPropRange, // Ref. to Bug 25749
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
@ -1066,7 +1065,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInHead, &gInHead,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadMisc, kCDATA, kNone,
/*parent,incl,exclgroups*/ kHeadContent, kCDATA, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn|kNonContainer, kNoPropRange,
/*special parents,kids,skip*/ &gInHead,0,eHTMLTag_style);
@ -1157,7 +1156,7 @@ void InitializeElementTable(void) {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInHead,&gInHead,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kHeadMisc,kPCDATA, kNone,
/*parent,incl,exclgroups*/ kHeadContent,kPCDATA, kNone,
/*special props, prop-range*/ kNoStyleLeaksIn, kNoPropRange,
/*special parents,kids,skip*/ &gInHead,&gContainsText,eHTMLTag_title);
@ -1234,6 +1233,10 @@ void InitializeElementTable(void) {
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
Initialize(
// Whitespace must have a parent model of kHeadMisc to ensure that we
// do the right thing for whitespace in the head section of a document.
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_whitespace,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInBody,&gInBody,
@ -1243,6 +1246,10 @@ void InitializeElementTable(void) {
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
Initialize(
// Newlines must have a parent model of kHeadMisc to ensure that we
// do the right thing for whitespace in the head section of a document.
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_newline,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gInBody,&gInBody,
@ -1252,11 +1259,15 @@ void InitializeElementTable(void) {
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
Initialize(
// Comments must have a parent model of kHeadMisc to ensure that we
// do the right thing for whitespace in the head section of a document
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_comment,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, kNone, kNone,
/*parent,incl,exclgroups*/ kFlowEntity|kHeadMisc, kNone, kNone,
/*special props, prop-range*/ kOmitEndTag|kLegalOpen,kNoPropRange,
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
@ -1297,11 +1308,15 @@ void InitializeElementTable(void) {
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown);
Initialize(
// Userdefined tags must have a parent model of kHeadMisc to ensure that
// we do the right thing for whitespace in the head section of a document.
// (i.e., it must be non-exclusively a child of the head).
/*tag*/ eHTMLTag_userdefined,
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_frameset,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ &gBodyAutoClose,0,0,0,
/*parent,incl,exclgroups*/ kFlowEntity, (kInlineEntity|kSelf), kNone, // Treat userdefined as inline element - Ref bug 56245,66772
/*parent,incl,exclgroups*/ (kFlowEntity|kHeadMisc), (kInlineEntity|kSelf), kNone, // Treat userdefined as inline element - Ref bug 56245,66772
/*special props, prop-range*/ kNone, kBodyPropRange,
/*special parents,kids,skip*/ &gInNoframes,&gBodyKids,eHTMLTag_unknown);
}//if
@ -1758,45 +1773,31 @@ PRBool nsHTMLElement::CanOmitStartTag(eHTMLTags aChild) const{
}
/**
*
* @update gess12/13/98
* @param
* @return
* Returns whether a given tag can be a direct child of the <head> node of
* an HTML document.
*
* @param aChild The tag in question.
* @param aExclusively [out]Whether or not this tag can *only* appear in the
* head (as opposed to things like <object> which can be
either in the body or the head).
* @return Whether this tag can appear in the head.
*/
PRBool nsHTMLElement::IsChildOfHead(eHTMLTags aChild,PRBool& aExclusively) {
#if 0
PRBool result=PR_FALSE;
aExclusively = PR_TRUE;
aExclusively=PR_FALSE;
switch(aChild) {
case eHTMLTag_base:
case eHTMLTag_link:
case eHTMLTag_meta:
case eHTMLTag_title:
case eHTMLTag_style:
aExclusively=result=PR_TRUE;
break;
case eHTMLTag_bgsound:
case eHTMLTag_script:
case eHTMLTag_noembed:
case eHTMLTag_noscript:
case eHTMLTag_whitespace:
case eHTMLTag_newline:
case eHTMLTag_comment:
result=PR_TRUE;
break;
default:
break;
// Is this a head-only tag?
if (gHTMLElements[aChild].mParentBits & kHeadContent) {
return PR_TRUE;
}
return result;
#else
aExclusively=PR_TRUE;
return FindTagInSet(aChild,gHeadKids.mTags,gHeadKids.mCount);
#endif
// If not, check if it can appear in the head.
if (gHTMLElements[aChild].mParentBits & kHeadMisc) {
aExclusively = PR_FALSE;
return PR_TRUE;
}
return PR_FALSE;
}

View File

@ -58,8 +58,8 @@
static const int kNone= 0x0;
static const int kHTMLContent = 0x0001; // HEAD, (FRAMESET | BODY)
static const int kHeadContent = 0x0002; // TITLE, ISINDEX, BASE
static const int kHeadMisc = 0x0004; // SCRIPT, STYLE, META, LINK, OBJECT
static const int kHeadContent = 0x0002; // Elements that *must* be in the head.
static const int kHeadMisc = 0x0004; // Elements that *can* be in the head.
static const int kSpecial = 0x0008; // A, IMG, APPLET, OBJECT, FONT, BASEFONT, BR, SCRIPT,
// MAP, Q, SUB, SUP, SPAN, BDO, IFRAME