| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956 | 'use strict';const Tokenizer = require('../tokenizer');const OpenElementStack = require('./open-element-stack');const FormattingElementList = require('./formatting-element-list');const LocationInfoParserMixin = require('../extensions/location-info/parser-mixin');const ErrorReportingParserMixin = require('../extensions/error-reporting/parser-mixin');const Mixin = require('../utils/mixin');const defaultTreeAdapter = require('../tree-adapters/default');const mergeOptions = require('../utils/merge-options');const doctype = require('../common/doctype');const foreignContent = require('../common/foreign-content');const ERR = require('../common/error-codes');const unicode = require('../common/unicode');const HTML = require('../common/html');//Aliasesconst $ = HTML.TAG_NAMES;const NS = HTML.NAMESPACES;const ATTRS = HTML.ATTRS;const DEFAULT_OPTIONS = {    scriptingEnabled: true,    sourceCodeLocationInfo: false,    onParseError: null,    treeAdapter: defaultTreeAdapter};//Misc constantsconst HIDDEN_INPUT_TYPE = 'hidden';//Adoption agency loops iteration countconst AA_OUTER_LOOP_ITER = 8;const AA_INNER_LOOP_ITER = 3;//Insertion modesconst INITIAL_MODE = 'INITIAL_MODE';const BEFORE_HTML_MODE = 'BEFORE_HTML_MODE';const BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE';const IN_HEAD_MODE = 'IN_HEAD_MODE';const IN_HEAD_NO_SCRIPT_MODE = 'IN_HEAD_NO_SCRIPT_MODE';const AFTER_HEAD_MODE = 'AFTER_HEAD_MODE';const IN_BODY_MODE = 'IN_BODY_MODE';const TEXT_MODE = 'TEXT_MODE';const IN_TABLE_MODE = 'IN_TABLE_MODE';const IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE';const IN_CAPTION_MODE = 'IN_CAPTION_MODE';const IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE';const IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE';const IN_ROW_MODE = 'IN_ROW_MODE';const IN_CELL_MODE = 'IN_CELL_MODE';const IN_SELECT_MODE = 'IN_SELECT_MODE';const IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE';const IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE';const AFTER_BODY_MODE = 'AFTER_BODY_MODE';const IN_FRAMESET_MODE = 'IN_FRAMESET_MODE';const AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE';const AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE';const AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE';//Insertion mode reset mapconst INSERTION_MODE_RESET_MAP = {    [$.TR]: IN_ROW_MODE,    [$.TBODY]: IN_TABLE_BODY_MODE,    [$.THEAD]: IN_TABLE_BODY_MODE,    [$.TFOOT]: IN_TABLE_BODY_MODE,    [$.CAPTION]: IN_CAPTION_MODE,    [$.COLGROUP]: IN_COLUMN_GROUP_MODE,    [$.TABLE]: IN_TABLE_MODE,    [$.BODY]: IN_BODY_MODE,    [$.FRAMESET]: IN_FRAMESET_MODE};//Template insertion mode switch mapconst TEMPLATE_INSERTION_MODE_SWITCH_MAP = {    [$.CAPTION]: IN_TABLE_MODE,    [$.COLGROUP]: IN_TABLE_MODE,    [$.TBODY]: IN_TABLE_MODE,    [$.TFOOT]: IN_TABLE_MODE,    [$.THEAD]: IN_TABLE_MODE,    [$.COL]: IN_COLUMN_GROUP_MODE,    [$.TR]: IN_TABLE_BODY_MODE,    [$.TD]: IN_ROW_MODE,    [$.TH]: IN_ROW_MODE};//Token handlers map for insertion modesconst TOKEN_HANDLERS = {    [INITIAL_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenInInitialMode,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInInitialMode,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: doctypeInInitialMode,        [Tokenizer.START_TAG_TOKEN]: tokenInInitialMode,        [Tokenizer.END_TAG_TOKEN]: tokenInInitialMode,        [Tokenizer.EOF_TOKEN]: tokenInInitialMode    },    [BEFORE_HTML_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHtml,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHtml,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagBeforeHtml,        [Tokenizer.END_TAG_TOKEN]: endTagBeforeHtml,        [Tokenizer.EOF_TOKEN]: tokenBeforeHtml    },    [BEFORE_HEAD_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHead,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHead,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,        [Tokenizer.START_TAG_TOKEN]: startTagBeforeHead,        [Tokenizer.END_TAG_TOKEN]: endTagBeforeHead,        [Tokenizer.EOF_TOKEN]: tokenBeforeHead    },    [IN_HEAD_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenInHead,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHead,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,        [Tokenizer.START_TAG_TOKEN]: startTagInHead,        [Tokenizer.END_TAG_TOKEN]: endTagInHead,        [Tokenizer.EOF_TOKEN]: tokenInHead    },    [IN_HEAD_NO_SCRIPT_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenInHeadNoScript,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHeadNoScript,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,        [Tokenizer.START_TAG_TOKEN]: startTagInHeadNoScript,        [Tokenizer.END_TAG_TOKEN]: endTagInHeadNoScript,        [Tokenizer.EOF_TOKEN]: tokenInHeadNoScript    },    [AFTER_HEAD_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenAfterHead,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterHead,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,        [Tokenizer.START_TAG_TOKEN]: startTagAfterHead,        [Tokenizer.END_TAG_TOKEN]: endTagAfterHead,        [Tokenizer.EOF_TOKEN]: tokenAfterHead    },    [IN_BODY_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInBody,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInBody,        [Tokenizer.END_TAG_TOKEN]: endTagInBody,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [TEXT_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.NULL_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: ignoreToken,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: ignoreToken,        [Tokenizer.END_TAG_TOKEN]: endTagInText,        [Tokenizer.EOF_TOKEN]: eofInText    },    [IN_TABLE_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInTable,        [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInTable,        [Tokenizer.END_TAG_TOKEN]: endTagInTable,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_TABLE_TEXT_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInTableText,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInTableText,        [Tokenizer.COMMENT_TOKEN]: tokenInTableText,        [Tokenizer.DOCTYPE_TOKEN]: tokenInTableText,        [Tokenizer.START_TAG_TOKEN]: tokenInTableText,        [Tokenizer.END_TAG_TOKEN]: tokenInTableText,        [Tokenizer.EOF_TOKEN]: tokenInTableText    },    [IN_CAPTION_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInBody,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInCaption,        [Tokenizer.END_TAG_TOKEN]: endTagInCaption,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_COLUMN_GROUP_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenInColumnGroup,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInColumnGroup,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInColumnGroup,        [Tokenizer.END_TAG_TOKEN]: endTagInColumnGroup,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_TABLE_BODY_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInTable,        [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInTableBody,        [Tokenizer.END_TAG_TOKEN]: endTagInTableBody,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_ROW_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInTable,        [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInRow,        [Tokenizer.END_TAG_TOKEN]: endTagInRow,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_CELL_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInBody,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInCell,        [Tokenizer.END_TAG_TOKEN]: endTagInCell,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_SELECT_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInSelect,        [Tokenizer.END_TAG_TOKEN]: endTagInSelect,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_SELECT_IN_TABLE_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInSelectInTable,        [Tokenizer.END_TAG_TOKEN]: endTagInSelectInTable,        [Tokenizer.EOF_TOKEN]: eofInBody    },    [IN_TEMPLATE_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: characterInBody,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInTemplate,        [Tokenizer.END_TAG_TOKEN]: endTagInTemplate,        [Tokenizer.EOF_TOKEN]: eofInTemplate    },    [AFTER_BODY_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenAfterBody,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterBody,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendCommentToRootHtmlElement,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagAfterBody,        [Tokenizer.END_TAG_TOKEN]: endTagAfterBody,        [Tokenizer.EOF_TOKEN]: stopParsing    },    [IN_FRAMESET_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagInFrameset,        [Tokenizer.END_TAG_TOKEN]: endTagInFrameset,        [Tokenizer.EOF_TOKEN]: stopParsing    },    [AFTER_FRAMESET_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,        [Tokenizer.COMMENT_TOKEN]: appendComment,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagAfterFrameset,        [Tokenizer.END_TAG_TOKEN]: endTagAfterFrameset,        [Tokenizer.EOF_TOKEN]: stopParsing    },    [AFTER_AFTER_BODY_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: tokenAfterAfterBody,        [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterAfterBody,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterBody,        [Tokenizer.END_TAG_TOKEN]: tokenAfterAfterBody,        [Tokenizer.EOF_TOKEN]: stopParsing    },    [AFTER_AFTER_FRAMESET_MODE]: {        [Tokenizer.CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,        [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,        [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument,        [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,        [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterFrameset,        [Tokenizer.END_TAG_TOKEN]: ignoreToken,        [Tokenizer.EOF_TOKEN]: stopParsing    }};//Parserclass Parser {    constructor(options) {        this.options = mergeOptions(DEFAULT_OPTIONS, options);        this.treeAdapter = this.options.treeAdapter;        this.pendingScript = null;        if (this.options.sourceCodeLocationInfo) {            Mixin.install(this, LocationInfoParserMixin);        }        if (this.options.onParseError) {            Mixin.install(this, ErrorReportingParserMixin, { onParseError: this.options.onParseError });        }    }    // API    parse(html) {        const document = this.treeAdapter.createDocument();        this._bootstrap(document, null);        this.tokenizer.write(html, true);        this._runParsingLoop(null);        return document;    }    parseFragment(html, fragmentContext) {        //NOTE: use <template> element as a fragment context if context element was not provided,        //so we will parse in "forgiving" manner        if (!fragmentContext) {            fragmentContext = this.treeAdapter.createElement($.TEMPLATE, NS.HTML, []);        }        //NOTE: create fake element which will be used as 'document' for fragment parsing.        //This is important for jsdom there 'document' can't be recreated, therefore        //fragment parsing causes messing of the main `document`.        const documentMock = this.treeAdapter.createElement('documentmock', NS.HTML, []);        this._bootstrap(documentMock, fragmentContext);        if (this.treeAdapter.getTagName(fragmentContext) === $.TEMPLATE) {            this._pushTmplInsertionMode(IN_TEMPLATE_MODE);        }        this._initTokenizerForFragmentParsing();        this._insertFakeRootElement();        this._resetInsertionMode();        this._findFormInFragmentContext();        this.tokenizer.write(html, true);        this._runParsingLoop(null);        const rootElement = this.treeAdapter.getFirstChild(documentMock);        const fragment = this.treeAdapter.createDocumentFragment();        this._adoptNodes(rootElement, fragment);        return fragment;    }    //Bootstrap parser    _bootstrap(document, fragmentContext) {        this.tokenizer = new Tokenizer(this.options);        this.stopped = false;        this.insertionMode = INITIAL_MODE;        this.originalInsertionMode = '';        this.document = document;        this.fragmentContext = fragmentContext;        this.headElement = null;        this.formElement = null;        this.openElements = new OpenElementStack(this.document, this.treeAdapter);        this.activeFormattingElements = new FormattingElementList(this.treeAdapter);        this.tmplInsertionModeStack = [];        this.tmplInsertionModeStackTop = -1;        this.currentTmplInsertionMode = null;        this.pendingCharacterTokens = [];        this.hasNonWhitespacePendingCharacterToken = false;        this.framesetOk = true;        this.skipNextNewLine = false;        this.fosterParentingEnabled = false;    }    //Errors    _err() {        // NOTE: err reporting is noop by default. Enabled by mixin.    }    //Parsing loop    _runParsingLoop(scriptHandler) {        while (!this.stopped) {            this._setupTokenizerCDATAMode();            const token = this.tokenizer.getNextToken();            if (token.type === Tokenizer.HIBERNATION_TOKEN) {                break;            }            if (this.skipNextNewLine) {                this.skipNextNewLine = false;                if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') {                    if (token.chars.length === 1) {                        continue;                    }                    token.chars = token.chars.substr(1);                }            }            this._processInputToken(token);            if (scriptHandler && this.pendingScript) {                break;            }        }    }    runParsingLoopForCurrentChunk(writeCallback, scriptHandler) {        this._runParsingLoop(scriptHandler);        if (scriptHandler && this.pendingScript) {            const script = this.pendingScript;            this.pendingScript = null;            scriptHandler(script);            return;        }        if (writeCallback) {            writeCallback();        }    }    //Text parsing    _setupTokenizerCDATAMode() {        const current = this._getAdjustedCurrentElement();        this.tokenizer.allowCDATA =            current &&            current !== this.document &&            this.treeAdapter.getNamespaceURI(current) !== NS.HTML &&            !this._isIntegrationPoint(current);    }    _switchToTextParsing(currentToken, nextTokenizerState) {        this._insertElement(currentToken, NS.HTML);        this.tokenizer.state = nextTokenizerState;        this.originalInsertionMode = this.insertionMode;        this.insertionMode = TEXT_MODE;    }    switchToPlaintextParsing() {        this.insertionMode = TEXT_MODE;        this.originalInsertionMode = IN_BODY_MODE;        this.tokenizer.state = Tokenizer.MODE.PLAINTEXT;    }    //Fragment parsing    _getAdjustedCurrentElement() {        return this.openElements.stackTop === 0 && this.fragmentContext            ? this.fragmentContext            : this.openElements.current;    }    _findFormInFragmentContext() {        let node = this.fragmentContext;        do {            if (this.treeAdapter.getTagName(node) === $.FORM) {                this.formElement = node;                break;            }            node = this.treeAdapter.getParentNode(node);        } while (node);    }    _initTokenizerForFragmentParsing() {        if (this.treeAdapter.getNamespaceURI(this.fragmentContext) === NS.HTML) {            const tn = this.treeAdapter.getTagName(this.fragmentContext);            if (tn === $.TITLE || tn === $.TEXTAREA) {                this.tokenizer.state = Tokenizer.MODE.RCDATA;            } else if (                tn === $.STYLE ||                tn === $.XMP ||                tn === $.IFRAME ||                tn === $.NOEMBED ||                tn === $.NOFRAMES ||                tn === $.NOSCRIPT            ) {                this.tokenizer.state = Tokenizer.MODE.RAWTEXT;            } else if (tn === $.SCRIPT) {                this.tokenizer.state = Tokenizer.MODE.SCRIPT_DATA;            } else if (tn === $.PLAINTEXT) {                this.tokenizer.state = Tokenizer.MODE.PLAINTEXT;            }        }    }    //Tree mutation    _setDocumentType(token) {        const name = token.name || '';        const publicId = token.publicId || '';        const systemId = token.systemId || '';        this.treeAdapter.setDocumentType(this.document, name, publicId, systemId);    }    _attachElementToTree(element) {        if (this._shouldFosterParentOnInsertion()) {            this._fosterParentElement(element);        } else {            const parent = this.openElements.currentTmplContent || this.openElements.current;            this.treeAdapter.appendChild(parent, element);        }    }    _appendElement(token, namespaceURI) {        const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);        this._attachElementToTree(element);    }    _insertElement(token, namespaceURI) {        const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);        this._attachElementToTree(element);        this.openElements.push(element);    }    _insertFakeElement(tagName) {        const element = this.treeAdapter.createElement(tagName, NS.HTML, []);        this._attachElementToTree(element);        this.openElements.push(element);    }    _insertTemplate(token) {        const tmpl = this.treeAdapter.createElement(token.tagName, NS.HTML, token.attrs);        const content = this.treeAdapter.createDocumentFragment();        this.treeAdapter.setTemplateContent(tmpl, content);        this._attachElementToTree(tmpl);        this.openElements.push(tmpl);    }    _insertFakeRootElement() {        const element = this.treeAdapter.createElement($.HTML, NS.HTML, []);        this.treeAdapter.appendChild(this.openElements.current, element);        this.openElements.push(element);    }    _appendCommentNode(token, parent) {        const commentNode = this.treeAdapter.createCommentNode(token.data);        this.treeAdapter.appendChild(parent, commentNode);    }    _insertCharacters(token) {        if (this._shouldFosterParentOnInsertion()) {            this._fosterParentText(token.chars);        } else {            const parent = this.openElements.currentTmplContent || this.openElements.current;            this.treeAdapter.insertText(parent, token.chars);        }    }    _adoptNodes(donor, recipient) {        for (let child = this.treeAdapter.getFirstChild(donor); child; child = this.treeAdapter.getFirstChild(donor)) {            this.treeAdapter.detachNode(child);            this.treeAdapter.appendChild(recipient, child);        }    }    //Token processing    _shouldProcessTokenInForeignContent(token) {        const current = this._getAdjustedCurrentElement();        if (!current || current === this.document) {            return false;        }        const ns = this.treeAdapter.getNamespaceURI(current);        if (ns === NS.HTML) {            return false;        }        if (            this.treeAdapter.getTagName(current) === $.ANNOTATION_XML &&            ns === NS.MATHML &&            token.type === Tokenizer.START_TAG_TOKEN &&            token.tagName === $.SVG        ) {            return false;        }        const isCharacterToken =            token.type === Tokenizer.CHARACTER_TOKEN ||            token.type === Tokenizer.NULL_CHARACTER_TOKEN ||            token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN;        const isMathMLTextStartTag =            token.type === Tokenizer.START_TAG_TOKEN && token.tagName !== $.MGLYPH && token.tagName !== $.MALIGNMARK;        if ((isMathMLTextStartTag || isCharacterToken) && this._isIntegrationPoint(current, NS.MATHML)) {            return false;        }        if (            (token.type === Tokenizer.START_TAG_TOKEN || isCharacterToken) &&            this._isIntegrationPoint(current, NS.HTML)        ) {            return false;        }        return token.type !== Tokenizer.EOF_TOKEN;    }    _processToken(token) {        TOKEN_HANDLERS[this.insertionMode][token.type](this, token);    }    _processTokenInBodyMode(token) {        TOKEN_HANDLERS[IN_BODY_MODE][token.type](this, token);    }    _processTokenInForeignContent(token) {        if (token.type === Tokenizer.CHARACTER_TOKEN) {            characterInForeignContent(this, token);        } else if (token.type === Tokenizer.NULL_CHARACTER_TOKEN) {            nullCharacterInForeignContent(this, token);        } else if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN) {            insertCharacters(this, token);        } else if (token.type === Tokenizer.COMMENT_TOKEN) {            appendComment(this, token);        } else if (token.type === Tokenizer.START_TAG_TOKEN) {            startTagInForeignContent(this, token);        } else if (token.type === Tokenizer.END_TAG_TOKEN) {            endTagInForeignContent(this, token);        }    }    _processInputToken(token) {        if (this._shouldProcessTokenInForeignContent(token)) {            this._processTokenInForeignContent(token);        } else {            this._processToken(token);        }        if (token.type === Tokenizer.START_TAG_TOKEN && token.selfClosing && !token.ackSelfClosing) {            this._err(ERR.nonVoidHtmlElementStartTagWithTrailingSolidus);        }    }    //Integration points    _isIntegrationPoint(element, foreignNS) {        const tn = this.treeAdapter.getTagName(element);        const ns = this.treeAdapter.getNamespaceURI(element);        const attrs = this.treeAdapter.getAttrList(element);        return foreignContent.isIntegrationPoint(tn, ns, attrs, foreignNS);    }    //Active formatting elements reconstruction    _reconstructActiveFormattingElements() {        const listLength = this.activeFormattingElements.length;        if (listLength) {            let unopenIdx = listLength;            let entry = null;            do {                unopenIdx--;                entry = this.activeFormattingElements.entries[unopenIdx];                if (entry.type === FormattingElementList.MARKER_ENTRY || this.openElements.contains(entry.element)) {                    unopenIdx++;                    break;                }            } while (unopenIdx > 0);            for (let i = unopenIdx; i < listLength; i++) {                entry = this.activeFormattingElements.entries[i];                this._insertElement(entry.token, this.treeAdapter.getNamespaceURI(entry.element));                entry.element = this.openElements.current;            }        }    }    //Close elements    _closeTableCell() {        this.openElements.generateImpliedEndTags();        this.openElements.popUntilTableCellPopped();        this.activeFormattingElements.clearToLastMarker();        this.insertionMode = IN_ROW_MODE;    }    _closePElement() {        this.openElements.generateImpliedEndTagsWithExclusion($.P);        this.openElements.popUntilTagNamePopped($.P);    }    //Insertion modes    _resetInsertionMode() {        for (let i = this.openElements.stackTop, last = false; i >= 0; i--) {            let element = this.openElements.items[i];            if (i === 0) {                last = true;                if (this.fragmentContext) {                    element = this.fragmentContext;                }            }            const tn = this.treeAdapter.getTagName(element);            const newInsertionMode = INSERTION_MODE_RESET_MAP[tn];            if (newInsertionMode) {                this.insertionMode = newInsertionMode;                break;            } else if (!last && (tn === $.TD || tn === $.TH)) {                this.insertionMode = IN_CELL_MODE;                break;            } else if (!last && tn === $.HEAD) {                this.insertionMode = IN_HEAD_MODE;                break;            } else if (tn === $.SELECT) {                this._resetInsertionModeForSelect(i);                break;            } else if (tn === $.TEMPLATE) {                this.insertionMode = this.currentTmplInsertionMode;                break;            } else if (tn === $.HTML) {                this.insertionMode = this.headElement ? AFTER_HEAD_MODE : BEFORE_HEAD_MODE;                break;            } else if (last) {                this.insertionMode = IN_BODY_MODE;                break;            }        }    }    _resetInsertionModeForSelect(selectIdx) {        if (selectIdx > 0) {            for (let i = selectIdx - 1; i > 0; i--) {                const ancestor = this.openElements.items[i];                const tn = this.treeAdapter.getTagName(ancestor);                if (tn === $.TEMPLATE) {                    break;                } else if (tn === $.TABLE) {                    this.insertionMode = IN_SELECT_IN_TABLE_MODE;                    return;                }            }        }        this.insertionMode = IN_SELECT_MODE;    }    _pushTmplInsertionMode(mode) {        this.tmplInsertionModeStack.push(mode);        this.tmplInsertionModeStackTop++;        this.currentTmplInsertionMode = mode;    }    _popTmplInsertionMode() {        this.tmplInsertionModeStack.pop();        this.tmplInsertionModeStackTop--;        this.currentTmplInsertionMode = this.tmplInsertionModeStack[this.tmplInsertionModeStackTop];    }    //Foster parenting    _isElementCausesFosterParenting(element) {        const tn = this.treeAdapter.getTagName(element);        return tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD || tn === $.TR;    }    _shouldFosterParentOnInsertion() {        return this.fosterParentingEnabled && this._isElementCausesFosterParenting(this.openElements.current);    }    _findFosterParentingLocation() {        const location = {            parent: null,            beforeElement: null        };        for (let i = this.openElements.stackTop; i >= 0; i--) {            const openElement = this.openElements.items[i];            const tn = this.treeAdapter.getTagName(openElement);            const ns = this.treeAdapter.getNamespaceURI(openElement);            if (tn === $.TEMPLATE && ns === NS.HTML) {                location.parent = this.treeAdapter.getTemplateContent(openElement);                break;            } else if (tn === $.TABLE) {                location.parent = this.treeAdapter.getParentNode(openElement);                if (location.parent) {                    location.beforeElement = openElement;                } else {                    location.parent = this.openElements.items[i - 1];                }                break;            }        }        if (!location.parent) {            location.parent = this.openElements.items[0];        }        return location;    }    _fosterParentElement(element) {        const location = this._findFosterParentingLocation();        if (location.beforeElement) {            this.treeAdapter.insertBefore(location.parent, element, location.beforeElement);        } else {            this.treeAdapter.appendChild(location.parent, element);        }    }    _fosterParentText(chars) {        const location = this._findFosterParentingLocation();        if (location.beforeElement) {            this.treeAdapter.insertTextBefore(location.parent, chars, location.beforeElement);        } else {            this.treeAdapter.insertText(location.parent, chars);        }    }    //Special elements    _isSpecialElement(element) {        const tn = this.treeAdapter.getTagName(element);        const ns = this.treeAdapter.getNamespaceURI(element);        return HTML.SPECIAL_ELEMENTS[ns][tn];    }}module.exports = Parser;//Adoption agency algorithm//(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency)//------------------------------------------------------------------//Steps 5-8 of the algorithmfunction aaObtainFormattingElementEntry(p, token) {    let formattingElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(token.tagName);    if (formattingElementEntry) {        if (!p.openElements.contains(formattingElementEntry.element)) {            p.activeFormattingElements.removeEntry(formattingElementEntry);            formattingElementEntry = null;        } else if (!p.openElements.hasInScope(token.tagName)) {            formattingElementEntry = null;        }    } else {        genericEndTagInBody(p, token);    }    return formattingElementEntry;}//Steps 9 and 10 of the algorithmfunction aaObtainFurthestBlock(p, formattingElementEntry) {    let furthestBlock = null;    for (let i = p.openElements.stackTop; i >= 0; i--) {        const element = p.openElements.items[i];        if (element === formattingElementEntry.element) {            break;        }        if (p._isSpecialElement(element)) {            furthestBlock = element;        }    }    if (!furthestBlock) {        p.openElements.popUntilElementPopped(formattingElementEntry.element);        p.activeFormattingElements.removeEntry(formattingElementEntry);    }    return furthestBlock;}//Step 13 of the algorithmfunction aaInnerLoop(p, furthestBlock, formattingElement) {    let lastElement = furthestBlock;    let nextElement = p.openElements.getCommonAncestor(furthestBlock);    for (let i = 0, element = nextElement; element !== formattingElement; i++, element = nextElement) {        //NOTE: store next element for the next loop iteration (it may be deleted from the stack by step 9.5)        nextElement = p.openElements.getCommonAncestor(element);        const elementEntry = p.activeFormattingElements.getElementEntry(element);        const counterOverflow = elementEntry && i >= AA_INNER_LOOP_ITER;        const shouldRemoveFromOpenElements = !elementEntry || counterOverflow;        if (shouldRemoveFromOpenElements) {            if (counterOverflow) {                p.activeFormattingElements.removeEntry(elementEntry);            }            p.openElements.remove(element);        } else {            element = aaRecreateElementFromEntry(p, elementEntry);            if (lastElement === furthestBlock) {                p.activeFormattingElements.bookmark = elementEntry;            }            p.treeAdapter.detachNode(lastElement);            p.treeAdapter.appendChild(element, lastElement);            lastElement = element;        }    }    return lastElement;}//Step 13.7 of the algorithmfunction aaRecreateElementFromEntry(p, elementEntry) {    const ns = p.treeAdapter.getNamespaceURI(elementEntry.element);    const newElement = p.treeAdapter.createElement(elementEntry.token.tagName, ns, elementEntry.token.attrs);    p.openElements.replace(elementEntry.element, newElement);    elementEntry.element = newElement;    return newElement;}//Step 14 of the algorithmfunction aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement) {    if (p._isElementCausesFosterParenting(commonAncestor)) {        p._fosterParentElement(lastElement);    } else {        const tn = p.treeAdapter.getTagName(commonAncestor);        const ns = p.treeAdapter.getNamespaceURI(commonAncestor);        if (tn === $.TEMPLATE && ns === NS.HTML) {            commonAncestor = p.treeAdapter.getTemplateContent(commonAncestor);        }        p.treeAdapter.appendChild(commonAncestor, lastElement);    }}//Steps 15-19 of the algorithmfunction aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry) {    const ns = p.treeAdapter.getNamespaceURI(formattingElementEntry.element);    const token = formattingElementEntry.token;    const newElement = p.treeAdapter.createElement(token.tagName, ns, token.attrs);    p._adoptNodes(furthestBlock, newElement);    p.treeAdapter.appendChild(furthestBlock, newElement);    p.activeFormattingElements.insertElementAfterBookmark(newElement, formattingElementEntry.token);    p.activeFormattingElements.removeEntry(formattingElementEntry);    p.openElements.remove(formattingElementEntry.element);    p.openElements.insertAfter(furthestBlock, newElement);}//Algorithm entry pointfunction callAdoptionAgency(p, token) {    let formattingElementEntry;    for (let i = 0; i < AA_OUTER_LOOP_ITER; i++) {        formattingElementEntry = aaObtainFormattingElementEntry(p, token, formattingElementEntry);        if (!formattingElementEntry) {            break;        }        const furthestBlock = aaObtainFurthestBlock(p, formattingElementEntry);        if (!furthestBlock) {            break;        }        p.activeFormattingElements.bookmark = formattingElementEntry;        const lastElement = aaInnerLoop(p, furthestBlock, formattingElementEntry.element);        const commonAncestor = p.openElements.getCommonAncestor(formattingElementEntry.element);        p.treeAdapter.detachNode(lastElement);        aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement);        aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry);    }}//Generic token handlers//------------------------------------------------------------------function ignoreToken() {    //NOTE: do nothing =)}function misplacedDoctype(p) {    p._err(ERR.misplacedDoctype);}function appendComment(p, token) {    p._appendCommentNode(token, p.openElements.currentTmplContent || p.openElements.current);}function appendCommentToRootHtmlElement(p, token) {    p._appendCommentNode(token, p.openElements.items[0]);}function appendCommentToDocument(p, token) {    p._appendCommentNode(token, p.document);}function insertCharacters(p, token) {    p._insertCharacters(token);}function stopParsing(p) {    p.stopped = true;}// The "initial" insertion mode//------------------------------------------------------------------function doctypeInInitialMode(p, token) {    p._setDocumentType(token);    const mode = token.forceQuirks ? HTML.DOCUMENT_MODE.QUIRKS : doctype.getDocumentMode(token);    if (!doctype.isConforming(token)) {        p._err(ERR.nonConformingDoctype);    }    p.treeAdapter.setDocumentMode(p.document, mode);    p.insertionMode = BEFORE_HTML_MODE;}function tokenInInitialMode(p, token) {    p._err(ERR.missingDoctype, { beforeToken: true });    p.treeAdapter.setDocumentMode(p.document, HTML.DOCUMENT_MODE.QUIRKS);    p.insertionMode = BEFORE_HTML_MODE;    p._processToken(token);}// The "before html" insertion mode//------------------------------------------------------------------function startTagBeforeHtml(p, token) {    if (token.tagName === $.HTML) {        p._insertElement(token, NS.HTML);        p.insertionMode = BEFORE_HEAD_MODE;    } else {        tokenBeforeHtml(p, token);    }}function endTagBeforeHtml(p, token) {    const tn = token.tagName;    if (tn === $.HTML || tn === $.HEAD || tn === $.BODY || tn === $.BR) {        tokenBeforeHtml(p, token);    }}function tokenBeforeHtml(p, token) {    p._insertFakeRootElement();    p.insertionMode = BEFORE_HEAD_MODE;    p._processToken(token);}// The "before head" insertion mode//------------------------------------------------------------------function startTagBeforeHead(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.HEAD) {        p._insertElement(token, NS.HTML);        p.headElement = p.openElements.current;        p.insertionMode = IN_HEAD_MODE;    } else {        tokenBeforeHead(p, token);    }}function endTagBeforeHead(p, token) {    const tn = token.tagName;    if (tn === $.HEAD || tn === $.BODY || tn === $.HTML || tn === $.BR) {        tokenBeforeHead(p, token);    } else {        p._err(ERR.endTagWithoutMatchingOpenElement);    }}function tokenBeforeHead(p, token) {    p._insertFakeElement($.HEAD);    p.headElement = p.openElements.current;    p.insertionMode = IN_HEAD_MODE;    p._processToken(token);}// The "in head" insertion mode//------------------------------------------------------------------function startTagInHead(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.BASE || tn === $.BASEFONT || tn === $.BGSOUND || tn === $.LINK || tn === $.META) {        p._appendElement(token, NS.HTML);        token.ackSelfClosing = true;    } else if (tn === $.TITLE) {        p._switchToTextParsing(token, Tokenizer.MODE.RCDATA);    } else if (tn === $.NOSCRIPT) {        if (p.options.scriptingEnabled) {            p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);        } else {            p._insertElement(token, NS.HTML);            p.insertionMode = IN_HEAD_NO_SCRIPT_MODE;        }    } else if (tn === $.NOFRAMES || tn === $.STYLE) {        p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);    } else if (tn === $.SCRIPT) {        p._switchToTextParsing(token, Tokenizer.MODE.SCRIPT_DATA);    } else if (tn === $.TEMPLATE) {        p._insertTemplate(token, NS.HTML);        p.activeFormattingElements.insertMarker();        p.framesetOk = false;        p.insertionMode = IN_TEMPLATE_MODE;        p._pushTmplInsertionMode(IN_TEMPLATE_MODE);    } else if (tn === $.HEAD) {        p._err(ERR.misplacedStartTagForHeadElement);    } else {        tokenInHead(p, token);    }}function endTagInHead(p, token) {    const tn = token.tagName;    if (tn === $.HEAD) {        p.openElements.pop();        p.insertionMode = AFTER_HEAD_MODE;    } else if (tn === $.BODY || tn === $.BR || tn === $.HTML) {        tokenInHead(p, token);    } else if (tn === $.TEMPLATE) {        if (p.openElements.tmplCount > 0) {            p.openElements.generateImpliedEndTagsThoroughly();            if (p.openElements.currentTagName !== $.TEMPLATE) {                p._err(ERR.closingOfElementWithOpenChildElements);            }            p.openElements.popUntilTagNamePopped($.TEMPLATE);            p.activeFormattingElements.clearToLastMarker();            p._popTmplInsertionMode();            p._resetInsertionMode();        } else {            p._err(ERR.endTagWithoutMatchingOpenElement);        }    } else {        p._err(ERR.endTagWithoutMatchingOpenElement);    }}function tokenInHead(p, token) {    p.openElements.pop();    p.insertionMode = AFTER_HEAD_MODE;    p._processToken(token);}// The "in head no script" insertion mode//------------------------------------------------------------------function startTagInHeadNoScript(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (        tn === $.BASEFONT ||        tn === $.BGSOUND ||        tn === $.HEAD ||        tn === $.LINK ||        tn === $.META ||        tn === $.NOFRAMES ||        tn === $.STYLE    ) {        startTagInHead(p, token);    } else if (tn === $.NOSCRIPT) {        p._err(ERR.nestedNoscriptInHead);    } else {        tokenInHeadNoScript(p, token);    }}function endTagInHeadNoScript(p, token) {    const tn = token.tagName;    if (tn === $.NOSCRIPT) {        p.openElements.pop();        p.insertionMode = IN_HEAD_MODE;    } else if (tn === $.BR) {        tokenInHeadNoScript(p, token);    } else {        p._err(ERR.endTagWithoutMatchingOpenElement);    }}function tokenInHeadNoScript(p, token) {    const errCode =        token.type === Tokenizer.EOF_TOKEN ? ERR.openElementsLeftAfterEof : ERR.disallowedContentInNoscriptInHead;    p._err(errCode);    p.openElements.pop();    p.insertionMode = IN_HEAD_MODE;    p._processToken(token);}// The "after head" insertion mode//------------------------------------------------------------------function startTagAfterHead(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.BODY) {        p._insertElement(token, NS.HTML);        p.framesetOk = false;        p.insertionMode = IN_BODY_MODE;    } else if (tn === $.FRAMESET) {        p._insertElement(token, NS.HTML);        p.insertionMode = IN_FRAMESET_MODE;    } else if (        tn === $.BASE ||        tn === $.BASEFONT ||        tn === $.BGSOUND ||        tn === $.LINK ||        tn === $.META ||        tn === $.NOFRAMES ||        tn === $.SCRIPT ||        tn === $.STYLE ||        tn === $.TEMPLATE ||        tn === $.TITLE    ) {        p._err(ERR.abandonedHeadElementChild);        p.openElements.push(p.headElement);        startTagInHead(p, token);        p.openElements.remove(p.headElement);    } else if (tn === $.HEAD) {        p._err(ERR.misplacedStartTagForHeadElement);    } else {        tokenAfterHead(p, token);    }}function endTagAfterHead(p, token) {    const tn = token.tagName;    if (tn === $.BODY || tn === $.HTML || tn === $.BR) {        tokenAfterHead(p, token);    } else if (tn === $.TEMPLATE) {        endTagInHead(p, token);    } else {        p._err(ERR.endTagWithoutMatchingOpenElement);    }}function tokenAfterHead(p, token) {    p._insertFakeElement($.BODY);    p.insertionMode = IN_BODY_MODE;    p._processToken(token);}// The "in body" insertion mode//------------------------------------------------------------------function whitespaceCharacterInBody(p, token) {    p._reconstructActiveFormattingElements();    p._insertCharacters(token);}function characterInBody(p, token) {    p._reconstructActiveFormattingElements();    p._insertCharacters(token);    p.framesetOk = false;}function htmlStartTagInBody(p, token) {    if (p.openElements.tmplCount === 0) {        p.treeAdapter.adoptAttributes(p.openElements.items[0], token.attrs);    }}function bodyStartTagInBody(p, token) {    const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();    if (bodyElement && p.openElements.tmplCount === 0) {        p.framesetOk = false;        p.treeAdapter.adoptAttributes(bodyElement, token.attrs);    }}function framesetStartTagInBody(p, token) {    const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();    if (p.framesetOk && bodyElement) {        p.treeAdapter.detachNode(bodyElement);        p.openElements.popAllUpToHtmlElement();        p._insertElement(token, NS.HTML);        p.insertionMode = IN_FRAMESET_MODE;    }}function addressStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._insertElement(token, NS.HTML);}function numberedHeaderStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    const tn = p.openElements.currentTagName;    if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) {        p.openElements.pop();    }    p._insertElement(token, NS.HTML);}function preStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._insertElement(token, NS.HTML);    //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move    //on to the next one. (Newlines at the start of pre blocks are ignored as an authoring convenience.)    p.skipNextNewLine = true;    p.framesetOk = false;}function formStartTagInBody(p, token) {    const inTemplate = p.openElements.tmplCount > 0;    if (!p.formElement || inTemplate) {        if (p.openElements.hasInButtonScope($.P)) {            p._closePElement();        }        p._insertElement(token, NS.HTML);        if (!inTemplate) {            p.formElement = p.openElements.current;        }    }}function listItemStartTagInBody(p, token) {    p.framesetOk = false;    const tn = token.tagName;    for (let i = p.openElements.stackTop; i >= 0; i--) {        const element = p.openElements.items[i];        const elementTn = p.treeAdapter.getTagName(element);        let closeTn = null;        if (tn === $.LI && elementTn === $.LI) {            closeTn = $.LI;        } else if ((tn === $.DD || tn === $.DT) && (elementTn === $.DD || elementTn === $.DT)) {            closeTn = elementTn;        }        if (closeTn) {            p.openElements.generateImpliedEndTagsWithExclusion(closeTn);            p.openElements.popUntilTagNamePopped(closeTn);            break;        }        if (elementTn !== $.ADDRESS && elementTn !== $.DIV && elementTn !== $.P && p._isSpecialElement(element)) {            break;        }    }    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._insertElement(token, NS.HTML);}function plaintextStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._insertElement(token, NS.HTML);    p.tokenizer.state = Tokenizer.MODE.PLAINTEXT;}function buttonStartTagInBody(p, token) {    if (p.openElements.hasInScope($.BUTTON)) {        p.openElements.generateImpliedEndTags();        p.openElements.popUntilTagNamePopped($.BUTTON);    }    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);    p.framesetOk = false;}function aStartTagInBody(p, token) {    const activeElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName($.A);    if (activeElementEntry) {        callAdoptionAgency(p, token);        p.openElements.remove(activeElementEntry.element);        p.activeFormattingElements.removeEntry(activeElementEntry);    }    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);    p.activeFormattingElements.pushElement(p.openElements.current, token);}function bStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);    p.activeFormattingElements.pushElement(p.openElements.current, token);}function nobrStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    if (p.openElements.hasInScope($.NOBR)) {        callAdoptionAgency(p, token);        p._reconstructActiveFormattingElements();    }    p._insertElement(token, NS.HTML);    p.activeFormattingElements.pushElement(p.openElements.current, token);}function appletStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);    p.activeFormattingElements.insertMarker();    p.framesetOk = false;}function tableStartTagInBody(p, token) {    if (        p.treeAdapter.getDocumentMode(p.document) !== HTML.DOCUMENT_MODE.QUIRKS &&        p.openElements.hasInButtonScope($.P)    ) {        p._closePElement();    }    p._insertElement(token, NS.HTML);    p.framesetOk = false;    p.insertionMode = IN_TABLE_MODE;}function areaStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    p._appendElement(token, NS.HTML);    p.framesetOk = false;    token.ackSelfClosing = true;}function inputStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    p._appendElement(token, NS.HTML);    const inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE);    if (!inputType || inputType.toLowerCase() !== HIDDEN_INPUT_TYPE) {        p.framesetOk = false;    }    token.ackSelfClosing = true;}function paramStartTagInBody(p, token) {    p._appendElement(token, NS.HTML);    token.ackSelfClosing = true;}function hrStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._appendElement(token, NS.HTML);    p.framesetOk = false;    p.ackSelfClosing = true;}function imageStartTagInBody(p, token) {    token.tagName = $.IMG;    areaStartTagInBody(p, token);}function textareaStartTagInBody(p, token) {    p._insertElement(token, NS.HTML);    //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move    //on to the next one. (Newlines at the start of textarea elements are ignored as an authoring convenience.)    p.skipNextNewLine = true;    p.tokenizer.state = Tokenizer.MODE.RCDATA;    p.originalInsertionMode = p.insertionMode;    p.framesetOk = false;    p.insertionMode = TEXT_MODE;}function xmpStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._reconstructActiveFormattingElements();    p.framesetOk = false;    p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);}function iframeStartTagInBody(p, token) {    p.framesetOk = false;    p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);}//NOTE: here we assume that we always act as an user agent with enabled plugins, so we parse//<noembed> as a rawtext.function noembedStartTagInBody(p, token) {    p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);}function selectStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);    p.framesetOk = false;    if (        p.insertionMode === IN_TABLE_MODE ||        p.insertionMode === IN_CAPTION_MODE ||        p.insertionMode === IN_TABLE_BODY_MODE ||        p.insertionMode === IN_ROW_MODE ||        p.insertionMode === IN_CELL_MODE    ) {        p.insertionMode = IN_SELECT_IN_TABLE_MODE;    } else {        p.insertionMode = IN_SELECT_MODE;    }}function optgroupStartTagInBody(p, token) {    if (p.openElements.currentTagName === $.OPTION) {        p.openElements.pop();    }    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);}function rbStartTagInBody(p, token) {    if (p.openElements.hasInScope($.RUBY)) {        p.openElements.generateImpliedEndTags();    }    p._insertElement(token, NS.HTML);}function rtStartTagInBody(p, token) {    if (p.openElements.hasInScope($.RUBY)) {        p.openElements.generateImpliedEndTagsWithExclusion($.RTC);    }    p._insertElement(token, NS.HTML);}function menuStartTagInBody(p, token) {    if (p.openElements.hasInButtonScope($.P)) {        p._closePElement();    }    p._insertElement(token, NS.HTML);}function mathStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    foreignContent.adjustTokenMathMLAttrs(token);    foreignContent.adjustTokenXMLAttrs(token);    if (token.selfClosing) {        p._appendElement(token, NS.MATHML);    } else {        p._insertElement(token, NS.MATHML);    }    token.ackSelfClosing = true;}function svgStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    foreignContent.adjustTokenSVGAttrs(token);    foreignContent.adjustTokenXMLAttrs(token);    if (token.selfClosing) {        p._appendElement(token, NS.SVG);    } else {        p._insertElement(token, NS.SVG);    }    token.ackSelfClosing = true;}function genericStartTagInBody(p, token) {    p._reconstructActiveFormattingElements();    p._insertElement(token, NS.HTML);}//OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.//It's faster than using dictionary.function startTagInBody(p, token) {    const tn = token.tagName;    switch (tn.length) {        case 1:            if (tn === $.I || tn === $.S || tn === $.B || tn === $.U) {                bStartTagInBody(p, token);            } else if (tn === $.P) {                addressStartTagInBody(p, token);            } else if (tn === $.A) {                aStartTagInBody(p, token);            } else {                genericStartTagInBody(p, token);            }            break;        case 2:            if (tn === $.DL || tn === $.OL || tn === $.UL) {                addressStartTagInBody(p, token);            } else if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) {                numberedHeaderStartTagInBody(p, token);            } else if (tn === $.LI || tn === $.DD || tn === $.DT) {                listItemStartTagInBody(p, token);            } else if (tn === $.EM || tn === $.TT) {                bStartTagInBody(p, token);            } else if (tn === $.BR) {                areaStartTagInBody(p, token);            } else if (tn === $.HR) {                hrStartTagInBody(p, token);            } else if (tn === $.RB) {                rbStartTagInBody(p, token);            } else if (tn === $.RT || tn === $.RP) {                rtStartTagInBody(p, token);            } else if (tn !== $.TH && tn !== $.TD && tn !== $.TR) {                genericStartTagInBody(p, token);            }            break;        case 3:            if (tn === $.DIV || tn === $.DIR || tn === $.NAV) {                addressStartTagInBody(p, token);            } else if (tn === $.PRE) {                preStartTagInBody(p, token);            } else if (tn === $.BIG) {                bStartTagInBody(p, token);            } else if (tn === $.IMG || tn === $.WBR) {                areaStartTagInBody(p, token);            } else if (tn === $.XMP) {                xmpStartTagInBody(p, token);            } else if (tn === $.SVG) {                svgStartTagInBody(p, token);            } else if (tn === $.RTC) {                rbStartTagInBody(p, token);            } else if (tn !== $.COL) {                genericStartTagInBody(p, token);            }            break;        case 4:            if (tn === $.HTML) {                htmlStartTagInBody(p, token);            } else if (tn === $.BASE || tn === $.LINK || tn === $.META) {                startTagInHead(p, token);            } else if (tn === $.BODY) {                bodyStartTagInBody(p, token);            } else if (tn === $.MAIN || tn === $.MENU) {                addressStartTagInBody(p, token);            } else if (tn === $.FORM) {                formStartTagInBody(p, token);            } else if (tn === $.CODE || tn === $.FONT) {                bStartTagInBody(p, token);            } else if (tn === $.NOBR) {                nobrStartTagInBody(p, token);            } else if (tn === $.AREA) {                areaStartTagInBody(p, token);            } else if (tn === $.MATH) {                mathStartTagInBody(p, token);            } else if (tn === $.MENU) {                menuStartTagInBody(p, token);            } else if (tn !== $.HEAD) {                genericStartTagInBody(p, token);            }            break;        case 5:            if (tn === $.STYLE || tn === $.TITLE) {                startTagInHead(p, token);            } else if (tn === $.ASIDE) {                addressStartTagInBody(p, token);            } else if (tn === $.SMALL) {                bStartTagInBody(p, token);            } else if (tn === $.TABLE) {                tableStartTagInBody(p, token);            } else if (tn === $.EMBED) {                areaStartTagInBody(p, token);            } else if (tn === $.INPUT) {                inputStartTagInBody(p, token);            } else if (tn === $.PARAM || tn === $.TRACK) {                paramStartTagInBody(p, token);            } else if (tn === $.IMAGE) {                imageStartTagInBody(p, token);            } else if (tn !== $.FRAME && tn !== $.TBODY && tn !== $.TFOOT && tn !== $.THEAD) {                genericStartTagInBody(p, token);            }            break;        case 6:            if (tn === $.SCRIPT) {                startTagInHead(p, token);            } else if (                tn === $.CENTER ||                tn === $.FIGURE ||                tn === $.FOOTER ||                tn === $.HEADER ||                tn === $.HGROUP ||                tn === $.DIALOG            ) {                addressStartTagInBody(p, token);            } else if (tn === $.BUTTON) {                buttonStartTagInBody(p, token);            } else if (tn === $.STRIKE || tn === $.STRONG) {                bStartTagInBody(p, token);            } else if (tn === $.APPLET || tn === $.OBJECT) {                appletStartTagInBody(p, token);            } else if (tn === $.KEYGEN) {                areaStartTagInBody(p, token);            } else if (tn === $.SOURCE) {                paramStartTagInBody(p, token);            } else if (tn === $.IFRAME) {                iframeStartTagInBody(p, token);            } else if (tn === $.SELECT) {                selectStartTagInBody(p, token);            } else if (tn === $.OPTION) {                optgroupStartTagInBody(p, token);            } else {                genericStartTagInBody(p, token);            }            break;        case 7:            if (tn === $.BGSOUND) {                startTagInHead(p, token);            } else if (                tn === $.DETAILS ||                tn === $.ADDRESS ||                tn === $.ARTICLE ||                tn === $.SECTION ||                tn === $.SUMMARY            ) {                addressStartTagInBody(p, token);            } else if (tn === $.LISTING) {                preStartTagInBody(p, token);            } else if (tn === $.MARQUEE) {                appletStartTagInBody(p, token);            } else if (tn === $.NOEMBED) {                noembedStartTagInBody(p, token);            } else if (tn !== $.CAPTION) {                genericStartTagInBody(p, token);            }            break;        case 8:            if (tn === $.BASEFONT) {                startTagInHead(p, token);            } else if (tn === $.FRAMESET) {                framesetStartTagInBody(p, token);            } else if (tn === $.FIELDSET) {                addressStartTagInBody(p, token);            } else if (tn === $.TEXTAREA) {                textareaStartTagInBody(p, token);            } else if (tn === $.TEMPLATE) {                startTagInHead(p, token);            } else if (tn === $.NOSCRIPT) {                if (p.options.scriptingEnabled) {                    noembedStartTagInBody(p, token);                } else {                    genericStartTagInBody(p, token);                }            } else if (tn === $.OPTGROUP) {                optgroupStartTagInBody(p, token);            } else if (tn !== $.COLGROUP) {                genericStartTagInBody(p, token);            }            break;        case 9:            if (tn === $.PLAINTEXT) {                plaintextStartTagInBody(p, token);            } else {                genericStartTagInBody(p, token);            }            break;        case 10:            if (tn === $.BLOCKQUOTE || tn === $.FIGCAPTION) {                addressStartTagInBody(p, token);            } else {                genericStartTagInBody(p, token);            }            break;        default:            genericStartTagInBody(p, token);    }}function bodyEndTagInBody(p) {    if (p.openElements.hasInScope($.BODY)) {        p.insertionMode = AFTER_BODY_MODE;    }}function htmlEndTagInBody(p, token) {    if (p.openElements.hasInScope($.BODY)) {        p.insertionMode = AFTER_BODY_MODE;        p._processToken(token);    }}function addressEndTagInBody(p, token) {    const tn = token.tagName;    if (p.openElements.hasInScope(tn)) {        p.openElements.generateImpliedEndTags();        p.openElements.popUntilTagNamePopped(tn);    }}function formEndTagInBody(p) {    const inTemplate = p.openElements.tmplCount > 0;    const formElement = p.formElement;    if (!inTemplate) {        p.formElement = null;    }    if ((formElement || inTemplate) && p.openElements.hasInScope($.FORM)) {        p.openElements.generateImpliedEndTags();        if (inTemplate) {            p.openElements.popUntilTagNamePopped($.FORM);        } else {            p.openElements.remove(formElement);        }    }}function pEndTagInBody(p) {    if (!p.openElements.hasInButtonScope($.P)) {        p._insertFakeElement($.P);    }    p._closePElement();}function liEndTagInBody(p) {    if (p.openElements.hasInListItemScope($.LI)) {        p.openElements.generateImpliedEndTagsWithExclusion($.LI);        p.openElements.popUntilTagNamePopped($.LI);    }}function ddEndTagInBody(p, token) {    const tn = token.tagName;    if (p.openElements.hasInScope(tn)) {        p.openElements.generateImpliedEndTagsWithExclusion(tn);        p.openElements.popUntilTagNamePopped(tn);    }}function numberedHeaderEndTagInBody(p) {    if (p.openElements.hasNumberedHeaderInScope()) {        p.openElements.generateImpliedEndTags();        p.openElements.popUntilNumberedHeaderPopped();    }}function appletEndTagInBody(p, token) {    const tn = token.tagName;    if (p.openElements.hasInScope(tn)) {        p.openElements.generateImpliedEndTags();        p.openElements.popUntilTagNamePopped(tn);        p.activeFormattingElements.clearToLastMarker();    }}function brEndTagInBody(p) {    p._reconstructActiveFormattingElements();    p._insertFakeElement($.BR);    p.openElements.pop();    p.framesetOk = false;}function genericEndTagInBody(p, token) {    const tn = token.tagName;    for (let i = p.openElements.stackTop; i > 0; i--) {        const element = p.openElements.items[i];        if (p.treeAdapter.getTagName(element) === tn) {            p.openElements.generateImpliedEndTagsWithExclusion(tn);            p.openElements.popUntilElementPopped(element);            break;        }        if (p._isSpecialElement(element)) {            break;        }    }}//OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.//It's faster than using dictionary.function endTagInBody(p, token) {    const tn = token.tagName;    switch (tn.length) {        case 1:            if (tn === $.A || tn === $.B || tn === $.I || tn === $.S || tn === $.U) {                callAdoptionAgency(p, token);            } else if (tn === $.P) {                pEndTagInBody(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 2:            if (tn === $.DL || tn === $.UL || tn === $.OL) {                addressEndTagInBody(p, token);            } else if (tn === $.LI) {                liEndTagInBody(p, token);            } else if (tn === $.DD || tn === $.DT) {                ddEndTagInBody(p, token);            } else if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) {                numberedHeaderEndTagInBody(p, token);            } else if (tn === $.BR) {                brEndTagInBody(p, token);            } else if (tn === $.EM || tn === $.TT) {                callAdoptionAgency(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 3:            if (tn === $.BIG) {                callAdoptionAgency(p, token);            } else if (tn === $.DIR || tn === $.DIV || tn === $.NAV || tn === $.PRE) {                addressEndTagInBody(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 4:            if (tn === $.BODY) {                bodyEndTagInBody(p, token);            } else if (tn === $.HTML) {                htmlEndTagInBody(p, token);            } else if (tn === $.FORM) {                formEndTagInBody(p, token);            } else if (tn === $.CODE || tn === $.FONT || tn === $.NOBR) {                callAdoptionAgency(p, token);            } else if (tn === $.MAIN || tn === $.MENU) {                addressEndTagInBody(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 5:            if (tn === $.ASIDE) {                addressEndTagInBody(p, token);            } else if (tn === $.SMALL) {                callAdoptionAgency(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 6:            if (                tn === $.CENTER ||                tn === $.FIGURE ||                tn === $.FOOTER ||                tn === $.HEADER ||                tn === $.HGROUP ||                tn === $.DIALOG            ) {                addressEndTagInBody(p, token);            } else if (tn === $.APPLET || tn === $.OBJECT) {                appletEndTagInBody(p, token);            } else if (tn === $.STRIKE || tn === $.STRONG) {                callAdoptionAgency(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 7:            if (                tn === $.ADDRESS ||                tn === $.ARTICLE ||                tn === $.DETAILS ||                tn === $.SECTION ||                tn === $.SUMMARY ||                tn === $.LISTING            ) {                addressEndTagInBody(p, token);            } else if (tn === $.MARQUEE) {                appletEndTagInBody(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 8:            if (tn === $.FIELDSET) {                addressEndTagInBody(p, token);            } else if (tn === $.TEMPLATE) {                endTagInHead(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        case 10:            if (tn === $.BLOCKQUOTE || tn === $.FIGCAPTION) {                addressEndTagInBody(p, token);            } else {                genericEndTagInBody(p, token);            }            break;        default:            genericEndTagInBody(p, token);    }}function eofInBody(p, token) {    if (p.tmplInsertionModeStackTop > -1) {        eofInTemplate(p, token);    } else {        p.stopped = true;    }}// The "text" insertion mode//------------------------------------------------------------------function endTagInText(p, token) {    if (token.tagName === $.SCRIPT) {        p.pendingScript = p.openElements.current;    }    p.openElements.pop();    p.insertionMode = p.originalInsertionMode;}function eofInText(p, token) {    p._err(ERR.eofInElementThatCanContainOnlyText);    p.openElements.pop();    p.insertionMode = p.originalInsertionMode;    p._processToken(token);}// The "in table" insertion mode//------------------------------------------------------------------function characterInTable(p, token) {    const curTn = p.openElements.currentTagName;    if (curTn === $.TABLE || curTn === $.TBODY || curTn === $.TFOOT || curTn === $.THEAD || curTn === $.TR) {        p.pendingCharacterTokens = [];        p.hasNonWhitespacePendingCharacterToken = false;        p.originalInsertionMode = p.insertionMode;        p.insertionMode = IN_TABLE_TEXT_MODE;        p._processToken(token);    } else {        tokenInTable(p, token);    }}function captionStartTagInTable(p, token) {    p.openElements.clearBackToTableContext();    p.activeFormattingElements.insertMarker();    p._insertElement(token, NS.HTML);    p.insertionMode = IN_CAPTION_MODE;}function colgroupStartTagInTable(p, token) {    p.openElements.clearBackToTableContext();    p._insertElement(token, NS.HTML);    p.insertionMode = IN_COLUMN_GROUP_MODE;}function colStartTagInTable(p, token) {    p.openElements.clearBackToTableContext();    p._insertFakeElement($.COLGROUP);    p.insertionMode = IN_COLUMN_GROUP_MODE;    p._processToken(token);}function tbodyStartTagInTable(p, token) {    p.openElements.clearBackToTableContext();    p._insertElement(token, NS.HTML);    p.insertionMode = IN_TABLE_BODY_MODE;}function tdStartTagInTable(p, token) {    p.openElements.clearBackToTableContext();    p._insertFakeElement($.TBODY);    p.insertionMode = IN_TABLE_BODY_MODE;    p._processToken(token);}function tableStartTagInTable(p, token) {    if (p.openElements.hasInTableScope($.TABLE)) {        p.openElements.popUntilTagNamePopped($.TABLE);        p._resetInsertionMode();        p._processToken(token);    }}function inputStartTagInTable(p, token) {    const inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE);    if (inputType && inputType.toLowerCase() === HIDDEN_INPUT_TYPE) {        p._appendElement(token, NS.HTML);    } else {        tokenInTable(p, token);    }    token.ackSelfClosing = true;}function formStartTagInTable(p, token) {    if (!p.formElement && p.openElements.tmplCount === 0) {        p._insertElement(token, NS.HTML);        p.formElement = p.openElements.current;        p.openElements.pop();    }}function startTagInTable(p, token) {    const tn = token.tagName;    switch (tn.length) {        case 2:            if (tn === $.TD || tn === $.TH || tn === $.TR) {                tdStartTagInTable(p, token);            } else {                tokenInTable(p, token);            }            break;        case 3:            if (tn === $.COL) {                colStartTagInTable(p, token);            } else {                tokenInTable(p, token);            }            break;        case 4:            if (tn === $.FORM) {                formStartTagInTable(p, token);            } else {                tokenInTable(p, token);            }            break;        case 5:            if (tn === $.TABLE) {                tableStartTagInTable(p, token);            } else if (tn === $.STYLE) {                startTagInHead(p, token);            } else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {                tbodyStartTagInTable(p, token);            } else if (tn === $.INPUT) {                inputStartTagInTable(p, token);            } else {                tokenInTable(p, token);            }            break;        case 6:            if (tn === $.SCRIPT) {                startTagInHead(p, token);            } else {                tokenInTable(p, token);            }            break;        case 7:            if (tn === $.CAPTION) {                captionStartTagInTable(p, token);            } else {                tokenInTable(p, token);            }            break;        case 8:            if (tn === $.COLGROUP) {                colgroupStartTagInTable(p, token);            } else if (tn === $.TEMPLATE) {                startTagInHead(p, token);            } else {                tokenInTable(p, token);            }            break;        default:            tokenInTable(p, token);    }}function endTagInTable(p, token) {    const tn = token.tagName;    if (tn === $.TABLE) {        if (p.openElements.hasInTableScope($.TABLE)) {            p.openElements.popUntilTagNamePopped($.TABLE);            p._resetInsertionMode();        }    } else if (tn === $.TEMPLATE) {        endTagInHead(p, token);    } else if (        tn !== $.BODY &&        tn !== $.CAPTION &&        tn !== $.COL &&        tn !== $.COLGROUP &&        tn !== $.HTML &&        tn !== $.TBODY &&        tn !== $.TD &&        tn !== $.TFOOT &&        tn !== $.TH &&        tn !== $.THEAD &&        tn !== $.TR    ) {        tokenInTable(p, token);    }}function tokenInTable(p, token) {    const savedFosterParentingState = p.fosterParentingEnabled;    p.fosterParentingEnabled = true;    p._processTokenInBodyMode(token);    p.fosterParentingEnabled = savedFosterParentingState;}// The "in table text" insertion mode//------------------------------------------------------------------function whitespaceCharacterInTableText(p, token) {    p.pendingCharacterTokens.push(token);}function characterInTableText(p, token) {    p.pendingCharacterTokens.push(token);    p.hasNonWhitespacePendingCharacterToken = true;}function tokenInTableText(p, token) {    let i = 0;    if (p.hasNonWhitespacePendingCharacterToken) {        for (; i < p.pendingCharacterTokens.length; i++) {            tokenInTable(p, p.pendingCharacterTokens[i]);        }    } else {        for (; i < p.pendingCharacterTokens.length; i++) {            p._insertCharacters(p.pendingCharacterTokens[i]);        }    }    p.insertionMode = p.originalInsertionMode;    p._processToken(token);}// The "in caption" insertion mode//------------------------------------------------------------------function startTagInCaption(p, token) {    const tn = token.tagName;    if (        tn === $.CAPTION ||        tn === $.COL ||        tn === $.COLGROUP ||        tn === $.TBODY ||        tn === $.TD ||        tn === $.TFOOT ||        tn === $.TH ||        tn === $.THEAD ||        tn === $.TR    ) {        if (p.openElements.hasInTableScope($.CAPTION)) {            p.openElements.generateImpliedEndTags();            p.openElements.popUntilTagNamePopped($.CAPTION);            p.activeFormattingElements.clearToLastMarker();            p.insertionMode = IN_TABLE_MODE;            p._processToken(token);        }    } else {        startTagInBody(p, token);    }}function endTagInCaption(p, token) {    const tn = token.tagName;    if (tn === $.CAPTION || tn === $.TABLE) {        if (p.openElements.hasInTableScope($.CAPTION)) {            p.openElements.generateImpliedEndTags();            p.openElements.popUntilTagNamePopped($.CAPTION);            p.activeFormattingElements.clearToLastMarker();            p.insertionMode = IN_TABLE_MODE;            if (tn === $.TABLE) {                p._processToken(token);            }        }    } else if (        tn !== $.BODY &&        tn !== $.COL &&        tn !== $.COLGROUP &&        tn !== $.HTML &&        tn !== $.TBODY &&        tn !== $.TD &&        tn !== $.TFOOT &&        tn !== $.TH &&        tn !== $.THEAD &&        tn !== $.TR    ) {        endTagInBody(p, token);    }}// The "in column group" insertion mode//------------------------------------------------------------------function startTagInColumnGroup(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.COL) {        p._appendElement(token, NS.HTML);        token.ackSelfClosing = true;    } else if (tn === $.TEMPLATE) {        startTagInHead(p, token);    } else {        tokenInColumnGroup(p, token);    }}function endTagInColumnGroup(p, token) {    const tn = token.tagName;    if (tn === $.COLGROUP) {        if (p.openElements.currentTagName === $.COLGROUP) {            p.openElements.pop();            p.insertionMode = IN_TABLE_MODE;        }    } else if (tn === $.TEMPLATE) {        endTagInHead(p, token);    } else if (tn !== $.COL) {        tokenInColumnGroup(p, token);    }}function tokenInColumnGroup(p, token) {    if (p.openElements.currentTagName === $.COLGROUP) {        p.openElements.pop();        p.insertionMode = IN_TABLE_MODE;        p._processToken(token);    }}// The "in table body" insertion mode//------------------------------------------------------------------function startTagInTableBody(p, token) {    const tn = token.tagName;    if (tn === $.TR) {        p.openElements.clearBackToTableBodyContext();        p._insertElement(token, NS.HTML);        p.insertionMode = IN_ROW_MODE;    } else if (tn === $.TH || tn === $.TD) {        p.openElements.clearBackToTableBodyContext();        p._insertFakeElement($.TR);        p.insertionMode = IN_ROW_MODE;        p._processToken(token);    } else if (        tn === $.CAPTION ||        tn === $.COL ||        tn === $.COLGROUP ||        tn === $.TBODY ||        tn === $.TFOOT ||        tn === $.THEAD    ) {        if (p.openElements.hasTableBodyContextInTableScope()) {            p.openElements.clearBackToTableBodyContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_MODE;            p._processToken(token);        }    } else {        startTagInTable(p, token);    }}function endTagInTableBody(p, token) {    const tn = token.tagName;    if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {        if (p.openElements.hasInTableScope(tn)) {            p.openElements.clearBackToTableBodyContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_MODE;        }    } else if (tn === $.TABLE) {        if (p.openElements.hasTableBodyContextInTableScope()) {            p.openElements.clearBackToTableBodyContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_MODE;            p._processToken(token);        }    } else if (        (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP) ||        (tn !== $.HTML && tn !== $.TD && tn !== $.TH && tn !== $.TR)    ) {        endTagInTable(p, token);    }}// The "in row" insertion mode//------------------------------------------------------------------function startTagInRow(p, token) {    const tn = token.tagName;    if (tn === $.TH || tn === $.TD) {        p.openElements.clearBackToTableRowContext();        p._insertElement(token, NS.HTML);        p.insertionMode = IN_CELL_MODE;        p.activeFormattingElements.insertMarker();    } else if (        tn === $.CAPTION ||        tn === $.COL ||        tn === $.COLGROUP ||        tn === $.TBODY ||        tn === $.TFOOT ||        tn === $.THEAD ||        tn === $.TR    ) {        if (p.openElements.hasInTableScope($.TR)) {            p.openElements.clearBackToTableRowContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_BODY_MODE;            p._processToken(token);        }    } else {        startTagInTable(p, token);    }}function endTagInRow(p, token) {    const tn = token.tagName;    if (tn === $.TR) {        if (p.openElements.hasInTableScope($.TR)) {            p.openElements.clearBackToTableRowContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_BODY_MODE;        }    } else if (tn === $.TABLE) {        if (p.openElements.hasInTableScope($.TR)) {            p.openElements.clearBackToTableRowContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_BODY_MODE;            p._processToken(token);        }    } else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {        if (p.openElements.hasInTableScope(tn) || p.openElements.hasInTableScope($.TR)) {            p.openElements.clearBackToTableRowContext();            p.openElements.pop();            p.insertionMode = IN_TABLE_BODY_MODE;            p._processToken(token);        }    } else if (        (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP) ||        (tn !== $.HTML && tn !== $.TD && tn !== $.TH)    ) {        endTagInTable(p, token);    }}// The "in cell" insertion mode//------------------------------------------------------------------function startTagInCell(p, token) {    const tn = token.tagName;    if (        tn === $.CAPTION ||        tn === $.COL ||        tn === $.COLGROUP ||        tn === $.TBODY ||        tn === $.TD ||        tn === $.TFOOT ||        tn === $.TH ||        tn === $.THEAD ||        tn === $.TR    ) {        if (p.openElements.hasInTableScope($.TD) || p.openElements.hasInTableScope($.TH)) {            p._closeTableCell();            p._processToken(token);        }    } else {        startTagInBody(p, token);    }}function endTagInCell(p, token) {    const tn = token.tagName;    if (tn === $.TD || tn === $.TH) {        if (p.openElements.hasInTableScope(tn)) {            p.openElements.generateImpliedEndTags();            p.openElements.popUntilTagNamePopped(tn);            p.activeFormattingElements.clearToLastMarker();            p.insertionMode = IN_ROW_MODE;        }    } else if (tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD || tn === $.TR) {        if (p.openElements.hasInTableScope(tn)) {            p._closeTableCell();            p._processToken(token);        }    } else if (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP && tn !== $.HTML) {        endTagInBody(p, token);    }}// The "in select" insertion mode//------------------------------------------------------------------function startTagInSelect(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.OPTION) {        if (p.openElements.currentTagName === $.OPTION) {            p.openElements.pop();        }        p._insertElement(token, NS.HTML);    } else if (tn === $.OPTGROUP) {        if (p.openElements.currentTagName === $.OPTION) {            p.openElements.pop();        }        if (p.openElements.currentTagName === $.OPTGROUP) {            p.openElements.pop();        }        p._insertElement(token, NS.HTML);    } else if (tn === $.INPUT || tn === $.KEYGEN || tn === $.TEXTAREA || tn === $.SELECT) {        if (p.openElements.hasInSelectScope($.SELECT)) {            p.openElements.popUntilTagNamePopped($.SELECT);            p._resetInsertionMode();            if (tn !== $.SELECT) {                p._processToken(token);            }        }    } else if (tn === $.SCRIPT || tn === $.TEMPLATE) {        startTagInHead(p, token);    }}function endTagInSelect(p, token) {    const tn = token.tagName;    if (tn === $.OPTGROUP) {        const prevOpenElement = p.openElements.items[p.openElements.stackTop - 1];        const prevOpenElementTn = prevOpenElement && p.treeAdapter.getTagName(prevOpenElement);        if (p.openElements.currentTagName === $.OPTION && prevOpenElementTn === $.OPTGROUP) {            p.openElements.pop();        }        if (p.openElements.currentTagName === $.OPTGROUP) {            p.openElements.pop();        }    } else if (tn === $.OPTION) {        if (p.openElements.currentTagName === $.OPTION) {            p.openElements.pop();        }    } else if (tn === $.SELECT && p.openElements.hasInSelectScope($.SELECT)) {        p.openElements.popUntilTagNamePopped($.SELECT);        p._resetInsertionMode();    } else if (tn === $.TEMPLATE) {        endTagInHead(p, token);    }}//12.2.5.4.17 The "in select in table" insertion mode//------------------------------------------------------------------function startTagInSelectInTable(p, token) {    const tn = token.tagName;    if (        tn === $.CAPTION ||        tn === $.TABLE ||        tn === $.TBODY ||        tn === $.TFOOT ||        tn === $.THEAD ||        tn === $.TR ||        tn === $.TD ||        tn === $.TH    ) {        p.openElements.popUntilTagNamePopped($.SELECT);        p._resetInsertionMode();        p._processToken(token);    } else {        startTagInSelect(p, token);    }}function endTagInSelectInTable(p, token) {    const tn = token.tagName;    if (        tn === $.CAPTION ||        tn === $.TABLE ||        tn === $.TBODY ||        tn === $.TFOOT ||        tn === $.THEAD ||        tn === $.TR ||        tn === $.TD ||        tn === $.TH    ) {        if (p.openElements.hasInTableScope(tn)) {            p.openElements.popUntilTagNamePopped($.SELECT);            p._resetInsertionMode();            p._processToken(token);        }    } else {        endTagInSelect(p, token);    }}// The "in template" insertion mode//------------------------------------------------------------------function startTagInTemplate(p, token) {    const tn = token.tagName;    if (        tn === $.BASE ||        tn === $.BASEFONT ||        tn === $.BGSOUND ||        tn === $.LINK ||        tn === $.META ||        tn === $.NOFRAMES ||        tn === $.SCRIPT ||        tn === $.STYLE ||        tn === $.TEMPLATE ||        tn === $.TITLE    ) {        startTagInHead(p, token);    } else {        const newInsertionMode = TEMPLATE_INSERTION_MODE_SWITCH_MAP[tn] || IN_BODY_MODE;        p._popTmplInsertionMode();        p._pushTmplInsertionMode(newInsertionMode);        p.insertionMode = newInsertionMode;        p._processToken(token);    }}function endTagInTemplate(p, token) {    if (token.tagName === $.TEMPLATE) {        endTagInHead(p, token);    }}function eofInTemplate(p, token) {    if (p.openElements.tmplCount > 0) {        p.openElements.popUntilTagNamePopped($.TEMPLATE);        p.activeFormattingElements.clearToLastMarker();        p._popTmplInsertionMode();        p._resetInsertionMode();        p._processToken(token);    } else {        p.stopped = true;    }}// The "after body" insertion mode//------------------------------------------------------------------function startTagAfterBody(p, token) {    if (token.tagName === $.HTML) {        startTagInBody(p, token);    } else {        tokenAfterBody(p, token);    }}function endTagAfterBody(p, token) {    if (token.tagName === $.HTML) {        if (!p.fragmentContext) {            p.insertionMode = AFTER_AFTER_BODY_MODE;        }    } else {        tokenAfterBody(p, token);    }}function tokenAfterBody(p, token) {    p.insertionMode = IN_BODY_MODE;    p._processToken(token);}// The "in frameset" insertion mode//------------------------------------------------------------------function startTagInFrameset(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.FRAMESET) {        p._insertElement(token, NS.HTML);    } else if (tn === $.FRAME) {        p._appendElement(token, NS.HTML);        token.ackSelfClosing = true;    } else if (tn === $.NOFRAMES) {        startTagInHead(p, token);    }}function endTagInFrameset(p, token) {    if (token.tagName === $.FRAMESET && !p.openElements.isRootHtmlElementCurrent()) {        p.openElements.pop();        if (!p.fragmentContext && p.openElements.currentTagName !== $.FRAMESET) {            p.insertionMode = AFTER_FRAMESET_MODE;        }    }}// The "after frameset" insertion mode//------------------------------------------------------------------function startTagAfterFrameset(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.NOFRAMES) {        startTagInHead(p, token);    }}function endTagAfterFrameset(p, token) {    if (token.tagName === $.HTML) {        p.insertionMode = AFTER_AFTER_FRAMESET_MODE;    }}// The "after after body" insertion mode//------------------------------------------------------------------function startTagAfterAfterBody(p, token) {    if (token.tagName === $.HTML) {        startTagInBody(p, token);    } else {        tokenAfterAfterBody(p, token);    }}function tokenAfterAfterBody(p, token) {    p.insertionMode = IN_BODY_MODE;    p._processToken(token);}// The "after after frameset" insertion mode//------------------------------------------------------------------function startTagAfterAfterFrameset(p, token) {    const tn = token.tagName;    if (tn === $.HTML) {        startTagInBody(p, token);    } else if (tn === $.NOFRAMES) {        startTagInHead(p, token);    }}// The rules for parsing tokens in foreign content//------------------------------------------------------------------function nullCharacterInForeignContent(p, token) {    token.chars = unicode.REPLACEMENT_CHARACTER;    p._insertCharacters(token);}function characterInForeignContent(p, token) {    p._insertCharacters(token);    p.framesetOk = false;}function startTagInForeignContent(p, token) {    if (foreignContent.causesExit(token) && !p.fragmentContext) {        while (            p.treeAdapter.getNamespaceURI(p.openElements.current) !== NS.HTML &&            !p._isIntegrationPoint(p.openElements.current)        ) {            p.openElements.pop();        }        p._processToken(token);    } else {        const current = p._getAdjustedCurrentElement();        const currentNs = p.treeAdapter.getNamespaceURI(current);        if (currentNs === NS.MATHML) {            foreignContent.adjustTokenMathMLAttrs(token);        } else if (currentNs === NS.SVG) {            foreignContent.adjustTokenSVGTagName(token);            foreignContent.adjustTokenSVGAttrs(token);        }        foreignContent.adjustTokenXMLAttrs(token);        if (token.selfClosing) {            p._appendElement(token, currentNs);        } else {            p._insertElement(token, currentNs);        }        token.ackSelfClosing = true;    }}function endTagInForeignContent(p, token) {    for (let i = p.openElements.stackTop; i > 0; i--) {        const element = p.openElements.items[i];        if (p.treeAdapter.getNamespaceURI(element) === NS.HTML) {            p._processToken(token);            break;        }        if (p.treeAdapter.getTagName(element).toLowerCase() === token.tagName) {            p.openElements.popUntilElementPopped(element);            break;        }    }}
 |