Mozilla FireFox Gecko内核源代码解析
(6.nsElementTable)
中科院计算技术研究所网络数据科学与工程研究中心
信息抽取小组
耿耘
上一章中我们介绍了负责语法解析的CNavDTD模块,比如<table><td>text</td>这段HTML代码,我们会知道<td>是不应直接作为table的直接子节点的,因而需要对其进行<tr>的补充,又如<div><area></area></div>,我们知道这里缺少了<map>节点,因为<area>必须嵌套在<map>中才行。这些规定构成了HTML的语法规范。
而在前面对于CNavDTD的解析中我们可以看到,它主要起到了一个HTML语法解析框架的作用,它维护了一个解析上下文,并在新的标签从Tokenizer中到来之时,根据当前的上下文进行判断,并调用相应类型的nsHTMLTag的方法以判断该节点是否能够正确地嵌入到当前上下文中。而在该文件中并没有存放具体的语法规范,比如<a>之下应当包含什么节点,什么样的节点应当只存在于<head>中,又或者<table>节点应当拥有什么样的子节点等等。
这些具体的语法规范就存放在了nsElementTable这个文件中,它为HTML标签定义了一种Struct结构,又通过属性的值为其规定出了相应的语法行为。之前的CNavDTD主要起到了一个框架和操作的作用,而更底层,更细节的操作,以及相应的Tag包含规范,都位于nsElementTable中。通过学习这个文件,我们可以全面掌握每种类型的HTML标签具体都有些什么语法特征,属性,行为。
下面我们就来看看这个文件,我们还是从头文件入手:
#ifndef_NSELEMENTABLE
#define_NSELEMENTABLE
#include "nsHTMLTokens.h"
#include "nsDTDUtils.h"
//*********************************************************************************************
// The following ints definethe standard groups of HTML elements...
//*********************************************************************************************
//下面定义了一系列标准的HTML元素
//这些实际上都是“某个类型的元素”的标示位,比如如果某个HTMLTag拥有下面某组的标示位,那么我们就认为它属于该类型元素,作者在后面的注释中已经给出了该种元素所包含的标签,读者可自行观察
//举个例子,如果想判断某个标签是否是修改字体的标签,我们只需使用该标签的标示位mParentBits和kFontStyle进行位与操作,结果便知。
static constint kNone= 0x0;
static constintkHTMLContent = 0x0001; // HEAD, (FRAMESET |BODY)
static constintkHeadContent = 0x0002; // Elements that*must* be in the head.
static constintkHeadMisc = 0x0004; // Elements that*can* be in the head.
static constintkSpecial = 0x0008; // A, IMG, APPLET, OBJECT, FONT, BASEFONT, BR, SCRIPT,
// MAP, Q, SUB, SUP, SPAN, BDO, IFRAME
static constintkFormControl = 0x0010; // INPUT SELECT TEXTAREA LABEL BUTTON
static constint kPreformatted = 0x0020; // PRE
static constintkPreExclusion = 0x0040; // IMG, OBJECT, APPLET, BIG, SMALL, SUB, SUP, FONT, BASEFONT
static constintkFontStyle = 0x0080; // TT, I, B, U, S,STRIKE, BIG, SMALL, BLINK
static constintkPhrase = 0x0100; // EM, STRONG, DFN,CODE, SAMP, KBD, VAR, CITE, ABBR, ACRONYM
static constintkHeading = 0x0200; // H1..H6
static constintkBlockMisc = 0x0400; // OBJECT, SCRIPT
static constint kBlock = 0x0800; // ADDRESS, BLOCKQUOTE, CENTER, DIV, DL,FIELDSET, FORM,
// ISINDEX, HR,NOSCRIPT, NOFRAMES, P, TABLE
static constint kList = 0x1000; // UL, OL, DIR, MENU
static constintkPCDATA = 0x2000; // plain text andentities...
static constint kSelf = 0x4000; // whatever THIS tag is...
static constintkExtensions = 0x8000; // BGSOUND, WBR,NOBR
static constint kTable = 0x10000;// TR,TD,THEAD,TBODY,TFOOT,CAPTION,TH
static constintkDLChild = 0x20000;// DL, DT
static constint kCDATA = 0x40000;// just plain text...
static constintkInlineEntity =(kPCDATA|kFontStyle|kPhrase|kSpecial|kFormControl|kExtensions); // #PCDATA, %fontstyle, %phrase, %special,%formctrl
static constint kBlockEntity = (kHeading|kList|kPreformatted|kBlock);// %heading, %list,%preformatted, %block
static constintkFlowEntity =(kBlockEntity|kInlineEntity); // %blockentity, %inlineentity
static constintkAllTags = 0xffffff;
#ifdefNS_DEBUG
extern voidCheckElementTable();
#endif
/**
* We're asking the question: is aTest a memberof bitset.
*
* @update gess01/04/99
* @param
* @return TRUE or FALSE
*/
//下面这个方法就是进行简单的位与操作来对相应的标示位进行判断的
inlinePRBool TestBits(int aBitset,int aTest) {
if(aTest) {
PRInt32 result=(aBitset & aTest);
return PRBool(result==aTest);
}
return PR_FALSE;
}
/**
*
* @update gess01/04/99
* @param
* @return
*/
//下面就是对结构体nsHTMLElement的定义了,该结构体便是每种不同的HTMLElement的代表,如Body,head,a,li等等。
structnsHTMLElement {
#ifdefDEBUG
static void DebugDumpMembership(constchar* aFilename);
static void DebugDumpContainment(constchar* aFilename,const char* aTitle);
static void DebugDumpContainType(constchar* aFilename);
#endif
static PRBool IsInlineEntity(eHTMLTagsaTag); //是否是inline级元素
static PRBool IsFlowEntity(eHTMLTagsaTag); //是否是flow元素
static PRBool IsBlockCloser(eHTMLTagsaTag); //该元素是否能关闭block级元素
inline PRBool IsBlock(void)const { //该元素是否是block元素
if((mTagID>=eHTMLTag_unknown)& (mTagID<=eHTMLTag_xmp)){
returnTestBits(mParentBits,kBlock);
}
returnPR_FALSE;
}
inline PRBool IsBlockEntity(void)const { //该元素是否是block entity类元素,注意block entity在上面的定义,是kHeading|kList|kPreformatted|kBlock的并集
if((mTagID>=eHTMLTag_unknown)& (mTagID<=eHTMLTag_xmp)){
returnTestBits(mParentBits,kBlockEntity);
}
returnPR_FALSE;
}
inline PRBool IsSpecialEntity(void)const { //是否是kspecial类节点
if((mTagID>=eHTMLTag_unknown)& (mTagID<=eHTMLTag_xmp)){
returnTestBits(mParentBits,kSpecial);
}
returnPR_FALSE;
}
inline PRBool IsPhraseEntity(void)const { //是否是Phrase类节点
if((mTagID>=eHTMLTag_unknown)& (mTagID<=eHTMLTag_xmp)){
returnTestBits(mParentBits,kPhrase);
}
returnPR_FALSE;
}
inline PRBool IsFontStyleEntity(void)const { //是fontStyle类节点
if((mTagID>=eHTMLTag_unknown)& (mTagID<=eHTMLTag_xmp)){
returnTestBits(mParentBits,kFontStyle);
}
returnPR_FALSE;
}
inline PRBool IsTableElement(void)const { //return yes ifit's a table or child of a table...
//本方法会在该节点是Table或Table的子节点时返回true
PRBool result=PR_FALSE;
switch(mTagID){ //目前来看包含table, thead, tbody, tfoot, caption , tr, td, th, col, colgroup等这些节点,但是需要注意的是前面的kTable的注释所提到的节点并没有全部包含下面全部这些元素(因此这里也没有用该标示位进行判断)
caseeHTMLTag_table:
caseeHTMLTag_thead:
caseeHTMLTag_tbody:
caseeHTMLTag_tfoot:
caseeHTMLTag_caption:
caseeHTMLTag_tr:
caseeHTMLTag_td:
caseeHTMLTag_th:
caseeHTMLTag_col:
caseeHTMLTag_colgroup:
result=PR_TRUE;
break;
default:
result=PR_FALSE;
}
returnresult;
}
//获取某个节点的上一个“同类型”(同样的,或者定义了属于同类型的)节点
static PRInt32GetIndexOfChildOrSynonym(nsDTDContext& aContext,eHTMLTags aChildTag);
//获取该节点同类型的节点
const TagList* GetSynonymousTags(void)const {returnmSynonymousTags;}
//获取该类型的可用根节点(其实按照定义来讲,应该是在上下文中该节点之上的,且不能被该节点自动关闭的起始型节点)
const TagList* GetRootTags(void)const {returnmRootNodes;}
//获取该类型的可用“结束型”根节点(其实按照定义来讲,应该是上下文中该节点之上的,且不能被该节点自动关闭的结束型节点)
const TagList* GetEndRootTags(void)const {returnmEndRootNodes;}
const TagList* GetAutoCloseStartTags(void)const {returnmAutocloseStart;}
//获取可以被该类型节点的起始型节点自动关闭的节点
const TagList* GetAutoCloseEndTags(void)const {returnmAutocloseEnd;}
//获取可以被该类型节点的结束型节点自动关闭的节点
eHTMLTags GetCloseTargetForEndTag(nsDTDContext&aContext,PRInt32 anIndex,nsDTDMode aMode)const;
//获取该节点的特殊子节点(对于某些特殊节点,我们需要用这个位来对其某些特殊子节点的类型进行记录)
const TagList* GetSpecialChildren(void)const {returnmSpecialKids;}
//获取该节点的特殊父节点
const TagList* GetSpecialParents(void)const {returnmSpecialParents;}
PRBool IsMemberOf(PRInt32aType) const; //判断该节点是否属于某种类型
PRBool ContainsSet(PRInt32 aType) const; //判断该节点是否包含该类型
PRBool CanContainType(PRInt32 aType) const; // 判断该节点之下能够包含该类型
PRBool CanContain(eHTMLTags aChild,nsDTDMode aMode) const; //判断该节点在当前的DTD模式下是否能够包含该aChild节点作为子节点
PRBool CanExclude(eHTMLTags aChild) const; //判断该节点是否“不希望”包含该aChild作为子节点
PRBool CanOmitEndTag(void)const; //判断该节点是否能够“容忍”结束型节点作为它的子节点
PRBool CanContainSelf(void)const; //判断该节点是否能包含同类型的节点作为子节点
PRBool CanAutoCloseTag(nsDTDContext& aContext,PRInt32 aIndex,eHTMLTagsaTag)const; //这个方法用来判断该节点能否关闭当前上下文中的另一个节点(aTag)
PRBool HasSpecialProperty(PRInt32 aProperty) const; //判断该节点是否有某个特殊的属性
PRBool IsSpecialParent(eHTMLTags aTag) const; //判断aTag是否是该节点的特殊Parent
PRBool IsExcludableParent(eHTMLTags aParent) const; //判断该节点是否“不愿意”作为aParent的子节点
PRBool SectionContains(eHTMLTags aTag,PRBool allowDepthSearch)const; //如果设置了allowDepthSearch,则循环向上遍历aTag节点的mRootTags中的第一个节点,看看能否找到当前节点,否则只查看aTag的第一层父节点中是否包含当前节点
PRBool ShouldVerifyHierarchy() const; //如果该节点不能够包含同类型节点,那么我们必须在遇到该类型节点时查看一下当前上下文,确保它不会被意外地包含在了同类型节点之中
//判断在当前的DTD模式下,aParent是否能够包含aChild
static PRBool CanContain(eHTMLTagsaParent,eHTMLTags aChild,nsDTDMode aMode);
//判断aTag是否是一个容器
static PRBool IsContainer(eHTMLTagsaTag) ;
//判断aTag是否是一个RS类型节点
static PRBool IsResidualStyleTag(eHTMLTags aTag) ;
//判断aTag是否是文本类型节点
static PRBool IsTextTag(eHTMLTags aTag);
//判断aTag是否是空字符类型节点
static PRBool IsWhitespaceTag(eHTMLTagsaTag);
static PRBool IsBlockParent(eHTMLTagsaTag); //判断该节点是否能够包含block级节点作为子节点
static PRBool IsInlineParent(eHTMLTagsaTag); //判断该节点是否能够包含inline级节点作为子节点
static PRBool IsFlowParent(eHTMLTagsaTag); //判断该节点是否能够包含flow级节点作为子节点
static PRBool IsSectionTag(eHTMLTagsaTag); //判断该节点是否是section类型节点
static PRBool IsChildOfHead(eHTMLTagsaTag,PRBool& aExclusively) ; //判断该节点是否是能作为<head>节点的直接子节点,如果设置了aExclusively则查看该节点是否只能存在于head中
//下面,我们就可以看到nsHTMLTags这个结构体的所有属性了
eHTMLTags mTagID; //一个唯一的标示符,代表该节点的类型
eHTMLTags mRequiredAncestor; //标示该节点所需要的父节点
eHTMLTags mExcludingAncestor; //If set, the presence ofthe excl-ancestor prevents this from opening. //如果设置了这个位,那么excl-ancestor的出现将会防止该节点在上下文中被打开
const TagList* mRootNodes; //These are the tags above which you many not autoclose aSTART tag //在上下文中该节点之上的,且不能被该节点自动关闭的起始型节点
const TagList* mEndRootNodes; //These are the tags above which you many not autoclose anEND tag //在当前上下文中该节点之上的,且不能被该节点自动关闭的结束型节点
const TagList* mAutocloseStart; //these are the start tags that you can automatically closewith this START tag //在当前上下文中能被该节点的起始型节点自动关闭的节点
const TagList* mAutocloseEnd; //these are the start tags that you can automatically closewith this END tag //在当前上下文中能被该节点的结束型节点自动关闭的节点
const TagList* mSynonymousTags; //These are morally equivalent; an end tag for one can closea start tag for another (like <Hn>)
//同类型的节点:其中任何一个的结束型标签都可以关闭任何另一种类型的起始型标签,比如h1,h2,h3…就是同类型的节点
const TagList* mExcludableParents;//These are the TAGS thatcannot contain you
//这些是不能够包含该节点的父节点
int mParentBits; //defines groups that can contain this element
//定义可以包含该节点的父节点集合
int mInclusionBits; //defines parental and containment rules
//定义该节点作为父节点的包含规则
int mExclusionBits; //defines things you CANNOT contain
//定义该节点所不能够包含的类型
int mSpecialProperties;//used for various special purposes...
//一些特殊属性,用于多种用途
PRUint32 mPropagateRange; //tells us how far a parent is willing to prop. badlyformed children
//告诉我们一个parent能够为错误格式的子节点延展多远的距离。
const TagList* mSpecialParents; //These are the special tags that contain this tag(directly)
//这些是能够包含这个tag的特殊节点
const TagList* mSpecialKids; //These are the extra things you can contain
//这些是一些你能够额外包含的子节点
};
extern const nsHTMLElement gHTMLElements[];
//special property bits...
//下面就是可以设置mSepcialProperty的各种标示位的值了,每种值都代表了一种特殊的属性,比如kNonContainer,如果一个标签元素的mSepicalProperty中拥有这个标示位,那么就说明该元素不是容器类型
static constintkPreferBody = 0x0001; //this kHeadMisc tag prefers to be in the body if thereisn't an explicit <head>
static constintkOmitEndTag = 0x0002; //safely ignore end tag
static constintkLegalOpen = 0x0004; //Lets BODY, TITLE, SCRIPT to reopen
static constintkNoPropagate = 0x0008; //If set, this tag won't propagate as a child
static constintkBadContentWatch = 0x0010;
static constintkNoStyleLeaksIn = 0x0020;
static constintkNoStyleLeaksOut = 0x0040;
static constintkMustCloseSelf = 0x0080;
static constintkSaveMisplaced = 0x0100; //If set, then children this tag can't contain are pushedonto the misplaced stack
static constintkNonContainer = 0x0200; //If set, then this tag is not a container.
static constintkHandleStrayTag = 0x0400; //If set, we automatically open a start tag
static constintkRequiresBody = 0x0800; //If set, then in case of no BODY one will be opened upimmediately.
static constintkVerifyHierarchy = 0x1000; //If set, check to see if the tag is a child or a sibling..
static constintkPreferHead = 0x2000; //This kHeadMisc tag prefers to be in the head if thereisn't an explicit <body>
#endif
#include "nsIAtom.h"
#include "nsElementTable.h"
/*****************************************************************************
Now it's time to list all the html elementsall with their capabilities...
******************************************************************************/
//现在是时候列出所有html的元素列表以及它们所包含的所有属性了
//首先下面使用宏定义了一个声明列表的方法
#defineDECL_TAG_LIST(name_, list_) \
static consteHTMLTags name_##list[] = list_; \
static const TagListname_ = { NS_ARRAY_LENGTH(name_##list), name_##list };
#defineCOMMA , //逗号都用宏定义了一下
//First, define the set oftaglists for tags with special parents...
//首先,定义一下带有特殊父节点的元素的列表
//下面这些语句采用的都是前面所用到的宏定义
//比如下面这个DECL_TAG_LIST(gAParents,{eHTMLTag_map})就相当于
//static const eHTMLTags gAParentslist[]= {eHTMLTag_map}
//static const TagList gAParents ={NS_ARRAY_LENGTH(gAParentslist), gAParentslist}
//NS_ARRAY_LENGTH是一个求数组长度的宏定义比较好理解,需要注意的是eHTMLTag_map是在nsHTMLTags.h中,结合了nsHTMLTagList.h这个文件一起进行定义的,宏嵌套写得很好,有心的读者可以去看一下,这里的eHTMLTag_map相当于{‘m’,’a’,’p’,’\0’}
DECL_TAG_LIST(gAParents,{eHTMLTag_map})
DECL_TAG_LIST(gInAddress,{eHTMLTag_address})
DECL_TAG_LIST(gInHead,{eHTMLTag_head})
DECL_TAG_LIST(gInTable,{eHTMLTag_table})
DECL_TAG_LIST(gInHTML,{eHTMLTag_html})
DECL_TAG_LIST(gInBody,{eHTMLTag_body})
DECL_TAG_LIST(gInForm,{eHTMLTag_form})
DECL_TAG_LIST(gInFieldset,{eHTMLTag_fieldset})
DECL_TAG_LIST(gInTR,{eHTMLTag_tr})
DECL_TAG_LIST(gInDL,{eHTMLTag_dl COMMAeHTMLTag_body})
DECL_TAG_LIST(gInFrameset,{eHTMLTag_frameset})
DECL_TAG_LIST(gInNoframes,{eHTMLTag_noframes})
//Removed ADDRESS to solve24885
// gInP:nsHTMLElement::CanContain() also allows table in Quirks mode for bug 43678,removed FORM bug 94269
DECL_TAG_LIST(gInP,{eHTMLTag_span})
DECL_TAG_LIST(gOptgroupParents,{eHTMLTag_selectCOMMA eHTMLTag_optgroup})
DECL_TAG_LIST(gBodyParents,{eHTMLTag_htmlCOMMA eHTMLTag_noframes})
DECL_TAG_LIST(gColParents,{eHTMLTag_tableCOMMA eHTMLTag_colgroup})
DECL_TAG_LIST(gFramesetParents,{eHTMLTag_htmlCOMMA eHTMLTag_frameset})
DECL_TAG_LIST(gLegendParents,{eHTMLTag_fieldset})
DECL_TAG_LIST(gAreaParent,{eHTMLTag_map})
DECL_TAG_LIST(gParamParents,{eHTMLTag_appletCOMMA eHTMLTag_object})
DECL_TAG_LIST(gTRParents,{eHTMLTag_tbodyCOMMA eHTMLTag_tfoot COMMA eHTMLTag_thead COMMA eHTMLTag_table})
DECL_TAG_LIST(gTREndParents,{eHTMLTag_tbodyCOMMA eHTMLTag_tfoot COMMA eHTMLTag_thead COMMA eHTMLTag_table COMMAeHTMLTag_applet})
#ifdefMOZ_MEDIA
DECL_TAG_LIST(gSourceParents,{eHTMLTag_videoCOMMA eHTMLTag_audio})
#endif
//*********************************************************************************************
// Next, define the set of taglists for tagswith special kids...
//*********************************************************************************************
//现在,定义一下带有特殊子节点的tags列表
DECL_TAG_LIST(gContainsText,{eHTMLTag_textCOMMA eHTMLTag_newline COMMA eHTMLTag_whitespace COMMA eHTMLTag_entity})
DECL_TAG_LIST(gUnknownKids,{eHTMLTag_htmlCOMMA eHTMLTag_frameset})
// The presence of<input>, <select>, and <textarea> in gContainsOpts is due to
// the exclgroup that<select> sets... If I don'tinclude those here, they
// just get droppedautomatically, since they are not allowed to open inside
// <select>. Note that we are NOT allowing them toactually open without
// closing the select -- seegInputAutoClose. Further note that I'mnot
// including <button>in the list because in IE it doesn't autoclose <select>!
//<input>,<select>和<textarea>在gContainsOpts中的出现是由于<select>的排斥列表exclgroup…如果我不在这里包含这些,它们则会被自动地抛弃掉,因为他们本不允许在<select>中打开。注意到我们并不是允许他们在关闭<select>之前就打开---请查看gInputAutoClose。另外,因为在IE中它不会自动关闭<select>,因此我没有在该列表中包含<button>节点!
DECL_TAG_LIST(gContainsOpts,{eHTMLTag_optionCOMMA eHTMLTag_optgroup COMMA eHTMLTag_script COMMA eHTMLTag_input COMMAeHTMLTag_select COMMA eHTMLTag_textarea })
// Similar deal for<option> except it allows all of gContainsText _and_ the things thatshould autoclose selects.
//<option>的处理方法也类似,只不过它允许所有的gContainsText以及那些应当自动关闭selects的东西。
DECL_TAG_LIST(gContainedInOpt,{eHTMLTag_textCOMMA eHTMLTag_newline COMMA eHTMLTag_whitespace COMMA eHTMLTag_entity COMMAeHTMLTag_input COMMA eHTMLTag_select COMMA eHTMLTag_textarea})
DECL_TAG_LIST(gContainsParam,{eHTMLTag_param})
DECL_TAG_LIST(gColgroupKids,{eHTMLTag_col})
DECL_TAG_LIST(gAddressKids,{eHTMLTag_p})
DECL_TAG_LIST(gBodyKids,{eHTMLTag_ddCOMMA eHTMLTag_del COMMA eHTMLTag_dt COMMA eHTMLTag_ins COMMA eHTMLTag_noscript COMMA eHTMLTag_script COMMAeHTMLTag_li COMMA eHTMLTag_param})// Added PARAM forbug 54448
DECL_TAG_LIST(gButtonKids,{eHTMLTag_captionCOMMA eHTMLTag_legend})
DECL_TAG_LIST(gDLRootTags,{eHTMLTag_bodyCOMMA eHTMLTag_td COMMA eHTMLTag_table COMMA eHTMLTag_applet COMMAeHTMLTag_dd})
DECL_TAG_LIST(gDLKids,{eHTMLTag_dd COMMAeHTMLTag_dt})
DECL_TAG_LIST(gDTKids,{eHTMLTag_dt})
DECL_TAG_LIST(gFieldsetKids,{eHTMLTag_legendCOMMA eHTMLTag_text})
DECL_TAG_LIST(gFontKids,{eHTMLTag_legendCOMMA eHTMLTag_table COMMA eHTMLTag_text COMMA eHTMLTag_li})// Added table to fix bug 93365, li to fix bug 96031
DECL_TAG_LIST(gFormKids,{eHTMLTag_keygen})
DECL_TAG_LIST(gFramesetKids,{eHTMLTag_frameCOMMA eHTMLTag_frameset COMMA eHTMLTag_noframes})
DECL_TAG_LIST(gHtmlKids,{eHTMLTag_bodyCOMMA eHTMLTag_frameset COMMA eHTMLTag_head COMMA eHTMLTag_noscript COMMAeHTMLTag_noframes COMMA eHTMLTag_script COMMA eHTMLTag_newline COMMAeHTMLTag_whitespace})
DECL_TAG_LIST(gLabelKids,{eHTMLTag_span})
DECL_TAG_LIST(gLIKids,{eHTMLTag_ol COMMAeHTMLTag_ul})
DECL_TAG_LIST(gMapKids,{eHTMLTag_area})
DECL_TAG_LIST(gPreKids,{eHTMLTag_hrCOMMA eHTMLTag_center}) //note that CENTER is here for backward compatibility; it'snot 4.0 spec.
DECL_TAG_LIST(gTableKids,{eHTMLTag_captionCOMMA eHTMLTag_col COMMA eHTMLTag_colgroup COMMA eHTMLTag_form COMMA eHTMLTag_thead COMMA eHTMLTag_tbody COMMAeHTMLTag_tfoot COMMA eHTMLTag_script})// RemovedINPUT - Ref. Bug 20087, 25382
DECL_TAG_LIST(gTableElemKids,{eHTMLTag_formCOMMA eHTMLTag_noscript COMMA eHTMLTag_script COMMA eHTMLTag_td COMMA eHTMLTag_thCOMMA eHTMLTag_tr})
DECL_TAG_LIST(gTRKids,{eHTMLTag_td COMMAeHTMLTag_th COMMA eHTMLTag_form COMMA eHTMLTag_script})//Removed INPUT - Ref. Bug 20087, 25382 | Removed MAP to fix 58942
DECL_TAG_LIST(gTBodyKids,{eHTMLTag_trCOMMA eHTMLTag_form}) // Removed INPUT - Ref. Bug20087, 25382
DECL_TAG_LIST(gULKids,{eHTMLTag_li COMMAeHTMLTag_p})
#ifdefMOZ_MEDIA
DECL_TAG_LIST(gVideoKids,{eHTMLTag