Mozilla FireFox Gecko内核源代码解析(6.nsElementTable)

来源:互联网 发布:懂球帝是腾讯软件吗 编辑:程序博客网 时间:2024/06/03 18:10

Mozilla FireFox Gecko内核源代码解析

(6.nsElementTable)

中科院计算技术研究所网络数据科学与工程研究中心

信息抽取小组

耿耘

gengyun@sohu.com

上一章中我们介绍了负责语法解析的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 BUTTONstatic constint kPreformatted  = 0x0020; //  PREstatic constintkPreExclusion  = 0x0040; //  IMG,  OBJECT, APPLET, BIG,  SMALL, SUB,  SUP,  FONT, BASEFONTstatic constintkFontStyle     = 0x0080; //  TT, I, B, U, S,STRIKE, BIG, SMALL, BLINKstatic constintkPhrase        = 0x0100; //  EM, STRONG, DFN,CODE, SAMP, KBD, VAR, CITE, ABBR, ACRONYMstatic constintkHeading       = 0x0200; //  H1..H6static constintkBlockMisc     = 0x0400; //  OBJECT, SCRIPTstatic constint kBlock         = 0x0800; //  ADDRESS, BLOCKQUOTE, CENTER, DIV, DL,FIELDSET, FORM,                                          //  ISINDEX, HR,NOSCRIPT, NOFRAMES, P, TABLEstatic constint kList          = 0x1000; //  UL, OL, DIR, MENUstatic constintkPCDATA        = 0x2000; //  plain text andentities...static constint kSelf          = 0x4000; //  whatever THIS tag is...static constintkExtensions    = 0x8000; //  BGSOUND, WBR,NOBRstatic constint kTable         = 0x10000;// TR,TD,THEAD,TBODY,TFOOT,CAPTION,THstatic constintkDLChild       = 0x20000;// DL, DTstatic constint kCDATA         = 0x40000;// just plain text...  static constintkInlineEntity  =(kPCDATA|kFontStyle|kPhrase|kSpecial|kFormControl|kExtensions); //  #PCDATA, %fontstyle, %phrase, %special,%formctrlstatic constint kBlockEntity   = (kHeading|kList|kPreformatted|kBlock);//  %heading, %list,%preformatted, %blockstatic constintkFlowEntity    =(kBlockEntity|kInlineEntity); //  %blockentity, %inlineentitystatic constintkAllTags       = 0xffffff; #ifdefNS_DEBUGextern 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 tagstatic constintkLegalOpen        = 0x0004; //Lets BODY, TITLE, SCRIPT to reopenstatic constintkNoPropagate      = 0x0008; //If set, this tag won't propagate as a childstatic 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 stackstatic constintkNonContainer     = 0x0200; //If set, then this tag is not a container.static constintkHandleStrayTag   = 0x0400; //If set, we automatically open a start tagstatic 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 94269DECL_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_MEDIADECL_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 54448DECL_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 96031DECL_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 58942DECL_TAG_LIST(gTBodyKids,{eHTMLTag_trCOMMA eHTMLTag_form}) // Removed INPUT - Ref. Bug20087, 25382DECL_TAG_LIST(gULKids,{eHTMLTag_li COMMAeHTMLTag_p})#ifdefMOZ_MEDIADECL_TAG_LIST(gVideoKids,{eHTMLTag_source})DECL_TAG_LIST(gAudioKids,{eHTMLTag_source})#endif //*********************************************************************************************// The following tag listsare used to define common set of root notes for the HTML elements...//********************************************************************************************* //下面的tag列表用来为HTML元素们定义一些HTML元素通用的根节点结合DECL_TAG_LIST(gRootTags,{eHTMLTag_bodyCOMMA eHTMLTag_td COMMA eHTMLTag_table COMMA eHTMLTag_applet COMMAeHTMLTag_select})// Added SELECT to fix bug 98645DECL_TAG_LIST(gTableRootTags,{eHTMLTag_appletCOMMA eHTMLTag_body COMMA eHTMLTag_dl COMMA eHTMLTag_ol COMMA eHTMLTag_td COMMAeHTMLTag_th})DECL_TAG_LIST(gHTMLRootTags,{eHTMLTag_unknown}) DECL_TAG_LIST(gLIRootTags,{eHTMLTag_ulCOMMA eHTMLTag_ol COMMA eHTMLTag_dir COMMA eHTMLTag_menu COMMA eHTMLTag_p COMMAeHTMLTag_body COMMA eHTMLTag_td COMMA eHTMLTag_th}) DECL_TAG_LIST(gOLRootTags,{eHTMLTag_bodyCOMMA eHTMLTag_li COMMA eHTMLTag_td COMMA eHTMLTag_th COMMA eHTMLTag_select})DECL_TAG_LIST(gTDRootTags,{eHTMLTag_trCOMMA eHTMLTag_tbody COMMA eHTMLTag_thead COMMA eHTMLTag_tfoot COMMAeHTMLTag_table COMMA eHTMLTag_applet})DECL_TAG_LIST(gNoframeRoot,{eHTMLTag_bodyCOMMA eHTMLTag_frameset}) //*********************************************************************************************// The following tag listsare used to define the autoclose properties of the html elements...//*********************************************************************************************//下面定义了一些可以进行自动关闭的元素集合DECL_TAG_LIST(gBodyAutoClose,{eHTMLTag_head})  //比如body可以自动关闭head节点DECL_TAG_LIST(gTBodyAutoClose,{eHTMLTag_theadCOMMA eHTMLTag_tfoot COMMA eHTMLTag_tbody COMMA eHTMLTag_td COMMAeHTMLTag_th}) //TD|TH inclusion - Bug# 24112DECL_TAG_LIST(gCaptionAutoClose,{eHTMLTag_tbody})DECL_TAG_LIST(gLIAutoClose,{eHTMLTag_pCOMMA eHTMLTag_li})DECL_TAG_LIST(gPAutoClose,{eHTMLTag_pCOMMA eHTMLTag_li})DECL_TAG_LIST(gHRAutoClose,{eHTMLTag_p})DECL_TAG_LIST(gOLAutoClose,{eHTMLTag_pCOMMA eHTMLTag_ol})DECL_TAG_LIST(gDivAutoClose,{eHTMLTag_p})// Form controls thatautoclose <select> use thisDECL_TAG_LIST(gInputAutoClose,{eHTMLTag_selectCOMMA eHTMLTag_optgroup COMMA eHTMLTag_option}) DECL_TAG_LIST(gHeadingTags,{eHTMLTag_h1COMMA eHTMLTag_h2 COMMA eHTMLTag_h3 COMMA eHTMLTag_h4 COMMA eHTMLTag_h5 COMMAeHTMLTag_h6}) DECL_TAG_LIST(gTableCloseTags,{eHTMLTag_tdCOMMA eHTMLTag_tr COMMA eHTMLTag_th COMMA eHTMLTag_tbody COMMA eHTMLTag_theadCOMMA eHTMLTag_tfoot})DECL_TAG_LIST(gTRCloseTags,{eHTMLTag_trCOMMA eHTMLTag_td COMMA eHTMLTag_th})DECL_TAG_LIST(gTDCloseTags,{eHTMLTag_tdCOMMA eHTMLTag_th})DECL_TAG_LIST(gDTCloseTags,{eHTMLTag_pCOMMA eHTMLTag_dd COMMA eHTMLTag_dt})DECL_TAG_LIST(gULCloseTags,{eHTMLTag_li})DECL_TAG_LIST(gULAutoClose,{eHTMLTag_pCOMMA eHTMLTag_ul}) //fix bug 50261.. DECL_TAG_LIST(gExcludableParents,{eHTMLTag_pre})// Ref Bug 22913DECL_TAG_LIST(gCaptionExcludableParents,{eHTMLTag_td})//Ref Bug 26488 //*********************************************************************************************//Lastly, bind tags withtheir rules, their special parents and special kids.//*********************************************************************************************//最后,我们将tag和相应的规则,它们的特殊父节点,特殊子节点等绑定起来。//首先我们定义一下一些常用的值,它们是进行延展的距离const int kNoPropRange=0;const int kDefaultPropRange=1;const int kBodyPropRange=2; //*********************************************************************************************////        Now let's declare the element table...////*********************************************************************************************//下面就是最重要的元素列表了,这个列表中声明了所有种类的html tag,以及利用前面的列表为他们相应的属性进行赋值,这样就相当于间接定义了它们的语法规则。//本列表中普通tag元素共计104个,另外还有3个mozilla自定义的media元素,以及本不属于tag类型,但是仍然被包含进来的如text,newline,comment等共计8个其他类型元素。其中还包括了当前HTML5规范中W3C所定义的所有类型标签。//由于大部分元素声明的格式都很类似,因此我们只挑几个例子来进行详细说明,其他的部分读者可以参考着例子进行理解。constnsHTMLElement gHTMLElements[] = { {   /*tag*/                             eHTMLTag_unknown,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,    /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kNone,   /*special props, prop-range*/       kNonContainer, 10,   /*special parents,kids*/            0,&gUnknownKids, }, //上面这个元素unknown为默认的空节点,它的所有属性都是空,可以参考着看一下。  //下面这个tag类型代表了<a>节点  //该节点没有必要的父节点,或者排斥的父节点  //该节点的可以包含于普通的根节点集合里  //它可以包含在kSpecial列表中的节点下,而它之下可以包含kInlineEntity所包含的所有类型节点,它没有任何可以防止它打开的祖先节点。需要注意的是,虽然kInlineEntity中包含<a>,但是它没有kSelf这个标示位,因此它不能包含其他同类型<a>节点  //它在打开的时候需要进行继承检查,对其进行的延展的最大深度为1  //它没有特殊的父节点和子节点 {   /*tag*/                             eHTMLTag_a,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kInlineEntity, kNone,    /*special props, prop-range*/       kVerifyHierarchy, kDefaultPropRange,   /*special parents,kids*/            0,0, },     //下面这个tag类型代表了<abbr>节点     //该节点没有必要的父节点,或者排斥的父节点     //该节点可以包含于普通的根节点集合里     //它可以包含在kPhrase列表中的节点下,而它之下可以包含kSelf和kInlineEntity所包含的所有类型节点,说明它也可以包含它自己,也就是说<abbr>中还可以包含其他<abbr>作为子节点。     //它没有特殊属性,对其进行延展的最大深度为1     //它没有特殊的父节点和子节点 {   /*tag*/                             eHTMLTag_abbr,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_acronym,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_address,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, kInlineEntity, kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,&gAddressKids, }, {   /*tag*/                             eHTMLTag_applet,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial,(kSelf|kInlineEntity|kFlowEntity), kNone,   /*special props, prop-range*/       kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            0,&gContainsParam, }, {   /*tag*/                             eHTMLTag_area,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gAreaParent,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kInlineEntity, kSelf,   /*special props, prop-range*/       kNonContainer,kDefaultPropRange,   /*special parents,kids*/            &gAreaParent,0, },#if defined(MOZ_MEDIA)  {    /*tag*/                             eHTMLTag_audio,    /*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|kSelf), kNone,    /*special props, prop-range*/       0,kDefaultPropRange,    /*special parents,kids*/            0,&gAudioKids,  }, {   /*tag*/                             eHTMLTag_b,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kInlineEntity|kSelf),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_base,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInHead,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kHeadContent, kNone, kNone,   /*special props, prop-range*/       kNonContainer, kNoPropRange,   /*special parents,kids*/            &gInHead,0, }, {   /*tag*/                             eHTMLTag_basefont,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kInlineEntity, kNone,   /*special props, prop-range*/       kNonContainer, kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_bdo,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_bgsound,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          (kFlowEntity|kHeadMisc), kNone,kNone,   /*special props, prop-range*/       kNonContainer,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_big,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kInlineEntity|kSelf),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, },   {   /*tag*/                             eHTMLTag_blink,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kFlowEntity|kSelf), kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                            eHTMLTag_blockquote,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0, //removeexcludeable parents to fix bug 53473   /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_body,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_frameset,   /*rootnodes,endrootnodes*/          &gInHTML,&gInHTML,   /*autoclose starttags and endtags*/&gBodyAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kHTMLContent,(kFlowEntity|kSelf),kNone,   /*special props, prop-range*/       kOmitEndTag, kBodyPropRange,   /*special parents,kids*/            0,&gBodyKids, }, {   /*tag*/                             eHTMLTag_br,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,   /*special props, prop-range*/       kRequiresBody|kNonContainer,kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_button,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFormControl, kFlowEntity,kFormControl,   /*special props, prop-range*/       kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            0,&gButtonKids, }, {   /*tag*/                             eHTMLTag_canvas,   /*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|kSelf), kNone,    /*special props,prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_caption,   /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInTable,&gInTable,   /*autoclose starttags and endtags*/&gCaptionAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kNone, kFlowEntity, kSelf,   /*special props, prop-range*/       (kNoPropagate|kNoStyleLeaksOut),kDefaultPropRange,   /*special parents,kids*/            &gInTable,0, }, {   /*tag*/                             eHTMLTag_center,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, },  {   /*tag*/                             eHTMLTag_cite,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_code,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_col,   /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gColParents,&gColParents,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kNone,   /*special props, prop-range*/      kNoPropagate|kNonContainer,kDefaultPropRange,   /*special parents,kids*/            &gColParents,0, }, {   /*tag*/                             eHTMLTag_colgroup,   /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInTable,&gInTable,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kNone,   /*special props, prop-range*/       kNoPropagate,kDefaultPropRange,   /*special parents,kids*/            &gInTable,&gColgroupKids, }, {   /*tag*/                             eHTMLTag_dd,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gDTCloseTags,0,&gDLKids,0,   /*parent,incl,exclgroups*/          kInlineEntity, kFlowEntity, kNone,   /*special props, prop-range*/      kNoPropagate|kMustCloseSelf|kVerifyHierarchy|kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            &gInDL,0, }, {   /*tag*/                             eHTMLTag_del,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, (kSelf|kFlowEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            &gInBody,0, }, {   /*tag*/                             eHTMLTag_dfn,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_dir,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gOLRootTags,&gOLRootTags,   /*autoclose starttags and endtags*/&gOLAutoClose, &gULCloseTags, 0,0,   /*parent,incl,exclgroups*/          kList, (kFlowEntity|kSelf), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,&gULKids, }, {   /*tag*/                             eHTMLTag_div,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gDivAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_dl,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gDLRootTags,&gRootTags, //fix bug 57634   /*autoclose starttags and endtags*/0,0,0,&gDTKids,           // DT should not contain DL - bug 100466   /*parent,incl,exclgroups*/          kBlock, kSelf|kFlowEntity, kNone,   /*special props, prop-range*/       0, kNoPropRange,   /*special parents,kids*/            0,&gDLKids, }, {   /*tag*/                            eHTMLTag_dt,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gDTCloseTags,0,&gDLKids,0,   /*parent,incl,exclgroups*/          kInlineEntity,(kFlowEntity-kHeading), kNone, // dt's parent group is inline - bug 65467   /*special props, prop-range*/      (kNoPropagate|kMustCloseSelf|kVerifyHierarchy|kRequiresBody),kDefaultPropRange,   /*special parents,kids*/            &gInDL,0, }, {   /*tag*/                             eHTMLTag_em,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_embed,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,   /*special props, prop-range*/      kNonContainer|kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            0,&gContainsParam, }, {   /*tag*/                             eHTMLTag_fieldset,   /*requiredAncestor*/               eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       kNoPropagate,kDefaultPropRange,   /*special parents,kids*/            0,&gFieldsetKids, }, {   /*tag*/                             eHTMLTag_font,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,&gFontKids, }, {   /*tag*/                             eHTMLTag_form,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, kFlowEntity, kNone,   /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,   /*special parents,kids*/            0,&gFormKids, }, {   /*tag*/                             eHTMLTag_frame,   /*req-parent excl-parent*/          eHTMLTag_frameset,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInFrameset,&gInFrameset,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kNone,   /*special props, prop-range*/      kNoPropagate|kNoStyleLeaksIn|kNonContainer, kNoPropRange,   /*special parents,kids*/            &gInFrameset,0, }, {   /*tag*/                             eHTMLTag_frameset,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_body,   /*rootnodes,endrootnodes*/          &gFramesetParents,&gInHTML,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kHTMLContent, kSelf, kAllTags,   /*special props, prop-range*/       kNoPropagate|kNoStyleLeaksIn,kNoPropRange,   /*special parents,kids*/            &gInHTML,&gFramesetKids, },  {   /*tag*/                             eHTMLTag_h1,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHeadingTags,  &gHeadingTags,&gHeadingTags,0,   /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,   /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_h2,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHeadingTags,  &gHeadingTags,&gHeadingTags,0,   /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,   /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_h3,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHeadingTags,  &gHeadingTags,&gHeadingTags,0,   /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,   /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_h4,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHeadingTags,  &gHeadingTags,&gHeadingTags,0,   /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,   /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_h5,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHeadingTags,  &gHeadingTags,&gHeadingTags,0,   /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,   /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_h6,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHeadingTags,  &gHeadingTags,&gHeadingTags,0,   /*parent,incl,exclgroups*/          kHeading, kFlowEntity, kNone,   /*special props, prop-range*/       kVerifyHierarchy,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_head,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInHTML,&gInHTML,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kHTMLContent,(kHeadContent|kHeadMisc), kNone,   /*special props, prop-range*/       kNoStyleLeaksIn, kDefaultPropRange,   /*special parents,kids*/            &gInHTML,0, }, {   /*tag*/                             eHTMLTag_hr,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gHRAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kBlock, kNone, kNone,   /*special props, prop-range*/      kNonContainer|kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_html,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_html,    /*rootnodes,endrootnodes*/         &gHTMLRootTags,&gHTMLRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kHTMLContent, kNone,   /*special props, prop-range*/       kSaveMisplaced|kOmitEndTag|kNoStyleLeaksIn,kDefaultPropRange,   /*special parents,kids*/            0,&gHtmlKids, }, {   /*tag*/                             eHTMLTag_i,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_iframe,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_image,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,   /*special props, prop-range*/       kNonContainer,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_img,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,   /*special props, prop-range*/       kNonContainer|kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_input,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gInputAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kFormControl, kNone, kNone,   /*special props, prop-range*/      kNonContainer|kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_ins,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, (kSelf|kFlowEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_isindex,   /*requiredAncestor*/               eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, kFlowEntity, kNone,   /*special props, prop-range*/      kNonContainer|kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            &gInBody,0, }, {   /*tag*/                             eHTMLTag_kbd,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_keygen,   /*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,   /*special props, prop-range*/       kNonContainer,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_label,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFormControl, kInlineEntity, kSelf,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,&gLabelKids, }, {   /*tag*/                             eHTMLTag_legend,   /*requiredAncestor*/               eHTMLTag_fieldset,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInFieldset,&gInFieldset,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kInlineEntity, kNone,   /*special props, prop-range*/       kRequiresBody,kDefaultPropRange,   /*special parents,kids*/            &gInFieldset,0, }, {   /*tag*/                             eHTMLTag_li,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gLIRootTags,&gLIRootTags,   /*autoclose starttags and endtags*/&gLIAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kBlockEntity, kFlowEntity, kSelf,// changed this back to kBlockEntity so we enable RShandling for phrasals. ref bug 181697   /*special props, prop-range*/      kNoPropagate|kVerifyHierarchy|kRequiresBody, kDefaultPropRange,   /*special parents,kids*/            0,&gLIKids, }, {   /*tag*/                             eHTMLTag_link,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInHead,&gInHead,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kAllTags - kHeadContent, kNone,kNone,   /*special props, prop-range*/      kNonContainer|kPreferHead|kLegalOpen,kDefaultPropRange,   /*special parents,kids*/            &gInHead,0, }, {   /*tag*/                             eHTMLTag_listing,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPreformatted, (kSelf|kFlowEntity),kNone, //addflowentity to fix 54993   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_map,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kInlineEntity|kBlockEntity,kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,&gMapKids, }, {   /*tag*/                             eHTMLTag_marquee,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       kRequiresBody, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_menu,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kList, (kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,&gULKids, }, {   /*tag*/                             eHTMLTag_meta,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInHead,&gInHead,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kHeadContent, kNone, kNone,   /*special props, prop-range*/       kNoStyleLeaksIn|kNonContainer,kDefaultPropRange,   /*special parents,kids*/            &gInHead,0, }, {   /*tag*/                             eHTMLTag_multicol,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, kFlowEntity, kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_nobr,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclosestarttags and endtags*/ 0,0,0,0,   /*parent,incl,exclgroups*/          kExtensions, kFlowEntity, kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_noembed,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, kFlowEntity, kNone,   /*special props, prop-range*/       0, kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_noframes,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gNoframeRoot,&gNoframeRoot,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, kFlowEntity, kNone,   /*special props, prop-range*/       0,kNoPropRange,   /*special parents,kids*/            &gNoframeRoot,0, }, {   /*tag*/                             eHTMLTag_noscript,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc,kFlowEntity|kSelf, kNone,   /*special props, prop-range*/       0, kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_object,   /*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|kSelf), kNone,   /*special props, prop-range*/      kNoStyleLeaksOut|kPreferBody,kDefaultPropRange,   /*special parents,kids*/            0,&gContainsParam, }, {   /*tag*/                             eHTMLTag_ol,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gOLRootTags,&gOLRootTags,   /*autoclose starttags and endtags*/&gOLAutoClose, &gULCloseTags, 0,0,   /*parent,incl,exclgroups*/          kList, (kFlowEntity|kSelf), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,     /*special parents,kids*/            0,&gULKids, }, {   /*tag*/                             eHTMLTag_optgroup,   /*requiredAncestor*/               eHTMLTag_select,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/         &gOptgroupParents,&gOptgroupParents,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/           &gOptgroupParents,&gContainsOpts, }, {   /*tag*/                             eHTMLTag_option,   /*requiredAncestor*/                eHTMLTag_select,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/         &gOptgroupParents,&gOptgroupParents,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kNone, kPCDATA,kFlowEntity|kHeadMisc,   /*special props, prop-range*/       kNoStyleLeaksIn|kNoPropagate,kDefaultPropRange,   /*special parents,kids*/           &gOptgroupParents,&gContainedInOpt, }, {   /*tag*/                             eHTMLTag_p,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock, kInlineEntity, kNone,     //this used tocontain FLOW. But it's really an inline container.   /*special props, prop-range*/       kHandleStrayTag,kDefaultPropRange,//otherwise it tries to contain things like H1..H6   /*special parents,kids*/            0,&gInP, }, {   /*tag*/                             eHTMLTag_param,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/         &gParamParents,&gParamParents,   /*autoclose starttags and endtags*/&gPAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,   /*special props, prop-range*/       kNonContainer, kNoPropRange,   /*special parents,kids*/            &gParamParents,0, }, {   /*tag*/                            eHTMLTag_plaintext,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kExtensions, kCDATA, kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_pre,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kBlock|kPreformatted,(kSelf|kFlowEntity), kNone, // Note: PRE is a block level element - bug 80009   /*special props, prop-range*/       kRequiresBody, kDefaultPropRange,   /*special parents,kids*/            0,&gPreKids, }, {   /*tag*/                             eHTMLTag_q,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_s,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_samp,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_script,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*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*/            0,&gContainsText, }, {   /*tag*/                             eHTMLTag_select,   /*requiredAncestor*/                eHTMLTag_unknown, eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInForm,&gInForm,   /*autoclose starttags and endtags*/&gInputAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kFormControl, kNone,kFlowEntity|kDLChild|kHeadMisc,// Added kHeadMisc tofix bug 287349   /*special props, prop-range*/      kNoPropagate|kNoStyleLeaksIn|kRequiresBody, kDefaultPropRange,   /*special parents,kids*/            &gInForm,&gContainsOpts, }, {   /*tag*/                             eHTMLTag_small,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, },#if defined(MOZ_MEDIA)  {    /*tag*/                             eHTMLTag_source,    /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,    /*rootnodes,endrootnodes*/         &gSourceParents,&gSourceParents,    /*autoclose starttags and endtags*/&gPAutoClose, 0, 0,0,    /*parent,incl,exclgroups*/          kSpecial, kNone, kNone,    /*special props, prop-range*/       kNonContainer,kNoPropRange,    /*special parents,kids*/            &gSourceParents,0,  },#endif  {      /*tag*/                             eHTMLTag_spacer,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kExtensions, kNone, kNone,   /*special props, prop-range*/       kNonContainer,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {            // I made span a special% tag again, (insteadof inline).         // This fixes the case:  <fontcolor="blue"><p><span>text</span>    /*tag*/                             eHTMLTag_span,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial,(kInlineEntity|kSelf|kFlowEntity), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {      /*tag*/                             eHTMLTag_strike,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {      /*tag*/                             eHTMLTag_strong,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone, //changedthis to inline per spec; fix bug 44584.   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,&gContainsText, }, {      /*tag*/                             eHTMLTag_style,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,    /*autoclosestarttags and endtags*/ 0,0,0,0,   /*parent,incl,exclgroups*/          kAllTags - kHeadContent, kCDATA,kNone,   /*special props, prop-range*/       kNoStyleLeaksIn|kPreferHead|kLegalOpen,kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_sub,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {      /*tag*/                             eHTMLTag_sup,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kSpecial, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_table,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/         &gTableRootTags,&gTableRootTags,   /*autoclose starttags and endtags*/0,&gTableCloseTags,0,0,   /*parent,incl,exclgroups*/          kBlock, kNone, (kSelf|kInlineEntity),   /*special props, prop-range*/       (kBadContentWatch|kNoStyleLeaksIn|kRequiresBody),2,   /*special parents,kids*/            0,&gTableKids, }, {   /*tag*/                             eHTMLTag_tbody,   /*requiredAncestor*/                eHTMLTag_table,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInTable,&gInTable,   /*autoclose starttags and endtags*/&gTBodyAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, (kSelf|kInlineEntity),   /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut),kDefaultPropRange,   /*special parents,kids*/            &gInTable,&gTBodyKids, }, {   /*tag*/                             eHTMLTag_td,   /*requiredAncestor*/                eHTMLTag_table, eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gTDRootTags,&gTDRootTags,   /*autoclose starttags and endtags*/&gTDCloseTags,&gTDCloseTags,0,&gExcludableParents,   /*parent,incl,exclgroups*/          kNone, kFlowEntity, kSelf,   /*special props, prop-range*/       kNoStyleLeaksIn|kNoStyleLeaksOut,kDefaultPropRange,   /*special parents,kids*/            &gTDRootTags,&gBodyKids, }, {   /*tag*/                             eHTMLTag_textarea,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInForm,&gInForm,   /*autoclose starttags and endtags*/&gInputAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kFormControl, kPCDATA, kNone,   /*special props, prop-range*/       kRequiresBody|kNoStyleLeaksIn,kDefaultPropRange,   /*special parents,kids*/            &gInForm,&gContainsText, }, {   /*tag*/                             eHTMLTag_tfoot,   /*requiredAncestor*/                eHTMLTag_table,eHTMLTag_unknown,    /*rootnodes,endrootnodes*/          &gInTable,&gInTable,   /*autoclose starttags and endtags*/&gTBodyAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kSelf,   /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut),kNoPropRange,   /*special parents,kids*/            &gInTable,&gTableElemKids, }, {   /*tag*/                             eHTMLTag_th,   /*requiredAncestor*/                eHTMLTag_table,eHTMLTag_unknown,    /*rootnodes,endrootnodes*/          &gTDRootTags,&gTDRootTags,   /*autoclose starttags and endtags*/&gTDCloseTags,&gTDCloseTags,0,0,   /*parent,incl,exclgroups*/          kNone, kFlowEntity, kSelf,   /*special props, prop-range*/       (kNoStyleLeaksIn|kNoStyleLeaksOut),kDefaultPropRange,   /*special parents,kids*/            &gTDRootTags,&gBodyKids, }, {   /*tag*/                             eHTMLTag_thead,   /*req-parent excl-parent*/          eHTMLTag_table,eHTMLTag_unknown, //fix bug 54840...   /*rootnodes,endrootnodes*/          &gInTable,&gInTable,    /*autoclose starttags and endtags*/&gTBodyAutoClose,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kSelf,   /*special props, prop-range*/       (kNoPropagate|kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut),kNoPropRange,   /*special parents,kids*/            &gInTable,&gTableElemKids, }, {   /*tag*/                             eHTMLTag_title,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInHead,&gInHead,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kHeadContent,kPCDATA, kNone,   /*special props, prop-range*/       kNoStyleLeaksIn, kNoPropRange,   /*special parents,kids*/            &gInHead,&gContainsText, }, {   /*tag*/                             eHTMLTag_tr,   /*requiredAncestor*/                eHTMLTag_table,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gTRParents,&gTREndParents,   /*autoclose starttags and endtags*/&gTRCloseTags,0,0,0,   /*parent,incl,exclgroups*/          kNone, kNone, kInlineEntity,   /*special props, prop-range*/      (kBadContentWatch|kNoStyleLeaksIn|kNoStyleLeaksOut), kNoPropRange,   /*special parents,kids*/            &gTRParents,&gTRKids, }, {   /*tag*/                             eHTMLTag_tt,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {    /*tag*/                             eHTMLTag_u,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFontStyle, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0, kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_ul,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gOLRootTags,&gOLRootTags,   /*autoclose starttags and endtags*/&gULAutoClose,&gULCloseTags,0,0,   /*parent,incl,exclgroups*/          kList, (kFlowEntity|kSelf), kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,&gULKids, }, {   /*tag*/                             eHTMLTag_var,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kPhrase, (kSelf|kInlineEntity),kNone,   /*special props, prop-range*/       0,kDefaultPropRange,   /*special parents,kids*/            0,0, },#if defined(MOZ_MEDIA)  {    /*tag*/                             eHTMLTag_video,    /*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|kSelf), kNone,    /*special props, prop-range*/       0,kDefaultPropRange,    /*special parents,kids*/            0,&gVideoKids,  },#endif {   /*tag*/                             eHTMLTag_wbr,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/ 0,0,0,0,   /*parent,incl,exclgroups*/          kExtensions, kNone, kNone,   /*special props, prop-range*/      kNonContainer|kRequiresBody,kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_xmp,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kInlineEntity|kPreformatted, kCDATA,kNone,   /*special props, prop-range*/       kNone,kDefaultPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_text,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInBody,&gInBody,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,   /*special props, prop-range*/       kNonContainer|kRequiresBody,kNoPropRange,   /*special parents,kids*/            0,0, }, {         // Whitespace must have a parent model ofkHeadMisc to ensure that we         // do the right thing for whitespace in thehead section of a document.         // (i.e., it must be non-exclusively a childof the head).    /*tag*/                            eHTMLTag_whitespace,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInBody,&gInBody,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc, kNone, kNone,   /*special props, prop-range*/       kNonContainer|kLegalOpen,kNoPropRange,   /*special parents,kids*/            0,0, }, {         //Newlines must have a parent model of kHeadMisc to ensure that we         // do the right thing for whitespace in thehead section of a document.         // (i.e., it must be non-exclusively a childof the head).    /*tag*/                             eHTMLTag_newline,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInBody,&gInBody,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity|kHeadMisc, kNone, kNone,   /*special props, prop-range*/       kNonContainer|kLegalOpen, kNoPropRange,   /*special parents,kids*/            0,0, }, {         // Comments must have a parent model ofkHeadMisc to ensure that we         // do the right thing for whitespace in thehead section of a document         // (i.e., it must be non-exclusively a childof 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|kHeadMisc, kNone, kNone,   /*special props, prop-range*/       kOmitEndTag|kLegalOpen,kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                             eHTMLTag_entity,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          &gInBody,&gInBody,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,   /*special props, prop-range*/       0, kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                            eHTMLTag_doctypeDecl,   /*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,   /*special props, prop-range*/       kOmitEndTag,kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                            eHTMLTag_markupDecl,   /*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,   /*special props, prop-range*/       kOmitEndTag,kNoPropRange,   /*special parents,kids*/            0,0, }, {   /*tag*/                            eHTMLTag_instruction,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_unknown,   /*rootnodes,endrootnodes*/          0,0,   /*autoclose starttags and endtags*/0,0,0,0,   /*parent,incl,exclgroups*/          kFlowEntity, kNone, kNone,   /*special props, prop-range*/       kOmitEndTag,kNoPropRange,   /*special parents,kids*/            0,0, }, {         // Userdefined tags must have a parent modelof kHeadMisc to ensure that         // we do the right thing for whitespace in thehead section of a document.         // (i.e., it must be non-exclusively a childof the head).    /*tag*/                            eHTMLTag_userdefined,   /*req-parent excl-parent*/          eHTMLTag_unknown,eHTMLTag_frameset,   /*rootnodes,endrootnodes*/          &gRootTags,&gRootTags,   /*autoclose starttags and endtags*/&gBodyAutoClose,0,0,0,   /*parent,incl,exclgroups*/          (kFlowEntity|kHeadMisc),(kInlineEntity|kSelf), kNone, // Treat userdefined as inline element - Ref bug56245,66772   /*special props, prop-range*/       kPreferBody, kBodyPropRange,   /*special parents,kids*/            &gInNoframes,&gBodyKids, }}; //以上就是所有HTML元素的定义了,我想到了这一步,结合我们之前所解析的内容,读者自己已经可以很轻松地看懂每条属性是干什么用的了。 /** *  Callthis to find the index of a given child, or (if not found) *  theindex of its nearest synonym. *   * @update  gess 3/25/98 * @param   aTagStack -- list of opentags * @param   aTag -- tag to test forcontainership * @return  index of kNotFound *///调用这个方法来查询一个指定的子节点,或者(如果没找到)它最近的相似节点的位置。//从当前上下文中获取aChildTag的同类型,或相似类型节点,方法很简单PRInt32nsHTMLElement::GetIndexOfChildOrSynonym(nsDTDContext& aContext,eHTMLTagsaChildTag) { PRInt32 theChildIndex=aContext.LastOf(aChildTag);  if(kNotFound==theChildIndex) {   const TagList*theSynTags=gHTMLElements[aChildTag].GetSynonymousTags();//get the list of tags that THIS tag can close     //直接调用GetSynonymousTags获取该节点的相似节点   if(theSynTags) {     theChildIndex=LastOf(aContext,*theSynTags);   } }  return theChildIndex;} /** * * @update    gess1/21/99 * @param * @return *///判断该节点是否拥有某个特殊属性,即直接用该mSepcialProperties和aProperty进行与操作,并将结果和aProperty比较即可PRBoolnsHTMLElement::HasSpecialProperty(PRInt32 aProperty) const{ PRBool result=TestBits(mSpecialProperties,aProperty);  return result;} /** * * @update    gess12/13/98 * @param * @return *///判断aChild是否是容器类型PRBool nsHTMLElement::IsContainer(eHTMLTagsaChild) { PRBool result=(eHTMLTag_unknown==aChild);   if(!result){   result=!TestBits(gHTMLElements[aChild].mSpecialProperties,kNonContainer); }  return result;} /** * This tests whether all the bits in theparentbits * are included in the given set. It may be too * broad a question for most cases. * * @update    gess12/13/98 * @param * @return *///这个方法判断一个在parentbits中的bits是否都包含在了给定的标示值中。这在大多数情况下是一个比较全面的方式。PRBool nsHTMLElement::IsMemberOf(PRInt32aSet) const{  return TestBits(aSet,mParentBits);} /** * This tests whether all the bits in theparentbits * are included in the given set. It may be too * broad a question for most cases. * * @update    gess12/13/98 * @param * @return *///同上,只不过两个参数反过来进行测试,位与的结果和aSet进行比较PRBoolnsHTMLElement::ContainsSet(PRInt32 aSet) const{  return TestBits(mParentBits,aSet);}/** * This method determines whether the given tagcloses other blocks. * * @update    gess12/20/99 -- added H1..H6 to this list. * @param * @return *///这个方法用来判断给定的tag是否能够关闭其他block级元素PRBoolnsHTMLElement::IsBlockCloser(eHTMLTags aTag){ PRBool result=PR_FALSE;     if((aTag>=eHTMLTag_unknown) &(aTag<=eHTMLTag_xmp)){  //首先判断aTag是tag类型     //下面首先判断一下aTag是否是Block元素,或者是BlockEntity列表内的元素,又或者它拥有kHead这一mParent属性(即该Tag是h1~h6元素之一)   result=(gHTMLElements[aTag].IsBlock() ||            gHTMLElements[aTag].IsBlockEntity()||            (kHeading==gHTMLElements[aTag].mParentBits));   if(!result) {  //如果以上情况都不是,那么我们再进行一下判断     // NOBR is a block closure   - Ref. Bug# 24462     // DIR is a block closure    - Ref. Bug# 25845     // TD is a block closure     - Ref. Bug# 27490     // TR is a block closure     - Ref. Bug# 26488     // OBJECT is a block closure - Ref. Bug# 88992     //下面就是判断aTag是否是下列元素之一,如果是则设置result为true     static eHTMLTags gClosers[]={eHTMLTag_table,eHTMLTag_tbody,                                   eHTMLTag_td,eHTMLTag_th,                                   eHTMLTag_tr,eHTMLTag_caption,                                   eHTMLTag_object,eHTMLTag_applet,                                   eHTMLTag_ol, eHTMLTag_ul,                                   eHTMLTag_optgroup,                                   eHTMLTag_nobr,eHTMLTag_dir};      result=FindTagInSet(aTag,gClosers,sizeof(gClosers)/sizeof(eHTMLTag_body));   } }  return result;       //返回结果} /** * * @update    gess01/04/99 * @param * @return *///判断该aTag是否是Inline级元素PRBoolnsHTMLElement::IsInlineEntity(eHTMLTags aTag){ PRBool result=PR_FALSE;  if((aTag>=eHTMLTag_unknown) &(aTag<=eHTMLTag_xmp)){     //直接利用mParentBits和kInlineEntity判断即可   result=TestBits(gHTMLElements[aTag].mParentBits,kInlineEntity); }  return result;} /** * * @update    gess01/04/99 * @param * @return *///判断aTag元素是否是flow级元素PRBoolnsHTMLElement::IsFlowEntity(eHTMLTags aTag){ PRBool result=PR_FALSE;   if((aTag>=eHTMLTag_unknown) &(aTag<=eHTMLTag_xmp)){     //同样直接利用mParentBits和kFlowEntity判断即可   result=TestBits(gHTMLElements[aTag].mParentBits,kFlowEntity); }  return result;} /** * * @update    gess01/04/99 * @param * @return *///判断aTag是否能包含Block级元素PRBoolnsHTMLElement::IsBlockParent(eHTMLTags aTag){ PRBool result=PR_FALSE;  if((aTag>=eHTMLTag_unknown) &(aTag<=eHTMLTag_xmp)){   result=TestBits(gHTMLElements[aTag].mInclusionBits,kBlockEntity); }  return result;}/** * * @update    gess01/04/99 * @param * @return *///判断aTag能包含inline级元素PRBoolnsHTMLElement::IsInlineParent(eHTMLTags aTag){ PRBool result=PR_FALSE;  if((aTag>=eHTMLTag_unknown) &(aTag<=eHTMLTag_xmp)){   result=TestBits(gHTMLElements[aTag].mInclusionBits,kInlineEntity); }  return result;} /** * * @update    gess01/04/99 * @param * @return *///判断aTag能否包含Flow级元素PRBoolnsHTMLElement::IsFlowParent(eHTMLTags aTag){ PRBool result=PR_FALSE;  if((aTag>=eHTMLTag_unknown) &(aTag<=eHTMLTag_xmp)){    result=TestBits(gHTMLElements[aTag].mInclusionBits,kFlowEntity); }  return result;} /** * * @update    harishd11/19/99 * @param * @return *///判断aTag的mSpecialParents中是否拥有aTag节点PRBoolnsHTMLElement::IsSpecialParent(eHTMLTags aTag) const{ PRBool result=PR_FALSE;  if(mSpecialParents) {   if(FindTagInSet(aTag,mSpecialParents->mTags,mSpecialParents->mCount))       result=PR_TRUE; }  return result;}/** * Tells us whether the given tag opens asection * @update    gess01/04/99 * @param   id of tag * @return TRUE if opens section *///判断给定的tag是否会打开一个section区域PRBoolnsHTMLElement::IsSectionTag(eHTMLTags aTag){ PRBool result=PR_FALSE;  switch(aTag){    //根据aTag进行判断   case eHTMLTag_html:   case eHTMLTag_frameset:   case eHTMLTag_body:   case eHTMLTag_head:     result=PR_TRUE;     break;   default:     result=PR_FALSE; }  return result;} /** * * @update    gess01/04/99 * @param * @return *///判断在当前的DTD模式下,aParent是否能够直接包含aChildPRBoolnsHTMLElement::CanContain(eHTMLTags aParent,eHTMLTags aChild,nsDTDMode aMode){  PRBool result=PR_FALSE;  if((aParent>=eHTMLTag_unknown) &&(aParent<=eHTMLTag_userdefined)){     //间接调用aParent节点的CanContain方法进行判断   result=gHTMLElements[aParent].CanContain(aChild,aMode); }  return result;} /** * * @update    gess01/04/99 * @param * @return *///判断该节点下是否一定不能包含aChild节点PRBoolnsHTMLElement::CanExclude(eHTMLTags aChild) const{ PRBool result=PR_FALSE;   if(gHTMLElements[aChild].HasSpecialProperty(kLegalOpen)){   // Some tags could be opened anywhere, in thedocument, as they please.     //有些tags可以任由他们在文档的任何地方被打开     //如果aChild拥有kLegalOpen属性,则说明它在任何地方都可以存放,因此返回false   return PR_FALSE; }   //Note that special kids takes precedence overexclusions... //注意到我们要在判断其排外标示位之前先判断special子节点  if(mSpecialKids) {     //如果aChild位于当前节点的特殊子节点列表中,说明可以包含if(FindTagInSet(aChild,mSpecialKids->mTags,mSpecialKids->mCount)){//因此返回false     return PR_FALSE;   } }   if(mExclusionBits){  //如果该节点确实有需要排除的子节点类型   if(gHTMLElements[aChild].IsMemberOf(mExclusionBits)){   //判断一下     result=PR_TRUE;  //说明找到了,该节点不能存放,返回true   } }  return result;} /** * * @update    harishd03/01/00 * @param * @return */PRBoolnsHTMLElement::IsExcludableParent(eHTMLTags aParent) const{ PRBool result=PR_FALSE;   if(!IsTextTag(mTagID)) {  //首先根据mTagID判断当前节点不是文本节点类型   if(mExcludableParents) {     const TagList*theParents=mExcludableParents;     //获取mExcludableParents,即一些不能够包含该节点的节点类型的列表,比如<DT>不能包含<DL> -- bug 100466(奇怪的是,我在编译出的Firefox中和最近下载的最新版本Firefox release版本(15.0.1)中仍然会遇到DT包含DL的问题,但在某些老版本的FF中则不会),我尝试了一下chrome也会有这个问题,也不像是DTD模式的问题很奇怪,如果读者明白这个问题请发信给我,非常感谢。     if(FindTagInSet(aParent,theParents->mTags,theParents->mCount))   //从该列表中寻找有没有aParent       result=PR_TRUE;     //如果找到了,说明aParent不能包含该节点,直接返回true}   if(!result) {     // If you're a block parent make sure thatyou're not the     // parent of a TABLE element. ex. <table><tr><td><div><td></tr></table>     // IE & Nav. render this as table with twocells ( which I think is correct ).     // NOTE: If need arise we could use the rootnode to solve this problem      // 如果你是一个block父节点,请确保你不是table元素的父节点。比如<table><tr><td><div><td></tr></table>无论是在IE或Nav中,都应当将这个代码渲染成两个单元格(我想这是正确的结果)     //注意:如果有需要,我们应当使用root节点来解决这个问题     if(nsHTMLElement::IsBlockParent(aParent)){       switch(mTagID) {         case eHTMLTag_caption:         case eHTMLTag_thead:         case eHTMLTag_tbody:         case eHTMLTag_tfoot:         case eHTMLTag_td:         case eHTMLTag_th:         case eHTMLTag_tr:            result=PR_TRUE;         default:            break;       }     }   } }  return result;} /** * * @update    gess01/04/99 * @param * @return *///判断该节点之下是否能忽略结束型节点(只有html,body,comment,doctype等几类节点才有此属性)PRBool nsHTMLElement::CanOmitEndTag(void)const{ PRBool result=!IsContainer(mTagID);  if(!result)   result=TestBits(mSpecialProperties,kOmitEndTag);  return result;} /** * Returns whether a given tag can be a directchild of the <head> node of * an HTML document. * * @param aChild The tag in question. * @param aExclusively [out]Whether or not thistag can *only* appear in the *                     head (as opposed to thingslike <object> which can be                       either in the body orthe head). * @return Whether this tag can appear in thehead. *///判断一个给定tag能否在html文档中作为head节点的直接子节点,如果该节点只能存在于head下,则会将aExclusively赋值为true,否则赋值为falsePRBoolnsHTMLElement::IsChildOfHead(eHTMLTags aChild,PRBool& aExclusively) { aExclusively = PR_TRUE;   // Is this a head-only tag? //这是不是一个只能够存在于head下的节点?  if (gHTMLElements[aChild].mParentBits &kHeadContent) {    //对kHeadContent进行判断,如果有则说明其只能存在于Head节点之下   return PR_TRUE; }   // If not, check if it can appear in the head. //否则,则检查它是否能出现在head中  if (gHTMLElements[aChild].mParentBits &kHeadMisc) {   aExclusively = PR_FALSE;     //设置“必须”为false   return PR_TRUE;    //返回true }   return PR_FALSE;     //否则说明不是,返回False}/** * * @update    gess12/13/98 * @param * @return *///判断当前节点是否能够包含aChild节点,注意这里的allowDepthSearch位,如果设置为true则可以递归地进行向上多层地查询PRBool nsHTMLElement::SectionContains(eHTMLTagsaChild,PRBool allowDepthSearch)const { PRBool result=PR_FALSE;  const TagList*theRootTags=gHTMLElements[aChild].GetRootTags();      //获取子节点的合法根节点类型   if(theRootTags){     //如果存在合法根节点if(!FindTagInSet(mTagID,theRootTags->mTags,theRootTags->mCount)){ //我们尝试在其中寻找当前根节点//如果没找到     eHTMLTags theRootBase=theRootTags->mTags[0]; //接续获取根节点的第一个节点     if((eHTMLTag_unknown!=theRootBase)&& (allowDepthSearch))  //判断是否允许递归       result=SectionContains(theRootBase,allowDepthSearch);    //递归对合法根节点集合中的第一个根节点进行查询   }   else result=PR_TRUE;    //找到了则返回true }  return result;} /** * This method should be called to determine ifthe a tags * hierarchy needs to be validated. * * @update    harishd04/19/00 * @param * @return *///这个方法被用来判断一个给定的tag是否需要溯源检查(检查上下文之上是否有同类型的节点,确保其不要误包含了本节点)PRBoolnsHTMLElement::ShouldVerifyHierarchy() const { PRBool result=PR_FALSE;  // If the tag cannot contain itself then we need to makesure that  // anywhere in the hierarchy we don't nest accidently.  // Ex: <H1><LI><H1><LI>. Inner LIhas the potential of getting nested  // inside outer LI.If the tag can contain self, Ex:<A><B><A>,  // ( B can contain self )then ask the child (<A>) ifit requires a containment check. //如果这个tag不能够包含和自己同类型的节点,我们需要确保在当前上下文中我们不会意外地将当前节点包含在该节点中。例子:<H1><LI><H1><LI>。内部的LI有可能会被外部的LI所包含。如果该tag可以包含自己,比如:<A><B><A>,(B可以包含自己)那么久询问child(<A>)它需不需要进行包含规则检查。  if(mTagID!=eHTMLTag_userdefined) { //首先得确定当前节点不是用户自定义节点   result=HasSpecialProperty(kVerifyHierarchy);   //看看其是否拥有kVerifyHierarchy节点,如A,DT,Hn系列,等节点都有这个属性 }  return result;} /** * * @update    gess12/13/98 * @param * @return *///判断aChild节点是否是RS型节点,从这个方法中我们就可以知道哪些节点属于RS类型的节点了PRBoolnsHTMLElement::IsResidualStyleTag(eHTMLTags aChild) { PRBool result=PR_FALSE;  switch(aChild) {   case eHTMLTag_a:         case eHTMLTag_b:   case eHTMLTag_bdo:       case eHTMLTag_big:         case eHTMLTag_blink:   case eHTMLTag_del:   case eHTMLTag_em:   case eHTMLTag_font:      case eHTMLTag_i:           case eHTMLTag_ins:   case eHTMLTag_q:   case eHTMLTag_s:         case eHTMLTag_small:   case eHTMLTag_strong:   case eHTMLTag_strike:      case eHTMLTag_sub:       case eHTMLTag_sup:         case eHTMLTag_tt:   case eHTMLTag_u:           result=PR_TRUE;     break;    case eHTMLTag_abbr:   case eHTMLTag_acronym:     case eHTMLTag_center:    case eHTMLTag_cite:        case eHTMLTag_code:   case eHTMLTag_dfn:         case eHTMLTag_kbd:       case eHTMLTag_samp:        case eHTMLTag_span:      case eHTMLTag_var:     result=PR_FALSE;   default:  //既然默认就是False,干嘛还做之上的false判断呢?     break; };  return result;} /** * * @update    gess12/13/98 * @param * @return *///判断该节点是否能够包含aType类型PRBoolnsHTMLElement::CanContainType(PRInt32 aType) const{ PRInt32 answer=mInclusionBits & aType; PRBool  result=PRBool(0!=answer);  return result;} /** * * @update    gess12/13/98 * @param * @return *///判断aChild是否是空白字符类型PRBoolnsHTMLElement::IsWhitespaceTag(eHTMLTags aChild) { PRBool result=PR_FALSE;   switch(aChild) {     //根据aChild的类型进行选择   case eHTMLTag_newline:   case eHTMLTag_whitespace:     result=PR_TRUE;  //只有空格和换行符属于空白类型字符,返回true     break;   default:     break; }  return result;   //其他字符都返回false} /** * * @update    gess12/13/98 * @param * @return *///判断aChild是否属于PRBoolnsHTMLElement::IsTextTag(eHTMLTags aChild) { PRBool result=PR_FALSE;   switch(aChild) {      //根据aChild的类型进行选择   case eHTMLTag_text:   case eHTMLTag_entity:   case eHTMLTag_newline:   case eHTMLTag_whitespace:     result=PR_TRUE;  //如果是以上几种类型的节点,则返回true     break;   default:     break; }  return result;} /** * * @update    gess12/13/98 * @param * @return *///判断该类型的节点是否能够包含同类型的节点PRBool nsHTMLElement::CanContainSelf(void)const { PRBool result=PRBool(TestBits(mInclusionBits,kSelf)!=0);   //直接对mInclusionBits中的kSelf位进行判断,值得注意的是这个kSelf没有被设置到mParentBits中  return result;} /** * This method is called to determine (once andfor all) whether a start tag * can close another tag on the stack. Thismethod will return * false if something prevents aParentTag fromclosing. * * @update    gess12/20/99 * @param  aContext is the tag stack we're testing against * @param  aIndex is the index of the tag we want to close * @param  aChildTag is the child we're trying to close * @return TRUE if we can autoclose the start tag; FALSE otherwise *///这个方法用来判断一个起始型的节点是否能关闭当前栈中的另一个节点。如果因为某些原因防止了aParentTag关闭的话,本方法会返回false。PRBoolnsHTMLElement::CanAutoCloseTag(nsDTDContext& aContext,PRInt32 aIndex,                                      eHTMLTagsaChildTag) const{  PRInt32 thePos; PRBool  result = PR_TRUE; eHTMLTags thePrevTag; //我们从栈顶元素开始向下进行遍历直到aIndex位置为止  for(thePos = aContext.GetCount() - 1; thePos >=aIndex; thePos--) {   thePrevTag = aContext.TagAt(thePos);  //从当前的上下文中获取thePos位置的节点    if (thePrevTag == eHTMLTag_applet ||       thePrevTag == eHTMLTag_td) { //如果该节点类型为applet或td         result = PR_FALSE;     //设置结果为FALSE         break;   //跳出循环并返回false,也就是说本方法主要是检测当前上下文栈中从栈顶到aIndex中间是否存在applet或td节点,如果有则说明当前不能自动对节点进行关闭   } }   return result;} /** * * @update    gess10.17.2000 * @param * @return  */  //下面这个方法用来在当前上下文中查找本类型的结束型节点所能应当关闭的节点位置eHTMLTagsnsHTMLElement::GetCloseTargetForEndTag(nsDTDContext& aContext,PRInt32anIndex,nsDTDMode aMode)const{ eHTMLTags result=eHTMLTag_unknown;   int theCount=aContext.GetCount();  //依旧是获取栈顶元素的位置  int theIndex=theCount;   if(IsMemberOf(kPhrase)){       //首先我们要判断当前节点是否是kPhrase型节点(EM,STRONG,DFN,CODE,CITE,ABBR…等标签),对此类标签进行统一处理    while((--theIndex>=anIndex)&& (eHTMLTag_unknown==result)){  //从栈顶元素开始向下遍历,直到aIndex     eHTMLTags theTag = aContext.TagAt(theIndex); //获取当前位于theIndex位置的元素     if(theTag != mTagID) {     //如果该位置的元素和当前元素类型不相同       // Allow phrasals to close userdefined tags.bug 256731        //允许phrasals关闭用户定义类的userdefined标签。修正bug 256731       if(eHTMLTag_userdefined == theTag) {   //如果是该位置的元素是userdefine型         continue; //We can close this. //我们允许kPhrase类型的标签关闭userdefine类型的标签,继续向后判断下一个元素       }       // Fixes a derivative of bug 22842...        //修正了一个bug22842衍生出来的问题       if(CanContainType(kBlock)) {// INS/DEL can contain blocks.   //INS/DEL可以包含blocks型元素         //如果当前元素可以包含kBlock级元素         if(gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kBlockEntity)||            gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kFlowEntity)) {   //并且当前元素是kBlock或Flow级元素            if(HasOptionalEndTag(theTag)){    //除此之外再对当前元素是否可以忽略其对应的结束型标签进行判断(如有些标签<p>可以不需要结束型标签</p>)              continue;// Then I can close it.   //该元素也可以被关闭,我们继续判断下一个元素            }         }       }        // Phrasal elements can close other phrasals,along with fontstyle,       // extensions, and special tags...        // Phrasal元素可以关闭其他的phrasals,以及fontstyle类,extension类,以及special类的标签       if(!gHTMLElements[theTag].IsMemberOf(kSpecial|                                             kFontStyle |                                            kPhrase |                                            kExtensions)) {  //fix bug 56665         break; // It'snot something I can close //如果程序到了这里,说明该元素是一个我不能进行关闭的元素       }     }     else {  //此时说明theTag等于当前tag的类型,我们找到了目标       result=theTag; // Stop because you just foundyourself on the stack         //停止循环,因为你刚刚在栈中找到了和你自己同类型的节点       break;     }   } }   else if(IsMemberOf(kSpecial)){     //前面对kPhrasal类型处理完,下面对kSpecial类型元素进行处理(如A,IMG,APPLET,SPAN,SUP,SCRIPT…等标签)    while((--theIndex>=anIndex)&& (eHTMLTag_unknown==result)){  //依旧是从栈顶元素开始向anIndex为止进行遍历     eHTMLTags theTag=aContext.TagAt(theIndex);   //获取当前位置的元素     if(theTag!=mTagID) {  //判断该位置元素和本元素不是同类型节点       // Special elements can close other specials,along with fontstyle       // extensions, and phrasal tags...        // Added Phrasal to fix bug 26347        //special类元素可以关闭其他special类型的元素,以及fontsytle类,extension类,以及phrasal类的元素。       //此处添加了Phrasal以修正bug 26347       if((eHTMLTag_userdefined==theTag) ||           gHTMLElements[theTag].IsSpecialEntity() ||           gHTMLElements[theTag].IsFontStyleEntity()||           gHTMLElements[theTag].IsPhraseEntity()  ||            gHTMLElements[theTag].IsMemberOf(kExtensions)){         continue;    //以上5种节点都可以被关闭,注意还包括userdefined类       }       else {          // Fixes bug 22842...         //修正bug 22842         if(CanContainType(kBlock)) {    //如果当前元素可以包含kBlock级元素            if(gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kBlockEntity)||               gHTMLElements[eHTMLTags(theTag)].IsMemberOf(kFlowEntity)){      //如果当前位置的元素是kBlockEntity或kFlowEntity类型              if(HasOptionalEndTag(theTag)){  //判断其是否必须需要结束型节点                continue;// Then I can close it. //如果不是必须需要结束型节点,那我们就可以直接关闭它              }            }         }         break; // It'snot something I can close //程序如果到了这里,说明该元素不是一个我可以进行关闭的元素,我们退出循环       }     }     else {  //其他情况下,说明我们找到了一个同类型的节点,该节点即是我们要找的目标,退出循环       result=theTag; // Stop because you just foundyourself on the stack       break;     }   } }     //前面两个if处理了kPhrasal和kSpecial类型的节点,下面我们处理其他的情形  else if(ContainsSet(kPreformatted)||          IsMemberOf(kFormControl|kExtensions|kPreformatted)){  //bug54834...     //如果本节点可以包含kPreformatted类型或属于kFormControl或kExtensions或kPreformatted类型之一(修正bug54834)   while((--theIndex>=anIndex)&& (eHTMLTag_unknown==result)){  //依旧从栈顶开始向下遍历     eHTMLTags theTag=aContext.TagAt(theIndex);     if(theTag!=mTagID) {       if(!CanContain(theTag,aMode)) {   //通过CanContain进行判断,如果本元素不能包含theTag         break; //it'snot something I can close  //那么该元素不是我能够包含的,跳出循环       }     }     else {  //说明theTag和本tag元素类型一致,我们找到了目标,跳出循环       result=theTag; //stop because you just found yourself on the stack       break;     }   } }//继续下一种情况的处理  else if(IsMemberOf(kList)){    //判断当前元素是否属于kList    while((--theIndex>=anIndex)&& (eHTMLTag_unknown==result)){     eHTMLTags theTag=aContext.TagAt(theIndex);     if(theTag!=mTagID) {       if(!CanContain(theTag,aMode)) {   //如果当前元素不能包含theTag         break; //it'snot something I can close  //该元素不是本元素所能够关闭的       }     }     else {  //说明theTag和本元素一样       result=theTag; //stop because you just foundyourself on the stack       break;     }   } }//下面是对ResidualStyle类型节点的处理  else if(IsResidualStyleTag(mTagID)){      // Before finding a close target, for thecurrent tag, make sure   // that the tag above does not gate.   // Note: we intentionally make 2 passes:   // The first pass tries to exactly match, the2nd pass matches the group. //在寻找一个可进行关闭的目标之前,对于当前的tag,确保其在之上的tag不会进行阻拦。//注意:我们主动地进行两种尝试//第一种尝试进行精准地匹配,第二种尝试对该类型元素进行组匹配   const TagList*theRootTags=gHTMLElements[mTagID].GetEndRootTags();     //这里直接用mEndRootTags不行么?   PRInt32 theIndexCopy=theIndex;   while(--theIndex>=anIndex){     eHTMLTags theTag=aContext.TagAt(theIndex);     if(theTag == mTagID) {     //这次是首先对是否是同类型节点进行判断了,如果是则说明找到了,直接返回       return theTag; //we found our target.     }     //如果本节点不能够包含theTag进行包含,或theTag位于当前节点的rootTag中     else if(!CanContain(theTag,aMode) ||               (theRootTags &&FindTagInSet(theTag,theRootTags->mTags,theRootTags->mCount))) {       // If you cannot contain this tag then       // you cannot close it either. It looks like       // the tag trying to close is misplaced.       // In the following Exs. notice the misplaced/font:       // Ex.<font><table><tr><td></font></td></tr></table.-- Ref. bug 56245       // Ex.<font><select><option></font></select> -- Ref.bug 37618       // Ex.<font><select></font><option></select> -- Ref.bug 98187        //如果你不能包含这个tag,那么你也不能关闭它。此时看起来我们正在进行关闭尝试的tag的位置是错误的。在下面的例子中,请注意错位的/font:        //例子:<font><table><tr><td></font></td></tr></table.– 根据bug 56245        //例子:<font><select><option></font></select>--Ref.bug 37618        //例子:<font><select></font><option></select>--Ref.bug98187       return eHTMLTag_unknown;     //此时相当于被gated掉了,因此返回错误结果     }   }     //上面我们进行了“精准”的匹配过程,到了这里说明我们还没有找到结果,下面我们继续进行“集合”式的匹配   theIndex=theIndexCopy;  //恢复index的原始值   while(--theIndex>=anIndex){      //重新从栈顶开始向下进行遍历     eHTMLTags theTag=aContext.TagAt(theIndex);     if(gHTMLElements[theTag].IsMemberOf(mParentBits)){    //如果theTag是当前元素的mParentBits中所规定的元素之一,我们就返回它,注意只有对RS节点,且不是kList、kSpecial、kPhrasal、kPreformatted的元素才会这么做       return theTag; //返回theTag     }   }    }//下面判断其是否是table相关的元素  else if(gHTMLElements[mTagID].IsTableElement()){        //This fixes 57378...     //example:<TABLE><THEAD><TR><TH></THEAD> which didn't closethe <THEAD>      //这修正了bug 57378…      //例子:<TABLE><THEAD><TR><TH></THEAD>这里的<THEAD>没有被关闭   PRInt32 theLastTable=aContext.LastOf(eHTMLTag_table);    //首先获取当前上下文中最近一次出现的table位置   PRInt32 theLastOfMe=aContext.LastOf(mTagID);   //然后获取本元素在当前上下文中最近一次出现的位置   if(theLastTable<theLastOfMe) {        //如果table在本元素之前     return mTagID;   //直接返回本元素   } }//下面判断本元素是不是eHTMLTag_legend  else if(mTagID ==eHTMLTag_legend)  {   while((--theIndex>=anIndex)&& (eHTMLTag_unknown==result)){  //自栈顶开始,在没有找到合适的目标结果的情况下进行循环遍历(这个eHTMLTag_unknown==result条件有必要么?)     eHTMLTags theTag = aContext.TagAt(theIndex);     if (theTag == mTagID) {    //找到自己的起始节点了       result = theTag;       break;     }      if (!CanContain(theTag, aMode)) {   //如果本节点不能包含当前节点,跳出循环       break;     }   } }  else if (mTagID ==eHTMLTag_head) {     //如果此时是要为<head>节点查找开始节点…   while (--theIndex >= anIndex) {  //依然从栈顶开始遍历     eHTMLTags tag = aContext.TagAt(theIndex);     if (tag == eHTMLTag_html) {    //如果找到了<html>       // HTML gates head closing, but the headshould never be the parent of       // an html tag.        //HTML会阻止head关闭,但是head永远不应成为html的父节点       break;     }      if (tag == eHTMLTag_head) {    //找到了       result = eHTMLTag_head;       break;     }   } }   return result;} //最后一个方法,用来判断当前元素能否包含aChild元素作为它的直接子节点PRBoolnsHTMLElement::CanContain(eHTMLTags aChild,nsDTDMode aMode)const{    if(IsContainer(mTagID)){  //如果当前元素是一个容器    if(gHTMLElements[aChild].HasSpecialProperty(kLegalOpen)){   //拥有kLegalOpen代表其可以在任意地方被打开,比如<script>     // Some tags could be opened anywhere, in thedocument, as they please.      //有些tags可以在任何地方被打开     return PR_TRUE;   }    if(mTagID==aChild) {    //如果找到了自己…     return CanContainSelf();  //not many tags cancontain themselves...  //没有多少节点可以包含自己… 直接调用CanContainSelf()进行判断和返回值}    const TagList*theCloseTags=gHTMLElements[aChild].GetAutoCloseStartTags(); //获取该节点可以自动进行关闭的节点列表   if(theCloseTags){     if(FindTagInSet(mTagID,theCloseTags->mTags,theCloseTags->mCount))    //如果本元素的ID在该列表之中,说明该元素可以自动关闭本元素,这种情况下一般说明该元素的位置级别要比本元素高       return PR_FALSE;    //因此返回false    }   if(gHTMLElements[aChild].mExcludableParents){ //判断本节点是否位于aChild显式表标明的不能包含于的节点之一     const TagList*theParents=gHTMLElements[aChild].mExcludableParents;     if(FindTagInSet(mTagID,theParents->mTags,theParents->mCount))       return PR_FALSE;   }      if(gHTMLElements[aChild].IsExcludableParent(mTagID))     //调用IsExcludableParent再判断一次(这个方法的前半部分和上面那个判断重复了,上面那个方法可以优化掉吧…)     return PR_FALSE;    if(gHTMLElements[aChild].IsBlockCloser(aChild)){    //判断aChild是否是可以关闭block级的元素     if(nsHTMLElement::IsBlockParent(mTagID)){    //如果此时恰好本元素下可以包含block级元素       return PR_TRUE;     //这种情况下可以直接判断可以包含     }   }    if(nsHTMLElement::IsInlineEntity(aChild)){     //对aChild是inline进行判断     if(nsHTMLElement::IsInlineParent(mTagID)){       return PR_TRUE;     }   }    if(nsHTMLElement::IsFlowEntity(aChild)){  //对aChild是Flow级元素进行判断     if(nsHTMLElement::IsFlowParent(mTagID)){       return PR_TRUE;     }   }    if(nsHTMLElement::IsTextTag(aChild)) {     //对于aChild是Text元素的情况进行处理     // Allow <xmp> to contain text.     if(nsHTMLElement::IsInlineParent(mTagID)|| CanContainType(kCDATA)){       return PR_TRUE;     }   }    if(CanContainType(gHTMLElements[aChild].mParentBits)){  //调用CanContainType直接对mInclusion和aChild的mParentBits位进行判断     return PR_TRUE;   }    if(mSpecialKids) { //如果aChild属于特殊子节点当然也可以包含     if(FindTagInSet(aChild,mSpecialKids->mTags,mSpecialKids->mCount)){       return PR_TRUE;     }    }