summaryrefslogtreecommitdiffstats
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/expat/COPYING22
-rw-r--r--parser/expat/expat_config.h148
-rw-r--r--parser/expat/expat_config_moz.h22
-rw-r--r--parser/expat/expat_config_rlbox.h20
-rw-r--r--parser/expat/lib/ascii.h92
-rw-r--r--parser/expat/lib/asciitab.h36
-rw-r--r--parser/expat/lib/expat.h1069
-rw-r--r--parser/expat/lib/expat_external.h138
-rw-r--r--parser/expat/lib/iasciitab.h37
-rw-r--r--parser/expat/lib/internal.h95
-rw-r--r--parser/expat/lib/latin1tab.h36
-rw-r--r--parser/expat/lib/moz.build19
-rw-r--r--parser/expat/lib/moz_extensions.c160
-rw-r--r--parser/expat/lib/nametab.h150
-rw-r--r--parser/expat/lib/siphash.h344
-rw-r--r--parser/expat/lib/sources.mozbuild15
-rw-r--r--parser/expat/lib/utf8tab.h37
-rw-r--r--parser/expat/lib/winconfig.h54
-rw-r--r--parser/expat/lib/xmlparse.c7314
-rw-r--r--parser/expat/lib/xmlrole.c1330
-rw-r--r--parser/expat/lib/xmlrole.h114
-rw-r--r--parser/expat/lib/xmltok.c1766
-rw-r--r--parser/expat/lib/xmltok.h322
-rw-r--r--parser/expat/lib/xmltok_impl.c1779
-rw-r--r--parser/expat/lib/xmltok_impl.h46
-rw-r--r--parser/expat/lib/xmltok_ns.c115
-rw-r--r--parser/expat/moz.build22
-rw-r--r--parser/expat/rlbox_expat.h28
-rw-r--r--parser/expat/rlbox_expat_types.h18
-rw-r--r--parser/html/jArray.h124
-rw-r--r--parser/html/java/Makefile52
-rw-r--r--parser/html/java/README.txt86
-rw-r--r--parser/html/java/manifest.txt2
-rw-r--r--parser/html/java/named-character-references.html7
-rw-r--r--parser/html/javasrc/AttributeName.java2278
-rw-r--r--parser/html/javasrc/ElementName.java1896
-rw-r--r--parser/html/javasrc/Portability.java159
-rw-r--r--parser/html/javasrc/README.txt6
-rw-r--r--parser/html/javasrc/StackNode.java364
-rw-r--r--parser/html/javasrc/StateSnapshot.java205
-rw-r--r--parser/html/javasrc/Tokenizer.java7636
-rw-r--r--parser/html/javasrc/TreeBuilder.java6550
-rw-r--r--parser/html/javasrc/UTF16Buffer.java151
-rw-r--r--parser/html/moz.build92
-rw-r--r--parser/html/nsAHtml5TreeBuilderState.h52
-rw-r--r--parser/html/nsAHtml5TreeOpSink.h29
-rw-r--r--parser/html/nsHtml5ArrayCopy.h60
-rw-r--r--parser/html/nsHtml5AtomTable.cpp32
-rw-r--r--parser/html/nsHtml5AtomTable.h91
-rw-r--r--parser/html/nsHtml5AttributeEntry.h70
-rw-r--r--parser/html/nsHtml5AttributeName.cpp2875
-rw-r--r--parser/html/nsHtml5AttributeName.h688
-rw-r--r--parser/html/nsHtml5AutoPauseUpdate.h29
-rw-r--r--parser/html/nsHtml5ByteReadable.h28
-rw-r--r--parser/html/nsHtml5ContentCreatorFunction.h16
-rw-r--r--parser/html/nsHtml5DependentUTF16Buffer.cpp30
-rw-r--r--parser/html/nsHtml5DependentUTF16Buffer.h30
-rw-r--r--parser/html/nsHtml5DocumentBuilder.cpp121
-rw-r--r--parser/html/nsHtml5DocumentBuilder.h129
-rw-r--r--parser/html/nsHtml5DocumentMode.h10
-rw-r--r--parser/html/nsHtml5ElementName.cpp1495
-rw-r--r--parser/html/nsHtml5ElementName.h408
-rw-r--r--parser/html/nsHtml5Highlighter.cpp790
-rw-r--r--parser/html/nsHtml5Highlighter.h444
-rw-r--r--parser/html/nsHtml5HtmlAttributes.cpp205
-rw-r--r--parser/html/nsHtml5HtmlAttributes.h92
-rw-r--r--parser/html/nsHtml5Macros.h30
-rw-r--r--parser/html/nsHtml5Module.cpp123
-rw-r--r--parser/html/nsHtml5Module.h28
-rw-r--r--parser/html/nsHtml5NamedCharacters.cpp102
-rw-r--r--parser/html/nsHtml5NamedCharacters.h50
-rw-r--r--parser/html/nsHtml5NamedCharactersAccel.cpp463
-rw-r--r--parser/html/nsHtml5NamedCharactersAccel.h22
-rw-r--r--parser/html/nsHtml5NamedCharactersInclude.h5467
-rw-r--r--parser/html/nsHtml5OplessBuilder.cpp37
-rw-r--r--parser/html/nsHtml5OplessBuilder.h32
-rw-r--r--parser/html/nsHtml5OwningUTF16Buffer.cpp57
-rw-r--r--parser/html/nsHtml5OwningUTF16Buffer.h64
-rw-r--r--parser/html/nsHtml5Parser.cpp695
-rw-r--r--parser/html/nsHtml5Parser.h337
-rw-r--r--parser/html/nsHtml5PlainTextUtils.cpp33
-rw-r--r--parser/html/nsHtml5PlainTextUtils.h16
-rw-r--r--parser/html/nsHtml5Portability.cpp109
-rw-r--r--parser/html/nsHtml5Portability.h80
-rw-r--r--parser/html/nsHtml5SVGLoadDispatcher.cpp35
-rw-r--r--parser/html/nsHtml5SVGLoadDispatcher.h21
-rw-r--r--parser/html/nsHtml5Speculation.cpp32
-rw-r--r--parser/html/nsHtml5Speculation.h69
-rw-r--r--parser/html/nsHtml5SpeculativeLoad.cpp158
-rw-r--r--parser/html/nsHtml5SpeculativeLoad.h419
-rw-r--r--parser/html/nsHtml5StackNode.cpp230
-rw-r--r--parser/html/nsHtml5StackNode.h111
-rw-r--r--parser/html/nsHtml5StateSnapshot.cpp126
-rw-r--r--parser/html/nsHtml5StateSnapshot.h95
-rw-r--r--parser/html/nsHtml5StreamListener.cpp92
-rw-r--r--parser/html/nsHtml5StreamListener.h62
-rw-r--r--parser/html/nsHtml5StreamParser.cpp2865
-rw-r--r--parser/html/nsHtml5StreamParser.h766
-rw-r--r--parser/html/nsHtml5StreamParserPtr.h228
-rw-r--r--parser/html/nsHtml5StreamParserReleaser.h25
-rw-r--r--parser/html/nsHtml5String.cpp188
-rw-r--r--parser/html/nsHtml5String.h139
-rw-r--r--parser/html/nsHtml5StringParser.cpp115
-rw-r--r--parser/html/nsHtml5StringParser.h87
-rw-r--r--parser/html/nsHtml5Tokenizer.cpp5153
-rw-r--r--parser/html/nsHtml5Tokenizer.h473
-rw-r--r--parser/html/nsHtml5TokenizerCppSupplement.h494
-rw-r--r--parser/html/nsHtml5TokenizerHSupplement.h220
-rw-r--r--parser/html/nsHtml5TokenizerLoopPolicies.h38
-rw-r--r--parser/html/nsHtml5TreeBuilder.cpp4744
-rw-r--r--parser/html/nsHtml5TreeBuilder.h593
-rw-r--r--parser/html/nsHtml5TreeBuilderCppSupplement.h1830
-rw-r--r--parser/html/nsHtml5TreeBuilderHSupplement.h274
-rw-r--r--parser/html/nsHtml5TreeOpExecutor.cpp1405
-rw-r--r--parser/html/nsHtml5TreeOpExecutor.h320
-rw-r--r--parser/html/nsHtml5TreeOpStage.cpp52
-rw-r--r--parser/html/nsHtml5TreeOpStage.h61
-rw-r--r--parser/html/nsHtml5TreeOperation.cpp1208
-rw-r--r--parser/html/nsHtml5TreeOperation.h637
-rw-r--r--parser/html/nsHtml5UTF16Buffer.cpp80
-rw-r--r--parser/html/nsHtml5UTF16Buffer.h77
-rw-r--r--parser/html/nsHtml5UTF16BufferCppSupplement.h26
-rw-r--r--parser/html/nsHtml5UTF16BufferHSupplement.h17
-rw-r--r--parser/html/nsHtml5ViewSourceUtils.cpp63
-rw-r--r--parser/html/nsHtml5ViewSourceUtils.h17
-rw-r--r--parser/html/nsIContentHandle.h5
-rw-r--r--parser/html/nsIParserUtils.idl141
-rw-r--r--parser/html/nsParserUtils.cpp127
-rw-r--r--parser/html/nsParserUtils.h20
-rw-r--r--parser/htmlparser/CNavDTD.cpp44
-rw-r--r--parser/htmlparser/CNavDTD.h32
-rw-r--r--parser/htmlparser/CParserContext.cpp60
-rw-r--r--parser/htmlparser/CParserContext.h60
-rw-r--r--parser/htmlparser/moz.build52
-rw-r--r--parser/htmlparser/nsElementTable.cpp205
-rw-r--r--parser/htmlparser/nsElementTable.h21
-rw-r--r--parser/htmlparser/nsExpatDriver.cpp1747
-rw-r--r--parser/htmlparser/nsExpatDriver.h256
-rw-r--r--parser/htmlparser/nsHTMLTagList.h198
-rw-r--r--parser/htmlparser/nsHTMLTags.cpp167
-rw-r--r--parser/htmlparser/nsHTMLTags.h80
-rw-r--r--parser/htmlparser/nsIContentSink.h143
-rw-r--r--parser/htmlparser/nsIDTD.h88
-rw-r--r--parser/htmlparser/nsIExpatSink.idl111
-rw-r--r--parser/htmlparser/nsIFragmentContentSink.h85
-rw-r--r--parser/htmlparser/nsIHTMLContentSink.h96
-rw-r--r--parser/htmlparser/nsIParser.h186
-rw-r--r--parser/htmlparser/nsParser.cpp1075
-rw-r--r--parser/htmlparser/nsParser.h312
-rw-r--r--parser/htmlparser/nsParserBase.h15
-rw-r--r--parser/htmlparser/nsParserConstants.h22
-rw-r--r--parser/htmlparser/nsParserMsgUtils.cpp62
-rw-r--r--parser/htmlparser/nsParserMsgUtils.h28
-rw-r--r--parser/htmlparser/nsRLBoxExpatDriver.h27
-rw-r--r--parser/htmlparser/nsScanner.cpp331
-rw-r--r--parser/htmlparser/nsScanner.h188
-rw-r--r--parser/htmlparser/nsScannerString.cpp379
-rw-r--r--parser/htmlparser/nsScannerString.h459
-rw-r--r--parser/htmlparser/tests/crashtests/121591-1.html22
-rw-r--r--parser/htmlparser/tests/crashtests/1373045-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/147179-1.html7
-rw-r--r--parser/htmlparser/tests/crashtests/151956-1.html18
-rw-r--r--parser/htmlparser/tests/crashtests/152444-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/1534346-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/1547895-1.html10
-rw-r--r--parser/htmlparser/tests/crashtests/1604307-1.html10
-rw-r--r--parser/htmlparser/tests/crashtests/1606499-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/1747514.html13
-rw-r--r--parser/htmlparser/tests/crashtests/1810896-1.html1081
-rw-r--r--parser/htmlparser/tests/crashtests/185073-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/188474-1.html13
-rw-r--r--parser/htmlparser/tests/crashtests/194329-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/197052-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/220542-1.html2
-rw-r--r--parser/htmlparser/tests/crashtests/253979-1.html4
-rw-r--r--parser/htmlparser/tests/crashtests/269095-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/286733-1.html4
-rw-r--r--parser/htmlparser/tests/crashtests/286733-2.html4
-rw-r--r--parser/htmlparser/tests/crashtests/299036-1.html2
-rw-r--r--parser/htmlparser/tests/crashtests/30885-1.html17
-rw-r--r--parser/htmlparser/tests/crashtests/30956-1.html10
-rw-r--r--parser/htmlparser/tests/crashtests/31392-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/31694-1.html8
-rw-r--r--parser/htmlparser/tests/crashtests/31940-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/32613-1.html18
-rw-r--r--parser/htmlparser/tests/crashtests/328751-1.html9
-rw-r--r--parser/htmlparser/tests/crashtests/34168-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/34168-1.xml6
-rw-r--r--parser/htmlparser/tests/crashtests/408939-1.html139
-rw-r--r--parser/htmlparser/tests/crashtests/41427-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/423373-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/44178-1.html8
-rw-r--r--parser/htmlparser/tests/crashtests/445171-1-inner.svg5
-rw-r--r--parser/htmlparser/tests/crashtests/445171-1.html9
-rw-r--r--parser/htmlparser/tests/crashtests/46495-1.html5
-rw-r--r--parser/htmlparser/tests/crashtests/468538-1.xhtml15
-rw-r--r--parser/htmlparser/tests/crashtests/50134-1.html8
-rw-r--r--parser/htmlparser/tests/crashtests/502103.html1
-rw-r--r--parser/htmlparser/tests/crashtests/502869-iframe.html9
-rw-r--r--parser/htmlparser/tests/crashtests/502869.html18
-rw-r--r--parser/htmlparser/tests/crashtests/50994-1.html12
-rw-r--r--parser/htmlparser/tests/crashtests/515278-1.html3
-rw-r--r--parser/htmlparser/tests/crashtests/515533-1-inner.html12
-rw-r--r--parser/htmlparser/tests/crashtests/515533-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/515816-1.html11
-rw-r--r--parser/htmlparser/tests/crashtests/522326-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/525229-1.html7
-rw-r--r--parser/htmlparser/tests/crashtests/536097-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/555462-iframe.html3
-rw-r--r--parser/htmlparser/tests/crashtests/555462.html21
-rw-r--r--parser/htmlparser/tests/crashtests/563514-1.html10
-rw-r--r--parser/htmlparser/tests/crashtests/574884-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/574884-2.html1
-rw-r--r--parser/htmlparser/tests/crashtests/58455-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/591330-1.html284
-rw-r--r--parser/htmlparser/tests/crashtests/60110-1.html22
-rw-r--r--parser/htmlparser/tests/crashtests/616027-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/650501-1.xhtml22
-rw-r--r--parser/htmlparser/tests/crashtests/662185-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/696651-1.html11
-rw-r--r--parser/htmlparser/tests/crashtests/699347-1.xml1
-rw-r--r--parser/htmlparser/tests/crashtests/721313-1.html2
-rw-r--r--parser/htmlparser/tests/crashtests/73331-1.html27
-rw-r--r--parser/htmlparser/tests/crashtests/742414-1.html4
-rw-r--r--parser/htmlparser/tests/crashtests/762726-1.html1
-rw-r--r--parser/htmlparser/tests/crashtests/92647-1.html33
-rw-r--r--parser/htmlparser/tests/crashtests/92788-1.html20
-rw-r--r--parser/htmlparser/tests/crashtests/981279-1.html15
-rw-r--r--parser/htmlparser/tests/crashtests/982285-1.html19
-rw-r--r--parser/htmlparser/tests/crashtests/crashtests.list67
-rw-r--r--parser/htmlparser/tests/crashtests/file_445171-1.html1
-rw-r--r--parser/htmlparser/tests/mochitest/blue.pngbin0 -> 2745 bytes
-rw-r--r--parser/htmlparser/tests/mochitest/broken_xml.xhtml7
-rw-r--r--parser/htmlparser/tests/mochitest/browser.ini17
-rw-r--r--parser/htmlparser/tests/mochitest/browser_elementindtd.dtd2
-rw-r--r--parser/htmlparser/tests/mochitest/browser_elementindtd.js31
-rw-r--r--parser/htmlparser/tests/mochitest/browser_elementindtd.xml8
-rw-r--r--parser/htmlparser/tests/mochitest/browser_viewsource.js28
-rw-r--r--parser/htmlparser/tests/mochitest/browser_ysod_telemetry.js49
-rw-r--r--parser/htmlparser/tests/mochitest/bug_502091_iframe.html17
-rw-r--r--parser/htmlparser/tests/mochitest/dir_bug534293/file_bug534293.sjs13
-rw-r--r--parser/htmlparser/tests/mochitest/file_async_bug1104732.sjs17
-rw-r--r--parser/htmlparser/tests/mochitest/file_base_csp_img.sjs18
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug102699.sjs19
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug534293-slow.sjs16
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug534293.sjs17
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug543062.sjs38
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug568470-script.sjs17
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug568470.sjs22
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-1.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-2.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-3.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-4.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-5.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-6.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-7.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-8.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug594730-9.html5
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug642908.sjs19
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug655682.sjs31
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_enc_error.html10
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_enc_error_inherited.html9
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html^headers^2
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html^headers^2
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html1028
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_after_head.html10
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_replacement.html10
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html1028
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_speculation_fail.html10
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_userdefined.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_xml_decl.html10
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug672453_xml_speculation_fail.html10
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug688580.js8
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-16.htmlbin0 -> 82 bytes
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-16.html^headers^1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-16.xhtmlbin0 -> 214 bytes
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml^headers^1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-8.html3
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-8.html^headers^1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml7
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml^headers^1
-rw-r--r--parser/htmlparser/tests/mochitest/file_bug717180.html1
-rw-r--r--parser/htmlparser/tests/mochitest/file_defer_bug1104732.js7
-rw-r--r--parser/htmlparser/tests/mochitest/file_img_picture_preload.html167
-rw-r--r--parser/htmlparser/tests/mochitest/file_img_picture_preload.sjs27
-rw-r--r--parser/htmlparser/tests/mochitest/file_viewsource.html18
-rw-r--r--parser/htmlparser/tests/mochitest/file_xml_parse_error.js1
-rw-r--r--parser/htmlparser/tests/mochitest/file_xml_parse_error.xml3
-rw-r--r--parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js11
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/README.md104
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption01.dat337
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat99
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/comments01.dat206
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/doctype01.dat424
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/domjs-unsafe.datbin0 -> 9884 bytes
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities01.dat792
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities02.dat283
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/foreign-fragment.dat550
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_license.txt21
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_upstream.txt11
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5test-com.dat291
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/inbody01.dat54
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/isindex.dat49
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/main-element.dat44
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes-plain-text-unsafe.datbin0 -> 816 bytes
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes.dat46
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/plain-text-unsafe.datbin0 -> 7925 bytes
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/ruby.dat298
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/scriptdata01.dat352
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/adoption01.dat15
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/ark.dat26
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/webkit01.dat28
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tables01.dat286
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/template.dat1406
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests1.dat1959
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests10.dat847
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat482
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests12.dat62
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests14.dat75
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests15.dat216
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests16.dat2396
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests17.dat180
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests18.dat322
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests19.dat1454
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests2.dat821
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests20.dat516
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests21.dat305
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests22.dat190
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests23.dat168
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests24.dat79
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests25.dat220
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests26.dat411
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests3.dat306
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests4.dat58
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests5.dat197
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests6.dat662
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests7.dat402
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests8.dat149
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests9.dat473
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests_innerHTML_1.dat902
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/tricky01.dat334
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit01.dat705
-rw-r--r--parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit02.dat116
-rw-r--r--parser/htmlparser/tests/mochitest/invalidchar.xml4
-rw-r--r--parser/htmlparser/tests/mochitest/mochitest.ini181
-rw-r--r--parser/htmlparser/tests/mochitest/parser_datreader.js218
-rw-r--r--parser/htmlparser/tests/mochitest/parser_web_testrunner.js149
-rw-r--r--parser/htmlparser/tests/mochitest/test_base_csp_img.html35
-rw-r--r--parser/htmlparser/tests/mochitest/test_base_header_csp_img.html32
-rw-r--r--parser/htmlparser/tests/mochitest/test_base_header_csp_img.html^headers^1
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug102699.html75
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug1104732.html59
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug1209658.html35
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug1364399.html43
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug1646140-1.html20
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug1646140-2.html28
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug174351.html31
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug213517.html30
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug339350.xhtml61
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug358797.html31
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug396568.html48
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug418464.html43
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug460437.xhtml40
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug502091.html37
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug534293.html22
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug543062.html26
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug552938-2.html38
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug552938.html33
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug563322.xhtml33
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug566879.html64
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug568470.html51
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug594730.html32
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug613662.html132
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug613662.xhtml137
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug639362.html28
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug642908.html32
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug645115.html32
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug655682.html80
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug667533.html28
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug672453.html131
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug688580.html64
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug688580.xhtml62
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug709083.html30
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug715112.html49
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug715739.html88
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug716579.html44
-rw-r--r--parser/htmlparser/tests/mochitest/test_bug717180.html44
-rw-r--r--parser/htmlparser/tests/mochitest/test_compatmode.html100
-rw-r--r--parser/htmlparser/tests/mochitest/test_html5_tree_construction.html60
-rw-r--r--parser/htmlparser/tests/mochitest/test_html5_tree_construction_part2.html60
-rw-r--r--parser/htmlparser/tests/mochitest/test_img_picture_preload.html88
-rw-r--r--parser/htmlparser/tests/mochitest/test_xml_mislabeled.html62
-rw-r--r--parser/htmlparser/tests/mochitest/test_xml_parse_error.html79
-rw-r--r--parser/htmlparser/tests/reftest/after-1kb-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-1kb.html955
-rw-r--r--parser/htmlparser/tests/reftest/after-bogus-after-1kb-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-bogus-after-1kb.html933
-rw-r--r--parser/htmlparser/tests/reftest/after-bogus-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-bogus.html10
-rw-r--r--parser/htmlparser/tests/reftest/after-head-after-1kb-crlf-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-head-after-1kb-crlf.html927
-rw-r--r--parser/htmlparser/tests/reftest/after-head-after-1kb-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-head-after-1kb.html933
-rw-r--r--parser/htmlparser/tests/reftest/after-head-in-1kb-crlf-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-head-in-1kb-crlf.html932
-rw-r--r--parser/htmlparser/tests/reftest/after-head-in-1kb-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/after-head-in-1kb.html938
-rw-r--r--parser/htmlparser/tests/reftest/baseline-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/baseline.html10
-rw-r--r--parser/htmlparser/tests/reftest/bug1153920-1-ref.html4
-rw-r--r--parser/htmlparser/tests/reftest/bug1153920-1.html3
-rw-r--r--parser/htmlparser/tests/reftest/bug1319410-1-ref.html6
-rw-r--r--parser/htmlparser/tests/reftest/bug1319410-1.html5
-rw-r--r--parser/htmlparser/tests/reftest/bug1636607-1-ref.html18
-rw-r--r--parser/htmlparser/tests/reftest/bug1636607-1.html18
-rw-r--r--parser/htmlparser/tests/reftest/bug1636607-2-ref.html17
-rw-r--r--parser/htmlparser/tests/reftest/bug1636607-2.html18
-rw-r--r--parser/htmlparser/tests/reftest/bug1650087-1-ref.html8
-rw-r--r--parser/htmlparser/tests/reftest/bug1650087-1.html7
-rw-r--r--parser/htmlparser/tests/reftest/bug1726374-1-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug1726374-1.html1
-rw-r--r--parser/htmlparser/tests/reftest/bug1749522-1-ref.txt3
-rw-r--r--parser/htmlparser/tests/reftest/bug1749522-1.txt3
-rw-r--r--parser/htmlparser/tests/reftest/bug482921-1-ref.html27
-rw-r--r--parser/htmlparser/tests/reftest/bug482921-1.html24
-rw-r--r--parser/htmlparser/tests/reftest/bug482921-2-ref.html28
-rw-r--r--parser/htmlparser/tests/reftest/bug482921-2.xhtml25
-rw-r--r--parser/htmlparser/tests/reftest/bug535530-1-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug535530-1.html14
-rw-r--r--parser/htmlparser/tests/reftest/bug535530-2-ref.html17
-rw-r--r--parser/htmlparser/tests/reftest/bug535530-2.html14
-rw-r--r--parser/htmlparser/tests/reftest/bug566280-1-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug566280-1.htmlbin0 -> 19 bytes
-rw-r--r--parser/htmlparser/tests/reftest/bug569229-1-ref.xml2
-rw-r--r--parser/htmlparser/tests/reftest/bug569229-1.xml6
-rw-r--r--parser/htmlparser/tests/reftest/bug577418-1-ref.html6
-rw-r--r--parser/htmlparser/tests/reftest/bug577418-1.html15
-rw-r--r--parser/htmlparser/tests/reftest/bug582788-1-ref.html11
-rw-r--r--parser/htmlparser/tests/reftest/bug582788-1.html11
-rw-r--r--parser/htmlparser/tests/reftest/bug582940-1-ref.html16
-rw-r--r--parser/htmlparser/tests/reftest/bug582940-1.html16
-rw-r--r--parser/htmlparser/tests/reftest/bug592656-1-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug592656-1.html32
-rw-r--r--parser/htmlparser/tests/reftest/bug599320-1-ref.html17
-rw-r--r--parser/htmlparser/tests/reftest/bug599320-1.htmlbin0 -> 616 bytes
-rw-r--r--parser/htmlparser/tests/reftest/bug608373-1-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug608373-1.html14
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-1-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-1.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-2-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-2.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-3-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-3.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-4-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-4.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-5-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-5.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-6-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug659763-6.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug673094-1-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug673094-1.html9
-rw-r--r--parser/htmlparser/tests/reftest/bug696651-1-ref.html1
-rw-r--r--parser/htmlparser/tests/reftest/bug696651-1.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug696651-2-ref.html1
-rw-r--r--parser/htmlparser/tests/reftest/bug696651-2.html6
-rw-r--r--parser/htmlparser/tests/reftest/bug696651-external.js1
-rw-r--r--parser/htmlparser/tests/reftest/bug700260-1-ref.html3
-rw-r--r--parser/htmlparser/tests/reftest/bug700260-1.html3
-rw-r--r--parser/htmlparser/tests/reftest/bug704667-1-ref.html4
-rw-r--r--parser/htmlparser/tests/reftest/bug704667-1.html1
-rw-r--r--parser/htmlparser/tests/reftest/bug731234-1-ref.html30
-rw-r--r--parser/htmlparser/tests/reftest/bug731234-1.html27
-rw-r--r--parser/htmlparser/tests/reftest/bug820508-1-ref.html6
-rw-r--r--parser/htmlparser/tests/reftest/bug820508-1.html6
-rw-r--r--parser/htmlparser/tests/reftest/bug910588-1-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/bug910588-1.html1
-rw-r--r--parser/htmlparser/tests/reftest/document-write-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/document-write.html10
-rw-r--r--parser/htmlparser/tests/reftest/frame582940-ref.html51
-rw-r--r--parser/htmlparser/tests/reftest/frame582940.html51
-rw-r--r--parser/htmlparser/tests/reftest/frame599320-1-ref.html15
-rw-r--r--parser/htmlparser/tests/reftest/frame599320-1.html1092
-rw-r--r--parser/htmlparser/tests/reftest/in-comment-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-comment.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb.html894
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-after-template-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-after-template.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-ncr-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-ncr.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-noscript.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-object-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-object.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-script-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-script.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-style-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-style.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt-ref.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-svg-in-cdata-ref.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-svg-in-cdata.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-svg-ref.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-svg.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-template-after-1kb-ref.html8
-rw-r--r--parser/htmlparser/tests/reftest/in-template-after-1kb.html1046
-rw-r--r--parser/htmlparser/tests/reftest/in-template-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/in-template.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-title-ref.html10
-rw-r--r--parser/htmlparser/tests/reftest/in-title.html10
-rw-r--r--parser/htmlparser/tests/reftest/incomplete-xml-decl-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/incomplete-xml-decl.xml1
-rw-r--r--parser/htmlparser/tests/reftest/ncr-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/ncr.html10
-rw-r--r--parser/htmlparser/tests/reftest/non-ascii-in-comment-before-ref.html9
-rw-r--r--parser/htmlparser/tests/reftest/non-ascii-in-comment-before.html11
-rw-r--r--parser/htmlparser/tests/reftest/non-ascii-in-title-before-ref.html10
-rw-r--r--parser/htmlparser/tests/reftest/non-ascii-in-title-before.html11
-rw-r--r--parser/htmlparser/tests/reftest/reftest.list73
-rw-r--r--parser/htmlparser/tests/reftest/view-source-bom-ref.html10
-rw-r--r--parser/htmlparser/tests/reftest/view-source-bom.html9
-rw-r--r--parser/htmlparser/tests/reftest/vs-after-head-after-1kb-ref.html11
-rw-r--r--parser/htmlparser/tests/reftest/vs-after-head-after-1kb.html10
-rw-r--r--parser/htmlparser/tests/reftest/vs-after-head-in-1kb-ref.html12
-rw-r--r--parser/htmlparser/tests/reftest/vs-after-head-in-1kb.html11
-rw-r--r--parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before-ref.html12
-rw-r--r--parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.html11
-rw-r--r--parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.sjs16
-rw-r--r--parser/htmlparser/tests/reftest/xml-1.xml1
-rw-r--r--parser/htmlparser/tests/reftest/xml-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/xml-trickle-1.sjs17
-rw-r--r--parser/htmlparser/tests/reftest/xml-trickle-2.sjs17
-rw-r--r--parser/htmlparser/tests/reftest/xml-trickle-3.sjs21
-rw-r--r--parser/htmlparser/tests/reftest/xml-trickle-4.sjs17
-rw-r--r--parser/htmlparser/tests/reftest/xml-trickle-5.sjs17
-rw-r--r--parser/htmlparser/tests/reftest/xml-trickle-6.sjs21
-rw-r--r--parser/htmlparser/tests/reftest/xml-utf-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/xml-without-tags-ref.html2
-rw-r--r--parser/htmlparser/tests/reftest/xml-without-tags.xml1
-rw-r--r--parser/moz.build14
-rw-r--r--parser/nsCharsetSource.h47
-rw-r--r--parser/prototype/PrototypeDocumentParser.cpp213
-rw-r--r--parser/prototype/PrototypeDocumentParser.h131
-rw-r--r--parser/prototype/moz.build24
-rw-r--r--parser/xml/moz.build10
-rw-r--r--parser/xml/test/moz.build8
-rw-r--r--parser/xml/test/unit/CC-BY-LICENSE59
-rw-r--r--parser/xml/test/unit/results.js924
-rw-r--r--parser/xml/test/unit/test_sanitizer.js53
-rw-r--r--parser/xml/test/unit/test_sanitizer_style.js125
-rw-r--r--parser/xml/test/unit/xpcshell.ini6
557 files changed, 121280 insertions, 0 deletions
diff --git a/parser/expat/COPYING b/parser/expat/COPYING
new file mode 100644
index 0000000000..dcb4506429
--- /dev/null
+++ b/parser/expat/COPYING
@@ -0,0 +1,22 @@
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ and Clark Cooper
+Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/parser/expat/expat_config.h b/parser/expat/expat_config.h
new file mode 100644
index 0000000000..d302adceb9
--- /dev/null
+++ b/parser/expat/expat_config.h
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __expat_config_h__
+#define __expat_config_h__
+
+#ifdef MOZ_IN_WASM_SANDBOX
+# include "expat_config_rlbox.h"
+#else
+# include "expat_config_moz.h"
+#endif
+
+/* Other Mozilla code relies on memmove already, so we assume it's available */
+#define HAVE_MEMMOVE 1
+
+#define XMLCALL
+#define XML_STATIC
+#define XMLIMPORT
+
+#define XML_UNICODE
+typedef char XML_LChar;
+/*
+ * The char16_t type is only usable in C++ code, so we need this ugly hack to
+ * select a binary compatible C type for the expat C code to use.
+ */
+#ifdef __cplusplus
+typedef char16_t XML_Char;
+#define XML_T(x) (char16_t)x
+#else
+#include <stdint.h>
+typedef uint16_t XML_Char;
+#define XML_T(x) (uint16_t)x
+#endif
+
+#define XML_DTD
+#define XML_NS
+
+/* avoid conflicts with system version of libexpat */
+
+/* expat.h */
+#define XML_SetElementDeclHandler MOZ_XML_SetElementDeclHandler
+#define XML_SetAttlistDeclHandler MOZ_XML_SetAttlistDeclHandler
+#define XML_SetXmlDeclHandler MOZ_XML_SetXmlDeclHandler
+#define XML_ParserCreate MOZ_XML_ParserCreate
+#define XML_ParserCreateNS MOZ_XML_ParserCreateNS
+#define XML_ParserCreate_MM MOZ_XML_ParserCreate_MM
+#define XML_ParserReset MOZ_XML_ParserReset
+#define XML_SetEntityDeclHandler MOZ_XML_SetEntityDeclHandler
+#define XML_SetElementHandler MOZ_XML_SetElementHandler
+#define XML_SetStartElementHandler MOZ_XML_SetStartElementHandler
+#define XML_SetEndElementHandler MOZ_XML_SetEndElementHandler
+#define XML_SetCharacterDataHandler MOZ_XML_SetCharacterDataHandler
+#ifndef __VMS
+#define XML_SetProcessingInstructionHandler MOZ_XML_SetProcessingInstructionHandler
+#else
+#define XML_SetProcessingInstrHandler MOZ_XML_SetProcessingInstrHandler
+#endif
+#define XML_SetCommentHandler MOZ_XML_SetCommentHandler
+#define XML_SetCdataSectionHandler MOZ_XML_SetCdataSectionHandler
+#define XML_SetStartCdataSectionHandler MOZ_XML_SetStartCdataSectionHandler
+#define XML_SetEndCdataSectionHandler MOZ_XML_SetEndCdataSectionHandler
+#define XML_SetDefaultHandler MOZ_XML_SetDefaultHandler
+#define XML_SetDefaultHandlerExpand MOZ_XML_SetDefaultHandlerExpand
+#define XML_SetDoctypeDeclHandler MOZ_XML_SetDoctypeDeclHandler
+#define XML_SetStartDoctypeDeclHandler MOZ_XML_SetStartDoctypeDeclHandler
+#define XML_SetEndDoctypeDeclHandler MOZ_XML_SetEndDoctypeDeclHandler
+#ifndef __VMS
+#define XML_SetUnparsedEntityDeclHandler MOZ_XML_SetUnparsedEntityDeclHandler
+#else
+#define XML_SetUnparsedEntDeclHandler MOZ_XML_SetUnparsedEntDeclHandler
+#endif
+#define XML_SetNotationDeclHandler MOZ_XML_SetNotationDeclHandler
+#define XML_SetNamespaceDeclHandler MOZ_XML_SetNamespaceDeclHandler
+#ifndef __VMS
+#define XML_SetStartNamespaceDeclHandler MOZ_XML_SetStartNamespaceDeclHandler
+#else
+#define XML_SetStartNamespcDeclHandler MOZ_XML_SetStartNamespcDeclHandler
+#endif
+#define XML_SetEndNamespaceDeclHandler MOZ_XML_SetEndNamespaceDeclHandler
+#define XML_SetNotStandaloneHandler MOZ_XML_SetNotStandaloneHandler
+#define XML_SetExternalEntityRefHandler MOZ_XML_SetExternalEntityRefHandler
+#ifndef __VMS
+#define XML_SetExternalEntityRefHandlerArg MOZ_XML_SetExternalEntityRefHandlerArg
+#else
+#define XML_SetExternalEntRefHandlerArg MOZ_XML_SetExternalEntRefHandlerArg
+#endif
+#define XML_SetSkippedEntityHandler MOZ_XML_SetSkippedEntityHandler
+#define XML_SetUnknownEncodingHandler MOZ_XML_SetUnknownEncodingHandler
+#define XML_DefaultCurrent MOZ_XML_DefaultCurrent
+#define XML_SetReturnNSTriplet MOZ_XML_SetReturnNSTriplet
+#define XML_SetUserData MOZ_XML_SetUserData
+#define XML_SetEncoding MOZ_XML_SetEncoding
+#define XML_UseParserAsHandlerArg MOZ_XML_UseParserAsHandlerArg
+#define XML_UseForeignDTD MOZ_XML_UseForeignDTD
+#define XML_SetBase MOZ_XML_SetBase
+#define XML_GetBase MOZ_XML_GetBase
+#define XML_GetSpecifiedAttributeCount MOZ_XML_GetSpecifiedAttributeCount
+#define XML_GetIdAttributeIndex MOZ_XML_GetIdAttributeIndex
+#define XML_Parse MOZ_XML_Parse
+#define XML_GetBuffer MOZ_XML_GetBuffer
+#define XML_ParseBuffer MOZ_XML_ParseBuffer
+#define XML_StopParser MOZ_XML_StopParser
+#define XML_ResumeParser MOZ_XML_ResumeParser
+#define XML_GetParsingStatus MOZ_XML_GetParsingStatus
+#define XML_ExternalEntityParserCreate MOZ_XML_ExternalEntityParserCreate
+#define XML_SetParamEntityParsing MOZ_XML_SetParamEntityParsing
+#define XML_GetErrorCode MOZ_XML_GetErrorCode
+#define XML_GetCurrentLineNumber MOZ_XML_GetCurrentLineNumber
+#define XML_GetCurrentColumnNumber MOZ_XML_GetCurrentColumnNumber
+#define XML_GetCurrentByteIndex MOZ_XML_GetCurrentByteIndex
+#define XML_GetCurrentByteCount MOZ_XML_GetCurrentByteCount
+#define XML_GetInputContext MOZ_XML_GetInputContext
+#define XML_FreeContentModel MOZ_XML_FreeContentModel
+#define XML_MemMalloc MOZ_XML_MemMalloc
+#define XML_MemRealloc MOZ_XML_MemRealloc
+#define XML_MemFree MOZ_XML_MemFree
+#define XML_ParserFree MOZ_XML_ParserFree
+#define XML_ErrorString MOZ_XML_ErrorString
+#define XML_ExpatVersion MOZ_XML_ExpatVersion
+#define XML_ExpatVersionInfo MOZ_XML_ExpatVersionInfo
+#define XML_GetFeatureList MOZ_XML_GetFeatureList
+
+/* xmlrole.h */
+#define XmlPrologStateInit MOZ_XmlPrologStateInit
+#ifndef __VMS
+#define XmlPrologStateInitExternalEntity MOZ_XmlPrologStateInitExternalEntity
+#else
+#define XmlPrologStateInitExternalEnt MOZ_XmlPrologStateInitExternalEnt
+#endif
+
+/* xmltok.h */
+#define XmlParseXmlDecl MOZ_XmlParseXmlDecl
+#define XmlParseXmlDeclNS MOZ_XmlParseXmlDeclNS
+#define XmlInitEncoding MOZ_XmlInitEncoding
+#define XmlInitEncodingNS MOZ_XmlInitEncodingNS
+#define XmlGetUtf8InternalEncoding MOZ_XmlGetUtf8InternalEncoding
+#define XmlGetUtf16InternalEncoding MOZ_XmlGetUtf16InternalEncoding
+#define XmlGetUtf8InternalEncodingNS MOZ_XmlGetUtf8InternalEncodingNS
+#define XmlGetUtf16InternalEncodingNS MOZ_XmlGetUtf16InternalEncodingNS
+#define XmlUtf8Encode MOZ_XmlUtf8Encode
+#define XmlUtf16Encode MOZ_XmlUtf16Encode
+#define XmlSizeOfUnknownEncoding MOZ_XmlSizeOfUnknownEncoding
+#define XmlInitUnknownEncoding MOZ_XmlInitUnknownEncoding
+#define XmlInitUnknownEncodingNS MOZ_XmlInitUnknownEncodingNS
+
+#endif /* __expat_config_h__ */
diff --git a/parser/expat/expat_config_moz.h b/parser/expat/expat_config_moz.h
new file mode 100644
index 0000000000..3bb1ee6ba6
--- /dev/null
+++ b/parser/expat/expat_config_moz.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __expat_config_moz_h__
+#define __expat_config_moz_h__
+
+#define MOZ_UNICODE
+#include "nspr.h"
+
+#ifdef IS_LITTLE_ENDIAN
+#define BYTEORDER 1234
+#else
+#define BYTEORDER 4321
+#endif /* IS_LITTLE_ENDIAN */
+
+#if PR_BYTES_PER_INT != 4
+#define int int32_t
+#endif /* PR_BYTES_PER_INT != 4 */
+
+#endif /* __expat_config_moz_h__ */
diff --git a/parser/expat/expat_config_rlbox.h b/parser/expat/expat_config_rlbox.h
new file mode 100644
index 0000000000..9764c7193e
--- /dev/null
+++ b/parser/expat/expat_config_rlbox.h
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __expat_config_rlbox_h__
+#define __expat_config_rlbox_h__
+
+/* Wasm is little endian */
+#define BYTEORDER 1234
+
+/* We don't redefine int as int32_t for our 32-bit Wasm machine. */
+#ifdef __cplusplus
+static_assert(sizeof(int) == sizeof(int32_t), "Expected int and int32_t to be of same size.");
+#endif
+
+/* We don't need to nor want to expose getpid() to expat */
+#define getpid() 0
+
+#endif /* __expat_config_rlbox_h__ */
diff --git a/parser/expat/lib/ascii.h b/parser/expat/lib/ascii.h
new file mode 100644
index 0000000000..d10530b09b
--- /dev/null
+++ b/parser/expat/lib/ascii.h
@@ -0,0 +1,92 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#define ASCII_A 0x41
+#define ASCII_B 0x42
+#define ASCII_C 0x43
+#define ASCII_D 0x44
+#define ASCII_E 0x45
+#define ASCII_F 0x46
+#define ASCII_G 0x47
+#define ASCII_H 0x48
+#define ASCII_I 0x49
+#define ASCII_J 0x4A
+#define ASCII_K 0x4B
+#define ASCII_L 0x4C
+#define ASCII_M 0x4D
+#define ASCII_N 0x4E
+#define ASCII_O 0x4F
+#define ASCII_P 0x50
+#define ASCII_Q 0x51
+#define ASCII_R 0x52
+#define ASCII_S 0x53
+#define ASCII_T 0x54
+#define ASCII_U 0x55
+#define ASCII_V 0x56
+#define ASCII_W 0x57
+#define ASCII_X 0x58
+#define ASCII_Y 0x59
+#define ASCII_Z 0x5A
+
+#define ASCII_a 0x61
+#define ASCII_b 0x62
+#define ASCII_c 0x63
+#define ASCII_d 0x64
+#define ASCII_e 0x65
+#define ASCII_f 0x66
+#define ASCII_g 0x67
+#define ASCII_h 0x68
+#define ASCII_i 0x69
+#define ASCII_j 0x6A
+#define ASCII_k 0x6B
+#define ASCII_l 0x6C
+#define ASCII_m 0x6D
+#define ASCII_n 0x6E
+#define ASCII_o 0x6F
+#define ASCII_p 0x70
+#define ASCII_q 0x71
+#define ASCII_r 0x72
+#define ASCII_s 0x73
+#define ASCII_t 0x74
+#define ASCII_u 0x75
+#define ASCII_v 0x76
+#define ASCII_w 0x77
+#define ASCII_x 0x78
+#define ASCII_y 0x79
+#define ASCII_z 0x7A
+
+#define ASCII_0 0x30
+#define ASCII_1 0x31
+#define ASCII_2 0x32
+#define ASCII_3 0x33
+#define ASCII_4 0x34
+#define ASCII_5 0x35
+#define ASCII_6 0x36
+#define ASCII_7 0x37
+#define ASCII_8 0x38
+#define ASCII_9 0x39
+
+#define ASCII_TAB 0x09
+#define ASCII_SPACE 0x20
+#define ASCII_EXCL 0x21
+#define ASCII_QUOT 0x22
+#define ASCII_AMP 0x26
+#define ASCII_APOS 0x27
+#define ASCII_MINUS 0x2D
+#define ASCII_PERIOD 0x2E
+#define ASCII_COLON 0x3A
+#define ASCII_SEMI 0x3B
+#define ASCII_LT 0x3C
+#define ASCII_EQUALS 0x3D
+#define ASCII_GT 0x3E
+#define ASCII_LSQB 0x5B
+#define ASCII_RSQB 0x5D
+#define ASCII_UNDERSCORE 0x5F
+#define ASCII_LPAREN 0x28
+#define ASCII_RPAREN 0x29
+#define ASCII_FF 0x0C
+#define ASCII_SLASH 0x2F
+#define ASCII_HASH 0x23
+#define ASCII_PIPE 0x7C
+#define ASCII_COMMA 0x2C
diff --git a/parser/expat/lib/asciitab.h b/parser/expat/lib/asciitab.h
new file mode 100644
index 0000000000..79a15c28ca
--- /dev/null
+++ b/parser/expat/lib/asciitab.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/parser/expat/lib/expat.h b/parser/expat/lib/expat.h
new file mode 100644
index 0000000000..555f2e146d
--- /dev/null
+++ b/parser/expat/lib/expat.h
@@ -0,0 +1,1069 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_INCLUDED
+#define Expat_INCLUDED 1
+
+#ifdef __VMS
+/* 0 1 2 3 0 1 2 3
+ 1234567890123456789012345678901 1234567890123456789012345678901 */
+#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler
+#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler
+#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler
+#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg
+#endif
+
+#include <stdlib.h>
+#include "expat_config.h"
+#include "expat_external.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct XML_ParserStruct;
+typedef struct XML_ParserStruct *XML_Parser;
+
+/* Should this be defined using stdbool.h when C99 is available? */
+typedef unsigned char XML_Bool;
+#define XML_TRUE ((XML_Bool) 1)
+#define XML_FALSE ((XML_Bool) 0)
+
+/* The XML_Status enum gives the possible return values for several
+ API functions. The preprocessor #defines are included so this
+ stanza can be added to code that still needs to support older
+ versions of Expat 1.95.x:
+
+ #ifndef XML_STATUS_OK
+ #define XML_STATUS_OK 1
+ #define XML_STATUS_ERROR 0
+ #endif
+
+ Otherwise, the #define hackery is quite ugly and would have been
+ dropped.
+*/
+enum XML_Status {
+ XML_STATUS_ERROR = 0,
+#define XML_STATUS_ERROR XML_STATUS_ERROR
+ XML_STATUS_OK = 1,
+#define XML_STATUS_OK XML_STATUS_OK
+ XML_STATUS_SUSPENDED = 2
+#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED
+};
+
+enum XML_Error {
+ XML_ERROR_NONE,
+ XML_ERROR_NO_MEMORY,
+ XML_ERROR_SYNTAX,
+ XML_ERROR_NO_ELEMENTS,
+ XML_ERROR_INVALID_TOKEN,
+ XML_ERROR_UNCLOSED_TOKEN,
+ XML_ERROR_PARTIAL_CHAR,
+ XML_ERROR_TAG_MISMATCH,
+ XML_ERROR_DUPLICATE_ATTRIBUTE,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+ XML_ERROR_PARAM_ENTITY_REF,
+ XML_ERROR_UNDEFINED_ENTITY,
+ XML_ERROR_RECURSIVE_ENTITY_REF,
+ XML_ERROR_ASYNC_ENTITY,
+ XML_ERROR_BAD_CHAR_REF,
+ XML_ERROR_BINARY_ENTITY_REF,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+ XML_ERROR_MISPLACED_XML_PI,
+ XML_ERROR_UNKNOWN_ENCODING,
+ XML_ERROR_INCORRECT_ENCODING,
+ XML_ERROR_UNCLOSED_CDATA_SECTION,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+ XML_ERROR_NOT_STANDALONE,
+ XML_ERROR_UNEXPECTED_STATE,
+ XML_ERROR_ENTITY_DECLARED_IN_PE,
+ XML_ERROR_FEATURE_REQUIRES_XML_DTD,
+ XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING,
+ /* Added in 1.95.7. */
+ XML_ERROR_UNBOUND_PREFIX,
+ /* Added in 1.95.8. */
+ XML_ERROR_UNDECLARING_PREFIX,
+ XML_ERROR_INCOMPLETE_PE,
+ XML_ERROR_XML_DECL,
+ XML_ERROR_TEXT_DECL,
+ XML_ERROR_PUBLICID,
+ XML_ERROR_SUSPENDED,
+ XML_ERROR_NOT_SUSPENDED,
+ XML_ERROR_ABORTED,
+ XML_ERROR_FINISHED,
+ XML_ERROR_SUSPEND_PE,
+ /* Added in 2.0. */
+ XML_ERROR_RESERVED_PREFIX_XML,
+ XML_ERROR_RESERVED_PREFIX_XMLNS,
+ XML_ERROR_RESERVED_NAMESPACE_URI,
+ /* Added in 2.2.1. */
+ XML_ERROR_INVALID_ARGUMENT
+};
+
+enum XML_Content_Type {
+ XML_CTYPE_EMPTY = 1,
+ XML_CTYPE_ANY,
+ XML_CTYPE_MIXED,
+ XML_CTYPE_NAME,
+ XML_CTYPE_CHOICE,
+ XML_CTYPE_SEQ
+};
+
+enum XML_Content_Quant {
+ XML_CQUANT_NONE,
+ XML_CQUANT_OPT,
+ XML_CQUANT_REP,
+ XML_CQUANT_PLUS
+};
+
+/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+ XML_CQUANT_NONE, and the other fields will be zero or NULL.
+ If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+ numchildren will contain number of elements that may be mixed in
+ and children point to an array of XML_Content cells that will be
+ all of XML_CTYPE_NAME type with no quantification.
+
+ If type == XML_CTYPE_NAME, then the name points to the name, and
+ the numchildren field will be zero and children will be NULL. The
+ quant fields indicates any quantifiers placed on the name.
+
+ CHOICE and SEQ will have name NULL, the number of children in
+ numchildren and children will point, recursively, to an array
+ of XML_Content cells.
+
+ The EMPTY, ANY, and MIXED types will only occur at top level.
+*/
+
+typedef struct XML_cp XML_Content;
+
+struct XML_cp {
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ XML_Char * name;
+ unsigned int numchildren;
+ XML_Content * children;
+};
+
+
+/* This is called for an element declaration. See above for
+ description of the model argument. It's the caller's responsibility
+ to free model when finished with it.
+*/
+typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
+ const XML_Char *name,
+ XML_Content *model);
+
+XMLPARSEAPI(void)
+XML_SetElementDeclHandler(XML_Parser parser,
+ XML_ElementDeclHandler eldecl);
+
+/* The Attlist declaration handler is called for *each* attribute. So
+ a single Attlist declaration with multiple attributes declared will
+ generate multiple calls to this handler. The "default" parameter
+ may be NULL in the case of the "#IMPLIED" or "#REQUIRED"
+ keyword. The "isrequired" parameter will be true and the default
+ value will be NULL in the case of "#REQUIRED". If "isrequired" is
+ true and default is non-NULL, then this is a "#FIXED" default.
+*/
+typedef void (XMLCALL *XML_AttlistDeclHandler) (
+ void *userData,
+ const XML_Char *elname,
+ const XML_Char *attname,
+ const XML_Char *att_type,
+ const XML_Char *dflt,
+ int isrequired);
+
+XMLPARSEAPI(void)
+XML_SetAttlistDeclHandler(XML_Parser parser,
+ XML_AttlistDeclHandler attdecl);
+
+/* The XML declaration handler is called for *both* XML declarations
+ and text declarations. The way to distinguish is that the version
+ parameter will be NULL for text declarations. The encoding
+ parameter may be NULL for XML declarations. The standalone
+ parameter will be -1, 0, or 1 indicating respectively that there
+ was no standalone parameter in the declaration, that it was given
+ as no, or that it was given as yes.
+*/
+typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData,
+ const XML_Char *version,
+ const XML_Char *encoding,
+ int standalone);
+
+XMLPARSEAPI(void)
+XML_SetXmlDeclHandler(XML_Parser parser,
+ XML_XmlDeclHandler xmldecl);
+
+
+typedef struct {
+ void *(*malloc_fcn)(size_t size);
+ void *(*realloc_fcn)(void *ptr, size_t size);
+ void (*free_fcn)(void *ptr);
+} XML_Memory_Handling_Suite;
+
+/* Constructs a new parser; encoding is the encoding specified by the
+ external protocol or NULL if there is none specified.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor. Element type
+ names and attribute names that belong to a namespace will be
+ expanded; unprefixed attribute names are never expanded; unprefixed
+ element type names are expanded only if there is a default
+ namespace. The expanded name is the concatenation of the namespace
+ URI, the namespace separator character, and the local part of the
+ name. If the namespace separator is '\0' then the namespace URI
+ and the local part will be concatenated without any separator.
+ It is a programming error to use the separator '\0' with namespace
+ triplets (see XML_SetReturnNSTriplet).
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* Constructs a new parser using the memory management suite referred to
+ by memsuite. If memsuite is NULL, then use the standard library memory
+ suite. If namespaceSeparator is non-NULL it creates a parser with
+ namespace processing as described above. The character pointed at
+ will serve as the namespace separator.
+
+ All further memory operations used for the created parser will come from
+ the given suite.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate_MM(const XML_Char *encoding,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *namespaceSeparator);
+
+/* Prepare a parser object to be re-used. This is particularly
+ valuable when memory allocation overhead is disproportionatly high,
+ such as when a large number of small documnents need to be parsed.
+ All handlers are cleared from the parser, except for the
+ unknownEncodingHandler. The parser's external state is re-initialized
+ except for the values of ns and ns_triplets.
+
+ Added in Expat 1.95.3.
+*/
+XMLPARSEAPI(XML_Bool)
+XML_ParserReset(XML_Parser parser, const XML_Char *encoding);
+
+/* atts is array of name/value pairs, terminated by 0;
+ names and values are 0 terminated.
+*/
+typedef void (XMLCALL *XML_StartElementHandler) (void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+
+typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
+ const XML_Char *name);
+
+
+/* s is not 0 terminated. */
+typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData,
+ const XML_Char *s,
+ int len);
+
+/* target and data are 0 terminated */
+typedef void (XMLCALL *XML_ProcessingInstructionHandler) (
+ void *userData,
+ const XML_Char *target,
+ const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (XMLCALL *XML_CommentHandler) (void *userData,
+ const XML_Char *data);
+
+typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData);
+typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData);
+
+/* This is called for any characters in the XML document for which
+ there is no applicable handler. This includes both characters that
+ are part of markup which is of a kind that is not reported
+ (comments, markup declarations), or characters that are part of a
+ construct which could be reported but for which no handler has been
+ supplied. The characters are passed exactly as they were in the XML
+ document except that they will be encoded in UTF-8 or UTF-16.
+ Line boundaries are not normalized. Note that a byte order mark
+ character is not passed to the default handler. There are no
+ guarantees about how characters are divided between calls to the
+ default handler: for example, a comment might be split between
+ multiple calls.
+*/
+typedef void (XMLCALL *XML_DefaultHandler) (void *userData,
+ const XML_Char *s,
+ int len);
+
+/* This is called for the start of the DOCTYPE declaration, before
+ any DTD or internal subset is parsed.
+*/
+typedef void (XMLCALL *XML_StartDoctypeDeclHandler) (
+ void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset);
+
+/* This is called for the start of the DOCTYPE declaration when the
+ closing > is encountered, but after processing any external
+ subset.
+*/
+typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for entity declarations. The is_parameter_entity
+ argument will be non-zero if the entity is a parameter entity, zero
+ otherwise.
+
+ For internal entities (<!ENTITY foo "bar">), value will
+ be non-NULL and systemId, publicID, and notationName will be NULL.
+ The value string is NOT nul-terminated; the length is provided in
+ the value_length argument. Since it is legal to have zero-length
+ values, do not use this argument to test for internal entities.
+
+ For external entities, value will be NULL and systemId will be
+ non-NULL. The publicId argument will be NULL unless a public
+ identifier was provided. The notationName argument will have a
+ non-NULL value only for unparsed entity declarations.
+
+ Note that is_parameter_entity can't be changed to XML_Bool, since
+ that would break binary compatibility.
+*/
+typedef void (XMLCALL *XML_EntityDeclHandler) (
+ void *userData,
+ const XML_Char *entityName,
+ int is_parameter_entity,
+ const XML_Char *value,
+ int value_length,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+XMLPARSEAPI(void)
+XML_SetEntityDeclHandler(XML_Parser parser,
+ XML_EntityDeclHandler handler);
+
+/* OBSOLETE -- OBSOLETE -- OBSOLETE
+ This handler has been superseded by the EntityDeclHandler above.
+ It is provided here for backward compatibility.
+
+ This is called for a declaration of an unparsed (NDATA) entity.
+ The base argument is whatever was set by XML_SetBase. The
+ entityName, systemId and notationName arguments will never be
+ NULL. The other arguments may be.
+*/
+typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) (
+ void *userData,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+/* This is called for a declaration of notation. The base argument is
+ whatever was set by XML_SetBase. The notationName will never be
+ NULL. The other arguments can be.
+*/
+typedef void (XMLCALL *XML_NotationDeclHandler) (
+ void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+ each namespace declaration. The call to the start and end element
+ handlers occur between the calls to the start and end namespace
+ declaration handlers. For an xmlns attribute, prefix will be
+ NULL. For an xmlns="" attribute, uri will be NULL.
+*/
+typedef void (XMLCALL *XML_StartNamespaceDeclHandler) (
+ void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri);
+
+typedef void (XMLCALL *XML_EndNamespaceDeclHandler) (
+ void *userData,
+ const XML_Char *prefix);
+
+/* This is called if the document is not standalone, that is, it has an
+ external subset or a reference to a parameter entity, but does not
+ have standalone="yes". If this handler returns XML_STATUS_ERROR,
+ then processing will not continue, and the parser will return a
+ XML_ERROR_NOT_STANDALONE error.
+ If parameter entity parsing is enabled, then in addition to the
+ conditions above this handler will only be called if the referenced
+ entity was actually read.
+*/
+typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData);
+
+/* This is called for a reference to an external parsed general
+ entity. The referenced entity is not automatically parsed. The
+ application can parse it immediately or later using
+ XML_ExternalEntityParserCreate.
+
+ The parser argument is the parser parsing the entity containing the
+ reference; it can be passed as the parser argument to
+ XML_ExternalEntityParserCreate. The systemId argument is the
+ system identifier as specified in the entity declaration; it will
+ not be NULL.
+
+ The base argument is the system identifier that should be used as
+ the base for resolving systemId if systemId was relative; this is
+ set by XML_SetBase; it may be NULL.
+
+ The publicId argument is the public identifier as specified in the
+ entity declaration, or NULL if none was specified; the whitespace
+ in the public identifier will have been normalized as required by
+ the XML spec.
+
+ The context argument specifies the parsing context in the format
+ expected by the context argument to XML_ExternalEntityParserCreate;
+ context is valid only until the handler returns, so if the
+ referenced entity is to be parsed later, it must be copied.
+ context is NULL only when the entity is a parameter entity.
+
+ The handler should return XML_STATUS_ERROR if processing should not
+ continue because of a fatal error in the handling of the external
+ entity. In this case the calling parser will return an
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+
+ Note that unlike other handlers the first argument is the parser,
+ not userData.
+*/
+typedef int (XMLCALL *XML_ExternalEntityRefHandler) (
+ XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* This is called in two situations:
+ 1) An entity reference is encountered for which no declaration
+ has been read *and* this is not an error.
+ 2) An internal entity reference is read, but not expanded, because
+ XML_SetDefaultHandler has been called.
+ Note: skipped parameter entities in declarations and skipped general
+ entities in attribute values cannot be reported, because
+ the event would be out of sync with the reporting of the
+ declarations or attribute values
+*/
+typedef void (XMLCALL *XML_SkippedEntityHandler) (
+ void *userData,
+ const XML_Char *entityName,
+ int is_parameter_entity);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler to
+ provide information to the parser about encodings that are unknown
+ to the parser.
+
+ The map[b] member gives information about byte sequences whose
+ first byte is b.
+
+ If map[b] is c where c is >= 0, then b by itself encodes the
+ Unicode scalar value c.
+
+ If map[b] is -1, then the byte sequence is malformed.
+
+ If map[b] is -n, where n >= 2, then b is the first byte of an
+ n-byte sequence that encodes a single Unicode scalar value.
+
+ The data member will be passed as the first argument to the convert
+ function.
+
+ The convert function is used to convert multibyte sequences; s will
+ point to a n-byte sequence where map[(unsigned char)*s] == -n. The
+ convert function must return the Unicode scalar value represented
+ by this byte sequence or -1 if the byte sequence is malformed.
+
+ The convert function may be NULL if the encoding is a single-byte
+ encoding, that is if map[b] >= -1 for all bytes b.
+
+ When the parser is finished with the encoding, then if release is
+ not NULL, it will call release passing it the data member; once
+ release has been called, the convert function will not be called
+ again.
+
+ Expat places certain restrictions on the encodings that are supported
+ using this mechanism.
+
+ 1. Every ASCII character that can appear in a well-formed XML document,
+ other than the characters
+
+ $@\^`{}~
+
+ must be represented by a single byte, and that byte must be the
+ same byte that represents that character in ASCII.
+
+ 2. No character may require more than 4 bytes to encode.
+
+ 3. All characters encoded must have Unicode scalar values <=
+ 0xFFFF, (i.e., characters that would be encoded by surrogates in
+ UTF-16 are not allowed). Note that this restriction doesn't
+ apply to the built-in support for UTF-8 and UTF-16.
+
+ 4. No Unicode character may be encoded by more than one distinct
+ sequence of bytes.
+*/
+typedef struct {
+ int map[256];
+ void *data;
+ int (XMLCALL *convert)(void *data, const char *s);
+ void (XMLCALL *release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+
+ The encodingHandlerData argument is that which was passed as the
+ second argument to XML_SetUnknownEncodingHandler.
+
+ The name argument gives the name of the encoding as specified in
+ the encoding declaration.
+
+ If the callback can provide information about the encoding, it must
+ fill in the XML_Encoding structure, and return XML_STATUS_OK.
+ Otherwise it must return XML_STATUS_ERROR.
+
+ If info does not describe a suitable encoding, then the parser will
+ return an XML_UNKNOWN_ENCODING error.
+*/
+typedef int (XMLCALL *XML_UnknownEncodingHandler) (
+ void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
+
+XMLPARSEAPI(void)
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartElementHandler(XML_Parser parser,
+ XML_StartElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetEndElementHandler(XML_Parser parser,
+ XML_EndElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler);
+XMLPARSEAPI(void)
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+ XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+ internal entities. These entity references will be passed to the
+ default handler, or to the skipped entity handler, if one is set.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of
+ internal entities. The entity reference will not be passed to the
+ default handler.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+ XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+ XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler);
+
+/* If a non-NULL value for arg is specified here, then it will be
+ passed as the first argument to the external entity ref handler
+ instead of the parser object.
+*/
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser,
+ void *arg);
+
+XMLPARSEAPI(void)
+XML_SetSkippedEntityHandler(XML_Parser parser,
+ XML_SkippedEntityHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end
+ element, processing instruction or character data. It causes the
+ corresponding markup to be passed to the default handler.
+*/
+XMLPARSEAPI(void)
+XML_DefaultCurrent(XML_Parser parser);
+
+/* If do_nst is non-zero, and namespace processing is in effect, and
+ a name has a prefix (i.e. an explicit namespace qualifier) then
+ that name is returned as a triplet in a single string separated by
+ the separator character specified when the parser was created: URI
+ + sep + local_name + sep + prefix.
+
+ If do_nst is zero, then namespace information is returned in the
+ default manner (URI + sep + local_name) whether or not the name
+ has a prefix.
+
+ Note: Calling XML_SetReturnNSTriplet after XML_Parse or
+ XML_ParseBuffer has no effect.
+*/
+
+XMLPARSEAPI(void)
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst);
+
+/* This value is passed as the userData argument to callbacks. */
+XMLPARSEAPI(void)
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or NULL. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument to
+ XML_ParserCreate. On success XML_SetEncoding returns non-zero,
+ zero otherwise.
+ Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer
+ has no effect and returns XML_STATUS_ERROR.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed as the
+ first argument to callbacks instead of userData. The userData will
+ still be accessible using XML_GetUserData.
+*/
+XMLPARSEAPI(void)
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* If useDTD == XML_TRUE is passed to this function, then the parser
+ will assume that there is an external subset, even if none is
+ specified in the document. In such a case the parser will call the
+ externalEntityRefHandler with a value of NULL for the systemId
+ argument (the publicId and context arguments will be NULL as well).
+ Note: For the purpose of checking WFC: Entity Declared, passing
+ useDTD == XML_TRUE will make the parser behave as if the document
+ had a DTD with an external subset.
+ Note: If this function is called, then this must be done before
+ the first call to XML_Parse or XML_ParseBuffer, since it will
+ have no effect after that. Returns
+ XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING.
+ Note: If the document does not have a DOCTYPE declaration at all,
+ then startDoctypeDeclHandler and endDoctypeDeclHandler will not
+ be called, despite an external subset being parsed.
+ Note: If XML_DTD is not defined when Expat is compiled, returns
+ XML_ERROR_FEATURE_REQUIRES_XML_DTD.
+ Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
+
+
+/* Sets the base to be used for resolving relative URIs in system
+ identifiers in declarations. Resolving relative identifiers is
+ left to the application: this value will be passed through as the
+ base argument to the XML_ExternalEntityRefHandler,
+ XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base
+ argument will be copied. Returns XML_STATUS_ERROR if out of memory,
+ XML_STATUS_OK otherwise.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+XMLPARSEAPI(const XML_Char *)
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+ to the XML_StartElementHandler that were specified in the start-tag
+ rather than defaulted. Each attribute/value pair counts as 2; thus
+ this correspondds to an index into the atts array passed to the
+ XML_StartElementHandler. Returns -1 if parser == NULL.
+*/
+XMLPARSEAPI(int)
+XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+ XML_StartElementHandler, or -1 if there is no ID attribute or
+ parser == NULL. Each attribute/value pair counts as 2; thus this
+ correspondds to an index into the atts array passed to the
+ XML_StartElementHandler.
+*/
+XMLPARSEAPI(int)
+XML_GetIdAttributeIndex(XML_Parser parser);
+
+#ifdef XML_ATTR_INFO
+/* Source file byte offsets for the start and end of attribute names and values.
+ The value indices are exclusive of surrounding quotes; thus in a UTF-8 source
+ file an attribute value of "blah" will yield:
+ info->valueEnd - info->valueStart = 4 bytes.
+*/
+typedef struct {
+ XML_Index nameStart; /* Offset to beginning of the attribute name. */
+ XML_Index nameEnd; /* Offset after the attribute name's last byte. */
+ XML_Index valueStart; /* Offset to beginning of the attribute value. */
+ XML_Index valueEnd; /* Offset after the attribute value's last byte. */
+} XML_AttrInfo;
+
+/* Returns an array of XML_AttrInfo structures for the attribute/value pairs
+ passed in last call to the XML_StartElementHandler that were specified
+ in the start-tag rather than defaulted. Each attribute/value pair counts
+ as 1; thus the number of entries in the array is
+ XML_GetSpecifiedAttributeCount(parser) / 2.
+*/
+XMLPARSEAPI(const XML_AttrInfo *)
+XML_GetAttributeInfo(XML_Parser parser);
+#endif
+
+/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is
+ detected. The last call to XML_Parse must have isFinal true; len
+ may be zero for this call (or any other).
+
+ Though the return values for these functions has always been
+ described as a Boolean value, the implementation, at least for the
+ 1.95.x series, has always returned exactly one of the XML_Status
+ values.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+XMLPARSEAPI(void *)
+XML_GetBuffer(XML_Parser parser, int len);
+
+XMLPARSEAPI(enum XML_Status)
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return.
+ Must be called from within a call-back handler, except when aborting
+ (resumable = 0) an already suspended parser. Some call-backs may
+ still follow because they would otherwise get lost. Examples:
+ - endElementHandler() for empty elements when stopped in
+ startElementHandler(),
+ - endNameSpaceDeclHandler() when stopped in endElementHandler(),
+ and possibly others.
+
+ Can be called from most handlers, including DTD related call-backs,
+ except when parsing an external parameter entity and resumable != 0.
+ Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise.
+ Possible error codes:
+ - XML_ERROR_SUSPENDED: when suspending an already suspended parser.
+ - XML_ERROR_FINISHED: when the parser has already finished.
+ - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE.
+
+ When resumable != 0 (true) then parsing is suspended, that is,
+ XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED.
+ Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer()
+ return XML_STATUS_ERROR with error code XML_ERROR_ABORTED.
+
+ *Note*:
+ This will be applied to the current parser instance only, that is, if
+ there is a parent parser then it will continue parsing when the
+ externalEntityRefHandler() returns. It is up to the implementation of
+ the externalEntityRefHandler() to call XML_StopParser() on the parent
+ parser (recursively), if one wants to stop parsing altogether.
+
+ When suspended, parsing can be resumed by calling XML_ResumeParser().
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_StopParser(XML_Parser parser, int resumable);
+
+/* Resumes parsing after it has been suspended with XML_StopParser().
+ Must not be called from within a handler call-back. Returns same
+ status codes as XML_Parse() or XML_ParseBuffer().
+ Additional error code XML_ERROR_NOT_SUSPENDED possible.
+
+ *Note*:
+ This must be called on the most deeply nested child parser instance
+ first, and on its parent parser only after the child parser has finished,
+ to be applied recursively until the document entity's parser is restarted.
+ That is, the parent parser will not resume by itself and it is up to the
+ application to call XML_ResumeParser() on it at the appropriate moment.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_ResumeParser(XML_Parser parser);
+
+enum XML_Parsing {
+ XML_INITIALIZED,
+ XML_PARSING,
+ XML_FINISHED,
+ XML_SUSPENDED
+};
+
+typedef struct {
+ enum XML_Parsing parsing;
+ XML_Bool finalBuffer;
+} XML_ParsingStatus;
+
+/* Returns status of parser with respect to being initialized, parsing,
+ finished, or suspended and processing the final buffer.
+ XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus,
+ XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED
+*/
+XMLPARSEAPI(void)
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status);
+
+/* Creates an XML_Parser object that can parse an external general
+ entity; context is a '\0'-terminated string specifying the parse
+ context; encoding is a '\0'-terminated string giving the name of
+ the externally specified encoding, or NULL if there is no
+ externally specified encoding. The context string consists of a
+ sequence of tokens separated by formfeeds (\f); a token consisting
+ of a name specifies that the general entity of the name is open; a
+ token of the form prefix=uri specifies the namespace for a
+ particular prefix; a token of the form =uri specifies the default
+ namespace. This can be called at any point after the first call to
+ an ExternalEntityRefHandler so longer as the parser has not yet
+ been freed. The new parser is completely independent and may
+ safely be used in a separate thread. The handlers and userData are
+ initialized from the parser argument. Returns NULL if out of memory.
+ Otherwise returns a new XML_Parser object.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ExternalEntityParserCreate(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+ XML_PARAM_ENTITY_PARSING_NEVER,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+ XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+ subset). If parsing of parameter entities is enabled, then
+ references to external parameter entities (including the external
+ DTD subset) will be passed to the handler set with
+ XML_SetExternalEntityRefHandler. The context passed will be 0.
+
+ Unlike external general entities, external parameter entities can
+ only be parsed synchronously. If the external parameter entity is
+ to be parsed, it must be parsed during the call to the external
+ entity ref handler: the complete sequence of
+ XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and
+ XML_ParserFree calls must be made during this call. After
+ XML_ExternalEntityParserCreate has been called to create the parser
+ for the external parameter entity (context must be 0 for this
+ call), it is illegal to make any calls on the old parser until
+ XML_ParserFree has been called on the newly created parser.
+ If the library has been compiled without support for parameter
+ entity parsing (ie without XML_DTD being defined), then
+ XML_SetParamEntityParsing will return 0 if parsing of parameter
+ entities is requested; otherwise it will return non-zero.
+ Note: If XML_SetParamEntityParsing is called after XML_Parse or
+ XML_ParseBuffer, then it has no effect and will always return 0.
+ Note: If parser == NULL, the function will do nothing and return 0.
+*/
+XMLPARSEAPI(int)
+XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing parsing);
+
+/* Sets the hash salt to use for internal hash calculations.
+ Helps in preventing DoS attacks based on predicting hash
+ function behavior. This must be called before parsing is started.
+ Returns 1 if successful, 0 when called after parsing has started.
+ Note: If parser == NULL, the function will do nothing and return 0.
+*/
+XMLPARSEAPI(int)
+XML_SetHashSalt(XML_Parser parser,
+ unsigned long hash_salt);
+
+/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+ XML_GetErrorCode returns information about the error.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse
+ location. They may be called from any callback called to report
+ some parse event; in this case the location is the location of the
+ first of the sequence of characters that generated the event. When
+ called from callbacks generated by declarations in the document
+ prologue, the location identified isn't as neatly defined, but will
+ be within the relevant markup. When called outside of the callback
+ functions, the position indicated will be just past the last parse
+ event (regardless of whether there was an associated callback).
+
+ They may also be called after returning from a call to XML_Parse
+ or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then
+ the location is the location of the character at which the error
+ was detected; otherwise the location is the location of the last
+ parse event, as described above.
+
+ Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber
+ return 0 to indicate an error.
+ Note: XML_GetCurrentByteIndex returns -1 to indicate an error.
+*/
+XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+ Returns 0 if the event is in an internal entity.
+*/
+XMLPARSEAPI(int)
+XML_GetCurrentByteCount(XML_Parser parser);
+
+/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets
+ the integer pointed to by offset to the offset within this buffer
+ of the current parse position, and sets the integer pointed to by size
+ to the size of this buffer (the number of input bytes). Otherwise
+ returns a NULL pointer. Also returns a NULL pointer if a parse isn't
+ active.
+
+ NOTE: The character pointer returned should not be used outside
+ the handler that makes the call.
+*/
+XMLPARSEAPI(const char *)
+XML_GetInputContext(XML_Parser parser,
+ int *offset,
+ int *size);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees the content model passed to the element declaration handler */
+XMLPARSEAPI(void)
+XML_FreeContentModel(XML_Parser parser, XML_Content *model);
+
+/* Exposing the memory handling functions used in Expat */
+XMLPARSEAPI(void *)
+XML_ATTR_MALLOC
+XML_ATTR_ALLOC_SIZE(2)
+XML_MemMalloc(XML_Parser parser, size_t size);
+
+XMLPARSEAPI(void *)
+XML_ATTR_ALLOC_SIZE(3)
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size);
+
+XMLPARSEAPI(void)
+XML_MemFree(XML_Parser parser, void *ptr);
+
+/* Frees memory used by the parser. */
+XMLPARSEAPI(void)
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+XMLPARSEAPI(const XML_LChar *)
+XML_ErrorString(enum XML_Error code);
+
+/* Return a string containing the version number of this expat */
+XMLPARSEAPI(const XML_LChar *)
+XML_ExpatVersion(void);
+
+typedef struct {
+ int major;
+ int minor;
+ int micro;
+} XML_Expat_Version;
+
+/* Return an XML_Expat_Version structure containing numeric version
+ number information for this version of expat.
+*/
+XMLPARSEAPI(XML_Expat_Version)
+XML_ExpatVersionInfo(void);
+
+/* Added in Expat 1.95.5. */
+enum XML_FeatureEnum {
+ XML_FEATURE_END = 0,
+ XML_FEATURE_UNICODE,
+ XML_FEATURE_UNICODE_WCHAR_T,
+ XML_FEATURE_DTD,
+ XML_FEATURE_CONTEXT_BYTES,
+ XML_FEATURE_MIN_SIZE,
+ XML_FEATURE_SIZEOF_XML_CHAR,
+ XML_FEATURE_SIZEOF_XML_LCHAR,
+ XML_FEATURE_NS,
+ XML_FEATURE_LARGE_SIZE,
+ XML_FEATURE_ATTR_INFO
+ /* Additional features must be added to the end of this enum. */
+};
+
+typedef struct {
+ enum XML_FeatureEnum feature;
+ const XML_LChar *name;
+ long int value;
+} XML_Feature;
+
+XMLPARSEAPI(const XML_Feature *)
+XML_GetFeatureList(void);
+
+
+/* Expat follows the semantic versioning convention.
+ See http://semver.org.
+*/
+#define XML_MAJOR_VERSION 2
+#define XML_MINOR_VERSION 2
+#define XML_MICRO_VERSION 1
+
+/* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
+XMLPARSEAPI(const XML_Char*)
+MOZ_XML_GetMismatchedTag(XML_Parser parser);
+/* END MOZILLA CHANGE */
+
+/* BEGIN MOZILLA CHANGE (Report whether the parser is currently expanding an entity) */
+XMLPARSEAPI(XML_Bool)
+MOZ_XML_ProcessingEntityValue(XML_Parser parser);
+/* END MOZILLA CHANGE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_INCLUDED */
diff --git a/parser/expat/lib/expat_external.h b/parser/expat/lib/expat_external.h
new file mode 100644
index 0000000000..07f945642d
--- /dev/null
+++ b/parser/expat/lib/expat_external.h
@@ -0,0 +1,138 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef Expat_External_INCLUDED
+#define Expat_External_INCLUDED 1
+
+/* External API definitions */
+
+#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+#define XML_USE_MSC_EXTENSIONS 1
+#endif
+
+/* Expat tries very hard to make the API boundary very specifically
+ defined. There are two macros defined to control this boundary;
+ each of these can be defined before including this header to
+ achieve some different behavior, but doing so it not recommended or
+ tested frequently.
+
+ XMLCALL - The calling convention to use for all calls across the
+ "library boundary." This will default to cdecl, and
+ try really hard to tell the compiler that's what we
+ want.
+
+ XMLIMPORT - Whatever magic is needed to note that a function is
+ to be imported from a dynamically loaded library
+ (.dll, .so, or .sl, depending on your platform).
+
+ The XMLCALL macro was added in Expat 1.95.7. The only one which is
+ expected to be directly useful in client code is XMLCALL.
+
+ Note that on at least some Unix versions, the Expat library must be
+ compiled with the cdecl calling convention as the default since
+ system headers may assume the cdecl convention.
+*/
+#ifndef XMLCALL
+#if defined(_MSC_VER)
+#define XMLCALL __cdecl
+#elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
+#define XMLCALL __attribute__((cdecl))
+#else
+/* For any platform which uses this definition and supports more than
+ one calling convention, we need to extend this definition to
+ declare the convention used on that platform, if it's possible to
+ do so.
+
+ If this is the case for your platform, please file a bug report
+ with information on how to identify your platform via the C
+ pre-processor and how to specify the same calling convention as the
+ platform's malloc() implementation.
+*/
+#define XMLCALL
+#endif
+#endif /* not defined XMLCALL */
+
+
+#if !defined(XML_STATIC) && !defined(XMLIMPORT)
+#ifndef XML_BUILDING_EXPAT
+/* using Expat from an application */
+
+#ifdef XML_USE_MSC_EXTENSIONS
+#define XMLIMPORT __declspec(dllimport)
+#endif
+
+#endif
+#endif /* not defined XML_STATIC */
+
+#if !defined(XMLIMPORT) && defined(__GNUC__) && (__GNUC__ >= 4)
+#define XMLIMPORT __attribute__ ((visibility ("default")))
+#endif
+
+/* If we didn't define it above, define it away: */
+#ifndef XMLIMPORT
+#define XMLIMPORT
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
+#define XML_ATTR_MALLOC __attribute__((__malloc__))
+#else
+#define XML_ATTR_MALLOC
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+#define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
+#else
+#define XML_ATTR_ALLOC_SIZE(x)
+#endif
+
+#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+# define XML_UNICODE
+# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
+# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
+# endif
+#endif
+
+/* BEGIN MOZILLA CHANGE (typedef XML_Char to char16_t) */
+#if 0
+
+#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
+#ifdef XML_UNICODE_WCHAR_T
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+#else
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE_WCHAR_T */
+#else /* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE */
+
+#endif
+/* END MOZILLA CHANGE */
+
+#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
+#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+typedef __int64 XML_Index;
+typedef unsigned __int64 XML_Size;
+#else
+typedef long long XML_Index;
+typedef unsigned long long XML_Size;
+#endif
+#else
+typedef long XML_Index;
+typedef unsigned long XML_Size;
+#endif /* XML_LARGE_SIZE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_External_INCLUDED */
diff --git a/parser/expat/lib/iasciitab.h b/parser/expat/lib/iasciitab.h
new file mode 100644
index 0000000000..24a1d5ccc9
--- /dev/null
+++ b/parser/expat/lib/iasciitab.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/parser/expat/lib/internal.h b/parser/expat/lib/internal.h
new file mode 100644
index 0000000000..94cb98e15c
--- /dev/null
+++ b/parser/expat/lib/internal.h
@@ -0,0 +1,95 @@
+/* internal.h
+
+ Internal definitions used by Expat. This is not needed to compile
+ client code.
+
+ The following calling convention macros are defined for frequently
+ called functions:
+
+ FASTCALL - Used for those internal functions that have a simple
+ body and a low number of arguments and local variables.
+
+ PTRCALL - Used for functions called though function pointers.
+
+ PTRFASTCALL - Like PTRCALL, but for low number of arguments.
+
+ inline - Used for selected internal functions for which inlining
+ may improve performance on some platforms.
+
+ Note: Use of these macros is based on judgement, not hard rules,
+ and therefore subject to change.
+*/
+
+#if defined(__GNUC__) && defined(__i386__) && !defined(__MINGW32__)
+/* We'll use this version by default only where we know it helps.
+
+ regparm() generates warnings on Solaris boxes. See SF bug #692878.
+
+ Instability reported with egcs on a RedHat Linux 7.3.
+ Let's comment out:
+ #define FASTCALL __attribute__((stdcall, regparm(3)))
+ and let's try this:
+*/
+#define FASTCALL __attribute__((regparm(3)))
+#define PTRFASTCALL __attribute__((regparm(3)))
+#endif
+
+/* Using __fastcall seems to have an unexpected negative effect under
+ MS VC++, especially for function pointers, so we won't use it for
+ now on that platform. It may be reconsidered for a future release
+ if it can be made more effective.
+ Likely reason: __fastcall on Windows is like stdcall, therefore
+ the compiler cannot perform stack optimizations for call clusters.
+*/
+
+/* Make sure all of these are defined if they aren't already. */
+
+#ifndef FASTCALL
+#define FASTCALL
+#endif
+
+#ifndef PTRCALL
+#define PTRCALL
+#endif
+
+#ifndef PTRFASTCALL
+#define PTRFASTCALL
+#endif
+
+#ifndef XML_MIN_SIZE
+#if !defined(__cplusplus) && !defined(inline)
+#ifdef __GNUC__
+#define inline __inline
+#endif /* __GNUC__ */
+#endif
+#endif /* XML_MIN_SIZE */
+
+#ifdef __cplusplus
+#define inline inline
+#else
+#ifndef inline
+#define inline
+#endif
+#endif
+
+#ifndef UNUSED_P
+# ifdef __GNUC__
+# define UNUSED_P(p) UNUSED_ ## p __attribute__((__unused__))
+# else
+# define UNUSED_P(p) UNUSED_ ## p
+# endif
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void
+align_limit_to_full_utf8_characters(const char * from, const char ** fromLimRef);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/parser/expat/lib/latin1tab.h b/parser/expat/lib/latin1tab.h
new file mode 100644
index 0000000000..53c25d76b2
--- /dev/null
+++ b/parser/expat/lib/latin1tab.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
diff --git a/parser/expat/lib/moz.build b/parser/expat/lib/moz.build
new file mode 100644
index 0000000000..ca86192bf3
--- /dev/null
+++ b/parser/expat/lib/moz.build
@@ -0,0 +1,19 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include("sources.mozbuild")
+
+EXPORTS += [
+ 'expat.h',
+ 'expat_external.h',
+]
+
+SOURCES += expat_sources
+
+FINAL_LIBRARY = 'gkmedias'
+
+for k, v in expat_defines:
+ DEFINES[k] = v
diff --git a/parser/expat/lib/moz_extensions.c b/parser/expat/lib/moz_extensions.c
new file mode 100644
index 0000000000..37b9e7f71e
--- /dev/null
+++ b/parser/expat/lib/moz_extensions.c
@@ -0,0 +1,160 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef IS_LITTLE_ENDIAN
+
+#define PREFIX(ident) little2_ ## ident
+#define BYTE_TYPE(p) LITTLE2_BYTE_TYPE(XmlGetUtf16InternalEncodingNS(), p)
+#define IS_NAME_CHAR_MINBPC(p) LITTLE2_IS_NAME_CHAR_MINBPC(0, p)
+#define IS_NMSTRT_CHAR_MINBPC(p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(0, p)
+
+#else
+
+#define PREFIX(ident) big2_ ## ident
+#define BYTE_TYPE(p) BIG2_BYTE_TYPE(XmlGetUtf16InternalEncodingNS(), p)
+#define IS_NAME_CHAR_MINBPC(p) BIG2_IS_NAME_CHAR_MINBPC(0, p)
+#define IS_NMSTRT_CHAR_MINBPC(p) BIG2_IS_NMSTRT_CHAR_MINBPC(0, p)
+
+#endif
+
+#define MOZ_EXPAT_VALID_QNAME (0)
+#define MOZ_EXPAT_EMPTY_QNAME (1 << 0)
+#define MOZ_EXPAT_INVALID_CHARACTER (1 << 1)
+#define MOZ_EXPAT_MALFORMED (1 << 2)
+
+int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
+ const char** colon)
+{
+ int result = MOZ_EXPAT_VALID_QNAME;
+ int nmstrt = 1;
+ *colon = 0;
+ if (ptr == end) {
+ return MOZ_EXPAT_EMPTY_QNAME;
+ }
+ do {
+ switch (BYTE_TYPE(ptr)) {
+ case BT_COLON:
+ /* We're namespace-aware and either first or last character is a colon
+ or we've already seen a colon. */
+ if (ns_aware && (nmstrt || *colon || ptr + 2 == end)) {
+ return MOZ_EXPAT_MALFORMED;
+ }
+ *colon = ptr;
+ nmstrt = ns_aware; /* e.g. "a:0" should be valid if !ns_aware */
+ break;
+ case BT_NONASCII:
+ if (!IS_NAME_CHAR_MINBPC(ptr) ||
+ (nmstrt && !*colon && !IS_NMSTRT_CHAR_MINBPC(ptr))) {
+ return MOZ_EXPAT_INVALID_CHARACTER;
+ }
+ if (nmstrt && *colon && !IS_NMSTRT_CHAR_MINBPC(ptr)) {
+ /* If a non-starting character like a number is right after the colon,
+ this is a namespace error, not invalid character */
+ return MOZ_EXPAT_MALFORMED;
+ }
+ nmstrt = 0;
+ break;
+ case BT_NMSTRT:
+ case BT_HEX:
+ nmstrt = 0;
+ break;
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ if (nmstrt) {
+ return MOZ_EXPAT_INVALID_CHARACTER;
+ }
+ break;
+ default:
+ return MOZ_EXPAT_INVALID_CHARACTER;
+ }
+ ptr += 2;
+ } while (ptr != end);
+ return result;
+}
+
+int MOZ_XMLIsLetter(const char* ptr)
+{
+ switch (BYTE_TYPE(ptr)) {
+ case BT_NONASCII:
+ if (!IS_NMSTRT_CHAR_MINBPC(ptr)) {
+ return 0;
+ }
+ /* fall through */
+ case BT_NMSTRT:
+ case BT_HEX:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int MOZ_XMLIsNCNameChar(const char* ptr)
+{
+ switch (BYTE_TYPE(ptr)) {
+ case BT_NONASCII:
+ if (!IS_NAME_CHAR_MINBPC(ptr)) {
+ return 0;
+ }
+ /* fall through */
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int MOZ_XMLTranslateEntity(const char* ptr, const char* end, const char** next,
+ XML_Char* result)
+{
+ // Can we assert here somehow?
+ // MOZ_ASSERT(*ptr == '&');
+
+ const ENCODING* enc = XmlGetUtf16InternalEncodingNS();
+ /* scanRef expects to be pointed to the char after the '&'. */
+ int tok = PREFIX(scanRef)(enc, ptr + enc->minBytesPerChar, end, next);
+ if (tok <= XML_TOK_INVALID) {
+ return 0;
+ }
+
+ if (tok == XML_TOK_CHAR_REF) {
+ /* XmlCharRefNumber expects to be pointed to the '&'. */
+ int n = XmlCharRefNumber(enc, ptr);
+
+ /* We could get away with just < 0, but better safe than sorry. */
+ if (n <= 0) {
+ return 0;
+ }
+
+ return XmlUtf16Encode(n, (unsigned short*)result);
+ }
+
+ if (tok == XML_TOK_ENTITY_REF) {
+ /* XmlPredefinedEntityName expects to be pointed to the char after '&'.
+
+ *next points to after the semicolon, so the entity ends at
+ *next - enc->minBytesPerChar. */
+ XML_Char ch =
+ (XML_Char)XmlPredefinedEntityName(enc, ptr + enc->minBytesPerChar,
+ *next - enc->minBytesPerChar);
+ if (!ch) {
+ return 0;
+ }
+
+ *result = ch;
+ return 1;
+ }
+
+ return 0;
+}
+
+#undef PREFIX
+#undef BYTE_TYPE
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR_MINBPC
diff --git a/parser/expat/lib/nametab.h b/parser/expat/lib/nametab.h
new file mode 100644
index 0000000000..b05e62c77a
--- /dev/null
+++ b/parser/expat/lib/nametab.h
@@ -0,0 +1,150 @@
+static const unsigned namingBitmap[] = {
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
+0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
+0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
+0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
+0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
+0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
+0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
+0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
+0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
+0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
+0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
+0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
+0x00000000, 0x00004C40, 0x00000000, 0x00000000,
+0x00000007, 0x00000000, 0x00000000, 0x00000000,
+0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
+0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
+0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
+0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
+0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
+0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
+0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
+0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
+0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
+0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
+0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
+0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+};
+static const unsigned char nmstrtPages[] = {
+0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
+0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+static const unsigned char namePages[] = {
+0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
+0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/parser/expat/lib/siphash.h b/parser/expat/lib/siphash.h
new file mode 100644
index 0000000000..23b56d2ae4
--- /dev/null
+++ b/parser/expat/lib/siphash.h
@@ -0,0 +1,344 @@
+/* ==========================================================================
+ * siphash.h - SipHash-2-4 in a single header file
+ * --------------------------------------------------------------------------
+ * Derived by William Ahern from the reference implementation[1] published[2]
+ * by Jean-Philippe Aumasson and Daniel J. Berstein. Licensed in kind.
+ * by Jean-Philippe Aumasson and Daniel J. Berstein.
+ * Minimal changes by Sebastian Pipping on top, details below.
+ * Licensed under the CC0 Public Domain Dedication license.
+ *
+ * 1. https://www.131002.net/siphash/siphash24.c
+ * 2. https://www.131002.net/siphash/
+ * --------------------------------------------------------------------------
+ * HISTORY:
+ *
+ * 2017-06-10 (Sebastian Pipping)
+ * - Clarify license note in the header
+ * - Address C89 issues:
+ * - Stop using inline keyword (and let compiler decide)
+ * - Turn integer suffix ULL to UL
+ * - Replace _Bool by int
+ * - Turn macro siphash24 into a function
+ * - Address invalid conversion (void pointer) by explicit cast
+ * - Always expose sip24_valid (for self-tests)
+ *
+ * 2012-11-04 - Born. (William Ahern)
+ * --------------------------------------------------------------------------
+ * USAGE:
+ *
+ * SipHash-2-4 takes as input two 64-bit words as the key, some number of
+ * message bytes, and outputs a 64-bit word as the message digest. This
+ * implementation employs two data structures: a struct sipkey for
+ * representing the key, and a struct siphash for representing the hash
+ * state.
+ *
+ * For converting a 16-byte unsigned char array to a key, use either the
+ * macro sip_keyof or the routine sip_tokey. The former instantiates a
+ * compound literal key, while the latter requires a key object as a
+ * parameter.
+ *
+ * unsigned char secret[16];
+ * arc4random_buf(secret, sizeof secret);
+ * struct sipkey *key = sip_keyof(secret);
+ *
+ * For hashing a message, use either the convenience macro siphash24 or the
+ * routines sip24_init, sip24_update, and sip24_final.
+ *
+ * struct siphash state;
+ * void *msg;
+ * size_t len;
+ * uint64_t hash;
+ *
+ * sip24_init(&state, key);
+ * sip24_update(&state, msg, len);
+ * hash = sip24_final(&state);
+ *
+ * or
+ *
+ * hash = siphash24(msg, len, key);
+ *
+ * To convert the 64-bit hash value to a canonical 8-byte little-endian
+ * binary representation, use either the macro sip_binof or the routine
+ * sip_tobin. The former instantiates and returns a compound literal array,
+ * while the latter requires an array object as a parameter.
+ * --------------------------------------------------------------------------
+ * NOTES:
+ *
+ * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers
+ * lacking compound literal support. Instead, you must use the lower-level
+ * interfaces which take as parameters the temporary state objects.
+ *
+ * o Uppercase macros may evaluate parameters more than once. Lowercase
+ * macros should not exhibit any such side effects.
+ * ==========================================================================
+ */
+#ifndef SIPHASH_H
+#define SIPHASH_H
+
+#include <stddef.h> /* size_t */
+#include <stdint.h> /* uint64_t uint32_t uint8_t */
+
+
+#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b))))
+
+#define SIP_U32TO8_LE(p, v) \
+ (p)[0] = (uint8_t)((v) >> 0); (p)[1] = (uint8_t)((v) >> 8); \
+ (p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24);
+
+#define SIP_U64TO8_LE(p, v) \
+ SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \
+ SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define SIP_U8TO64_LE(p) \
+ (((uint64_t)((p)[0]) << 0) | \
+ ((uint64_t)((p)[1]) << 8) | \
+ ((uint64_t)((p)[2]) << 16) | \
+ ((uint64_t)((p)[3]) << 24) | \
+ ((uint64_t)((p)[4]) << 32) | \
+ ((uint64_t)((p)[5]) << 40) | \
+ ((uint64_t)((p)[6]) << 48) | \
+ ((uint64_t)((p)[7]) << 56))
+
+
+#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 }
+
+struct siphash {
+ uint64_t v0, v1, v2, v3;
+
+ unsigned char buf[8], *p;
+ uint64_t c;
+}; /* struct siphash */
+
+
+#define SIP_KEYLEN 16
+
+struct sipkey {
+ uint64_t k[2];
+}; /* struct sipkey */
+
+#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k))
+
+static struct sipkey *sip_tokey(struct sipkey *key, const void *src) {
+ key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
+ key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
+ return key;
+} /* sip_tokey() */
+
+
+#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v))
+
+static void *sip_tobin(void *dst, uint64_t u64) {
+ SIP_U64TO8_LE((unsigned char *)dst, u64);
+ return dst;
+} /* sip_tobin() */
+
+
+static void sip_round(struct siphash *H, const int rounds) {
+ int i;
+
+ for (i = 0; i < rounds; i++) {
+ H->v0 += H->v1;
+ H->v1 = SIP_ROTL(H->v1, 13);
+ H->v1 ^= H->v0;
+ H->v0 = SIP_ROTL(H->v0, 32);
+
+ H->v2 += H->v3;
+ H->v3 = SIP_ROTL(H->v3, 16);
+ H->v3 ^= H->v2;
+
+ H->v0 += H->v3;
+ H->v3 = SIP_ROTL(H->v3, 21);
+ H->v3 ^= H->v0;
+
+ H->v2 += H->v1;
+ H->v1 = SIP_ROTL(H->v1, 17);
+ H->v1 ^= H->v2;
+ H->v2 = SIP_ROTL(H->v2, 32);
+ }
+} /* sip_round() */
+
+
+static struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) {
+ H->v0 = 0x736f6d6570736575UL ^ key->k[0];
+ H->v1 = 0x646f72616e646f6dUL ^ key->k[1];
+ H->v2 = 0x6c7967656e657261UL ^ key->k[0];
+ H->v3 = 0x7465646279746573UL ^ key->k[1];
+
+ H->p = H->buf;
+ H->c = 0;
+
+ return H;
+} /* sip24_init() */
+
+
+#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)])
+
+static struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) {
+ const unsigned char *p = (const unsigned char *)src, *pe = p + len;
+ uint64_t m;
+
+ do {
+ while (p < pe && H->p < sip_endof(H->buf))
+ *H->p++ = *p++;
+
+ if (H->p < sip_endof(H->buf))
+ break;
+
+ m = SIP_U8TO64_LE(H->buf);
+ H->v3 ^= m;
+ sip_round(H, 2);
+ H->v0 ^= m;
+
+ H->p = H->buf;
+ H->c += 8;
+ } while (p < pe);
+
+ return H;
+} /* sip24_update() */
+
+
+static uint64_t sip24_final(struct siphash *H) {
+ char left = H->p - H->buf;
+ uint64_t b = (H->c + left) << 56;
+
+ switch (left) {
+ case 7: b |= (uint64_t)H->buf[6] << 48;
+ case 6: b |= (uint64_t)H->buf[5] << 40;
+ case 5: b |= (uint64_t)H->buf[4] << 32;
+ case 4: b |= (uint64_t)H->buf[3] << 24;
+ case 3: b |= (uint64_t)H->buf[2] << 16;
+ case 2: b |= (uint64_t)H->buf[1] << 8;
+ case 1: b |= (uint64_t)H->buf[0] << 0;
+ case 0: break;
+ }
+
+ H->v3 ^= b;
+ sip_round(H, 2);
+ H->v0 ^= b;
+ H->v2 ^= 0xff;
+ sip_round(H, 4);
+
+ return H->v0 ^ H->v1 ^ H->v2 ^ H->v3;
+} /* sip24_final() */
+
+
+static uint64_t siphash24(const void *src, size_t len, const struct sipkey *key) {
+ struct siphash state = SIPHASH_INITIALIZER;
+ return sip24_final(sip24_update(sip24_init(&state, key), src, len));
+} /* siphash24() */
+
+
+/*
+ * SipHash-2-4 output with
+ * k = 00 01 02 ...
+ * and
+ * in = (empty string)
+ * in = 00 (1 byte)
+ * in = 00 01 (2 bytes)
+ * in = 00 01 02 (3 bytes)
+ * ...
+ * in = 00 01 02 ... 3e (63 bytes)
+ */
+static int sip24_valid(void) {
+ static const unsigned char vectors[64][8] = {
+ { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+ { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+ { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+ { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+ { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+ { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+ { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+ { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+ { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+ { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+ { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+ { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+ { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+ { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+ { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+ { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+ { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+ { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+ { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+ { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+ { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+ { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+ { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+ { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+ { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+ { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+ { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+ { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+ { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+ { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+ { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+ { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+ { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+ { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+ { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+ { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+ { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+ { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+ { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+ { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+ { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+ { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+ { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+ { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+ { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+ { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+ { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+ { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+ { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+ { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+ { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+ { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+ { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+ { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+ { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+ { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+ { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+ { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+ { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+ { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+ { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+ { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+ { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+ { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+ };
+ unsigned char in[64];
+ struct sipkey k;
+ size_t i;
+
+ sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017");
+
+ for (i = 0; i < sizeof in; ++i) {
+ in[i] = i;
+
+ if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i]))
+ return 0;
+ }
+
+ return 1;
+} /* sip24_valid() */
+
+
+#if SIPHASH_MAIN
+
+#include <stdio.h>
+
+int main(void) {
+ int ok = sip24_valid();
+
+ if (ok)
+ puts("OK");
+ else
+ puts("FAIL");
+
+ return !ok;
+} /* main() */
+
+#endif /* SIPHASH_MAIN */
+
+
+#endif /* SIPHASH_H */
diff --git a/parser/expat/lib/sources.mozbuild b/parser/expat/lib/sources.mozbuild
new file mode 100644
index 0000000000..30d0f76c0a
--- /dev/null
+++ b/parser/expat/lib/sources.mozbuild
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+expat_sources = [
+ 'xmlparse.c',
+ 'xmlrole.c',
+ 'xmltok.c',
+]
+
+expat_defines = [
+ ('HAVE_EXPAT_CONFIG_H', True)
+]
diff --git a/parser/expat/lib/utf8tab.h b/parser/expat/lib/utf8tab.h
new file mode 100644
index 0000000000..7bb3e77603
--- /dev/null
+++ b/parser/expat/lib/utf8tab.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
diff --git a/parser/expat/lib/winconfig.h b/parser/expat/lib/winconfig.h
new file mode 100644
index 0000000000..1a1821fbb5
--- /dev/null
+++ b/parser/expat/lib/winconfig.h
@@ -0,0 +1,54 @@
+/*================================================================
+** Copyright 2000, Clark Cooper
+** All rights reserved.
+**
+** This is free software. You are permitted to copy, distribute, or modify
+** it under the terms of the MIT/X license (contained in the COPYING file
+** with this distribution.)
+*/
+
+#ifndef WINCONFIG_H
+#define WINCONFIG_H
+
+/* BEGIN MOZILLA CHANGE (don't define WIN32_LEAN_AND_MEAN if it was already set) */
+#ifdef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN_WAS_SET
+#undef WIN32_LEAN_AND_MEAN
+#endif
+/* END MOZILLA CHANGE */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+/* BEGIN MOZILLA CHANGE (redefine WIN32_LEAN_AND_MEAN if it was already set) */
+#ifdef WIN32_LEAN_AND_MEAN_WAS_SET
+#define WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN_WAS_SET
+#endif
+/* END MOZILLA CHANGE */
+
+#include <memory.h>
+#include <string.h>
+
+
+#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */
+# include <expat_config.h>
+#else /* !defined(HAVE_EXPAT_CONFIG_H) */
+
+
+#define XML_NS 1
+#define XML_DTD 1
+#define XML_CONTEXT_BYTES 1024
+
+/* we will assume all Windows platforms are little endian */
+#define BYTEORDER 1234
+
+/* Windows has memmove() available. */
+#define HAVE_MEMMOVE
+
+
+#endif /* !defined(HAVE_EXPAT_CONFIG_H) */
+
+
+#endif /* ndef WINCONFIG_H */
diff --git a/parser/expat/lib/xmlparse.c b/parser/expat/lib/xmlparse.c
new file mode 100644
index 0000000000..e060f39e48
--- /dev/null
+++ b/parser/expat/lib/xmlparse.c
@@ -0,0 +1,7314 @@
+/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+
+ 77fea421d361dca90041d0040ecf1dca651167fadf2af79e990e35168d70d933 (2.2.1+)
+*/
+
+#define _GNU_SOURCE /* syscall prototype */
+
+#include <stddef.h>
+#include <string.h> /* memset(), memcpy() */
+#include <assert.h>
+#include <limits.h> /* UINT_MAX */
+#include <stdio.h> /* fprintf */
+#include <stdlib.h> /* getenv */
+
+#ifdef _WIN32
+#define getpid GetCurrentProcessId
+#else
+#include <sys/time.h> /* gettimeofday() */
+#include <sys/types.h> /* getpid() */
+#include <unistd.h> /* getpid() */
+#endif
+
+#define XML_BUILDING_EXPAT 1
+
+#ifdef _WIN32
+#include "winconfig.h"
+#elif defined(HAVE_EXPAT_CONFIG_H)
+#include <expat_config.h>
+#endif /* ndef _WIN32 */
+
+#include "ascii.h"
+#include "expat.h"
+#include "siphash.h"
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+#define XmlEncode XmlUtf16Encode
+/* Using pointer subtraction to convert to integer type. */
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+#define XmlEncode XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS XmlInitEncoding
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
+
+#endif
+
+/* BEGIN MOZILLA CHANGE (typedef XML_Char to char16_t) */
+#if 0
+
+#ifdef XML_UNICODE
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) (const wchar_t)x
+#define XML_L(x) L ## x
+#else
+#define XML_T(x) (const unsigned short)x
+#define XML_L(x) x
+#endif
+
+#else
+
+#define XML_T(x) x
+#define XML_L(x) x
+
+#endif
+
+#endif
+/* END MOZILLA CHANGE */
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+/* Handle the case where memmove() doesn't exist. */
+#ifndef HAVE_MEMMOVE
+#ifdef HAVE_BCOPY
+#define memmove(d,s,l) bcopy((s),(d),(l))
+#else
+#error memmove does not exist on this platform, nor is a substitute available
+#endif /* HAVE_BCOPY */
+#endif /* HAVE_MEMMOVE */
+
+#include "internal.h"
+#include "xmltok.h"
+#include "xmlrole.h"
+
+typedef const XML_Char *KEY;
+
+typedef struct {
+ KEY name;
+} NAMED;
+
+typedef struct {
+ NAMED **v;
+ unsigned char power;
+ size_t size;
+ size_t used;
+ const XML_Memory_Handling_Suite *mem;
+} HASH_TABLE;
+
+static size_t
+keylen(KEY s);
+
+static void
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
+
+/* For probing (after a collision) we need a step size relative prime
+ to the hash table size, which is a power of 2. We use double-hashing,
+ since we can calculate a second hash value cheaply by taking those bits
+ of the first hash value that were discarded (masked out) when the table
+ index was calculated: index = hash & mask, where mask = table->size - 1.
+ We limit the maximum step size to table->size / 4 (mask >> 2) and make
+ it odd, since odd numbers are always relative prime to a power of 2.
+*/
+#define SECOND_HASH(hash, mask, power) \
+ ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
+#define PROBE_STEP(hash, mask, power) \
+ ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
+
+typedef struct {
+ NAMED **p;
+ NAMED **end;
+} HASH_TABLE_ITER;
+
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_ATTS_VERSION 0xFFFFFFFF
+/* BEGIN MOZILLA CHANGE (Avoid slop in poolGrow() allocations) */
+#define INIT_BLOCK_SIZE ((int)(1024 - (offsetof(BLOCK, s) / sizeof(XML_Char))))
+/* END MOZILLA CHANGE */
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+ struct prefix *prefix;
+ struct binding *nextTagBinding;
+ struct binding *prevPrefixBinding;
+ const struct attribute_id *attId;
+ XML_Char *uri;
+ int uriLen;
+ int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+ const XML_Char *name;
+ BINDING *binding;
+} PREFIX;
+
+typedef struct {
+ const XML_Char *str;
+ const XML_Char *localPart;
+ const XML_Char *prefix;
+ int strLen;
+ int uriLen;
+ int prefixLen;
+} TAG_NAME;
+
+/* TAG represents an open element.
+ The name of the element is stored in both the document and API
+ encodings. The memory buffer 'buf' is a separately-allocated
+ memory area which stores the name. During the XML_Parse()/
+ XMLParseBuffer() when the element is open, the memory for the 'raw'
+ version of the name (in the document encoding) is shared with the
+ document buffer. If the element is open across calls to
+ XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
+ contain the 'raw' name as well.
+
+ A parser re-uses these structures, maintaining a list of allocated
+ TAG objects in a free list.
+*/
+typedef struct tag {
+ struct tag *parent; /* parent of this element */
+ const char *rawName; /* tagName in the original encoding */
+ int rawNameLength;
+ TAG_NAME name; /* tagName in the API encoding */
+ char *buf; /* buffer for name components */
+ char *bufEnd; /* end of the buffer */
+ BINDING *bindings;
+} TAG;
+
+typedef struct {
+ const XML_Char *name;
+ const XML_Char *textPtr;
+ int textLen; /* length in XML_Chars */
+ int processed; /* # of processed bytes - when suspended */
+ const XML_Char *systemId;
+ const XML_Char *base;
+ const XML_Char *publicId;
+ const XML_Char *notation;
+ XML_Bool open;
+ XML_Bool is_param;
+ XML_Bool is_internal; /* true if declared in internal subset outside PE */
+} ENTITY;
+
+typedef struct {
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ const XML_Char * name;
+ int firstchild;
+ int lastchild;
+ int childcnt;
+ int nextsib;
+} CONTENT_SCAFFOLD;
+
+#define INIT_SCAFFOLD_ELEMENTS 32
+
+typedef struct block {
+ struct block *next;
+ int size;
+ XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+ BLOCK *blocks;
+ BLOCK *freeBlocks;
+ const XML_Char *end;
+ XML_Char *ptr;
+ XML_Char *start;
+ const XML_Memory_Handling_Suite *mem;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+ an attribute has been specified. */
+typedef struct attribute_id {
+ XML_Char *name;
+ PREFIX *prefix;
+ XML_Bool maybeTokenized;
+ XML_Bool xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+ const ATTRIBUTE_ID *id;
+ XML_Bool isCdata;
+ const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+ unsigned long version;
+ unsigned long hash;
+ const XML_Char *uriName;
+} NS_ATT;
+
+typedef struct {
+ const XML_Char *name;
+ PREFIX *prefix;
+ const ATTRIBUTE_ID *idAtt;
+ int nDefaultAtts;
+ int allocDefaultAtts;
+ DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+ HASH_TABLE generalEntities;
+ HASH_TABLE elementTypes;
+ HASH_TABLE attributeIds;
+ HASH_TABLE prefixes;
+ STRING_POOL pool;
+ STRING_POOL entityValuePool;
+ /* false once a parameter entity reference has been skipped */
+ XML_Bool keepProcessing;
+ /* true once an internal or external PE reference has been encountered;
+ this includes the reference to an external subset */
+ XML_Bool hasParamEntityRefs;
+ XML_Bool standalone;
+#ifdef XML_DTD
+ /* indicates if external PE has been read */
+ XML_Bool paramEntityRead;
+ HASH_TABLE paramEntities;
+#endif /* XML_DTD */
+ PREFIX defaultPrefix;
+ /* === scaffolding for building content model === */
+ XML_Bool in_eldecl;
+ CONTENT_SCAFFOLD *scaffold;
+ unsigned contentStringLen;
+ unsigned scaffSize;
+ unsigned scaffCount;
+ int scaffLevel;
+ int *scaffIndex;
+} DTD;
+
+typedef struct open_internal_entity {
+ const char *internalEventPtr;
+ const char *internalEventEndPtr;
+ struct open_internal_entity *next;
+ ENTITY *entity;
+ int startTagLevel;
+ XML_Bool betweenDecl; /* WFC: PE Between Declarations */
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+#ifdef XML_DTD
+static Processor ignoreSectionProcessor;
+static Processor externalParEntProcessor;
+static Processor externalParEntInitProcessor;
+static Processor entityValueProcessor;
+static Processor entityValueInitProcessor;
+#endif /* XML_DTD */
+static Processor epilogProcessor;
+static Processor errorProcessor;
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+static Processor internalEntityProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
+ const char *end, int tok, const char *next, const char **nextPtr,
+ XML_Bool haveMore, XML_Bool allowClosingDoctype);
+static enum XML_Error
+processInternalEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *start, const char *end, const char **endPtr,
+ XML_Bool haveMore);
+static enum XML_Error
+doContentInternal(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *start, const char *end, const char **endPtr,
+ XML_Bool haveMore);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
+ const char *end, const char **nextPtr, XML_Bool haveMore);
+#ifdef XML_DTD
+static enum XML_Error
+doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
+ const char *end, const char **nextPtr, XML_Bool haveMore);
+#endif /* XML_DTD */
+
+static void
+freeBindings(XML_Parser parser, BINDING *bindings);
+static enum XML_Error
+storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static enum XML_Error
+addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
+ const XML_Char *uri, BINDING **bindingsPtr);
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
+ XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
+ const char *, const char *, STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
+ const char *, const char *, STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+static int
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end);
+
+static const XML_Char * getContext(XML_Parser parser);
+static XML_Bool
+setContext(XML_Parser parser, const XML_Char *context);
+
+static void FASTCALL normalizePublicId(XML_Char *s);
+
+static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
+/* BEGIN MOZILLA CHANGE (unused API) */
+/* do not call if parentParser != NULL */
+//static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
+/* END MOZILLA CHANGE */
+static void
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
+static int
+dtdCopy(XML_Parser oldParser,
+ DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
+static int
+copyEntityTable(XML_Parser oldParser,
+ HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
+static NAMED *
+lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
+static void FASTCALL
+hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
+/* BEGIN MOZILLA CHANGE (unused API) */
+//static void FASTCALL hashTableClear(HASH_TABLE *);
+/* END MOZILLA CHANGE */
+static void FASTCALL hashTableDestroy(HASH_TABLE *);
+static void FASTCALL
+hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
+
+static void FASTCALL
+poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
+static void FASTCALL poolClear(STRING_POOL *);
+static void FASTCALL poolDestroy(STRING_POOL *);
+static XML_Char *
+poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Char *
+poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
+static const XML_Char * FASTCALL
+poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+static const XML_Char * FASTCALL
+poolAppendString(STRING_POOL *pool, const XML_Char *s);
+
+static int FASTCALL nextScaffoldPart(XML_Parser parser);
+static XML_Content * build_model(XML_Parser parser);
+static ELEMENT_TYPE *
+getElementType(XML_Parser parser, const ENCODING *enc,
+ const char *ptr, const char *end);
+
+static unsigned long generate_hash_secret_salt(XML_Parser parser);
+static XML_Bool startParsing(XML_Parser parser);
+
+static XML_Parser
+parserCreate(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep,
+ DTD *dtd);
+
+static void
+parserInit(XML_Parser parser, const XML_Char *encodingName);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+ ? 0 \
+ : ((*((pool)->ptr)++ = c), 1))
+
+struct XML_ParserStruct {
+ /* The first member must be userData so that the XML_GetUserData
+ macro works. */
+ void *m_userData;
+ void *m_handlerArg;
+ char *m_buffer;
+ const XML_Memory_Handling_Suite m_mem;
+ /* first character to be parsed */
+ const char *m_bufferPtr;
+ /* past last character to be parsed */
+ char *m_bufferEnd;
+ /* allocated end of buffer */
+ const char *m_bufferLim;
+ XML_Index m_parseEndByteIndex;
+ const char *m_parseEndPtr;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+ XML_EndElementHandler m_endElementHandler;
+ XML_CharacterDataHandler m_characterDataHandler;
+ XML_ProcessingInstructionHandler m_processingInstructionHandler;
+ XML_CommentHandler m_commentHandler;
+ XML_StartCdataSectionHandler m_startCdataSectionHandler;
+ XML_EndCdataSectionHandler m_endCdataSectionHandler;
+ XML_DefaultHandler m_defaultHandler;
+ XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
+ XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
+ XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+ XML_NotationDeclHandler m_notationDeclHandler;
+ XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+ XML_NotStandaloneHandler m_notStandaloneHandler;
+ XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+ XML_Parser m_externalEntityRefHandlerArg;
+ XML_SkippedEntityHandler m_skippedEntityHandler;
+ XML_UnknownEncodingHandler m_unknownEncodingHandler;
+ XML_ElementDeclHandler m_elementDeclHandler;
+ XML_AttlistDeclHandler m_attlistDeclHandler;
+ XML_EntityDeclHandler m_entityDeclHandler;
+ XML_XmlDeclHandler m_xmlDeclHandler;
+ const ENCODING *m_encoding;
+ INIT_ENCODING m_initEncoding;
+ const ENCODING *m_internalEncoding;
+ const XML_Char *m_protocolEncodingName;
+ XML_Bool m_ns;
+ XML_Bool m_ns_triplets;
+ void *m_unknownEncodingMem;
+ void *m_unknownEncodingData;
+ void *m_unknownEncodingHandlerData;
+ void (XMLCALL *m_unknownEncodingRelease)(void *);
+ PROLOG_STATE m_prologState;
+ Processor *m_processor;
+ enum XML_Error m_errorCode;
+ const char *m_eventPtr;
+ const char *m_eventEndPtr;
+ const char *m_positionPtr;
+ OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+ OPEN_INTERNAL_ENTITY *m_freeInternalEntities;
+ XML_Bool m_defaultExpandInternalEntities;
+ int m_tagLevel;
+ ENTITY *m_declEntity;
+ const XML_Char *m_doctypeName;
+ const XML_Char *m_doctypeSysid;
+ const XML_Char *m_doctypePubid;
+ const XML_Char *m_declAttributeType;
+ const XML_Char *m_declNotationName;
+ const XML_Char *m_declNotationPublicId;
+ ELEMENT_TYPE *m_declElementType;
+ ATTRIBUTE_ID *m_declAttributeId;
+ XML_Bool m_declAttributeIsCdata;
+ XML_Bool m_declAttributeIsId;
+ DTD *m_dtd;
+ const XML_Char *m_curBase;
+ TAG *m_tagStack;
+ TAG *m_freeTagList;
+ BINDING *m_inheritedBindings;
+ BINDING *m_freeBindingList;
+ int m_attsSize;
+ int m_nSpecifiedAtts;
+ int m_idAttIndex;
+ ATTRIBUTE *m_atts;
+ NS_ATT *m_nsAtts;
+ unsigned long m_nsAttsVersion;
+ unsigned char m_nsAttsPower;
+#ifdef XML_ATTR_INFO
+ XML_AttrInfo *m_attInfo;
+#endif
+ POSITION m_position;
+ STRING_POOL m_tempPool;
+ STRING_POOL m_temp2Pool;
+ char *m_groupConnector;
+ unsigned int m_groupSize;
+ XML_Char m_namespaceSeparator;
+ XML_Parser m_parentParser;
+ XML_ParsingStatus m_parsingStatus;
+#ifdef XML_DTD
+ XML_Bool m_isParamEntity;
+ XML_Bool m_useForeignDTD;
+ enum XML_ParamEntityParsing m_paramEntityParsing;
+#endif
+ unsigned long m_hash_secret_salt;
+/* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
+ const XML_Char* m_mismatch;
+/* END MOZILLA CHANGE */
+};
+
+#define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
+#define REALLOC(p,s) (parser->m_mem.realloc_fcn((p),(s)))
+#define FREE(p) (parser->m_mem.free_fcn((p)))
+
+#define userData (parser->m_userData)
+#define handlerArg (parser->m_handlerArg)
+#define startElementHandler (parser->m_startElementHandler)
+#define endElementHandler (parser->m_endElementHandler)
+#define characterDataHandler (parser->m_characterDataHandler)
+#define processingInstructionHandler \
+ (parser->m_processingInstructionHandler)
+#define commentHandler (parser->m_commentHandler)
+#define startCdataSectionHandler \
+ (parser->m_startCdataSectionHandler)
+#define endCdataSectionHandler (parser->m_endCdataSectionHandler)
+#define defaultHandler (parser->m_defaultHandler)
+#define startDoctypeDeclHandler (parser->m_startDoctypeDeclHandler)
+#define endDoctypeDeclHandler (parser->m_endDoctypeDeclHandler)
+#define unparsedEntityDeclHandler \
+ (parser->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (parser->m_notationDeclHandler)
+#define startNamespaceDeclHandler \
+ (parser->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (parser->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (parser->m_notStandaloneHandler)
+#define externalEntityRefHandler \
+ (parser->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg \
+ (parser->m_externalEntityRefHandlerArg)
+#define internalEntityRefHandler \
+ (parser->m_internalEntityRefHandler)
+#define skippedEntityHandler (parser->m_skippedEntityHandler)
+#define unknownEncodingHandler (parser->m_unknownEncodingHandler)
+#define elementDeclHandler (parser->m_elementDeclHandler)
+#define attlistDeclHandler (parser->m_attlistDeclHandler)
+#define entityDeclHandler (parser->m_entityDeclHandler)
+#define xmlDeclHandler (parser->m_xmlDeclHandler)
+#define encoding (parser->m_encoding)
+#define initEncoding (parser->m_initEncoding)
+#define internalEncoding (parser->m_internalEncoding)
+#define unknownEncodingMem (parser->m_unknownEncodingMem)
+#define unknownEncodingData (parser->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+ (parser->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (parser->m_unknownEncodingRelease)
+#define protocolEncodingName (parser->m_protocolEncodingName)
+#define ns (parser->m_ns)
+#define ns_triplets (parser->m_ns_triplets)
+#define prologState (parser->m_prologState)
+#define processor (parser->m_processor)
+#define errorCode (parser->m_errorCode)
+#define eventPtr (parser->m_eventPtr)
+#define eventEndPtr (parser->m_eventEndPtr)
+#define positionPtr (parser->m_positionPtr)
+#define position (parser->m_position)
+#define openInternalEntities (parser->m_openInternalEntities)
+#define freeInternalEntities (parser->m_freeInternalEntities)
+#define defaultExpandInternalEntities \
+ (parser->m_defaultExpandInternalEntities)
+#define tagLevel (parser->m_tagLevel)
+#define buffer (parser->m_buffer)
+#define bufferPtr (parser->m_bufferPtr)
+#define bufferEnd (parser->m_bufferEnd)
+#define parseEndByteIndex (parser->m_parseEndByteIndex)
+#define parseEndPtr (parser->m_parseEndPtr)
+#define bufferLim (parser->m_bufferLim)
+#define dataBuf (parser->m_dataBuf)
+#define dataBufEnd (parser->m_dataBufEnd)
+#define _dtd (parser->m_dtd)
+#define curBase (parser->m_curBase)
+#define declEntity (parser->m_declEntity)
+#define doctypeName (parser->m_doctypeName)
+#define doctypeSysid (parser->m_doctypeSysid)
+#define doctypePubid (parser->m_doctypePubid)
+#define declAttributeType (parser->m_declAttributeType)
+#define declNotationName (parser->m_declNotationName)
+#define declNotationPublicId (parser->m_declNotationPublicId)
+#define declElementType (parser->m_declElementType)
+#define declAttributeId (parser->m_declAttributeId)
+#define declAttributeIsCdata (parser->m_declAttributeIsCdata)
+#define declAttributeIsId (parser->m_declAttributeIsId)
+#define freeTagList (parser->m_freeTagList)
+#define freeBindingList (parser->m_freeBindingList)
+#define inheritedBindings (parser->m_inheritedBindings)
+#define tagStack (parser->m_tagStack)
+#define atts (parser->m_atts)
+#define attsSize (parser->m_attsSize)
+#define nSpecifiedAtts (parser->m_nSpecifiedAtts)
+#define idAttIndex (parser->m_idAttIndex)
+#define nsAtts (parser->m_nsAtts)
+#define nsAttsVersion (parser->m_nsAttsVersion)
+#define nsAttsPower (parser->m_nsAttsPower)
+#define attInfo (parser->m_attInfo)
+#define tempPool (parser->m_tempPool)
+#define temp2Pool (parser->m_temp2Pool)
+#define groupConnector (parser->m_groupConnector)
+#define groupSize (parser->m_groupSize)
+#define namespaceSeparator (parser->m_namespaceSeparator)
+#define parentParser (parser->m_parentParser)
+#define ps_parsing (parser->m_parsingStatus.parsing)
+#define ps_finalBuffer (parser->m_parsingStatus.finalBuffer)
+#ifdef XML_DTD
+#define isParamEntity (parser->m_isParamEntity)
+#define useForeignDTD (parser->m_useForeignDTD)
+#define paramEntityParsing (parser->m_paramEntityParsing)
+#endif /* XML_DTD */
+#define hash_secret_salt (parser->m_hash_secret_salt)
+/* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
+#define mismatch (parser->m_mismatch)
+/* END MOZILLA CHANGE */
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+XML_Parser XMLCALL
+XML_ParserCreate(const XML_Char *encodingName)
+{
+ return XML_ParserCreate_MM(encodingName, NULL, NULL);
+}
+
+XML_Parser XMLCALL
+XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+ XML_Char tmp[2];
+ *tmp = nsSep;
+ return XML_ParserCreate_MM(encodingName, NULL, tmp);
+}
+#endif
+/* END MOZILLA CHANGE */
+
+static const XML_Char implicitContext[] = {
+ ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
+ ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
+ ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
+ ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
+ ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
+ ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
+};
+
+
+#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+# include <errno.h>
+
+# if defined(HAVE_GETRANDOM)
+# include <sys/random.h> /* getrandom */
+# else
+# include <unistd.h> /* syscall */
+# include <sys/syscall.h> /* SYS_getrandom */
+# endif
+
+/* Obtain entropy on Linux 3.17+ */
+static int
+writeRandomBytes_getrandom(void * target, size_t count) {
+ int success = 0; /* full count bytes written? */
+ size_t bytesWrittenTotal = 0;
+ const unsigned int getrandomFlags = 0;
+
+ do {
+ void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
+ const size_t bytesToWrite = count - bytesWrittenTotal;
+
+ const int bytesWrittenMore =
+#if defined(HAVE_GETRANDOM)
+ getrandom(currentTarget, bytesToWrite, getrandomFlags);
+#else
+ syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
+#endif
+
+ if (bytesWrittenMore > 0) {
+ bytesWrittenTotal += bytesWrittenMore;
+ if (bytesWrittenTotal >= count)
+ success = 1;
+ }
+ } while (! success && (errno == EINTR || errno == EAGAIN));
+
+ return success;
+}
+
+#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
+
+
+#ifdef _WIN32
+
+typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
+
+/* Obtain entropy on Windows XP / Windows Server 2003 and later.
+ * Hint on RtlGenRandom and the following article from libsodioum.
+ *
+ * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
+ * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
+ */
+static int
+writeRandomBytes_RtlGenRandom(void * target, size_t count) {
+ int success = 0; /* full count bytes written? */
+ const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL");
+
+ if (advapi32) {
+ const RTLGENRANDOM_FUNC RtlGenRandom
+ = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
+ if (RtlGenRandom) {
+ if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
+ success = 1;
+ }
+ }
+ FreeLibrary(advapi32);
+ }
+
+ return success;
+}
+
+#endif /* _WIN32 */
+
+
+static unsigned long
+gather_time_entropy(void)
+{
+#ifdef _WIN32
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft); /* never fails */
+ return ft.dwHighDateTime ^ ft.dwLowDateTime;
+#else
+ struct timeval tv;
+ int gettimeofday_res;
+
+ gettimeofday_res = gettimeofday(&tv, NULL);
+
+#if defined(NDEBUG)
+ (void)gettimeofday_res;
+#else
+ assert (gettimeofday_res == 0);
+#endif /* defined(NDEBUG) */
+
+ /* Microseconds time is <20 bits entropy */
+ return tv.tv_usec;
+#endif
+}
+
+#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD)
+# include <bsd/stdlib.h>
+#endif
+
+/* BEGIN MOZILLA CHANGE (not all Android NDK versions have the function
+ * declaration, although the function has been available in bionic forever) */
+#if defined(HAVE_ARC4RANDOM_BUF) && defined(__ANDROID__)
+__attribute__((visibility("default"))) void arc4random_buf(void*, size_t);
+#endif
+/* END MOZILLA CHANGE */
+
+static unsigned long
+ENTROPY_DEBUG(const char * label, unsigned long entropy) {
+/* BEGIN MOZILLA CHANGE (don't getenv every time we set up a hash) */
+#if 0
+ const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
+ if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
+ fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
+ label,
+ (int)sizeof(entropy) * 2, entropy,
+ (unsigned long)sizeof(entropy));
+ }
+#endif
+/* END MOZILLA CHANGE */
+ return entropy;
+}
+
+static unsigned long
+generate_hash_secret_salt(XML_Parser parser)
+{
+ unsigned long entropy;
+ (void)parser;
+#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__)
+ (void)gather_time_entropy;
+ arc4random_buf(&entropy, sizeof(entropy));
+ return ENTROPY_DEBUG("arc4random_buf", entropy);
+#else
+ /* Try high quality providers first .. */
+#ifdef _WIN32
+ if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("RtlGenRandom", entropy);
+ }
+#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+ if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("getrandom", entropy);
+ }
+#endif
+ /* .. and self-made low quality for backup: */
+
+ /* Process ID is 0 bits entropy if attacker has local access */
+ entropy = gather_time_entropy() ^ getpid();
+
+ /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
+ if (sizeof(unsigned long) == 4) {
+ return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
+ } else {
+ return ENTROPY_DEBUG("fallback(8)",
+ entropy * (unsigned long)2305843009213693951);
+ }
+#endif
+}
+
+static unsigned long
+get_hash_secret_salt(XML_Parser parser) {
+ if (parser->m_parentParser != NULL)
+ return get_hash_secret_salt(parser->m_parentParser);
+ return parser->m_hash_secret_salt;
+}
+
+static XML_Bool /* only valid for root parser */
+startParsing(XML_Parser parser)
+{
+ /* hash functions must be initialized before setContext() is called */
+ if (hash_secret_salt == 0)
+ hash_secret_salt = generate_hash_secret_salt(parser);
+ if (ns) {
+ /* implicit context only set for root parser, since child
+ parsers (i.e. external entity parsers) will inherit it
+ */
+ return setContext(parser, implicitContext);
+ }
+ return XML_TRUE;
+}
+
+XML_Parser XMLCALL
+XML_ParserCreate_MM(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep)
+{
+ return parserCreate(encodingName, memsuite, nameSep, NULL);
+}
+
+static XML_Parser
+parserCreate(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep,
+ DTD *dtd)
+{
+ XML_Parser parser;
+
+ if (memsuite) {
+ XML_Memory_Handling_Suite *mtemp;
+ parser = (XML_Parser)
+ memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
+ if (parser != NULL) {
+ mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
+ mtemp->malloc_fcn = memsuite->malloc_fcn;
+ mtemp->realloc_fcn = memsuite->realloc_fcn;
+ mtemp->free_fcn = memsuite->free_fcn;
+ }
+ }
+ else {
+ XML_Memory_Handling_Suite *mtemp;
+ parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
+ if (parser != NULL) {
+ mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
+ mtemp->malloc_fcn = malloc;
+ mtemp->realloc_fcn = realloc;
+ mtemp->free_fcn = free;
+ }
+ }
+
+ if (!parser)
+ return parser;
+
+ buffer = NULL;
+ bufferLim = NULL;
+
+ attsSize = INIT_ATTS_SIZE;
+ atts = (ATTRIBUTE *)MALLOC(attsSize * sizeof(ATTRIBUTE));
+ if (atts == NULL) {
+ FREE(parser);
+ return NULL;
+ }
+#ifdef XML_ATTR_INFO
+ attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
+ if (attInfo == NULL) {
+ FREE(atts);
+ FREE(parser);
+ return NULL;
+ }
+#endif
+ dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ if (dataBuf == NULL) {
+ FREE(atts);
+#ifdef XML_ATTR_INFO
+ FREE(attInfo);
+#endif
+ FREE(parser);
+ return NULL;
+ }
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+
+ if (dtd)
+ _dtd = dtd;
+ else {
+ _dtd = dtdCreate(&parser->m_mem);
+ if (_dtd == NULL) {
+ FREE(dataBuf);
+ FREE(atts);
+#ifdef XML_ATTR_INFO
+ FREE(attInfo);
+#endif
+ FREE(parser);
+ return NULL;
+ }
+ }
+
+ freeBindingList = NULL;
+ freeTagList = NULL;
+ freeInternalEntities = NULL;
+
+ groupSize = 0;
+ groupConnector = NULL;
+
+ unknownEncodingHandler = NULL;
+ unknownEncodingHandlerData = NULL;
+
+ namespaceSeparator = ASCII_EXCL;
+ ns = XML_FALSE;
+ ns_triplets = XML_FALSE;
+
+ nsAtts = NULL;
+ nsAttsVersion = 0;
+ nsAttsPower = 0;
+
+ poolInit(&tempPool, &(parser->m_mem));
+ poolInit(&temp2Pool, &(parser->m_mem));
+ parserInit(parser, encodingName);
+
+ if (encodingName && !protocolEncodingName) {
+ if (dtd) {
+ // We need to stop the upcoming call to XML_ParserFree from happily
+ // destroying parser->m_dtd because the DTD is shared with the parent
+ // parser and the only guard that keeps XML_ParserFree from destroying
+ // parser->m_dtd is parser->m_isParamEntity but it will be set to
+ // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all).
+ parser->m_dtd = NULL;
+ }
+ XML_ParserFree(parser);
+ return NULL;
+ }
+
+ if (nameSep) {
+ ns = XML_TRUE;
+ internalEncoding = XmlGetInternalEncodingNS();
+ namespaceSeparator = *nameSep;
+ }
+ else {
+ internalEncoding = XmlGetInternalEncoding();
+ }
+
+/* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
+ mismatch = NULL;
+/* END MOZILLA CHANGE */
+
+ return parser;
+}
+
+static void
+parserInit(XML_Parser parser, const XML_Char *encodingName)
+{
+ processor = prologInitProcessor;
+ XmlPrologStateInit(&prologState);
+ protocolEncodingName = (encodingName != NULL
+ ? poolCopyString(&tempPool, encodingName)
+ : NULL);
+ curBase = NULL;
+ XmlInitEncoding(&initEncoding, &encoding, 0);
+ userData = NULL;
+ handlerArg = NULL;
+ startElementHandler = NULL;
+ endElementHandler = NULL;
+ characterDataHandler = NULL;
+ processingInstructionHandler = NULL;
+ commentHandler = NULL;
+ startCdataSectionHandler = NULL;
+ endCdataSectionHandler = NULL;
+ defaultHandler = NULL;
+ startDoctypeDeclHandler = NULL;
+ endDoctypeDeclHandler = NULL;
+ unparsedEntityDeclHandler = NULL;
+ notationDeclHandler = NULL;
+ startNamespaceDeclHandler = NULL;
+ endNamespaceDeclHandler = NULL;
+ notStandaloneHandler = NULL;
+ externalEntityRefHandler = NULL;
+ externalEntityRefHandlerArg = parser;
+ skippedEntityHandler = NULL;
+ elementDeclHandler = NULL;
+ attlistDeclHandler = NULL;
+ entityDeclHandler = NULL;
+ xmlDeclHandler = NULL;
+ bufferPtr = buffer;
+ bufferEnd = buffer;
+ parseEndByteIndex = 0;
+ parseEndPtr = NULL;
+ declElementType = NULL;
+ declAttributeId = NULL;
+ declEntity = NULL;
+ doctypeName = NULL;
+ doctypeSysid = NULL;
+ doctypePubid = NULL;
+ declAttributeType = NULL;
+ declNotationName = NULL;
+ declNotationPublicId = NULL;
+ declAttributeIsCdata = XML_FALSE;
+ declAttributeIsId = XML_FALSE;
+ memset(&position, 0, sizeof(POSITION));
+ errorCode = XML_ERROR_NONE;
+ eventPtr = NULL;
+ eventEndPtr = NULL;
+ positionPtr = NULL;
+ openInternalEntities = NULL;
+ defaultExpandInternalEntities = XML_TRUE;
+ tagLevel = 0;
+ tagStack = NULL;
+ inheritedBindings = NULL;
+ nSpecifiedAtts = 0;
+ unknownEncodingMem = NULL;
+ unknownEncodingRelease = NULL;
+ unknownEncodingData = NULL;
+ parentParser = NULL;
+ ps_parsing = XML_INITIALIZED;
+#ifdef XML_DTD
+ isParamEntity = XML_FALSE;
+ useForeignDTD = XML_FALSE;
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+ hash_secret_salt = 0;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+/* moves list of bindings to freeBindingList */
+static void FASTCALL
+moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
+{
+ while (bindings) {
+ BINDING *b = bindings;
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ }
+}
+
+XML_Bool XMLCALL
+XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
+{
+ TAG *tStk;
+ OPEN_INTERNAL_ENTITY *openEntityList;
+
+ if (parser == NULL)
+ return XML_FALSE;
+
+ if (parentParser)
+ return XML_FALSE;
+ /* move tagStack to freeTagList */
+ tStk = tagStack;
+ while (tStk) {
+ TAG *tag = tStk;
+ tStk = tStk->parent;
+ tag->parent = freeTagList;
+ moveToFreeBindingList(parser, tag->bindings);
+ tag->bindings = NULL;
+ freeTagList = tag;
+ }
+ /* move openInternalEntities to freeInternalEntities */
+ openEntityList = openInternalEntities;
+ while (openEntityList) {
+ OPEN_INTERNAL_ENTITY *openEntity = openEntityList;
+ openEntityList = openEntity->next;
+ openEntity->next = freeInternalEntities;
+ freeInternalEntities = openEntity;
+ }
+ moveToFreeBindingList(parser, inheritedBindings);
+ FREE(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ poolClear(&tempPool);
+ poolClear(&temp2Pool);
+ parserInit(parser, encodingName);
+ dtdReset(_dtd, &parser->m_mem);
+ return XML_TRUE;
+}
+
+enum XML_Status XMLCALL
+XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
+ /* Block after XML_Parse()/XML_ParseBuffer() has been called.
+ XXX There's no way for the caller to determine which of the
+ XXX possible error cases caused the XML_STATUS_ERROR return.
+ */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return XML_STATUS_ERROR;
+ if (encodingName == NULL)
+ protocolEncodingName = NULL;
+ else {
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);
+ if (!protocolEncodingName)
+ return XML_STATUS_ERROR;
+ }
+ return XML_STATUS_OK;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+XML_Parser XMLCALL
+XML_ExternalEntityParserCreate(XML_Parser oldParser,
+ const XML_Char *context,
+ const XML_Char *encodingName)
+{
+ XML_Parser parser = oldParser;
+ DTD *newDtd = NULL;
+ DTD *oldDtd;
+ XML_StartElementHandler oldStartElementHandler;
+ XML_EndElementHandler oldEndElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
+ XML_CommentHandler oldCommentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler;
+ XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
+ XML_NotationDeclHandler oldNotationDeclHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
+ XML_SkippedEntityHandler oldSkippedEntityHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler;
+ XML_ElementDeclHandler oldElementDeclHandler;
+ XML_AttlistDeclHandler oldAttlistDeclHandler;
+ XML_EntityDeclHandler oldEntityDeclHandler;
+ XML_XmlDeclHandler oldXmlDeclHandler;
+ ELEMENT_TYPE * oldDeclElementType;
+
+ void *oldUserData;
+ void *oldHandlerArg;
+ XML_Bool oldDefaultExpandInternalEntities;
+ XML_Parser oldExternalEntityRefHandlerArg;
+#ifdef XML_DTD
+ enum XML_ParamEntityParsing oldParamEntityParsing;
+ int oldInEntityValue;
+#endif
+ XML_Bool oldns_triplets;
+ /* Note that the new parser shares the same hash secret as the old
+ parser, so that dtdCopy and copyEntityTable can lookup values
+ from hash tables associated with either parser without us having
+ to worry which hash secrets each table has.
+ */
+ unsigned long oldhash_secret_salt;
+
+ /* Validate the oldParser parameter before we pull everything out of it */
+ if (oldParser == NULL)
+ return NULL;
+
+ /* Stash the original parser contents on the stack */
+ oldDtd = _dtd;
+ oldStartElementHandler = startElementHandler;
+ oldEndElementHandler = endElementHandler;
+ oldCharacterDataHandler = characterDataHandler;
+ oldProcessingInstructionHandler = processingInstructionHandler;
+ oldCommentHandler = commentHandler;
+ oldStartCdataSectionHandler = startCdataSectionHandler;
+ oldEndCdataSectionHandler = endCdataSectionHandler;
+ oldDefaultHandler = defaultHandler;
+ oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+ oldNotationDeclHandler = notationDeclHandler;
+ oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+ oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+ oldNotStandaloneHandler = notStandaloneHandler;
+ oldExternalEntityRefHandler = externalEntityRefHandler;
+ oldSkippedEntityHandler = skippedEntityHandler;
+ oldUnknownEncodingHandler = unknownEncodingHandler;
+ oldElementDeclHandler = elementDeclHandler;
+ oldAttlistDeclHandler = attlistDeclHandler;
+ oldEntityDeclHandler = entityDeclHandler;
+ oldXmlDeclHandler = xmlDeclHandler;
+ oldDeclElementType = declElementType;
+
+ oldUserData = userData;
+ oldHandlerArg = handlerArg;
+ oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+ oldParamEntityParsing = paramEntityParsing;
+ oldInEntityValue = prologState.inEntityValue;
+#endif
+ oldns_triplets = ns_triplets;
+ /* Note that the new parser shares the same hash secret as the old
+ parser, so that dtdCopy and copyEntityTable can lookup values
+ from hash tables associated with either parser without us having
+ to worry which hash secrets each table has.
+ */
+ oldhash_secret_salt = hash_secret_salt;
+
+#ifdef XML_DTD
+ if (!context)
+ newDtd = oldDtd;
+#endif /* XML_DTD */
+
+ /* Note that the magical uses of the pre-processor to make field
+ access look more like C++ require that `parser' be overwritten
+ here. This makes this function more painful to follow than it
+ would be otherwise.
+ */
+ if (ns) {
+ XML_Char tmp[2];
+ *tmp = namespaceSeparator;
+ parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
+ }
+ else {
+ parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
+ }
+
+ if (!parser)
+ return NULL;
+
+ startElementHandler = oldStartElementHandler;
+ endElementHandler = oldEndElementHandler;
+ characterDataHandler = oldCharacterDataHandler;
+ processingInstructionHandler = oldProcessingInstructionHandler;
+ commentHandler = oldCommentHandler;
+ startCdataSectionHandler = oldStartCdataSectionHandler;
+ endCdataSectionHandler = oldEndCdataSectionHandler;
+ defaultHandler = oldDefaultHandler;
+ unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
+ notationDeclHandler = oldNotationDeclHandler;
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+ notStandaloneHandler = oldNotStandaloneHandler;
+ externalEntityRefHandler = oldExternalEntityRefHandler;
+ skippedEntityHandler = oldSkippedEntityHandler;
+ unknownEncodingHandler = oldUnknownEncodingHandler;
+ elementDeclHandler = oldElementDeclHandler;
+ attlistDeclHandler = oldAttlistDeclHandler;
+ entityDeclHandler = oldEntityDeclHandler;
+ xmlDeclHandler = oldXmlDeclHandler;
+ declElementType = oldDeclElementType;
+ userData = oldUserData;
+ if (oldUserData == oldHandlerArg)
+ handlerArg = userData;
+ else
+ handlerArg = parser;
+ if (oldExternalEntityRefHandlerArg != oldParser)
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ ns_triplets = oldns_triplets;
+ hash_secret_salt = oldhash_secret_salt;
+ parentParser = oldParser;
+#ifdef XML_DTD
+ paramEntityParsing = oldParamEntityParsing;
+ prologState.inEntityValue = oldInEntityValue;
+ if (context) {
+#endif /* XML_DTD */
+ if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
+ || !setContext(parser, context)) {
+ XML_ParserFree(parser);
+ return NULL;
+ }
+ processor = externalEntityInitProcessor;
+#ifdef XML_DTD
+ }
+ else {
+ /* The DTD instance referenced by _dtd is shared between the document's
+ root parser and external PE parsers, therefore one does not need to
+ call setContext. In addition, one also *must* not call setContext,
+ because this would overwrite existing prefix->binding pointers in
+ _dtd with ones that get destroyed with the external PE parser.
+ This would leave those prefixes with dangling pointers.
+ */
+ isParamEntity = XML_TRUE;
+ XmlPrologStateInitExternalEntity(&prologState);
+ processor = externalParEntInitProcessor;
+ }
+#endif /* XML_DTD */
+ return parser;
+}
+
+static void FASTCALL
+destroyBindings(BINDING *bindings, XML_Parser parser)
+{
+ for (;;) {
+ BINDING *b = bindings;
+ if (!b)
+ break;
+ bindings = b->nextTagBinding;
+ FREE(b->uri);
+ FREE(b);
+ }
+}
+
+void XMLCALL
+XML_ParserFree(XML_Parser parser)
+{
+ TAG *tagList;
+ OPEN_INTERNAL_ENTITY *entityList;
+ if (parser == NULL)
+ return;
+ /* free tagStack and freeTagList */
+ tagList = tagStack;
+ for (;;) {
+ TAG *p;
+ if (tagList == NULL) {
+ if (freeTagList == NULL)
+ break;
+ tagList = freeTagList;
+ freeTagList = NULL;
+ }
+ p = tagList;
+ tagList = tagList->parent;
+ FREE(p->buf);
+ destroyBindings(p->bindings, parser);
+ FREE(p);
+ }
+ /* free openInternalEntities and freeInternalEntities */
+ entityList = openInternalEntities;
+ for (;;) {
+ OPEN_INTERNAL_ENTITY *openEntity;
+ if (entityList == NULL) {
+ if (freeInternalEntities == NULL)
+ break;
+ entityList = freeInternalEntities;
+ freeInternalEntities = NULL;
+ }
+ openEntity = entityList;
+ entityList = entityList->next;
+ FREE(openEntity);
+ }
+
+ destroyBindings(freeBindingList, parser);
+ destroyBindings(inheritedBindings, parser);
+ poolDestroy(&tempPool);
+ poolDestroy(&temp2Pool);
+#ifdef XML_DTD
+ /* external parameter entity parsers share the DTD structure
+ parser->m_dtd with the root parser, so we must not destroy it
+ */
+ if (!isParamEntity && _dtd)
+#else
+ if (_dtd)
+#endif /* XML_DTD */
+ dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
+ FREE((void *)atts);
+#ifdef XML_ATTR_INFO
+ FREE((void *)attInfo);
+#endif
+ FREE(groupConnector);
+ FREE(buffer);
+ FREE(dataBuf);
+ FREE(nsAtts);
+ FREE(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ FREE(parser);
+}
+
+void XMLCALL
+XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+ if (parser != NULL)
+ handlerArg = parser;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+enum XML_Error XMLCALL
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
+{
+ if (parser == NULL)
+ return XML_ERROR_INVALID_ARGUMENT;
+#ifdef XML_DTD
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
+ useForeignDTD = useDTD;
+ return XML_ERROR_NONE;
+#else
+ return XML_ERROR_FEATURE_REQUIRES_XML_DTD;
+#endif
+}
+#endif
+/* END MOZILLA CHANGE */
+
+void XMLCALL
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
+{
+ if (parser == NULL)
+ return;
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return;
+ ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
+}
+
+void XMLCALL
+XML_SetUserData(XML_Parser parser, void *p)
+{
+ if (parser == NULL)
+ return;
+ if (handlerArg == userData)
+ handlerArg = userData = p;
+ else
+ userData = p;
+}
+
+enum XML_Status XMLCALL
+XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
+ if (p) {
+ p = poolCopyString(&_dtd->pool, p);
+ if (!p)
+ return XML_STATUS_ERROR;
+ curBase = p;
+ }
+ else
+ curBase = NULL;
+ return XML_STATUS_OK;
+}
+
+const XML_Char * XMLCALL
+XML_GetBase(XML_Parser parser)
+{
+ if (parser == NULL)
+ return NULL;
+ return curBase;
+}
+
+int XMLCALL
+XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+ if (parser == NULL)
+ return -1;
+ return nSpecifiedAtts;
+}
+
+int XMLCALL
+XML_GetIdAttributeIndex(XML_Parser parser)
+{
+ if (parser == NULL)
+ return -1;
+ return idAttIndex;
+}
+
+#ifdef XML_ATTR_INFO
+const XML_AttrInfo * XMLCALL
+XML_GetAttributeInfo(XML_Parser parser)
+{
+ if (parser == NULL)
+ return NULL;
+ return attInfo;
+}
+#endif
+
+void XMLCALL
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end)
+{
+ if (parser == NULL)
+ return;
+ startElementHandler = start;
+ endElementHandler = end;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+void XMLCALL
+XML_SetStartElementHandler(XML_Parser parser,
+ XML_StartElementHandler start) {
+ if (parser != NULL)
+ startElementHandler = start;
+}
+
+void XMLCALL
+XML_SetEndElementHandler(XML_Parser parser,
+ XML_EndElementHandler end) {
+ if (parser != NULL)
+ endElementHandler = end;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+void XMLCALL
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler)
+{
+ if (parser != NULL)
+ characterDataHandler = handler;
+}
+
+void XMLCALL
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler)
+{
+ if (parser != NULL)
+ processingInstructionHandler = handler;
+}
+
+void XMLCALL
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler)
+{
+ if (parser != NULL)
+ commentHandler = handler;
+}
+
+void XMLCALL
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end)
+{
+ if (parser == NULL)
+ return;
+ startCdataSectionHandler = start;
+ endCdataSectionHandler = end;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+void XMLCALL
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start) {
+ if (parser != NULL)
+ startCdataSectionHandler = start;
+}
+
+void XMLCALL
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+ XML_EndCdataSectionHandler end) {
+ if (parser != NULL)
+ endCdataSectionHandler = end;
+}
+
+void XMLCALL
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ if (parser == NULL)
+ return;
+ defaultHandler = handler;
+ defaultExpandInternalEntities = XML_FALSE;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+void XMLCALL
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ if (parser == NULL)
+ return;
+ defaultHandler = handler;
+ defaultExpandInternalEntities = XML_TRUE;
+}
+
+void XMLCALL
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end)
+{
+ if (parser == NULL)
+ return;
+ startDoctypeDeclHandler = start;
+ endDoctypeDeclHandler = end;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+void XMLCALL
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start) {
+ if (parser != NULL)
+ startDoctypeDeclHandler = start;
+}
+
+void XMLCALL
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+ XML_EndDoctypeDeclHandler end) {
+ if (parser != NULL)
+ endDoctypeDeclHandler = end;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+void XMLCALL
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler)
+{
+ if (parser != NULL)
+ unparsedEntityDeclHandler = handler;
+}
+
+void XMLCALL
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler)
+{
+ if (parser != NULL)
+ notationDeclHandler = handler;
+}
+
+void XMLCALL
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end)
+{
+ if (parser == NULL)
+ return;
+ startNamespaceDeclHandler = start;
+ endNamespaceDeclHandler = end;
+}
+
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+void XMLCALL
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start) {
+ if (parser != NULL)
+ startNamespaceDeclHandler = start;
+}
+
+void XMLCALL
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+ XML_EndNamespaceDeclHandler end) {
+ if (parser != NULL)
+ endNamespaceDeclHandler = end;
+}
+
+void XMLCALL
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler)
+{
+ if (parser != NULL)
+ notStandaloneHandler = handler;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+void XMLCALL
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler)
+{
+ if (parser != NULL)
+ externalEntityRefHandler = handler;
+}
+
+void XMLCALL
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+ if (parser == NULL)
+ return;
+ if (arg)
+ externalEntityRefHandlerArg = (XML_Parser)arg;
+ else
+ externalEntityRefHandlerArg = parser;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+void XMLCALL
+XML_SetSkippedEntityHandler(XML_Parser parser,
+ XML_SkippedEntityHandler handler)
+{
+ if (parser != NULL)
+ skippedEntityHandler = handler;
+}
+
+void XMLCALL
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *data)
+{
+ if (parser == NULL)
+ return;
+ unknownEncodingHandler = handler;
+ unknownEncodingHandlerData = data;
+}
+
+void XMLCALL
+XML_SetElementDeclHandler(XML_Parser parser,
+ XML_ElementDeclHandler eldecl)
+{
+ if (parser != NULL)
+ elementDeclHandler = eldecl;
+}
+
+void XMLCALL
+XML_SetAttlistDeclHandler(XML_Parser parser,
+ XML_AttlistDeclHandler attdecl)
+{
+ if (parser != NULL)
+ attlistDeclHandler = attdecl;
+}
+
+void XMLCALL
+XML_SetEntityDeclHandler(XML_Parser parser,
+ XML_EntityDeclHandler handler)
+{
+ if (parser != NULL)
+ entityDeclHandler = handler;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+void XMLCALL
+XML_SetXmlDeclHandler(XML_Parser parser,
+ XML_XmlDeclHandler handler) {
+ if (parser != NULL)
+ xmlDeclHandler = handler;
+}
+
+int XMLCALL
+XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing peParsing)
+{
+ if (parser == NULL)
+ return 0;
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return 0;
+#ifdef XML_DTD
+ paramEntityParsing = peParsing;
+ return 1;
+#else
+ return peParsing == XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+}
+
+int XMLCALL
+XML_SetHashSalt(XML_Parser parser,
+ unsigned long hash_salt)
+{
+ if (parser == NULL)
+ return 0;
+ if (parser->m_parentParser)
+ return XML_SetHashSalt(parser->m_parentParser, hash_salt);
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
+ return 0;
+ hash_secret_salt = hash_salt;
+ return 1;
+}
+
+enum XML_Status XMLCALL
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+ if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
+ errorCode = XML_ERROR_INVALID_ARGUMENT;
+ return XML_STATUS_ERROR;
+ }
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+ return XML_STATUS_ERROR;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return XML_STATUS_ERROR;
+ case XML_INITIALIZED:
+ if (parentParser == NULL && !startParsing(parser)) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return XML_STATUS_ERROR;
+ }
+ default:
+ ps_parsing = XML_PARSING;
+ }
+
+ if (len == 0) {
+ ps_finalBuffer = (XML_Bool)isFinal;
+ if (!isFinal)
+ return XML_STATUS_OK;
+ positionPtr = bufferPtr;
+ parseEndPtr = bufferEnd;
+
+ /* If data are left over from last buffer, and we now know that these
+ data are the final chunk of input, then we have to check them again
+ to detect errors based on that fact.
+ */
+ errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
+
+ if (errorCode == XML_ERROR_NONE) {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ positionPtr = bufferPtr;
+ return XML_STATUS_SUSPENDED;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ ps_parsing = XML_FINISHED;
+ /* fall through */
+ default:
+ return XML_STATUS_OK;
+ }
+ }
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+#ifndef XML_CONTEXT_BYTES
+ else if (bufferPtr == bufferEnd) {
+ const char *end;
+ int nLeftOver;
+ enum XML_Status result;
+ /* Detect overflow (a+b > MAX <==> b > MAX-a) */
+/* BEGIN MOZILLA CHANGE (len is signed, trying to compare it to an unsigned value) */
+#if 0
+ if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) {
+#else
+ if ((XML_Size)len > ((XML_Size)-1) / 2 - parseEndByteIndex) {
+#endif
+/* END MOZILLA CHANGE */
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = NULL;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ parseEndByteIndex += len;
+ positionPtr = s;
+ ps_finalBuffer = (XML_Bool)isFinal;
+
+ errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ else {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ result = XML_STATUS_SUSPENDED;
+ break;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ if (isFinal) {
+ ps_parsing = XML_FINISHED;
+ return XML_STATUS_OK;
+ }
+ /* fall through */
+ default:
+ result = XML_STATUS_OK;
+ }
+ }
+
+ XmlUpdatePosition(encoding, positionPtr, end, &position);
+ nLeftOver = s + len - end;
+ if (nLeftOver) {
+ if (buffer == NULL || nLeftOver > bufferLim - buffer) {
+ /* avoid _signed_ integer overflow */
+ char *temp = NULL;
+ const int bytesToAllocate = (int)((unsigned)len * 2U);
+ if (bytesToAllocate > 0) {
+ temp = (buffer == NULL
+ ? (char *)MALLOC(bytesToAllocate)
+ : (char *)REALLOC(buffer, bytesToAllocate));
+ }
+ if (temp == NULL) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = NULL;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ buffer = temp;
+ bufferLim = buffer + bytesToAllocate;
+ }
+ memcpy(buffer, end, nLeftOver);
+ }
+ bufferPtr = buffer;
+ bufferEnd = buffer + nLeftOver;
+ positionPtr = bufferPtr;
+ parseEndPtr = bufferEnd;
+ eventPtr = bufferPtr;
+ eventEndPtr = bufferPtr;
+ return result;
+ }
+#endif /* not defined XML_CONTEXT_BYTES */
+ else {
+ void *buff = XML_GetBuffer(parser, len);
+ if (buff == NULL)
+ return XML_STATUS_ERROR;
+ else {
+ memcpy(buff, s, len);
+ return XML_ParseBuffer(parser, len, isFinal);
+ }
+ }
+}
+
+enum XML_Status XMLCALL
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+ const char *start;
+ enum XML_Status result = XML_STATUS_OK;
+
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+ return XML_STATUS_ERROR;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return XML_STATUS_ERROR;
+ case XML_INITIALIZED:
+ if (parentParser == NULL && !startParsing(parser)) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return XML_STATUS_ERROR;
+ }
+ default:
+ ps_parsing = XML_PARSING;
+ }
+
+ start = bufferPtr;
+ positionPtr = start;
+ bufferEnd += len;
+ parseEndPtr = bufferEnd;
+ parseEndByteIndex += len;
+ ps_finalBuffer = (XML_Bool)isFinal;
+
+ errorCode = processor(parser, start, parseEndPtr, &bufferPtr);
+
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ else {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ result = XML_STATUS_SUSPENDED;
+ break;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ if (isFinal) {
+ ps_parsing = XML_FINISHED;
+ return result;
+ }
+ default: ; /* should not happen */
+ }
+ }
+
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ positionPtr = bufferPtr;
+ return result;
+}
+
+void * XMLCALL
+XML_GetBuffer(XML_Parser parser, int len)
+{
+ if (parser == NULL)
+ return NULL;
+ if (len < 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+ return NULL;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return NULL;
+ default: ;
+ }
+
+ if (len > bufferLim - bufferEnd) {
+#ifdef XML_CONTEXT_BYTES
+ int keep;
+#endif /* defined XML_CONTEXT_BYTES */
+ /* Do not invoke signed arithmetic overflow: */
+ int neededSize = (int) ((unsigned)len + (unsigned)(bufferEnd - bufferPtr));
+ if (neededSize < 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
+#ifdef XML_CONTEXT_BYTES
+ keep = (int)(bufferPtr - buffer);
+ if (keep > XML_CONTEXT_BYTES)
+ keep = XML_CONTEXT_BYTES;
+ neededSize += keep;
+#endif /* defined XML_CONTEXT_BYTES */
+ if (neededSize <= bufferLim - buffer) {
+#ifdef XML_CONTEXT_BYTES
+ if (keep < bufferPtr - buffer) {
+ int offset = (int)(bufferPtr - buffer) - keep;
+ memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
+ bufferEnd -= offset;
+ bufferPtr -= offset;
+ }
+#else
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+ bufferEnd = buffer + (bufferEnd - bufferPtr);
+ bufferPtr = buffer;
+#endif /* not defined XML_CONTEXT_BYTES */
+ }
+ else {
+ char *newBuf;
+ int bufferSize = (int)(bufferLim - bufferPtr);
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ /* Do not invoke signed arithmetic overflow: */
+ bufferSize = (int) (2U * (unsigned) bufferSize);
+ } while (bufferSize < neededSize && bufferSize > 0);
+ if (bufferSize <= 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
+ newBuf = (char *)MALLOC(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
+ bufferLim = newBuf + bufferSize;
+#ifdef XML_CONTEXT_BYTES
+ if (bufferPtr) {
+ int keep = (int)(bufferPtr - buffer);
+ if (keep > XML_CONTEXT_BYTES)
+ keep = XML_CONTEXT_BYTES;
+ memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
+ FREE(buffer);
+ buffer = newBuf;
+ bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
+ bufferPtr = buffer + keep;
+ }
+ else {
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+ }
+#else
+ if (bufferPtr) {
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+ FREE(buffer);
+ }
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+#endif /* not defined XML_CONTEXT_BYTES */
+ }
+ eventPtr = eventEndPtr = NULL;
+ positionPtr = NULL;
+ }
+ return bufferEnd;
+}
+
+enum XML_Status XMLCALL
+XML_StopParser(XML_Parser parser, int resumable)
+{
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ if (resumable) {
+ errorCode = XML_ERROR_SUSPENDED;
+ return XML_STATUS_ERROR;
+ }
+ ps_parsing = XML_FINISHED;
+ break;
+ case XML_FINISHED:
+ errorCode = XML_ERROR_FINISHED;
+ return XML_STATUS_ERROR;
+ default:
+ if (resumable) {
+#ifdef XML_DTD
+ if (isParamEntity) {
+ errorCode = XML_ERROR_SUSPEND_PE;
+ return XML_STATUS_ERROR;
+ }
+#endif
+ ps_parsing = XML_SUSPENDED;
+ }
+ else
+ ps_parsing = XML_FINISHED;
+ }
+ return XML_STATUS_OK;
+}
+
+enum XML_Status XMLCALL
+XML_ResumeParser(XML_Parser parser)
+{
+ enum XML_Status result = XML_STATUS_OK;
+
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
+ if (ps_parsing != XML_SUSPENDED) {
+ errorCode = XML_ERROR_NOT_SUSPENDED;
+ return XML_STATUS_ERROR;
+ }
+ ps_parsing = XML_PARSING;
+
+ errorCode = processor(parser, bufferPtr, parseEndPtr, &bufferPtr);
+
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
+ else {
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ result = XML_STATUS_SUSPENDED;
+ break;
+ case XML_INITIALIZED:
+ case XML_PARSING:
+ if (ps_finalBuffer) {
+ ps_parsing = XML_FINISHED;
+ return result;
+ }
+ default: ;
+ }
+ }
+
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ positionPtr = bufferPtr;
+/* BEGIN MOZILLA CHANGE (always set eventPtr/eventEndPtr) */
+ eventPtr = bufferPtr;
+ eventEndPtr = bufferPtr;
+/* END MOZILLA CHANGE */
+ return result;
+}
+
+void XMLCALL
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
+{
+ if (parser == NULL)
+ return;
+ assert(status != NULL);
+ *status = parser->m_parsingStatus;
+}
+
+enum XML_Error XMLCALL
+XML_GetErrorCode(XML_Parser parser)
+{
+ if (parser == NULL)
+ return XML_ERROR_INVALID_ARGUMENT;
+ return errorCode;
+}
+
+XML_Index XMLCALL
+XML_GetCurrentByteIndex(XML_Parser parser)
+{
+ if (parser == NULL)
+ return -1;
+ if (eventPtr)
+ return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
+/* BEGIN MOZILLA CHANGE (fix XML_GetCurrentByteIndex) */
+#if 0
+ return -1;
+#else
+ return parseEndByteIndex;
+#endif
+/* END MOZILLA CHANGE */
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+int XMLCALL
+XML_GetCurrentByteCount(XML_Parser parser)
+{
+ if (parser == NULL)
+ return 0;
+ if (eventEndPtr && eventPtr)
+ return (int)(eventEndPtr - eventPtr);
+ return 0;
+}
+
+const char * XMLCALL
+XML_GetInputContext(XML_Parser parser, int *offset, int *size)
+{
+#ifdef XML_CONTEXT_BYTES
+ if (parser == NULL)
+ return NULL;
+ if (eventPtr && buffer) {
+ if (offset != NULL)
+ *offset = (int)(eventPtr - buffer);
+ if (size != NULL)
+ *size = (int)(bufferEnd - buffer);
+ return buffer;
+ }
+#else
+ (void)parser;
+ (void)offset;
+ (void)size;
+#endif /* defined XML_CONTEXT_BYTES */
+ return (char *) 0;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+XML_Size XMLCALL
+XML_GetCurrentLineNumber(XML_Parser parser)
+{
+ if (parser == NULL)
+ return 0;
+ if (eventPtr && eventPtr >= positionPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.lineNumber + 1;
+}
+
+XML_Size XMLCALL
+XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+ if (parser == NULL)
+ return 0;
+ if (eventPtr && eventPtr >= positionPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.columnNumber;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+void XMLCALL
+XML_FreeContentModel(XML_Parser parser, XML_Content *model)
+{
+ if (parser != NULL)
+ FREE(model);
+}
+
+void * XMLCALL
+XML_MemMalloc(XML_Parser parser, size_t size)
+{
+ if (parser == NULL)
+ return NULL;
+ return MALLOC(size);
+}
+
+void * XMLCALL
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
+{
+ if (parser == NULL)
+ return NULL;
+ return REALLOC(ptr, size);
+}
+
+void XMLCALL
+XML_MemFree(XML_Parser parser, void *ptr)
+{
+ if (parser != NULL)
+ FREE(ptr);
+}
+
+void XMLCALL
+XML_DefaultCurrent(XML_Parser parser)
+{
+ if (parser == NULL)
+ return;
+ if (defaultHandler) {
+ if (openInternalEntities)
+ reportDefault(parser,
+ internalEncoding,
+ openInternalEntities->internalEventPtr,
+ openInternalEntities->internalEventEndPtr);
+ else
+ reportDefault(parser, encoding, eventPtr, eventEndPtr);
+ }
+}
+
+const XML_LChar * XMLCALL
+XML_ErrorString(enum XML_Error code)
+{
+ static const XML_LChar* const message[] = {
+ 0,
+ XML_L("out of memory"),
+ XML_L("syntax error"),
+ XML_L("no element found"),
+ XML_L("not well-formed (invalid token)"),
+ XML_L("unclosed token"),
+ XML_L("partial character"),
+ XML_L("mismatched tag"),
+ XML_L("duplicate attribute"),
+ XML_L("junk after document element"),
+ XML_L("illegal parameter entity reference"),
+ XML_L("undefined entity"),
+ XML_L("recursive entity reference"),
+ XML_L("asynchronous entity"),
+ XML_L("reference to invalid character number"),
+ XML_L("reference to binary entity"),
+ XML_L("reference to external entity in attribute"),
+ XML_L("XML or text declaration not at start of entity"),
+ XML_L("unknown encoding"),
+ XML_L("encoding specified in XML declaration is incorrect"),
+ XML_L("unclosed CDATA section"),
+ XML_L("error in processing external entity reference"),
+ XML_L("document is not standalone"),
+ XML_L("unexpected parser state - please send a bug report"),
+ XML_L("entity declared in parameter entity"),
+ XML_L("requested feature requires XML_DTD support in Expat"),
+ XML_L("cannot change setting once parsing has begun"),
+ XML_L("unbound prefix"),
+ XML_L("must not undeclare prefix"),
+ XML_L("incomplete markup in parameter entity"),
+ XML_L("XML declaration not well-formed"),
+ XML_L("text declaration not well-formed"),
+ XML_L("illegal character(s) in public id"),
+ XML_L("parser suspended"),
+ XML_L("parser not suspended"),
+ XML_L("parsing aborted"),
+ XML_L("parsing finished"),
+ XML_L("cannot suspend in external parameter entity"),
+ XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name"),
+ XML_L("reserved prefix (xmlns) must not be declared or undeclared"),
+ XML_L("prefix must not be bound to one of the reserved namespace names")
+ };
+ if (code > 0 && code < sizeof(message)/sizeof(message[0]))
+ return message[code];
+ return NULL;
+}
+
+const XML_LChar * XMLCALL
+XML_ExpatVersion(void) {
+
+ /* V1 is used to string-ize the version number. However, it would
+ string-ize the actual version macro *names* unless we get them
+ substituted before being passed to V1. CPP is defined to expand
+ a macro, then rescan for more expansions. Thus, we use V2 to expand
+ the version macros, then CPP will expand the resulting V1() macro
+ with the correct numerals. */
+ /* ### I'm assuming cpp is portable in this respect... */
+
+#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
+#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
+
+ return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
+
+#undef V1
+#undef V2
+}
+
+XML_Expat_Version XMLCALL
+XML_ExpatVersionInfo(void)
+{
+ XML_Expat_Version version;
+
+ version.major = XML_MAJOR_VERSION;
+ version.minor = XML_MINOR_VERSION;
+ version.micro = XML_MICRO_VERSION;
+
+ return version;
+}
+
+const XML_Feature * XMLCALL
+XML_GetFeatureList(void)
+{
+ static const XML_Feature features[] = {
+ {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
+ sizeof(XML_Char)},
+ {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
+ sizeof(XML_LChar)},
+#ifdef XML_UNICODE
+ {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
+#endif
+#ifdef XML_UNICODE_WCHAR_T
+ {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
+#endif
+#ifdef XML_DTD
+ {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
+#endif
+#ifdef XML_CONTEXT_BYTES
+ {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
+ XML_CONTEXT_BYTES},
+#endif
+#ifdef XML_MIN_SIZE
+ {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
+#endif
+#ifdef XML_NS
+ {XML_FEATURE_NS, XML_L("XML_NS"), 0},
+#endif
+#ifdef XML_LARGE_SIZE
+ {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
+#endif
+#ifdef XML_ATTR_INFO
+ {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
+#endif
+ {XML_FEATURE_END, NULL, 0}
+ };
+
+ return features;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+/* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
+const XML_Char * XMLCALL
+MOZ_XML_GetMismatchedTag(XML_Parser parser)
+{
+ return mismatch;
+}
+/* END MOZILLA CHANGE */
+
+/* BEGIN MOZILLA CHANGE (Report whether the parser is currently expanding an entity) */
+XML_Bool XMLCALL
+MOZ_XML_ProcessingEntityValue(XML_Parser parser) {
+ return openInternalEntities != NULL;
+}
+/* END MOZILLA CHANGE */
+
+/* Initially tag->rawName always points into the parse buffer;
+ for those TAG instances opened while the current parse buffer was
+ processed, and not yet closed, we need to store tag->rawName in a more
+ permanent location, since the parse buffer is about to be discarded.
+*/
+static XML_Bool
+storeRawNames(XML_Parser parser)
+{
+ TAG *tag = tagStack;
+ while (tag) {
+ int bufSize;
+ int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
+ char *rawNameBuf = tag->buf + nameLen;
+ /* Stop if already stored. Since tagStack is a stack, we can stop
+ at the first entry that has already been copied; everything
+ below it in the stack is already been accounted for in a
+ previous call to this function.
+ */
+ if (tag->rawName == rawNameBuf)
+ break;
+ /* For re-use purposes we need to ensure that the
+ size of tag->buf is a multiple of sizeof(XML_Char).
+ */
+ bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
+ if (bufSize > tag->bufEnd - tag->buf) {
+ char *temp = (char *)REALLOC(tag->buf, bufSize);
+ if (temp == NULL)
+ return XML_FALSE;
+ /* if tag->name.str points to tag->buf (only when namespace
+ processing is off) then we have to update it
+ */
+ if (tag->name.str == (XML_Char *)tag->buf)
+ tag->name.str = (XML_Char *)temp;
+ /* if tag->name.localPart is set (when namespace processing is on)
+ then update it as well, since it will always point into tag->buf
+ */
+ if (tag->name.localPart)
+ tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
+ (XML_Char *)tag->buf);
+ tag->buf = temp;
+ tag->bufEnd = temp + bufSize;
+ rawNameBuf = temp + nameLen;
+ }
+ memcpy(rawNameBuf, tag->rawName, tag->rawNameLength);
+ tag->rawName = rawNameBuf;
+ tag = tag->parent;
+ }
+ return XML_TRUE;
+}
+
+static enum XML_Error PTRCALL
+contentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 0, encoding, start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+}
+
+static enum XML_Error PTRCALL
+externalEntityInitProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = externalEntityInitProcessor2;
+ return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static enum XML_Error PTRCALL
+externalEntityInitProcessor2(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next = start; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_BOM:
+ /* If we are at the end of the buffer, this would cause the next stage,
+ i.e. externalEntityInitProcessor3, to pass control directly to
+ doContent (by detecting XML_TOK_NONE) without processing any xml text
+ declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
+ */
+ if (next == end && !ps_finalBuffer) {
+ *endPtr = next;
+ return XML_ERROR_NONE;
+ }
+ start = next;
+ break;
+ case XML_TOK_PARTIAL:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityInitProcessor3;
+ return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static enum XML_Error PTRCALL
+externalEntityInitProcessor3(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ int tok;
+ const char *next = start; /* XmlContentTok doesn't always set the last arg */
+ eventPtr = start;
+ tok = XmlContentTok(encoding, start, end, &next);
+ eventEndPtr = next;
+
+ switch (tok) {
+ case XML_TOK_XML_DECL:
+ {
+ enum XML_Error result;
+ result = processXmlDecl(parser, 1, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *endPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ start = next;
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (!ps_finalBuffer) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityContentProcessor;
+ tagLevel = 1;
+ return externalEntityContentProcessor(parser, start, end, endPtr);
+}
+
+static enum XML_Error PTRCALL
+externalEntityContentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 1, encoding, start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+ int startTagLevel,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ enum XML_Error result = doContentInternal(parser, startTagLevel, enc,
+ s, end, nextPtr, haveMore);
+ if (result == XML_ERROR_NONE) {
+ if (!storeRawNames(parser))
+ return XML_ERROR_NO_MEMORY;
+ }
+ return result;
+}
+
+static enum XML_Error
+doContentInternal(XML_Parser parser,
+ int startTagLevel,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ /* save one level of indirection */
+ DTD * const dtd = _dtd;
+
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+
+ for (;;) {
+ const char *next = s; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ *eventEndPP = end;
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ /* We are at the end of the final buffer, should we check for
+ XML_SUSPENDED, XML_FINISHED?
+ */
+ if (startTagLevel == 0)
+ return XML_ERROR_NO_ELEMENTS;
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (startTagLevel > 0) {
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (characterDataHandler)
+ characterDataHandler(handlerArg, &ch, 1);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ name = poolStoreString(&dtd->pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
+ poolDiscard(&dtd->pool);
+ /* First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity or default handler.
+ */
+ if (!dtd->hasParamEntityRefs || dtd->standalone) {
+ if (!entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (!entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ }
+ else if (!entity) {
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, name, 0);
+/* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
+#if 0
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+#else
+ return XML_ERROR_UNDEFINED_ENTITY;
+#endif
+/* END MOZILLA CHANGE */
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->notation)
+ return XML_ERROR_BINARY_ENTITY_REF;
+ if (entity->textPtr) {
+ enum XML_Error result;
+ if (!defaultExpandInternalEntities) {
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, entity->name, 0);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ result = processInternalEntity(parser, entity, XML_FALSE);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ else if (externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = XML_TRUE;
+ context = getContext(parser);
+ entity->open = XML_FALSE;
+ if (!context)
+ return XML_ERROR_NO_MEMORY;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ context,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ poolDiscard(&tempPool);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ case XML_TOK_START_TAG_NO_ATTS:
+ /* fall through */
+ case XML_TOK_START_TAG_WITH_ATTS:
+ {
+ TAG *tag;
+ enum XML_Error result;
+ XML_Char *toPtr;
+ if (freeTagList) {
+ tag = freeTagList;
+ freeTagList = freeTagList->parent;
+ }
+ else {
+ tag = (TAG *)MALLOC(sizeof(TAG));
+ if (!tag)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = (char *)MALLOC(INIT_TAG_BUF_SIZE);
+ if (!tag->buf) {
+ FREE(tag);
+ return XML_ERROR_NO_MEMORY;
+ }
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = NULL;
+ tag->parent = tagStack;
+ tagStack = tag;
+ tag->name.localPart = NULL;
+ tag->name.prefix = NULL;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+ ++tagLevel;
+ {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ toPtr = (XML_Char *)tag->buf;
+ for (;;) {
+ int bufSize;
+ int convLen;
+ const enum XML_Convert_Result convert_res = XmlConvert(enc,
+ &fromPtr, rawNameEnd,
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+ convLen = (int)(toPtr - (XML_Char *)tag->buf);
+ if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
+ tag->name.strLen = convLen;
+ break;
+ }
+ bufSize = (int)(tag->bufEnd - tag->buf) << 1;
+ {
+ char *temp = (char *)REALLOC(tag->buf, bufSize);
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = temp;
+ tag->bufEnd = temp + bufSize;
+ toPtr = (XML_Char *)temp + convLen;
+ }
+ }
+ }
+ tag->name.str = (XML_Char *)tag->buf;
+ *toPtr = XML_T('\0');
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ if (result)
+ return result;
+ if (startElementHandler)
+ startElementHandler(handlerArg, tag->name.str,
+ (const XML_Char **)atts);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ poolClear(&tempPool);
+ break;
+ }
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+ /* fall through */
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+ {
+ const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = NULL;
+ XML_Bool noElmHandlers = XML_TRUE;
+ TAG_NAME name;
+ name.str = poolStoreString(&tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (!name.str)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result != XML_ERROR_NONE) {
+ freeBindings(parser, bindings);
+ return result;
+ }
+ poolFinish(&tempPool);
+ if (startElementHandler) {
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+ noElmHandlers = XML_FALSE;
+ }
+ if (endElementHandler) {
+ if (startElementHandler)
+ *eventPP = *eventEndPP;
+ endElementHandler(handlerArg, name.str);
+ noElmHandlers = XML_FALSE;
+ }
+ if (noElmHandlers && defaultHandler)
+ reportDefault(parser, enc, s, next);
+ poolClear(&tempPool);
+ freeBindings(parser, bindings);
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ break;
+ case XML_TOK_END_TAG:
+ if (tagLevel == startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ else {
+ int len;
+ const char *rawName;
+ TAG *tag = tagStack;
+ tagStack = tag->parent;
+ tag->parent = freeTagList;
+ freeTagList = tag;
+ rawName = s + enc->minBytesPerChar*2;
+ len = XmlNameLength(enc, rawName);
+ if (len != tag->rawNameLength
+ || memcmp(tag->rawName, rawName, len) != 0) {
+/* BEGIN MOZILLA CHANGE (Report opening tag of mismatched closing tag) */
+ /* This code is copied from the |if (endElementHandler)| block below */
+ const XML_Char *localPart;
+ const XML_Char *prefix;
+ XML_Char *uri;
+ localPart = tag->name.localPart;
+ if (ns && localPart) {
+ /* localPart and prefix may have been overwritten in
+ tag->name.str, since this points to the binding->uri
+ buffer which gets re-used; so we have to add them again
+ */
+ uri = (XML_Char *)tag->name.str + tag->name.uriLen;
+ /* don't need to check for space - already done in storeAtts() */
+ while (*localPart) *uri++ = *localPart++;
+ prefix = (XML_Char *)tag->name.prefix;
+ if (ns_triplets && prefix) {
+ *uri++ = namespaceSeparator;
+ while (*prefix) *uri++ = *prefix++;
+ }
+ *uri = XML_T('\0');
+ }
+ mismatch = tag->name.str;
+/* END MOZILLA CHANGE */
+ *eventPP = rawName;
+ return XML_ERROR_TAG_MISMATCH;
+ }
+ --tagLevel;
+ if (endElementHandler) {
+ const XML_Char *localPart;
+ const XML_Char *prefix;
+ XML_Char *uri;
+ localPart = tag->name.localPart;
+ if (ns && localPart) {
+ /* localPart and prefix may have been overwritten in
+ tag->name.str, since this points to the binding->uri
+ buffer which gets re-used; so we have to add them again
+ */
+ uri = (XML_Char *)tag->name.str + tag->name.uriLen;
+ /* don't need to check for space - already done in storeAtts() */
+ while (*localPart) *uri++ = *localPart++;
+ prefix = (XML_Char *)tag->name.prefix;
+ if (ns_triplets && prefix) {
+ *uri++ = namespaceSeparator;
+ while (*prefix) *uri++ = *prefix++;
+ }
+ *uri = XML_T('\0');
+ }
+ endElementHandler(handlerArg, tag->name.str);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ while (tag->bindings) {
+ BINDING *b = tag->bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ }
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ int n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ return XML_ERROR_BAD_CHAR_REF;
+ if (characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_CDATA_SECT_OPEN:
+ {
+ enum XML_Error result;
+ if (startCdataSectionHandler)
+ startCdataSectionHandler(handlerArg);
+#if 0
+ /* Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the
+ transformation and writes the characters out escaping them as
+ necessary. This case will fail to work if we leave out the
+ following two lines (because & and < inside CDATA sections will
+ be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this.
+ */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (!next) {
+ processor = cdataSectionProcessor;
+ return result;
+ }
+ }
+ break;
+ case XML_TOK_TRAILING_RSQB:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ characterDataHandler(handlerArg, dataBuf,
+ (int)(dataPtr - (ICHAR *)dataBuf));
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (int)((XML_Char *)end - (XML_Char *)s));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ /* We are at the end of the final buffer, should we check for
+ XML_SUSPENDED, XML_FINISHED?
+ */
+ if (startTagLevel == 0) {
+ *eventPP = end;
+ return XML_ERROR_NO_ELEMENTS;
+ }
+ if (tagLevel != startTagLevel) {
+ *eventPP = end;
+ return XML_ERROR_ASYNC_ENTITY;
+ }
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_CHARS:
+ {
+ XML_CharacterDataHandler charDataHandler = characterDataHandler;
+ if (charDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ charDataHandler(handlerArg, dataBuf,
+ (int)(dataPtr - (ICHAR *)dataBuf));
+ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ charDataHandler(handlerArg,
+ (XML_Char *)s,
+ (int)((XML_Char *)next - (XML_Char *)s));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ default:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ *eventPP = s = next;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default: ;
+ }
+ }
+ /* not reached */
+}
+
+/* This function does not call free() on the allocated memory, merely
+ * moving it to the parser's freeBindingList where it can be freed or
+ * reused as appropriate.
+ */
+static void
+freeBindings(XML_Parser parser, BINDING *bindings)
+{
+ while (bindings) {
+ BINDING *b = bindings;
+
+ /* startNamespaceDeclHandler will have been called for this
+ * binding in addBindings(), so call the end handler now.
+ */
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+}
+
+/* Precondition: all arguments must be non-NULL;
+ Purpose:
+ - normalize attributes
+ - check attributes for well-formedness
+ - generate namespace aware attribute names (URI, prefix)
+ - build list of attributes for startElementHandler
+ - default attributes
+ - process namespace declarations (check and report them)
+ - generate namespace aware element name (URI, prefix)
+*/
+static enum XML_Error
+storeAtts(XML_Parser parser, const ENCODING *enc,
+ const char *attStr, TAG_NAME *tagNamePtr,
+ BINDING **bindingsPtr)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ ELEMENT_TYPE *elementType;
+ int nDefaultAtts;
+ const XML_Char **appAtts; /* the attribute list for the application */
+ int attIndex = 0;
+ int prefixLen;
+ int i;
+ int n;
+ XML_Char *uri;
+ int nPrefixes = 0;
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+ int nXMLNSDeclarations = 0;
+/* END MOZILLA CHANGE */
+ BINDING *binding;
+ const XML_Char *localPart;
+
+ /* lookup the element type name */
+ elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
+ if (!elementType) {
+ const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
+ sizeof(ELEMENT_TYPE));
+ if (!elementType)
+ return XML_ERROR_NO_MEMORY;
+ if (ns && !setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ nDefaultAtts = elementType->nDefaultAtts;
+
+ /* get the attributes from the tokenizer */
+ n = XmlGetAttributes(enc, attStr, attsSize, atts);
+
+ /* Detect and prevent integer overflow */
+ if (n > INT_MAX - nDefaultAtts) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ if (n + nDefaultAtts > attsSize) {
+ int oldAttsSize = attsSize;
+ ATTRIBUTE *temp;
+#ifdef XML_ATTR_INFO
+ XML_AttrInfo *temp2;
+#endif
+
+ /* Detect and prevent integer overflow */
+ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
+ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
+ parser->m_attsSize = oldAttsSize;
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
+ temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ atts = temp;
+#ifdef XML_ATTR_INFO
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+# if UINT_MAX >= SIZE_MAX
+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
+ parser->m_attsSize = oldAttsSize;
+ return XML_ERROR_NO_MEMORY;
+ }
+# endif
+
+ temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
+ if (temp2 == NULL)
+ return XML_ERROR_NO_MEMORY;
+ attInfo = temp2;
+#endif
+ if (n > oldAttsSize)
+ XmlGetAttributes(enc, attStr, n, atts);
+ }
+
+ appAtts = (const XML_Char **)atts;
+ for (i = 0; i < n; i++) {
+ ATTRIBUTE *currAtt = &atts[i];
+#ifdef XML_ATTR_INFO
+ XML_AttrInfo *currAttInfo = &attInfo[i];
+#endif
+ /* add the name and value to the attribute list */
+ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
+ currAtt->name
+ + XmlNameLength(enc, currAtt->name));
+ if (!attId)
+ return XML_ERROR_NO_MEMORY;
+#ifdef XML_ATTR_INFO
+ currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
+ currAttInfo->nameEnd = currAttInfo->nameStart +
+ XmlNameLength(enc, currAtt->name);
+ currAttInfo->valueStart = parseEndByteIndex -
+ (parseEndPtr - currAtt->valuePtr);
+ currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
+#endif
+ /* Detect duplicate attributes by their QNames. This does not work when
+ namespace processing is turned on and different prefixes for the same
+ namespace are used. For this case we have a check further down.
+ */
+ if ((attId->name)[-1]) {
+ if (enc == encoding)
+ eventPtr = atts[i].name;
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ (attId->name)[-1] = 1;
+ appAtts[attIndex++] = attId->name;
+ if (!atts[i].normalized) {
+ enum XML_Error result;
+ XML_Bool isCdata = XML_TRUE;
+
+ /* figure out whether declared as other than CDATA */
+ if (attId->maybeTokenized) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ if (attId == elementType->defaultAtts[j].id) {
+ isCdata = elementType->defaultAtts[j].isCdata;
+ break;
+ }
+ }
+ }
+
+ /* normalize the attribute value */
+ result = storeAttributeValue(parser, enc, isCdata,
+ atts[i].valuePtr, atts[i].valueEnd,
+ &tempPool);
+ if (result)
+ return result;
+ appAtts[attIndex] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ else {
+ /* the value did not need normalizing */
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr,
+ atts[i].valueEnd);
+ if (appAtts[attIndex] == 0)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ /* handle prefixed attribute names */
+ if (attId->prefix) {
+ if (attId->xmlns) {
+ /* deal with namespace declarations here */
+ enum XML_Error result = addBinding(parser, attId->prefix, attId,
+ appAtts[attIndex], bindingsPtr);
+ if (result)
+ return result;
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+#if 0
+ --attIndex;
+#else
+ attIndex++;
+ nXMLNSDeclarations++;
+ (attId->name)[-1] = 3;
+#endif
+/* END MOZILLA CHANGE */
+ }
+ else {
+ /* deal with other prefixed names later */
+ attIndex++;
+ nPrefixes++;
+ (attId->name)[-1] = 2;
+ }
+ }
+ else
+ attIndex++;
+ }
+
+ /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */
+ nSpecifiedAtts = attIndex;
+ if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
+ for (i = 0; i < attIndex; i += 2)
+ if (appAtts[i] == elementType->idAtt->name) {
+ idAttIndex = i;
+ break;
+ }
+ }
+ else
+ idAttIndex = -1;
+
+ /* do attribute defaulting */
+ for (i = 0; i < nDefaultAtts; i++) {
+ const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
+ if (!(da->id->name)[-1] && da->value) {
+ if (da->id->prefix) {
+ if (da->id->xmlns) {
+ enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
+ da->value, bindingsPtr);
+ if (result)
+ return result;
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+ (da->id->name)[-1] = 3;
+ nXMLNSDeclarations++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+/* END MOZILLA CHANGE */
+ }
+ else {
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ }
+ appAtts[attIndex] = 0;
+
+ /* expand prefixed attribute names, check for duplicates,
+ and clear flags that say whether attributes were specified */
+ i = 0;
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+#if 0
+ if (nPrefixes) {
+#else
+ if (nPrefixes || nXMLNSDeclarations) {
+#endif
+/* END MOZILLA CHANGE */
+ int j; /* hash table index */
+ unsigned long version = nsAttsVersion;
+
+ /* Detect and prevent invalid shift */
+ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ unsigned int nsAttsSize = 1u << nsAttsPower;
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+ if (nPrefixes) {
+/* END MOZILLA CHANGE */
+ unsigned char oldNsAttsPower = parser->m_nsAttsPower;
+ /* size of hash table must be at least 2 * (# of prefixed attributes) */
+ if ((nPrefixes << 1) >> nsAttsPower) { /* true for nsAttsPower = 0 */
+ NS_ATT *temp;
+ /* hash table size must also be a power of 2 and >= 8 */
+ while (nPrefixes >> nsAttsPower++);
+ if (nsAttsPower < 3)
+ nsAttsPower = 3;
+
+ /* Detect and prevent invalid shift */
+ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
+ /* Restore actual size of memory in m_nsAtts */
+ parser->m_nsAttsPower = oldNsAttsPower;
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ nsAttsSize = 1u << parser->m_nsAttsPower;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
+ /* Restore actual size of memory in m_nsAtts */
+ parser->m_nsAttsPower = oldNsAttsPower;
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
+ temp = (NS_ATT *)REALLOC(nsAtts, nsAttsSize * sizeof(NS_ATT));
+ if (!temp)
+ return XML_ERROR_NO_MEMORY;
+ nsAtts = temp;
+ version = 0; /* force re-initialization of nsAtts hash table */
+ }
+ /* using a version flag saves us from initializing nsAtts every time */
+ if (!version) { /* initialize version flags when version wraps around */
+ version = INIT_ATTS_VERSION;
+ for (j = nsAttsSize; j != 0; )
+ nsAtts[--j].version = version;
+ }
+ nsAttsVersion = --version;
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+ }
+/* END MOZILLA CHANGE */
+
+ /* expand prefixed names and check for duplicates */
+ for (; i < attIndex; i += 2) {
+ const XML_Char *s = appAtts[i];
+ if (s[-1] == 2) { /* prefixed */
+ ATTRIBUTE_ID *id;
+ const BINDING *b;
+ unsigned long uriHash;
+ struct siphash sip_state;
+ struct sipkey sip_key;
+
+ copy_salt_to_sipkey(parser, &sip_key);
+ sip24_init(&sip_state, &sip_key);
+
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
+ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
+ if (!id || !id->prefix)
+ return XML_ERROR_NO_MEMORY;
+ b = id->prefix->binding;
+ if (!b)
+ return XML_ERROR_UNBOUND_PREFIX;
+
+ for (j = 0; j < b->uriLen; j++) {
+ const XML_Char c = b->uri[j];
+ if (!poolAppendChar(&tempPool, c))
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
+
+ while (*s++ != XML_T(ASCII_COLON))
+ ;
+
+ sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
+
+ do { /* copies null terminator */
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+
+ uriHash = (unsigned long)sip24_final(&sip_state);
+
+ { /* Check hash table for duplicate of expanded name (uriName).
+ Derived from code in lookup(parser, HASH_TABLE *table, ...).
+ */
+ unsigned char step = 0;
+ unsigned long mask = nsAttsSize - 1;
+ j = uriHash & mask; /* index into hash table */
+ while (nsAtts[j].version == version) {
+ /* for speed we compare stored hash values first */
+ if (uriHash == nsAtts[j].hash) {
+ const XML_Char *s1 = poolStart(&tempPool);
+ const XML_Char *s2 = nsAtts[j].uriName;
+ /* s1 is null terminated, but not s2 */
+ for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
+ if (*s1 == 0)
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ if (!step)
+ step = PROBE_STEP(uriHash, mask, nsAttsPower);
+ j < step ? (j += nsAttsSize - step) : (j -= step);
+ }
+ }
+
+ if (ns_triplets) { /* append namespace separator and prefix */
+ tempPool.ptr[-1] = namespaceSeparator;
+ s = b->prefix->name;
+ do {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ }
+
+ /* store expanded name in attribute list */
+ s = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ appAtts[i] = s;
+
+ /* fill empty slot with new version, uriName and hash value */
+ nsAtts[j].version = version;
+ nsAtts[j].hash = uriHash;
+ nsAtts[j].uriName = s;
+
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+#if 0
+ if (!--nPrefixes) {
+#else
+ if (!--nPrefixes && !nXMLNSDeclarations) {
+#endif
+/* END MOZILLA CHANGE */
+ i += 2;
+ break;
+ }
+ }
+/* BEGIN MOZILLA CHANGE (Include xmlns attributes in attributes array) */
+ else if (s[-1] == 3) { /* xmlns attribute */
+ static const XML_Char xmlnsNamespace[] = {
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0, ASCII_0,
+ ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s, ASCII_SLASH, '\0'
+ };
+ static const XML_Char xmlnsPrefix[] = {
+ ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s, '\0'
+ };
+
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
+ if (!poolAppendString(&tempPool, xmlnsNamespace)
+ || !poolAppendChar(&tempPool, namespaceSeparator))
+ return XML_ERROR_NO_MEMORY;
+ s += sizeof(xmlnsPrefix) / sizeof(xmlnsPrefix[0]) - 1;
+ if (*s == XML_T(':')) {
+ ++s;
+ do { /* copies null terminator */
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ if (ns_triplets) { /* append namespace separator and prefix */
+ tempPool.ptr[-1] = namespaceSeparator;
+ if (!poolAppendString(&tempPool, xmlnsPrefix)
+ || !poolAppendChar(&tempPool, '\0'))
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ else {
+ /* xlmns attribute without a prefix. */
+ if (!poolAppendString(&tempPool, xmlnsPrefix)
+ || !poolAppendChar(&tempPool, '\0'))
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ /* store expanded name in attribute list */
+ s = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ appAtts[i] = s;
+
+ if (!--nXMLNSDeclarations && !nPrefixes) {
+ i += 2;
+ break;
+ }
+ }
+/* END MOZILLA CHANGE */
+ else /* not prefixed */
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
+ }
+ }
+ /* clear flags for the remaining attributes */
+ for (; i < attIndex; i += 2)
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+ binding->attId->name[-1] = 0;
+
+ if (!ns)
+ return XML_ERROR_NONE;
+
+ /* expand the element type name */
+ if (elementType->prefix) {
+ binding = elementType->prefix->binding;
+ if (!binding)
+ return XML_ERROR_UNBOUND_PREFIX;
+ localPart = tagNamePtr->str;
+ while (*localPart++ != XML_T(ASCII_COLON))
+ ;
+ }
+ else if (dtd->defaultPrefix.binding) {
+ binding = dtd->defaultPrefix.binding;
+ localPart = tagNamePtr->str;
+ }
+ else
+ return XML_ERROR_NONE;
+ prefixLen = 0;
+ if (ns_triplets && binding->prefix->name) {
+ for (; binding->prefix->name[prefixLen++];)
+ ; /* prefixLen includes null terminator */
+ }
+ tagNamePtr->localPart = localPart;
+ tagNamePtr->uriLen = binding->uriLen;
+ tagNamePtr->prefix = binding->prefix->name;
+ tagNamePtr->prefixLen = prefixLen;
+ for (i = 0; localPart[i++];)
+ ; /* i includes null terminator */
+
+ /* Detect and prevent integer overflow */
+ if (binding->uriLen > INT_MAX - prefixLen
+ || i > INT_MAX - (binding->uriLen + prefixLen)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ n = i + binding->uriLen + prefixLen;
+ if (n > binding->uriAlloc) {
+ TAG *p;
+
+ /* Detect and prevent integer overflow */
+ if (n > INT_MAX - EXPAND_SPARE) {
+ return XML_ERROR_NO_MEMORY;
+ }
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
+ uri = (XML_Char *)MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
+ if (!uri)
+ return XML_ERROR_NO_MEMORY;
+ binding->uriAlloc = n + EXPAND_SPARE;
+ memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
+ for (p = tagStack; p; p = p->parent)
+ if (p->name.str == binding->uri)
+ p->name.str = uri;
+ FREE(binding->uri);
+ binding->uri = uri;
+ }
+ /* if namespaceSeparator != '\0' then uri includes it already */
+ uri = binding->uri + binding->uriLen;
+ memcpy(uri, localPart, i * sizeof(XML_Char));
+ /* we always have a namespace separator between localPart and prefix */
+ if (prefixLen) {
+ uri += i - 1;
+ *uri = namespaceSeparator; /* replace null terminator */
+ memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
+ }
+ tagNamePtr->str = binding->uri;
+ return XML_ERROR_NONE;
+}
+
+/* addBinding() overwrites the value of prefix->binding without checking.
+ Therefore one must keep track of the old value outside of addBinding().
+*/
+static enum XML_Error
+addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
+ const XML_Char *uri, BINDING **bindingsPtr)
+{
+ static const XML_Char xmlNamespace[] = {
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
+ ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
+ ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
+ ASCII_e, '\0'
+ };
+ static const int xmlLen =
+ (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
+ static const XML_Char xmlnsNamespace[] = {
+ ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
+ ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
+ ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
+ ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
+ ASCII_SLASH, '\0'
+ };
+ static const int xmlnsLen =
+ (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
+
+ XML_Bool mustBeXML = XML_FALSE;
+ XML_Bool isXML = XML_TRUE;
+ XML_Bool isXMLNS = XML_TRUE;
+
+ BINDING *b;
+ int len;
+
+ /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */
+ if (*uri == XML_T('\0') && prefix->name)
+ return XML_ERROR_UNDECLARING_PREFIX;
+
+ if (prefix->name
+ && prefix->name[0] == XML_T(ASCII_x)
+ && prefix->name[1] == XML_T(ASCII_m)
+ && prefix->name[2] == XML_T(ASCII_l)) {
+
+ /* Not allowed to bind xmlns */
+ if (prefix->name[3] == XML_T(ASCII_n)
+ && prefix->name[4] == XML_T(ASCII_s)
+ && prefix->name[5] == XML_T('\0'))
+ return XML_ERROR_RESERVED_PREFIX_XMLNS;
+
+ if (prefix->name[3] == XML_T('\0'))
+ mustBeXML = XML_TRUE;
+ }
+
+ for (len = 0; uri[len]; len++) {
+ if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
+ isXML = XML_FALSE;
+
+ if (!mustBeXML && isXMLNS
+ && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
+ isXMLNS = XML_FALSE;
+ }
+ isXML = isXML && len == xmlLen;
+ isXMLNS = isXMLNS && len == xmlnsLen;
+
+ if (mustBeXML != isXML)
+ return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML
+ : XML_ERROR_RESERVED_NAMESPACE_URI;
+
+ if (isXMLNS)
+ return XML_ERROR_RESERVED_NAMESPACE_URI;
+
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ /* Detect and prevent integer overflow */
+ if (len > INT_MAX - EXPAND_SPARE) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
+ XML_Char *temp = (XML_Char *)REALLOC(b->uri,
+ sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ b->uri = temp;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
+ }
+ else {
+ b = (BINDING *)MALLOC(sizeof(BINDING));
+ if (!b)
+ return XML_ERROR_NO_MEMORY;
+
+ /* Detect and prevent integer overflow */
+ if (len > INT_MAX - EXPAND_SPARE) {
+ return XML_ERROR_NO_MEMORY;
+ }
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
+ b->uri = (XML_Char *)MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (!b->uri) {
+ FREE(b);
+ return XML_ERROR_NO_MEMORY;
+ }
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = prefix->binding;
+ /* NULL binding when default namespace undeclared */
+ if (*uri == XML_T('\0') && prefix == &_dtd->defaultPrefix)
+ prefix->binding = NULL;
+ else
+ prefix->binding = b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ /* if attId == NULL then we are not starting a namespace scope */
+ if (attId && startNamespaceDeclHandler)
+ startNamespaceDeclHandler(handlerArg, prefix->name,
+ prefix->binding ? uri : 0);
+ return XML_ERROR_NONE;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+ the whole file is parsed with one call.
+*/
+static enum XML_Error PTRCALL
+cdataSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doCdataSection(parser, encoding, &start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+ if (result != XML_ERROR_NONE)
+ return result;
+ if (start) {
+ if (parentParser) { /* we are parsing an external entity */
+ processor = externalEntityContentProcessor;
+ return externalEntityContentProcessor(parser, start, end, endPtr);
+ }
+ else {
+ processor = contentProcessor;
+ return contentProcessor(parser, start, end, endPtr);
+ }
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null if the section is closed, and to null if
+ the section is not yet closed.
+*/
+static enum XML_Error
+doCdataSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = NULL;
+
+ for (;;) {
+ const char *next;
+ int tok = XmlCdataSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_CDATA_SECT_CLOSE:
+ if (endCdataSectionHandler)
+ endCdataSectionHandler(handlerArg);
+#if 0
+ /* see comment under XML_TOK_CDATA_SECT_OPEN */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ *nextPtr = next;
+ if (ps_parsing == XML_FINISHED)
+ return XML_ERROR_ABORTED;
+ else
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_DATA_CHARS:
+ {
+ XML_CharacterDataHandler charDataHandler = characterDataHandler;
+ if (charDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = next;
+ charDataHandler(handlerArg, dataBuf,
+ (int)(dataPtr - (ICHAR *)dataBuf));
+ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ charDataHandler(handlerArg,
+ (XML_Char *)s,
+ (int)((XML_Char *)next - (XML_Char *)s));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_CDATA_SECTION;
+ default:
+ *eventPP = next;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+
+ *eventPP = s = next;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default: ;
+ }
+ }
+ /* not reached */
+}
+
+#ifdef XML_DTD
+
+/* The idea here is to avoid using stack for each IGNORE section when
+ the whole file is parsed with one call.
+*/
+static enum XML_Error PTRCALL
+ignoreSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
+ endPtr, (XML_Bool)!ps_finalBuffer);
+ if (result != XML_ERROR_NONE)
+ return result;
+ if (start) {
+ processor = prologProcessor;
+ return prologProcessor(parser, start, end, endPtr);
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null
+ if the section is not yet closed.
+*/
+static enum XML_Error
+doIgnoreSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr,
+ XML_Bool haveMore)
+{
+ const char *next;
+ int tok;
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = NULL;
+ tok = XmlIgnoreSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_IGNORE_SECT:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ *nextPtr = next;
+ if (ps_parsing == XML_FINISHED)
+ return XML_ERROR_ABORTED;
+ else
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (haveMore) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
+ default:
+ *eventPP = next;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ /* not reached */
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+ const char *s;
+#ifdef XML_UNICODE
+ char encodingBuf[128];
+ if (!protocolEncodingName)
+ s = NULL;
+ else {
+ int i;
+ for (i = 0; protocolEncodingName[i]; i++) {
+ if (i == sizeof(encodingBuf) - 1
+ || (protocolEncodingName[i] & ~0x7f) != 0) {
+ encodingBuf[0] = '\0';
+ break;
+ }
+ encodingBuf[i] = (char)protocolEncodingName[i];
+ }
+ encodingBuf[i] = '\0';
+ s = encodingBuf;
+ }
+#else
+ s = protocolEncodingName;
+#endif
+ if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+ return XML_ERROR_NONE;
+ return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next)
+{
+ const char *encodingName = NULL;
+ const XML_Char *storedEncName = NULL;
+ const ENCODING *newEncoding = NULL;
+ const char *version = NULL;
+ const char *versionend;
+ const XML_Char *storedversion = NULL;
+ int standalone = -1;
+ if (!(ns
+ ? XmlParseXmlDeclNS
+ : XmlParseXmlDecl)(isGeneralTextEntity,
+ encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &versionend,
+ &encodingName,
+ &newEncoding,
+ &standalone)) {
+ if (isGeneralTextEntity)
+ return XML_ERROR_TEXT_DECL;
+ else
+ return XML_ERROR_XML_DECL;
+ }
+ if (!isGeneralTextEntity && standalone == 1) {
+ _dtd->standalone = XML_TRUE;
+#ifdef XML_DTD
+ if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif /* XML_DTD */
+ }
+ if (xmlDeclHandler) {
+ if (encodingName != NULL) {
+ storedEncName = poolStoreString(&temp2Pool,
+ encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(encoding, encodingName));
+ if (!storedEncName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&temp2Pool);
+ }
+ if (version) {
+ storedversion = poolStoreString(&temp2Pool,
+ encoding,
+ version,
+ versionend - encoding->minBytesPerChar);
+ if (!storedversion)
+ return XML_ERROR_NO_MEMORY;
+ }
+ xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ if (protocolEncodingName == NULL) {
+ if (newEncoding) {
+ if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+ eventPtr = encodingName;
+ return XML_ERROR_INCORRECT_ENCODING;
+ }
+ encoding = newEncoding;
+ }
+ else if (encodingName) {
+ enum XML_Error result;
+ if (!storedEncName) {
+ storedEncName = poolStoreString(
+ &temp2Pool, encoding, encodingName,
+ encodingName + XmlNameLength(encoding, encodingName));
+ if (!storedEncName)
+ return XML_ERROR_NO_MEMORY;
+ }
+ result = handleUnknownEncoding(parser, storedEncName);
+ poolClear(&temp2Pool);
+ if (result == XML_ERROR_UNKNOWN_ENCODING)
+ eventPtr = encodingName;
+ return result;
+ }
+ }
+
+ if (storedEncName || storedversion)
+ poolClear(&temp2Pool);
+
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (unknownEncodingHandler) {
+ XML_Encoding info;
+ int i;
+ for (i = 0; i < 256; i++)
+ info.map[i] = -1;
+ info.convert = NULL;
+ info.data = NULL;
+ info.release = NULL;
+ if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName,
+ &info)) {
+ ENCODING *enc;
+ unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
+ if (!unknownEncodingMem) {
+ if (info.release)
+ info.release(info.data);
+ return XML_ERROR_NO_MEMORY;
+ }
+ enc = (ns
+ ? XmlInitUnknownEncodingNS
+ : XmlInitUnknownEncoding)(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data);
+ if (enc) {
+ unknownEncodingData = info.data;
+ unknownEncodingRelease = info.release;
+ encoding = enc;
+ return XML_ERROR_NONE;
+ }
+ }
+ if (info.release != NULL)
+ info.release(info.data);
+ }
+ return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error PTRCALL
+prologInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = prologProcessor;
+ return prologProcessor(parser, s, end, nextPtr);
+}
+
+#ifdef XML_DTD
+
+static enum XML_Error PTRCALL
+externalParEntInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+
+ /* we know now that XML_Parse(Buffer) has been called,
+ so we consider the external parameter entity read */
+ _dtd->paramEntityRead = XML_TRUE;
+
+ if (prologState.inEntityValue) {
+ processor = entityValueInitProcessor;
+ return entityValueInitProcessor(parser, s, end, nextPtr);
+ }
+ else {
+ processor = externalParEntProcessor;
+ return externalParEntProcessor(parser, s, end, nextPtr);
+ }
+}
+
+static enum XML_Error PTRCALL
+entityValueInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ int tok;
+ const char *start = s;
+ const char *next = start;
+ eventPtr = start;
+
+ for (;;) {
+ tok = XmlPrologTok(encoding, start, end, &next);
+ eventEndPtr = next;
+ if (tok <= 0) {
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE: /* start == end */
+ default:
+ break;
+ }
+ /* found end of entity value - can store it now */
+ return storeEntityValue(parser, encoding, s, end);
+ }
+ else if (tok == XML_TOK_XML_DECL) {
+ enum XML_Error result;
+ result = processXmlDecl(parser, 0, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ *nextPtr = next;
+ }
+ /* stop scanning for text declaration - we found one */
+ processor = entityValueProcessor;
+ return entityValueProcessor(parser, next, end, nextPtr);
+ }
+ /* If we are at the end of the buffer, this would cause XmlPrologTok to
+ return XML_TOK_NONE on the next call, which would then cause the
+ function to exit with *nextPtr set to s - that is what we want for other
+ tokens, but not for the BOM - we would rather like to skip it;
+ then, when this routine is entered the next time, XmlPrologTok will
+ return XML_TOK_INVALID, since the BOM is still in the buffer
+ */
+ else if (tok == XML_TOK_BOM && next == end && !ps_finalBuffer) {
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ }
+ /* If we get this token, we have the start of what might be a
+ normal tag, but not a declaration (i.e. it doesn't begin with
+ "<!"). In a DTD context, that isn't legal.
+ */
+ else if (tok == XML_TOK_INSTANCE_START) {
+ *nextPtr = next;
+ return XML_ERROR_SYNTAX;
+ }
+ start = next;
+ eventPtr = start;
+ }
+}
+
+static enum XML_Error PTRCALL
+externalParEntProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *next = s;
+ int tok;
+
+ tok = XmlPrologTok(encoding, s, end, &next);
+ if (tok <= 0) {
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE: /* start == end */
+ default:
+ break;
+ }
+ }
+ /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
+ However, when parsing an external subset, doProlog will not accept a BOM
+ as valid, and report a syntax error, so we have to skip the BOM
+ */
+ else if (tok == XML_TOK_BOM) {
+ s = next;
+ tok = XmlPrologTok(encoding, s, end, &next);
+ }
+
+ processor = prologProcessor;
+ return doProlog(parser, encoding, s, end, tok, next,
+ nextPtr, (XML_Bool)!ps_finalBuffer, XML_TRUE);
+}
+
+static enum XML_Error PTRCALL
+entityValueProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *start = s;
+ const char *next = s;
+ const ENCODING *enc = encoding;
+ int tok;
+
+ for (;;) {
+ tok = XmlPrologTok(enc, start, end, &next);
+ if (tok <= 0) {
+ if (!ps_finalBuffer && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE: /* start == end */
+ default:
+ break;
+ }
+ /* found end of entity value - can store it now */
+ return storeEntityValue(parser, enc, s, end);
+ }
+ start = next;
+ }
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error PTRCALL
+prologProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *next = s;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ return doProlog(parser, encoding, s, end, tok, next,
+ nextPtr, (XML_Bool)!ps_finalBuffer, XML_TRUE);
+}
+
+static enum XML_Error
+doProlog(XML_Parser parser,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ int tok,
+ const char *next,
+ const char **nextPtr,
+ XML_Bool haveMore,
+ XML_Bool allowClosingDoctype)
+{
+#ifdef XML_DTD
+ static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
+#endif /* XML_DTD */
+ static const XML_Char atypeCDATA[] =
+ { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+ static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
+ static const XML_Char atypeIDREF[] =
+ { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+ static const XML_Char atypeIDREFS[] =
+ { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+ static const XML_Char atypeENTITY[] =
+ { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+ static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
+ ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
+ static const XML_Char atypeNMTOKEN[] = {
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+ static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
+ ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
+ static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
+ ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
+ static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
+ static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
+
+ /* save one level of indirection */
+ DTD * const dtd = _dtd;
+
+ const char **eventPP;
+ const char **eventEndPP;
+ enum XML_Content_Quant quant;
+
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+
+ for (;;) {
+ int role;
+ XML_Bool handleDefault = XML_TRUE;
+ *eventPP = s;
+ *eventEndPP = next;
+ if (tok <= 0) {
+ if (haveMore && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE:
+#ifdef XML_DTD
+ /* for internal PE NOT referenced between declarations */
+ if (enc != encoding && !openInternalEntities->betweenDecl) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ /* WFC: PE Between Declarations - must check that PE contains
+ complete markup, not only for external PEs, but also for
+ internal PEs if the reference occurs between declarations.
+ */
+ if (isParamEntity || enc != encoding) {
+ if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
+ == XML_ROLE_ERROR)
+ return XML_ERROR_INCOMPLETE_PE;
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+#endif /* XML_DTD */
+ return XML_ERROR_NO_ELEMENTS;
+ default:
+ tok = -tok;
+ next = end;
+ break;
+ }
+ }
+ role = XmlTokenRole(&prologState, tok, s, next, enc);
+ switch (role) {
+ case XML_ROLE_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = encoding;
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_NAME:
+ if (startDoctypeDeclHandler) {
+ doctypeName = poolStoreString(&tempPool, enc, s, next);
+ if (!doctypeName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ doctypePubid = NULL;
+ handleDefault = XML_FALSE;
+ }
+ doctypeSysid = NULL; /* always initialize to NULL */
+ break;
+ case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
+ if (startDoctypeDeclHandler) {
+ startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
+ doctypePubid, 1);
+ doctypeName = NULL;
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ break;
+#ifdef XML_DTD
+ case XML_ROLE_TEXT_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 1, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = encoding;
+ handleDefault = XML_FALSE;
+ }
+ break;
+#endif /* XML_DTD */
+ case XML_ROLE_DOCTYPE_PUBLIC_ID:
+#ifdef XML_DTD
+ useForeignDTD = XML_FALSE;
+ declEntity = (ENTITY *)lookup(parser,
+ &dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+#endif /* XML_DTD */
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (startDoctypeDeclHandler) {
+ XML_Char *pubId;
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_PUBLICID;
+ pubId = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!pubId)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(pubId);
+ poolFinish(&tempPool);
+ doctypePubid = pubId;
+ handleDefault = XML_FALSE;
+ goto alreadyChecked;
+ }
+ /* fall through */
+ case XML_ROLE_ENTITY_PUBLIC_ID:
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_PUBLICID;
+ alreadyChecked:
+ if (dtd->keepProcessing && declEntity) {
+ XML_Char *tem = poolStoreString(&dtd->pool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declEntity->publicId = tem;
+ poolFinish(&dtd->pool);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_CLOSE:
+ if (allowClosingDoctype != XML_TRUE) {
+ /* Must not close doctype from within expanded parameter entities */
+ return XML_ERROR_INVALID_TOKEN;
+ }
+
+ if (doctypeName) {
+ startDoctypeDeclHandler(handlerArg, doctypeName,
+ doctypeSysid, doctypePubid, 0);
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ /* doctypeSysid will be non-NULL in the case of a previous
+ XML_ROLE_DOCTYPE_SYSTEM_ID, even if startDoctypeDeclHandler
+ was not set, indicating an external subset
+ */
+#ifdef XML_DTD
+ if (doctypeSysid || useForeignDTD) {
+ XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (paramEntityParsing && externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(parser,
+ &dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!entity)
+ return XML_ERROR_NO_MEMORY;
+ if (useForeignDTD)
+ entity->base = curBase;
+ dtd->paramEntityRead = XML_FALSE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ if (dtd->paramEntityRead) {
+ if (!dtd->standalone &&
+ notStandaloneHandler &&
+ !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ }
+ /* if we didn't read the foreign DTD then this means that there
+ is no external subset and we must reset dtd->hasParamEntityRefs
+ */
+ else if (!doctypeSysid)
+ dtd->hasParamEntityRefs = hadParamEntityRefs;
+ /* end of DTD - no need to update dtd->keepProcessing */
+ }
+ useForeignDTD = XML_FALSE;
+ }
+#endif /* XML_DTD */
+ if (endDoctypeDeclHandler) {
+ endDoctypeDeclHandler(handlerArg);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_INSTANCE_START:
+#ifdef XML_DTD
+ /* if there is no DOCTYPE declaration then now is the
+ last chance to read the foreign DTD
+ */
+ if (useForeignDTD) {
+ XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (paramEntityParsing && externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!entity)
+ return XML_ERROR_NO_MEMORY;
+ entity->base = curBase;
+ dtd->paramEntityRead = XML_FALSE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ if (dtd->paramEntityRead) {
+ if (!dtd->standalone &&
+ notStandaloneHandler &&
+ !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ }
+ /* if we didn't read the foreign DTD then this means that there
+ is no external subset and we must reset dtd->hasParamEntityRefs
+ */
+ else
+ dtd->hasParamEntityRefs = hadParamEntityRefs;
+ /* end of DTD - no need to update dtd->keepProcessing */
+ }
+ }
+#endif /* XML_DTD */
+ processor = contentProcessor;
+ return contentProcessor(parser, s, end, nextPtr);
+ case XML_ROLE_ATTLIST_ELEMENT_NAME:
+ declElementType = getElementType(parser, enc, s, next);
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_NAME:
+ declAttributeId = getAttributeId(parser, enc, s, next);
+ if (!declAttributeId)
+ return XML_ERROR_NO_MEMORY;
+ declAttributeIsCdata = XML_FALSE;
+ declAttributeType = NULL;
+ declAttributeIsId = XML_FALSE;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+ declAttributeIsCdata = XML_TRUE;
+ declAttributeType = atypeCDATA;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_ID:
+ declAttributeIsId = XML_TRUE;
+ declAttributeType = atypeID;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
+ declAttributeType = atypeIDREF;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
+ declAttributeType = atypeIDREFS;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
+ declAttributeType = atypeENTITY;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
+ declAttributeType = atypeENTITIES;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
+ declAttributeType = atypeNMTOKEN;
+ goto checkAttListDeclHandler;
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
+ declAttributeType = atypeNMTOKENS;
+ checkAttListDeclHandler:
+ if (dtd->keepProcessing && attlistDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
+ case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
+ if (dtd->keepProcessing && attlistDeclHandler) {
+ const XML_Char *prefix;
+ if (declAttributeType) {
+ prefix = enumValueSep;
+ }
+ else {
+ prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
+ ? notationPrefix
+ : enumValueStart);
+ }
+ if (!poolAppendString(&tempPool, prefix))
+ return XML_ERROR_NO_MEMORY;
+ if (!poolAppend(&tempPool, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+ case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+ if (dtd->keepProcessing) {
+ if (!defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata, declAttributeIsId,
+ 0, parser))
+ return XML_ERROR_NO_MEMORY;
+ if (attlistDeclHandler && declAttributeType) {
+ if (*declAttributeType == XML_T(ASCII_LPAREN)
+ || (*declAttributeType == XML_T(ASCII_N)
+ && declAttributeType[1] == XML_T(ASCII_O))) {
+ /* Enumerated or Notation type */
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
+ || !poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ poolFinish(&tempPool);
+ }
+ *eventEndPP = s;
+ attlistDeclHandler(handlerArg, declElementType->name,
+ declAttributeId->name, declAttributeType,
+ 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ }
+ break;
+ case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+ case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+ if (dtd->keepProcessing) {
+ const XML_Char *attVal;
+ enum XML_Error result =
+ storeAttributeValue(parser, enc, declAttributeIsCdata,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar,
+ &dtd->pool);
+ if (result)
+ return result;
+ attVal = poolStart(&dtd->pool);
+ poolFinish(&dtd->pool);
+ /* ID attributes aren't allowed to have a default */
+ if (!defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata, XML_FALSE, attVal, parser))
+ return XML_ERROR_NO_MEMORY;
+ if (attlistDeclHandler && declAttributeType) {
+ if (*declAttributeType == XML_T(ASCII_LPAREN)
+ || (*declAttributeType == XML_T(ASCII_N)
+ && declAttributeType[1] == XML_T(ASCII_O))) {
+ /* Enumerated or Notation type */
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_RPAREN))
+ || !poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ poolFinish(&tempPool);
+ }
+ *eventEndPP = s;
+ attlistDeclHandler(handlerArg, declElementType->name,
+ declAttributeId->name, declAttributeType,
+ attVal,
+ role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
+ poolClear(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ }
+ break;
+ case XML_ROLE_ENTITY_VALUE:
+ if (dtd->keepProcessing) {
+ enum XML_Error result = storeEntityValue(parser, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (declEntity) {
+ declEntity->textPtr = poolStart(&dtd->entityValuePool);
+ declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
+ poolFinish(&dtd->entityValuePool);
+ if (entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->is_param,
+ declEntity->textPtr,
+ declEntity->textLen,
+ curBase, 0, 0, 0);
+ handleDefault = XML_FALSE;
+ }
+ }
+ else
+ poolDiscard(&dtd->entityValuePool);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_SYSTEM_ID:
+#ifdef XML_DTD
+ useForeignDTD = XML_FALSE;
+#endif /* XML_DTD */
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (startDoctypeDeclHandler) {
+ doctypeSysid = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (doctypeSysid == NULL)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+#ifdef XML_DTD
+ else
+ /* use externalSubsetName to make doctypeSysid non-NULL
+ for the case where no startDoctypeDeclHandler is set */
+ doctypeSysid = externalSubsetName;
+#endif /* XML_DTD */
+ if (!dtd->standalone
+#ifdef XML_DTD
+ && !paramEntityParsing
+#endif /* XML_DTD */
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+#ifndef XML_DTD
+ break;
+#else /* XML_DTD */
+ if (!declEntity) {
+ declEntity = (ENTITY *)lookup(parser,
+ &dtd->paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->publicId = NULL;
+ }
+ /* fall through */
+#endif /* XML_DTD */
+ case XML_ROLE_ENTITY_SYSTEM_ID:
+ if (dtd->keepProcessing && declEntity) {
+ declEntity->systemId = poolStoreString(&dtd->pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!declEntity->systemId)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->base = curBase;
+ poolFinish(&dtd->pool);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_ENTITY_COMPLETE:
+ if (dtd->keepProcessing && declEntity && entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->is_param,
+ 0,0,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ 0);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_ENTITY_NOTATION_NAME:
+ if (dtd->keepProcessing && declEntity) {
+ declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
+ if (!declEntity->notation)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&dtd->pool);
+ if (unparsedEntityDeclHandler) {
+ *eventEndPP = s;
+ unparsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ handleDefault = XML_FALSE;
+ }
+ else if (entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ 0,0,0,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ handleDefault = XML_FALSE;
+ }
+ }
+ break;
+ case XML_ROLE_GENERAL_ENTITY_NAME:
+ {
+ if (XmlPredefinedEntityName(enc, s, next)) {
+ declEntity = NULL;
+ break;
+ }
+ if (dtd->keepProcessing) {
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+ else {
+ poolFinish(&dtd->pool);
+ declEntity->publicId = NULL;
+ declEntity->is_param = XML_FALSE;
+ /* if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal"
+ */
+ declEntity->is_internal = !(parentParser || openInternalEntities);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ }
+ else {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+ }
+ break;
+ case XML_ROLE_PARAM_ENTITY_NAME:
+#ifdef XML_DTD
+ if (dtd->keepProcessing) {
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
+ name, sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+ else {
+ poolFinish(&dtd->pool);
+ declEntity->publicId = NULL;
+ declEntity->is_param = XML_TRUE;
+ /* if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal"
+ */
+ declEntity->is_internal = !(parentParser || openInternalEntities);
+ if (entityDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ }
+ else {
+ poolDiscard(&dtd->pool);
+ declEntity = NULL;
+ }
+#else /* not XML_DTD */
+ declEntity = NULL;
+#endif /* XML_DTD */
+ break;
+ case XML_ROLE_NOTATION_NAME:
+ declNotationPublicId = NULL;
+ declNotationName = NULL;
+ if (notationDeclHandler) {
+ declNotationName = poolStoreString(&tempPool, enc, s, next);
+ if (!declNotationName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_NOTATION_PUBLIC_ID:
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_PUBLICID;
+ if (declNotationName) { /* means notationDeclHandler != NULL */
+ XML_Char *tem = poolStoreString(&tempPool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declNotationPublicId = tem;
+ poolFinish(&tempPool);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_NOTATION_SYSTEM_ID:
+ if (declNotationName && notationDeclHandler) {
+ const XML_Char *systemId
+ = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!systemId)
+ return XML_ERROR_NO_MEMORY;
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ systemId,
+ declNotationPublicId);
+ handleDefault = XML_FALSE;
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+ if (declNotationPublicId && notationDeclHandler) {
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ 0,
+ declNotationPublicId);
+ handleDefault = XML_FALSE;
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_ERROR:
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ /* PE references in internal subset are
+ not allowed within declarations. */
+ return XML_ERROR_PARAM_ENTITY_REF;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ default:
+ return XML_ERROR_SYNTAX;
+ }
+#ifdef XML_DTD
+ case XML_ROLE_IGNORE_SECT:
+ {
+ enum XML_Error result;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ handleDefault = XML_FALSE;
+ result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (!next) {
+ processor = ignoreSectionProcessor;
+ return result;
+ }
+ }
+ break;
+#endif /* XML_DTD */
+ case XML_ROLE_GROUP_OPEN:
+ if (prologState.level >= groupSize) {
+ if (groupSize) {
+ /* Detect and prevent integer overflow */
+ if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ char *temp = (char *)REALLOC(groupConnector, groupSize *= 2);
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ groupConnector = temp;
+ if (dtd->scaffIndex) {
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
+ return XML_ERROR_NO_MEMORY;
+ }
+#endif
+
+ int *temp = (int *)REALLOC(dtd->scaffIndex,
+ groupSize * sizeof(int));
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffIndex = temp;
+ }
+ }
+ else {
+ groupConnector = (char *)MALLOC(groupSize = 32);
+ if (!groupConnector)
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ groupConnector[prologState.level] = 0;
+ if (dtd->in_eldecl) {
+ int myindex = nextScaffoldPart(parser);
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffIndex[dtd->scaffLevel] = myindex;
+ dtd->scaffLevel++;
+ dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+ case XML_ROLE_GROUP_SEQUENCE:
+ if (groupConnector[prologState.level] == ASCII_PIPE)
+ return XML_ERROR_SYNTAX;
+ groupConnector[prologState.level] = ASCII_COMMA;
+ if (dtd->in_eldecl && elementDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_GROUP_CHOICE:
+ if (groupConnector[prologState.level] == ASCII_COMMA)
+ return XML_ERROR_SYNTAX;
+ if (dtd->in_eldecl
+ && !groupConnector[prologState.level]
+ && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
+ != XML_CTYPE_MIXED)
+ ) {
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
+ = XML_CTYPE_CHOICE;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ groupConnector[prologState.level] = ASCII_PIPE;
+ break;
+ case XML_ROLE_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+ case XML_ROLE_INNER_PARAM_ENTITY_REF:
+ dtd->hasParamEntityRefs = XML_TRUE;
+ if (!paramEntityParsing)
+ dtd->keepProcessing = dtd->standalone;
+ else {
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&dtd->pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
+ poolDiscard(&dtd->pool);
+ /* first, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity handler
+ */
+ if (prologState.documentEntity &&
+ (dtd->standalone
+ ? !openInternalEntities
+ : !dtd->hasParamEntityRefs)) {
+ if (!entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (!entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ }
+ else if (!entity) {
+ dtd->keepProcessing = dtd->standalone;
+ /* cannot report skipped entities in declarations */
+ if ((role == XML_ROLE_PARAM_ENTITY_REF) && skippedEntityHandler) {
+ skippedEntityHandler(handlerArg, name, 1);
+ handleDefault = XML_FALSE;
+ }
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->textPtr) {
+ enum XML_Error result;
+ XML_Bool betweenDecl =
+ (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
+ result = processInternalEntity(parser, entity, betweenDecl);
+ if (result != XML_ERROR_NONE)
+ return result;
+ handleDefault = XML_FALSE;
+ break;
+ }
+ if (externalEntityRefHandler) {
+ dtd->paramEntityRead = XML_FALSE;
+ entity->open = XML_TRUE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+/* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=191482) */
+#if 0
+ 0,
+#else
+ entity->name,
+#endif
+/* END MOZILLA CHANGE */
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ entity->open = XML_FALSE;
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ }
+ entity->open = XML_FALSE;
+ handleDefault = XML_FALSE;
+ if (!dtd->paramEntityRead) {
+ dtd->keepProcessing = dtd->standalone;
+ break;
+ }
+ }
+ else {
+ dtd->keepProcessing = dtd->standalone;
+ break;
+ }
+ }
+#endif /* XML_DTD */
+ if (!dtd->standalone &&
+ notStandaloneHandler &&
+ !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ break;
+
+ /* Element declaration stuff */
+
+ case XML_ROLE_ELEMENT_NAME:
+ if (elementDeclHandler) {
+ declElementType = getElementType(parser, enc, s, next);
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffLevel = 0;
+ dtd->scaffCount = 0;
+ dtd->in_eldecl = XML_TRUE;
+ handleDefault = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_ANY:
+ case XML_ROLE_CONTENT_EMPTY:
+ if (dtd->in_eldecl) {
+ if (elementDeclHandler) {
+ XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
+ if (!content)
+ return XML_ERROR_NO_MEMORY;
+ content->quant = XML_CQUANT_NONE;
+ content->name = NULL;
+ content->numchildren = 0;
+ content->children = NULL;
+ content->type = ((role == XML_ROLE_CONTENT_ANY) ?
+ XML_CTYPE_ANY :
+ XML_CTYPE_EMPTY);
+ *eventEndPP = s;
+ elementDeclHandler(handlerArg, declElementType->name, content);
+ handleDefault = XML_FALSE;
+ }
+ dtd->in_eldecl = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_PCDATA:
+ if (dtd->in_eldecl) {
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
+ = XML_CTYPE_MIXED;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_ELEMENT:
+ quant = XML_CQUANT_NONE;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_OPT:
+ quant = XML_CQUANT_OPT;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_REP:
+ quant = XML_CQUANT_REP;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_PLUS:
+ quant = XML_CQUANT_PLUS;
+ elementContent:
+ if (dtd->in_eldecl) {
+ ELEMENT_TYPE *el;
+ const XML_Char *name;
+ int nameLen;
+ const char *nxt = (quant == XML_CQUANT_NONE
+ ? next
+ : next - enc->minBytesPerChar);
+ int myindex = nextScaffoldPart(parser);
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ dtd->scaffold[myindex].type = XML_CTYPE_NAME;
+ dtd->scaffold[myindex].quant = quant;
+ el = getElementType(parser, enc, s, nxt);
+ if (!el)
+ return XML_ERROR_NO_MEMORY;
+ name = el->name;
+ dtd->scaffold[myindex].name = name;
+ nameLen = 0;
+ for (; name[nameLen++]; );
+ dtd->contentStringLen += nameLen;
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ }
+ break;
+
+ case XML_ROLE_GROUP_CLOSE:
+ quant = XML_CQUANT_NONE;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_OPT:
+ quant = XML_CQUANT_OPT;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_REP:
+ quant = XML_CQUANT_REP;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_PLUS:
+ quant = XML_CQUANT_PLUS;
+ closeGroup:
+ if (dtd->in_eldecl) {
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ dtd->scaffLevel--;
+ dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
+ if (dtd->scaffLevel == 0) {
+ if (!handleDefault) {
+ XML_Content *model = build_model(parser);
+ if (!model)
+ return XML_ERROR_NO_MEMORY;
+ *eventEndPP = s;
+ elementDeclHandler(handlerArg, declElementType->name, model);
+ }
+ dtd->in_eldecl = XML_FALSE;
+ dtd->contentStringLen = 0;
+ }
+ }
+ break;
+ /* End element declaration stuff */
+
+ case XML_ROLE_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_NONE:
+ switch (tok) {
+ case XML_TOK_BOM:
+ handleDefault = XML_FALSE;
+ break;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_NONE:
+ if (startDoctypeDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ENTITY_NONE:
+ if (dtd->keepProcessing && entityDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_NOTATION_NONE:
+ if (notationDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ATTLIST_NONE:
+ if (dtd->keepProcessing && attlistDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ case XML_ROLE_ELEMENT_NONE:
+ if (elementDeclHandler)
+ handleDefault = XML_FALSE;
+ break;
+ } /* end of big switch */
+
+ if (handleDefault && defaultHandler)
+ reportDefault(parser, enc, s, next);
+
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ s = next;
+ tok = XmlPrologTok(enc, s, end, &next);
+ }
+ }
+ /* not reached */
+}
+
+static enum XML_Error PTRCALL
+epilogProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ processor = epilogProcessor;
+ eventPtr = s;
+ for (;;) {
+ const char *next = NULL;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ eventEndPtr = next;
+ switch (tok) {
+ /* report partial linebreak - it might be the last token */
+ case -XML_TOK_PROLOG_S:
+ if (defaultHandler) {
+ reportDefault(parser, encoding, s, next);
+ if (ps_parsing == XML_FINISHED)
+ return XML_ERROR_ABORTED;
+ }
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ case XML_TOK_PROLOG_S:
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (!ps_finalBuffer) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (!ps_finalBuffer) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ default:
+ return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+ }
+ eventPtr = s = next;
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ *nextPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default: ;
+ }
+ }
+}
+
+static enum XML_Error
+processInternalEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl)
+{
+ const char *textStart, *textEnd;
+ const char *next;
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY *openEntity;
+
+ if (freeInternalEntities) {
+ openEntity = freeInternalEntities;
+ freeInternalEntities = openEntity->next;
+ }
+ else {
+ openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(sizeof(OPEN_INTERNAL_ENTITY));
+ if (!openEntity)
+ return XML_ERROR_NO_MEMORY;
+ }
+ entity->open = XML_TRUE;
+ entity->processed = 0;
+ openEntity->next = openInternalEntities;
+ openInternalEntities = openEntity;
+ openEntity->entity = entity;
+ openEntity->startTagLevel = tagLevel;
+ openEntity->betweenDecl = betweenDecl;
+ openEntity->internalEventPtr = NULL;
+ openEntity->internalEventEndPtr = NULL;
+ textStart = (char *)entity->textPtr;
+ textEnd = (char *)(entity->textPtr + entity->textLen);
+ /* Set a safe default value in case 'next' does not get set */
+ next = textStart;
+
+#ifdef XML_DTD
+ if (entity->is_param) {
+ int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
+ result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
+ next, &next, XML_FALSE, XML_FALSE);
+ }
+ else
+#endif /* XML_DTD */
+ result = doContent(parser, tagLevel, internalEncoding, textStart,
+ textEnd, &next, XML_FALSE);
+
+ if (result == XML_ERROR_NONE) {
+ if (textEnd != next && ps_parsing == XML_SUSPENDED) {
+ entity->processed = (int)(next - textStart);
+ processor = internalEntityProcessor;
+ }
+ else {
+ entity->open = XML_FALSE;
+/* BEGIN MOZILLA CHANGE (Deal with parser interruption from nested entities) */
+#if 0
+ openInternalEntities = openEntity->next;
+#else
+ if (openInternalEntities == openEntity) {
+ openInternalEntities = openEntity->next;
+ }
+ else {
+ /* openEntity should be closed, but it contains an inner entity that is
+ still open. Remove openEntity from the openInternalEntities linked
+ list by looking for the inner entity in the list that links to
+ openEntity and fixing up its 'next' member
+ */
+ OPEN_INTERNAL_ENTITY *innerOpenEntity = openInternalEntities;
+ do {
+ if (innerOpenEntity->next == openEntity) {
+ innerOpenEntity->next = openEntity->next;
+ break;
+ }
+ } while ((innerOpenEntity = innerOpenEntity->next));
+ }
+#endif
+/* END MOZILLA CHANGE */
+ /* put openEntity back in list of free instances */
+ openEntity->next = freeInternalEntities;
+ freeInternalEntities = openEntity;
+ }
+ }
+ return result;
+}
+
+static enum XML_Error PTRCALL
+internalEntityProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ ENTITY *entity;
+ const char *textStart, *textEnd;
+ const char *next;
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY *openEntity = openInternalEntities;
+ if (!openEntity)
+ return XML_ERROR_UNEXPECTED_STATE;
+
+ entity = openEntity->entity;
+ textStart = ((char *)entity->textPtr) + entity->processed;
+ textEnd = (char *)(entity->textPtr + entity->textLen);
+ /* Set a safe default value in case 'next' does not get set */
+ next = textStart;
+
+#ifdef XML_DTD
+ if (entity->is_param) {
+ int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
+ result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
+ next, &next, XML_FALSE, XML_TRUE);
+ }
+ else
+#endif /* XML_DTD */
+ result = doContent(parser, openEntity->startTagLevel, internalEncoding,
+ textStart, textEnd, &next, XML_FALSE);
+
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (textEnd != next && ps_parsing == XML_SUSPENDED) {
+ entity->processed = (int)(next - (char *)entity->textPtr);
+ return result;
+ }
+ else {
+ entity->open = XML_FALSE;
+ openInternalEntities = openEntity->next;
+ /* put openEntity back in list of free instances */
+ openEntity->next = freeInternalEntities;
+ freeInternalEntities = openEntity;
+ }
+
+#ifdef XML_DTD
+ if (entity->is_param) {
+ int tok;
+ processor = prologProcessor;
+ tok = XmlPrologTok(encoding, s, end, &next);
+ return doProlog(parser, encoding, s, end, tok, next, nextPtr,
+ (XML_Bool)!ps_finalBuffer, XML_TRUE);
+ }
+ else
+#endif /* XML_DTD */
+ {
+ processor = contentProcessor;
+ /* see externalEntityContentProcessor vs contentProcessor */
+ result = doContent(parser, parser->m_parentParser ? 1 : 0,
+ parser->m_encoding, s, end, nextPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer);
+ if (result == XML_ERROR_NONE) {
+ if (! storeRawNames(parser))
+ return XML_ERROR_NO_MEMORY;
+ }
+ return result;
+ }
+}
+
+static enum XML_Error PTRCALL
+errorProcessor(XML_Parser parser,
+ const char *UNUSED_P(s),
+ const char *UNUSED_P(end),
+ const char **UNUSED_P(nextPtr))
+{
+ return errorCode;
+}
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
+ end, pool);
+ if (result)
+ return result;
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ poolChop(pool);
+ if (!poolAppendChar(pool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ for (;;) {
+ const char *next;
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+ switch (tok) {
+ case XML_TOK_NONE:
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ if (!isCdata
+ && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (!poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, ptr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = ptr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_ATTRIBUTE_VALUE_S:
+ case XML_TOK_DATA_NEWLINE:
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ if (!poolAppendChar(pool, 0x20))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ char checkEntityDecl;
+ XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (!poolAppendChar(pool, ch))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ name = poolStoreString(&temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
+ poolDiscard(&temp2Pool);
+ /* First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal.
+ */
+ if (pool == &dtd->pool) /* are we called from prolog? */
+ checkEntityDecl =
+#ifdef XML_DTD
+ prologState.documentEntity &&
+#endif /* XML_DTD */
+ (dtd->standalone
+ ? !openInternalEntities
+ : !dtd->hasParamEntityRefs);
+ else /* if (pool == &tempPool): we are called from content */
+ checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
+ if (checkEntityDecl) {
+ if (!entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (!entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ }
+ else if (!entity) {
+ /* Cannot report skipped entity here - see comments on
+ skippedEntityHandler.
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, name, 0);
+ */
+ /* Cannot call the default handler because this would be
+ out of sync with the call to the startElementHandler.
+ if ((pool == &tempPool) && defaultHandler)
+ reportDefault(parser, enc, ptr, next);
+ */
+/* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=35984) */
+#if 0
+ break;
+#else
+ return XML_ERROR_UNDEFINED_ENTITY;
+#endif
+/* END MOZILLA CHANGE */
+ }
+ if (entity->open) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ if (entity->notation) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ if (!entity->textPtr) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ }
+ else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = XML_TRUE;
+ result = appendAttributeValue(parser, internalEncoding, isCdata,
+ (char *)entity->textPtr,
+ (char *)textEnd, pool);
+ entity->open = XML_FALSE;
+ if (result)
+ return result;
+ }
+ }
+ break;
+ default:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ ptr = next;
+ }
+ /* not reached */
+}
+
+static enum XML_Error
+storeEntityValue(XML_Parser parser,
+ const ENCODING *enc,
+ const char *entityTextPtr,
+ const char *entityTextEnd)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ STRING_POOL *pool = &(dtd->entityValuePool);
+ enum XML_Error result = XML_ERROR_NONE;
+#ifdef XML_DTD
+ int oldInEntityValue = prologState.inEntityValue;
+ prologState.inEntityValue = 1;
+#endif /* XML_DTD */
+ /* never return Null for the value argument in EntityDeclHandler,
+ since this would indicate an external entity; therefore we
+ have to make sure that entityValuePool.start is not null */
+ if (!pool->blocks) {
+ if (!poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ }
+
+ for (;;) {
+ const char *next;
+ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+ if (isParamEntity || enc != encoding) {
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&tempPool, enc,
+ entityTextPtr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
+ poolDiscard(&tempPool);
+ if (!entity) {
+ /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
+ /* cannot report skipped entity here - see comments on
+ skippedEntityHandler
+ if (skippedEntityHandler)
+ skippedEntityHandler(handlerArg, name, 0);
+ */
+ dtd->keepProcessing = dtd->standalone;
+ goto endEntityValue;
+ }
+ if (entity->open) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_RECURSIVE_ENTITY_REF;
+ goto endEntityValue;
+ }
+ if (entity->systemId) {
+ if (externalEntityRefHandler) {
+ dtd->paramEntityRead = XML_FALSE;
+ entity->open = XML_TRUE;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ entity->open = XML_FALSE;
+ result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ goto endEntityValue;
+ }
+ entity->open = XML_FALSE;
+ if (!dtd->paramEntityRead)
+ dtd->keepProcessing = dtd->standalone;
+ }
+ else
+ dtd->keepProcessing = dtd->standalone;
+ }
+ else {
+ entity->open = XML_TRUE;
+ result = storeEntityValue(parser,
+ internalEncoding,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr
+ + entity->textLen));
+ entity->open = XML_FALSE;
+ if (result)
+ goto endEntityValue;
+ }
+ break;
+ }
+#endif /* XML_DTD */
+ /* In the internal subset, PE references are not legal
+ within markup declarations, e.g entity values in this case. */
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_PARAM_ENTITY_REF;
+ goto endEntityValue;
+ case XML_TOK_NONE:
+ result = XML_ERROR_NONE;
+ goto endEntityValue;
+ case XML_TOK_ENTITY_REF:
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, entityTextPtr, next)) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = entityTextPtr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_DATA_NEWLINE:
+ if (pool->end == pool->ptr && !poolGrow(pool)) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ *(pool->ptr)++ = 0xA;
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, entityTextPtr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_BAD_CHAR_REF;
+ goto endEntityValue;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_BAD_CHAR_REF;
+ goto endEntityValue;
+ }
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && !poolGrow(pool)) {
+ result = XML_ERROR_NO_MEMORY;
+ goto endEntityValue;
+ }
+ *(pool->ptr)++ = buf[i];
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_INVALID_TOKEN;
+ goto endEntityValue;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ result = XML_ERROR_INVALID_TOKEN;
+ goto endEntityValue;
+ default:
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ result = XML_ERROR_UNEXPECTED_STATE;
+ goto endEntityValue;
+ }
+ entityTextPtr = next;
+ }
+endEntityValue:
+#ifdef XML_DTD
+ prologState.inEntityValue = oldInEntityValue;
+#endif /* XML_DTD */
+ return result;
+}
+
+static void FASTCALL
+normalizeLines(XML_Char *s)
+{
+ XML_Char *p;
+ for (;; s++) {
+ if (*s == XML_T('\0'))
+ return;
+ if (*s == 0xD)
+ break;
+ }
+ p = s;
+ do {
+ if (*s == 0xD) {
+ *p++ = 0xA;
+ if (*++s == 0xA)
+ s++;
+ }
+ else
+ *p++ = *s++;
+ } while (*s);
+ *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end)
+{
+ const XML_Char *target;
+ XML_Char *data;
+ const char *tem;
+ if (!processingInstructionHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ start += enc->minBytesPerChar * 2;
+ tem = start + XmlNameLength(enc, start);
+ target = poolStoreString(&tempPool, enc, start, tem);
+ if (!target)
+ return 0;
+ poolFinish(&tempPool);
+ data = poolStoreString(&tempPool, enc,
+ XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar*2);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ processingInstructionHandler(handlerArg, target, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static int
+reportComment(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end)
+{
+ XML_Char *data;
+ if (!commentHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ data = poolStoreString(&tempPool,
+ enc,
+ start + enc->minBytesPerChar * 4,
+ end - enc->minBytesPerChar * 3);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ commentHandler(handlerArg, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc,
+ const char *s, const char *end)
+{
+ if (MUST_CONVERT(enc, s)) {
+ enum XML_Convert_Result convert_res;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ do {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ defaultHandler(handlerArg, dataBuf, (int)(dataPtr - (ICHAR *)dataBuf));
+ *eventPP = s;
+ } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
+ }
+ else
+ defaultHandler(handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
+ XML_Bool isId, const XML_Char *value, XML_Parser parser)
+{
+ DEFAULT_ATTRIBUTE *att;
+ if (value || isId) {
+ /* The handling of default attributes gets messed up if we have
+ a default which duplicates a non-default. */
+ int i;
+ for (i = 0; i < type->nDefaultAtts; i++)
+ if (attId == type->defaultAtts[i].id)
+ return 1;
+ if (isId && !type->idAtt && !attId->xmlns)
+ type->idAtt = attId;
+ }
+ if (type->nDefaultAtts == type->allocDefaultAtts) {
+ if (type->allocDefaultAtts == 0) {
+ type->allocDefaultAtts = 8;
+ type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(type->allocDefaultAtts
+ * sizeof(DEFAULT_ATTRIBUTE));
+ if (!type->defaultAtts)
+ return 0;
+ }
+ else {
+ DEFAULT_ATTRIBUTE *temp;
+
+ /* Detect and prevent integer overflow */
+ if (type->allocDefaultAtts > INT_MAX / 2) {
+ return 0;
+ }
+
+ int count = type->allocDefaultAtts * 2;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
+ return 0;
+ }
+#endif
+
+ temp = (DEFAULT_ATTRIBUTE *)
+ REALLOC(type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
+ if (temp == NULL)
+ return 0;
+ type->allocDefaultAtts = count;
+ type->defaultAtts = temp;
+ }
+ }
+ att = type->defaultAtts + type->nDefaultAtts;
+ att->id = attId;
+ att->value = value;
+ att->isCdata = isCdata;
+ if (!isCdata)
+ attId->maybeTokenized = XML_TRUE;
+ type->nDefaultAtts += 1;
+ return 1;
+}
+
+static int
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(ASCII_COLON)) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd->pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
+ sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd->pool))
+ poolFinish(&dtd->pool);
+ else
+ poolDiscard(&dtd->pool);
+ elementType->prefix = prefix;
+
+ }
+ }
+ return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ ATTRIBUTE_ID *id;
+ const XML_Char *name;
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ return NULL;
+ name = poolStoreString(&dtd->pool, enc, start, end);
+ if (!name)
+ return NULL;
+ /* skip quotation mark - its storage will be re-used (like in name[-1]) */
+ ++name;
+ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
+ if (!id)
+ return NULL;
+ if (id->name != name)
+ poolDiscard(&dtd->pool);
+ else {
+ poolFinish(&dtd->pool);
+ if (!ns)
+ ;
+ else if (name[0] == XML_T(ASCII_x)
+ && name[1] == XML_T(ASCII_m)
+ && name[2] == XML_T(ASCII_l)
+ && name[3] == XML_T(ASCII_n)
+ && name[4] == XML_T(ASCII_s)
+ && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
+ if (name[5] == XML_T('\0'))
+ id->prefix = &dtd->defaultPrefix;
+ else
+ id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = XML_TRUE;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ /* attributes without prefix are *not* in the default namespace */
+ if (name[i] == XML_T(ASCII_COLON)) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd->pool, name[j]))
+ return NULL;
+ }
+ if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ return NULL;
+ id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
+ sizeof(PREFIX));
+ if (!id->prefix)
+ return NULL;
+ if (id->prefix->name == poolStart(&dtd->pool))
+ poolFinish(&dtd->pool);
+ else
+ poolDiscard(&dtd->pool);
+ break;
+ }
+ }
+ }
+ }
+ return id;
+}
+
+#define CONTEXT_SEP XML_T(ASCII_FF)
+
+static const XML_Char *
+getContext(XML_Parser parser)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ HASH_TABLE_ITER iter;
+ XML_Bool needSep = XML_FALSE;
+
+ if (dtd->defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
+ return NULL;
+ len = dtd->defaultPrefix.binding->uriLen;
+ if (namespaceSeparator)
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd->defaultPrefix.binding->uri[i]))
+ return NULL;
+ needSep = XML_TRUE;
+ }
+
+ hashTableIterInit(&iter, &(dtd->prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return NULL;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return NULL;
+ if (!poolAppendChar(&tempPool, XML_T(ASCII_EQUALS)))
+ return NULL;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator)
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return NULL;
+ needSep = XML_TRUE;
+ }
+
+
+ hashTableIterInit(&iter, &(dtd->generalEntities));
+ for (;;) {
+ const XML_Char *s;
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (!e->open)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return NULL;
+ for (s = e->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ needSep = XML_TRUE;
+ }
+
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return NULL;
+ return tempPool.start;
+}
+
+static XML_Bool
+setContext(XML_Parser parser, const XML_Char *context)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+ ENTITY *e;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_FALSE;
+ e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
+ if (e)
+ e->open = XML_TRUE;
+ if (*s != XML_T('\0'))
+ s++;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == XML_T(ASCII_EQUALS)) {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd->defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_FALSE;
+ prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
+ sizeof(PREFIX));
+ if (!prefix)
+ return XML_FALSE;
+ if (prefix->name == poolStart(&tempPool)) {
+ prefix->name = poolCopyString(&dtd->pool, prefix->name);
+ if (!prefix->name)
+ return XML_FALSE;
+ }
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1;
+ *context != CONTEXT_SEP && *context != XML_T('\0');
+ context++)
+ if (!poolAppendChar(&tempPool, *context))
+ return XML_FALSE;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return XML_FALSE;
+ if (addBinding(parser, prefix, NULL, poolStart(&tempPool),
+ &inheritedBindings) != XML_ERROR_NONE)
+ return XML_FALSE;
+ poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
+ }
+ else {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_FALSE;
+ s++;
+ }
+ }
+ return XML_TRUE;
+}
+
+static void FASTCALL
+normalizePublicId(XML_Char *publicId)
+{
+ XML_Char *p = publicId;
+ XML_Char *s;
+ for (s = publicId; *s; s++) {
+ switch (*s) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ if (p != publicId && p[-1] != 0x20)
+ *p++ = 0x20;
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ if (p != publicId && p[-1] == 0x20)
+ --p;
+ *p = XML_T('\0');
+}
+
+static DTD *
+dtdCreate(const XML_Memory_Handling_Suite *ms)
+{
+ DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
+ if (p == NULL)
+ return p;
+ poolInit(&(p->pool), ms);
+ poolInit(&(p->entityValuePool), ms);
+ hashTableInit(&(p->generalEntities), ms);
+ hashTableInit(&(p->elementTypes), ms);
+ hashTableInit(&(p->attributeIds), ms);
+ hashTableInit(&(p->prefixes), ms);
+#ifdef XML_DTD
+ p->paramEntityRead = XML_FALSE;
+ hashTableInit(&(p->paramEntities), ms);
+#endif /* XML_DTD */
+ p->defaultPrefix.name = NULL;
+ p->defaultPrefix.binding = NULL;
+
+ p->in_eldecl = XML_FALSE;
+ p->scaffIndex = NULL;
+ p->scaffold = NULL;
+ p->scaffLevel = 0;
+ p->scaffSize = 0;
+ p->scaffCount = 0;
+ p->contentStringLen = 0;
+
+ p->keepProcessing = XML_TRUE;
+ p->hasParamEntityRefs = XML_FALSE;
+ p->standalone = XML_FALSE;
+ return p;
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+static void
+dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ ms->free_fcn(e->defaultAtts);
+ }
+ hashTableClear(&(p->generalEntities));
+#ifdef XML_DTD
+ p->paramEntityRead = XML_FALSE;
+ hashTableClear(&(p->paramEntities));
+#endif /* XML_DTD */
+ hashTableClear(&(p->elementTypes));
+ hashTableClear(&(p->attributeIds));
+ hashTableClear(&(p->prefixes));
+ poolClear(&(p->pool));
+ poolClear(&(p->entityValuePool));
+ p->defaultPrefix.name = NULL;
+ p->defaultPrefix.binding = NULL;
+
+ p->in_eldecl = XML_FALSE;
+
+ ms->free_fcn(p->scaffIndex);
+ p->scaffIndex = NULL;
+ ms->free_fcn(p->scaffold);
+ p->scaffold = NULL;
+
+ p->scaffLevel = 0;
+ p->scaffSize = 0;
+ p->scaffCount = 0;
+ p->contentStringLen = 0;
+
+ p->keepProcessing = XML_TRUE;
+ p->hasParamEntityRefs = XML_FALSE;
+ p->standalone = XML_FALSE;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+static void
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ ms->free_fcn(e->defaultAtts);
+ }
+ hashTableDestroy(&(p->generalEntities));
+#ifdef XML_DTD
+ hashTableDestroy(&(p->paramEntities));
+#endif /* XML_DTD */
+ hashTableDestroy(&(p->elementTypes));
+ hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
+ poolDestroy(&(p->pool));
+ poolDestroy(&(p->entityValuePool));
+ if (isDocEntity) {
+ ms->free_fcn(p->scaffIndex);
+ ms->free_fcn(p->scaffold);
+ }
+ ms->free_fcn(p);
+}
+
+/* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise.
+ The new DTD has already been initialized.
+*/
+static int
+dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
+{
+ HASH_TABLE_ITER iter;
+
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
+ }
+
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+ /* Copy the attribute id table. */
+
+ for (;;) {
+ ATTRIBUTE_ID *newA;
+ const XML_Char *name;
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+ if (!oldA)
+ break;
+ /* Remember to allocate the scratch byte before the name. */
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ return 0;
+ name = poolCopyString(&(newDtd->pool), oldA->name);
+ if (!name)
+ return 0;
+ ++name;
+ newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
+ sizeof(ATTRIBUTE_ID));
+ if (!newA)
+ return 0;
+ newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
+ oldA->prefix->name, 0);
+ }
+ }
+
+ /* Copy the element type table. */
+
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+ for (;;) {
+ int i;
+ ELEMENT_TYPE *newE;
+ const XML_Char *name;
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
+ sizeof(ELEMENT_TYPE));
+ if (!newE)
+ return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
+ ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts) {
+ return 0;
+ }
+ }
+ if (oldE->idAtt)
+ newE->idAtt = (ATTRIBUTE_ID *)
+ lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
+ oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
+ lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value
+ = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+ if (!newE->defaultAtts[i].value)
+ return 0;
+ }
+ else
+ newE->defaultAtts[i].value = NULL;
+ }
+ }
+
+ /* Copy the entity tables. */
+ if (!copyEntityTable(oldParser,
+ &(newDtd->generalEntities),
+ &(newDtd->pool),
+ &(oldDtd->generalEntities)))
+ return 0;
+
+#ifdef XML_DTD
+ if (!copyEntityTable(oldParser,
+ &(newDtd->paramEntities),
+ &(newDtd->pool),
+ &(oldDtd->paramEntities)))
+ return 0;
+ newDtd->paramEntityRead = oldDtd->paramEntityRead;
+#endif /* XML_DTD */
+
+ newDtd->keepProcessing = oldDtd->keepProcessing;
+ newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs;
+ newDtd->standalone = oldDtd->standalone;
+
+ /* Don't want deep copying for scaffolding */
+ newDtd->in_eldecl = oldDtd->in_eldecl;
+ newDtd->scaffold = oldDtd->scaffold;
+ newDtd->contentStringLen = oldDtd->contentStringLen;
+ newDtd->scaffSize = oldDtd->scaffSize;
+ newDtd->scaffLevel = oldDtd->scaffLevel;
+ newDtd->scaffIndex = oldDtd->scaffIndex;
+
+ return 1;
+} /* End dtdCopy */
+
+static int
+copyEntityTable(XML_Parser oldParser,
+ HASH_TABLE *newTable,
+ STRING_POOL *newPool,
+ const HASH_TABLE *oldTable)
+{
+ HASH_TABLE_ITER iter;
+ const XML_Char *cachedOldBase = NULL;
+ const XML_Char *cachedNewBase = NULL;
+
+ hashTableIterInit(&iter, oldTable);
+
+ for (;;) {
+ ENTITY *newE;
+ const XML_Char *name;
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(newPool, oldE->name);
+ if (!name)
+ return 0;
+ newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
+ if (!newE)
+ return 0;
+ if (oldE->systemId) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
+ if (!tem)
+ return 0;
+ newE->systemId = tem;
+ if (oldE->base) {
+ if (oldE->base == cachedOldBase)
+ newE->base = cachedNewBase;
+ else {
+ cachedOldBase = oldE->base;
+ tem = poolCopyString(newPool, cachedOldBase);
+ if (!tem)
+ return 0;
+ cachedNewBase = newE->base = tem;
+ }
+ }
+ if (oldE->publicId) {
+ tem = poolCopyString(newPool, oldE->publicId);
+ if (!tem)
+ return 0;
+ newE->publicId = tem;
+ }
+ }
+ else {
+ const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
+ oldE->textLen);
+ if (!tem)
+ return 0;
+ newE->textPtr = tem;
+ newE->textLen = oldE->textLen;
+ }
+ if (oldE->notation) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->notation);
+ if (!tem)
+ return 0;
+ newE->notation = tem;
+ }
+ newE->is_param = oldE->is_param;
+ newE->is_internal = oldE->is_internal;
+ }
+ return 1;
+}
+
+#define INIT_POWER 6
+
+static XML_Bool FASTCALL
+keyeq(KEY s1, KEY s2)
+{
+ for (; *s1 == *s2; s1++, s2++)
+ if (*s1 == 0)
+ return XML_TRUE;
+ return XML_FALSE;
+}
+
+static size_t
+keylen(KEY s)
+{
+ size_t len = 0;
+ for (; *s; s++, len++);
+ return len;
+}
+
+static void
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
+{
+ key->k[0] = 0;
+ key->k[1] = get_hash_secret_salt(parser);
+}
+
+static unsigned long FASTCALL
+hash(XML_Parser parser, KEY s)
+{
+ struct siphash state;
+ struct sipkey key;
+ (void)sip_tobin;
+ (void)sip24_valid;
+ copy_salt_to_sipkey(parser, &key);
+ sip24_init(&state, &key);
+ sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
+ return (unsigned long)sip24_final(&state);
+}
+
+static NAMED *
+lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
+{
+ size_t i;
+ if (table->size == 0) {
+ size_t tsize;
+ if (!createSize)
+ return NULL;
+ table->power = INIT_POWER;
+ /* table->size is a power of 2 */
+ table->size = (size_t)1 << INIT_POWER;
+ tsize = table->size * sizeof(NAMED *);
+ table->v = (NAMED **)table->mem->malloc_fcn(tsize);
+ if (!table->v) {
+ table->size = 0;
+ return NULL;
+ }
+ memset(table->v, 0, tsize);
+ i = hash(parser, name) & ((unsigned long)table->size - 1);
+ }
+ else {
+ unsigned long h = hash(parser, name);
+ unsigned long mask = (unsigned long)table->size - 1;
+ unsigned char step = 0;
+ i = h & mask;
+ while (table->v[i]) {
+ if (keyeq(name, table->v[i]->name))
+ return table->v[i];
+ if (!step)
+ step = PROBE_STEP(h, mask, table->power);
+ i < step ? (i += table->size - step) : (i -= step);
+ }
+ if (!createSize)
+ return NULL;
+
+ /* check for overflow (table is half full) */
+ if (table->used >> (table->power - 1)) {
+ unsigned char newPower = table->power + 1;
+
+ /* Detect and prevent invalid shift */
+ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
+ return NULL;
+ }
+
+ size_t newSize = (size_t)1 << newPower;
+ unsigned long newMask = (unsigned long)newSize - 1;
+
+ /* Detect and prevent integer overflow */
+ if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
+ return NULL;
+ }
+
+ size_t tsize = newSize * sizeof(NAMED *);
+ NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
+ if (!newV)
+ return NULL;
+ memset(newV, 0, tsize);
+ for (i = 0; i < table->size; i++)
+ if (table->v[i]) {
+ unsigned long newHash = hash(parser, table->v[i]->name);
+ size_t j = newHash & newMask;
+ step = 0;
+ while (newV[j]) {
+ if (!step)
+ step = PROBE_STEP(newHash, newMask, newPower);
+ j < step ? (j += newSize - step) : (j -= step);
+ }
+ newV[j] = table->v[i];
+ }
+ table->mem->free_fcn(table->v);
+ table->v = newV;
+ table->power = newPower;
+ table->size = newSize;
+ i = h & newMask;
+ step = 0;
+ while (table->v[i]) {
+ if (!step)
+ step = PROBE_STEP(h, newMask, newPower);
+ i < step ? (i += newSize - step) : (i -= step);
+ }
+ }
+ }
+ table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
+ if (!table->v[i])
+ return NULL;
+ memset(table->v[i], 0, createSize);
+ table->v[i]->name = name;
+ (table->used)++;
+ return table->v[i];
+}
+
+/* BEGIN MOZILLA CHANGE (unused API) */
+#if 0
+static void FASTCALL
+hashTableClear(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++) {
+ table->mem->free_fcn(table->v[i]);
+ table->v[i] = NULL;
+ }
+ table->used = 0;
+}
+#endif
+/* END MOZILLA CHANGE */
+
+static void FASTCALL
+hashTableDestroy(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++)
+ table->mem->free_fcn(table->v[i]);
+ table->mem->free_fcn(table->v);
+}
+
+static void FASTCALL
+hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
+{
+ p->power = 0;
+ p->size = 0;
+ p->used = 0;
+ p->v = NULL;
+ p->mem = ms;
+}
+
+static void FASTCALL
+hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+ iter->p = table->v;
+ iter->end = iter->p + table->size;
+}
+
+static NAMED * FASTCALL
+hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+ while (iter->p != iter->end) {
+ NAMED *tem = *(iter->p)++;
+ if (tem)
+ return tem;
+ }
+ return NULL;
+}
+
+static void FASTCALL
+poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
+{
+ pool->blocks = NULL;
+ pool->freeBlocks = NULL;
+ pool->start = NULL;
+ pool->ptr = NULL;
+ pool->end = NULL;
+ pool->mem = ms;
+}
+
+static void FASTCALL
+poolClear(STRING_POOL *pool)
+{
+ if (!pool->freeBlocks)
+ pool->freeBlocks = pool->blocks;
+ else {
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ p->next = pool->freeBlocks;
+ pool->freeBlocks = p;
+ p = tem;
+ }
+ }
+ pool->blocks = NULL;
+ pool->start = NULL;
+ pool->ptr = NULL;
+ pool->end = NULL;
+}
+
+static void FASTCALL
+poolDestroy(STRING_POOL *pool)
+{
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ pool->mem->free_fcn(p);
+ p = tem;
+ }
+ p = pool->freeBlocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ pool->mem->free_fcn(p);
+ p = tem;
+ }
+}
+
+static XML_Char *
+poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return NULL;
+ for (;;) {
+ const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+ break;
+ if (!poolGrow(pool))
+ return NULL;
+ }
+ return pool->start;
+}
+
+static const XML_Char * FASTCALL
+poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+ do {
+ if (!poolAppendChar(pool, *s))
+ return NULL;
+ } while (*s++);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char *
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return NULL;
+ for (; n > 0; --n, s++) {
+ if (!poolAppendChar(pool, *s))
+ return NULL;
+ }
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char * FASTCALL
+poolAppendString(STRING_POOL *pool, const XML_Char *s)
+{
+ while (*s) {
+ if (!poolAppendChar(pool, *s))
+ return NULL;
+ s++;
+ }
+ return pool->start;
+}
+
+static XML_Char *
+poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!poolAppend(pool, enc, ptr, end))
+ return NULL;
+ if (pool->ptr == pool->end && !poolGrow(pool))
+ return NULL;
+ *(pool->ptr)++ = 0;
+ return pool->start;
+}
+
+static size_t
+poolBytesToAllocateFor(int blockSize)
+{
+ /* Unprotected math would be:
+ ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
+ **
+ ** Detect overflow, avoiding _signed_ overflow undefined behavior
+ ** For a + b * c we check b * c in isolation first, so that addition of a
+ ** on top has no chance of making us accept a small non-negative number
+ */
+ const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
+
+ if (blockSize <= 0)
+ return 0;
+
+ if (blockSize > (int)(INT_MAX / stretch))
+ return 0;
+
+ {
+ const int stretchedBlockSize = blockSize * (int)stretch;
+ const int bytesToAllocate = (int)(
+ offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
+ if (bytesToAllocate < 0)
+ return 0;
+
+ return (size_t)bytesToAllocate;
+ }
+}
+
+static XML_Bool FASTCALL
+poolGrow(STRING_POOL *pool)
+{
+ if (pool->freeBlocks) {
+ if (pool->start == 0) {
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = pool->freeBlocks->next;
+ pool->blocks->next = NULL;
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ pool->ptr = pool->start;
+ return XML_TRUE;
+ }
+ if (pool->end - pool->start < pool->freeBlocks->size) {
+ BLOCK *tem = pool->freeBlocks->next;
+ pool->freeBlocks->next = pool->blocks;
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = tem;
+ memcpy(pool->blocks->s, pool->start,
+ (pool->end - pool->start) * sizeof(XML_Char));
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ return XML_TRUE;
+ }
+ }
+ if (pool->blocks && pool->start == pool->blocks->s) {
+ BLOCK *temp;
+ int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
+ size_t bytesToAllocate;
+
+ if (blockSize < 0)
+ return XML_FALSE;
+
+ bytesToAllocate = poolBytesToAllocateFor(blockSize);
+ if (bytesToAllocate == 0)
+ return XML_FALSE;
+
+ temp = (BLOCK *)
+ pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
+ if (temp == NULL)
+ return XML_FALSE;
+ pool->blocks = temp;
+ pool->blocks->size = blockSize;
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + blockSize;
+ }
+ else {
+ BLOCK *tem;
+ int blockSize = (int)(pool->end - pool->start);
+ size_t bytesToAllocate;
+
+ if (blockSize < 0)
+ return XML_FALSE;
+
+ if (blockSize < INIT_BLOCK_SIZE)
+ blockSize = INIT_BLOCK_SIZE;
+ else {
+ /* Detect overflow, avoiding _signed_ overflow undefined behavior */
+ if ((int)((unsigned)blockSize * 2U) < 0) {
+ return XML_FALSE;
+ }
+ blockSize *= 2;
+ }
+
+ bytesToAllocate = poolBytesToAllocateFor(blockSize);
+ if (bytesToAllocate == 0)
+ return XML_FALSE;
+
+ tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
+ if (!tem)
+ return XML_FALSE;
+ tem->size = blockSize;
+ tem->next = pool->blocks;
+ pool->blocks = tem;
+ if (pool->ptr != pool->start)
+ memcpy(tem->s, pool->start,
+ (pool->ptr - pool->start) * sizeof(XML_Char));
+ pool->ptr = tem->s + (pool->ptr - pool->start);
+ pool->start = tem->s;
+ pool->end = tem->s + blockSize;
+ }
+ return XML_TRUE;
+}
+
+static int FASTCALL
+nextScaffoldPart(XML_Parser parser)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ CONTENT_SCAFFOLD * me;
+ int next;
+
+ if (!dtd->scaffIndex) {
+ dtd->scaffIndex = (int *)MALLOC(groupSize * sizeof(int));
+ if (!dtd->scaffIndex)
+ return -1;
+ dtd->scaffIndex[0] = 0;
+ }
+
+ if (dtd->scaffCount >= dtd->scaffSize) {
+ CONTENT_SCAFFOLD *temp;
+ if (dtd->scaffold) {
+ /* Detect and prevent integer overflow */
+ if (dtd->scaffSize > UINT_MAX / 2u) {
+ return -1;
+ }
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
+ return -1;
+ }
+#endif
+
+ temp = (CONTENT_SCAFFOLD *)
+ REALLOC(dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
+ if (temp == NULL)
+ return -1;
+ dtd->scaffSize *= 2;
+ }
+ else {
+ temp = (CONTENT_SCAFFOLD *)MALLOC(INIT_SCAFFOLD_ELEMENTS
+ * sizeof(CONTENT_SCAFFOLD));
+ if (temp == NULL)
+ return -1;
+ dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
+ }
+ dtd->scaffold = temp;
+ }
+ next = dtd->scaffCount++;
+ me = &dtd->scaffold[next];
+ if (dtd->scaffLevel) {
+ CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
+ if (parent->lastchild) {
+ dtd->scaffold[parent->lastchild].nextsib = next;
+ }
+ if (!parent->childcnt)
+ parent->firstchild = next;
+ parent->lastchild = next;
+ parent->childcnt++;
+ }
+ me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
+ return next;
+}
+
+static void
+build_node(XML_Parser parser,
+ int src_node,
+ XML_Content *dest,
+ XML_Content **contpos,
+ XML_Char **strpos)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ dest->type = dtd->scaffold[src_node].type;
+ dest->quant = dtd->scaffold[src_node].quant;
+ if (dest->type == XML_CTYPE_NAME) {
+ const XML_Char *src;
+ dest->name = *strpos;
+ src = dtd->scaffold[src_node].name;
+ for (;;) {
+ *(*strpos)++ = *src;
+ if (!*src)
+ break;
+ src++;
+ }
+ dest->numchildren = 0;
+ dest->children = NULL;
+ }
+ else {
+ unsigned int i;
+ int cn;
+ dest->numchildren = dtd->scaffold[src_node].childcnt;
+ dest->children = *contpos;
+ *contpos += dest->numchildren;
+ for (i = 0, cn = dtd->scaffold[src_node].firstchild;
+ i < dest->numchildren;
+ i++, cn = dtd->scaffold[cn].nextsib) {
+ build_node(parser, cn, &(dest->children[i]), contpos, strpos);
+ }
+ dest->name = NULL;
+ }
+}
+
+static XML_Content *
+build_model (XML_Parser parser)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ XML_Content *ret;
+ XML_Content *cpos;
+ XML_Char * str;
+
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+ * from -Wtype-limits on platforms where
+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
+#if UINT_MAX >= SIZE_MAX
+ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
+ return NULL;
+ }
+ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
+ return NULL;
+ }
+#endif
+ if (dtd->scaffCount * sizeof(XML_Content)
+ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
+ return NULL;
+ }
+
+ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
+ + (dtd->contentStringLen * sizeof(XML_Char)));
+
+ ret = (XML_Content *)MALLOC(allocsize);
+ if (!ret)
+ return NULL;
+
+ str = (XML_Char *) (&ret[dtd->scaffCount]);
+ cpos = &ret[1];
+
+ build_node(parser, 0, ret, &cpos, &str);
+ return ret;
+}
+
+static ELEMENT_TYPE *
+getElementType(XML_Parser parser,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end)
+{
+ DTD * const dtd = _dtd; /* save one level of indirection */
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
+ ELEMENT_TYPE *ret;
+
+ if (!name)
+ return NULL;
+ ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
+ if (!ret)
+ return NULL;
+ if (ret->name != name)
+ poolDiscard(&dtd->pool);
+ else {
+ poolFinish(&dtd->pool);
+ if (!setElementTypePrefix(parser, ret))
+ return NULL;
+ }
+ return ret;
+}
diff --git a/parser/expat/lib/xmlrole.c b/parser/expat/lib/xmlrole.c
new file mode 100644
index 0000000000..a7c5630279
--- /dev/null
+++ b/parser/expat/lib/xmlrole.c
@@ -0,0 +1,1330 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include "winconfig.h"
+#else
+#ifdef HAVE_EXPAT_CONFIG_H
+#include <expat_config.h>
+#endif
+#endif /* ndef _WIN32 */
+
+#include "expat_external.h"
+#include "internal.h"
+#include "xmlrole.h"
+#include "ascii.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+static const char KW_ANY[] = {
+ ASCII_A, ASCII_N, ASCII_Y, '\0' };
+static const char KW_ATTLIST[] = {
+ ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' };
+static const char KW_CDATA[] = {
+ ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_DOCTYPE[] = {
+ ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' };
+static const char KW_ELEMENT[] = {
+ ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' };
+static const char KW_EMPTY[] = {
+ ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' };
+static const char KW_ENTITIES[] = {
+ ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S,
+ '\0' };
+static const char KW_ENTITY[] = {
+ ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+static const char KW_FIXED[] = {
+ ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' };
+static const char KW_ID[] = {
+ ASCII_I, ASCII_D, '\0' };
+static const char KW_IDREF[] = {
+ ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+static const char KW_IDREFS[] = {
+ ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+#ifdef XML_DTD
+static const char KW_IGNORE[] = {
+ ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' };
+#endif
+static const char KW_IMPLIED[] = {
+ ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' };
+#ifdef XML_DTD
+static const char KW_INCLUDE[] = {
+ ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' };
+#endif
+static const char KW_NDATA[] = {
+ ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_NMTOKEN[] = {
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+static const char KW_NMTOKENS[] = {
+ ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S,
+ '\0' };
+static const char KW_NOTATION[] =
+ { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N,
+ '\0' };
+static const char KW_PCDATA[] = {
+ ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_PUBLIC[] = {
+ ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' };
+static const char KW_REQUIRED[] = {
+ ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D,
+ '\0' };
+static const char KW_SYSTEM[] = {
+ ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' };
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+#ifdef XML_DTD
+#define setTopLevel(state) \
+ ((state)->handler = ((state)->documentEntity \
+ ? internalSubset \
+ : externalSubset1))
+#else /* not XML_DTD */
+#define setTopLevel(state) ((state)->handler = internalSubset)
+#endif /* not XML_DTD */
+
+typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+
+static PROLOG_HANDLER
+ prolog0, prolog1, prolog2,
+ doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+ internalSubset,
+ entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+ entity7, entity8, entity9, entity10,
+ notation0, notation1, notation2, notation3, notation4,
+ attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+ attlist7, attlist8, attlist9,
+ element0, element1, element2, element3, element4, element5, element6,
+ element7,
+#ifdef XML_DTD
+ externalSubset0, externalSubset1,
+ condSect0, condSect1, condSect2,
+#endif /* XML_DTD */
+ declClose,
+ error;
+
+static int FASTCALL common(PROLOG_STATE *state, int tok);
+
+static int PTRCALL
+prolog0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_XML_DECL:
+ state->handler = prolog1;
+ return XML_ROLE_XML_DECL;
+ case XML_TOK_PI:
+ state->handler = prolog1;
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ state->handler = prolog1;
+ return XML_ROLE_COMMENT;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_DOCTYPE))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+prolog1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ return XML_ROLE_COMMENT;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_DOCTYPE))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+prolog2(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ return XML_ROLE_COMMENT;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype0(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = doctype1;
+ return XML_ROLE_DOCTYPE_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = doctype2;
+ return XML_ROLE_DOCTYPE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype2(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype3(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype4;
+ return XML_ROLE_DOCTYPE_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype4(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+doctype5(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+internalSubset(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ENTITY)) {
+ state->handler = entity0;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ATTLIST)) {
+ state->handler = attlist0;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ELEMENT)) {
+ state->handler = element0;
+ return XML_ROLE_ELEMENT_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_NOTATION)) {
+ state->handler = notation0;
+ return XML_ROLE_NOTATION_NONE;
+ }
+ break;
+ case XML_TOK_PI:
+ return XML_ROLE_PI;
+ case XML_TOK_COMMENT:
+ return XML_ROLE_COMMENT;
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ROLE_PARAM_ENTITY_REF;
+ case XML_TOK_CLOSE_BRACKET:
+ state->handler = doctype5;
+ return XML_ROLE_DOCTYPE_NONE;
+ case XML_TOK_NONE:
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static int PTRCALL
+externalSubset0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ state->handler = externalSubset1;
+ if (tok == XML_TOK_XML_DECL)
+ return XML_ROLE_TEXT_DECL;
+ return externalSubset1(state, tok, ptr, end, enc);
+}
+
+static int PTRCALL
+externalSubset1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_COND_SECT_OPEN:
+ state->handler = condSect0;
+ return XML_ROLE_NONE;
+ case XML_TOK_COND_SECT_CLOSE:
+ if (state->includeLevel == 0)
+ break;
+ state->includeLevel -= 1;
+ return XML_ROLE_NONE;
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_BRACKET:
+ break;
+ case XML_TOK_NONE:
+ if (state->includeLevel)
+ break;
+ return XML_ROLE_NONE;
+ default:
+ return internalSubset(state, tok, ptr, end, enc);
+ }
+ return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static int PTRCALL
+entity0(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_PERCENT:
+ state->handler = entity1;
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity2;
+ return XML_ROLE_GENERAL_ENTITY_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity1(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity7;
+ return XML_ROLE_PARAM_ENTITY_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = entity3;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ENTITY_NONE;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity3(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity4(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity5;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ENTITY_COMPLETE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) {
+ state->handler = entity6;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity6(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ENTITY_NONE;
+ return XML_ROLE_ENTITY_NOTATION_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = entity8;
+ return XML_ROLE_ENTITY_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ENTITY_NONE;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity8(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity9(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity10;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+entity10(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ENTITY_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ENTITY_COMPLETE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation0(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_NAME:
+ state->handler = notation1;
+ return XML_ROLE_NOTATION_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = notation3;
+ return XML_ROLE_NOTATION_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = notation2;
+ return XML_ROLE_NOTATION_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation2(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = notation4;
+ return XML_ROLE_NOTATION_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation3(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_NOTATION_NONE;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+notation4(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NOTATION_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_NOTATION_NONE;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist0(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist1;
+ return XML_ROLE_ATTLIST_ELEMENT_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist1(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist2;
+ return XML_ROLE_ATTRIBUTE_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ {
+ static const char * const types[] = {
+ KW_CDATA,
+ KW_ID,
+ KW_IDREF,
+ KW_IDREFS,
+ KW_ENTITY,
+ KW_ENTITIES,
+ KW_NMTOKEN,
+ KW_NMTOKENS,
+ };
+ int i;
+ for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+ if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
+ state->handler = attlist8;
+ return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) {
+ state->handler = attlist5;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist3;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist3(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NMTOKEN:
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist4;
+ return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist4(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist3;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist5(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist6;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist6(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_NAME:
+ state->handler = attlist7;
+ return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist7(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist6;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ return common(state, tok);
+}
+
+/* default value */
+static int PTRCALL
+attlist8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_IMPLIED)) {
+ state->handler = attlist1;
+ return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_REQUIRED)) {
+ state->handler = attlist1;
+ return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_FIXED)) {
+ state->handler = attlist9;
+ return XML_ROLE_ATTLIST_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+attlist9(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ATTLIST_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element0(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element1;
+ return XML_ROLE_ELEMENT_NAME;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_CONTENT_EMPTY;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_CONTENT_ANY;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = element2;
+ state->level = 1;
+ return XML_ROLE_GROUP_OPEN;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_PCDATA)) {
+ state->handler = element3;
+ return XML_ROLE_CONTENT_PCDATA;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->level = 2;
+ state->handler = element6;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element3(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_ELEMENT_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element4(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element5;
+ return XML_ROLE_CONTENT_ELEMENT;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element5(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_ELEMENT_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element6(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->level += 1;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+element7(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_ELEMENT_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_CLOSE_PAREN_QUESTION:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE_OPT;
+ case XML_TOK_CLOSE_PAREN_PLUS:
+ state->level -= 1;
+ if (state->level == 0) {
+ state->handler = declClose;
+ state->role_none = XML_ROLE_ELEMENT_NONE;
+ }
+ return XML_ROLE_GROUP_CLOSE_PLUS;
+ case XML_TOK_COMMA:
+ state->handler = element6;
+ return XML_ROLE_GROUP_SEQUENCE;
+ case XML_TOK_OR:
+ state->handler = element6;
+ return XML_ROLE_GROUP_CHOICE;
+ }
+ return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static int PTRCALL
+condSect0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) {
+ state->handler = condSect1;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) {
+ state->handler = condSect2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+condSect1(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ state->includeLevel += 1;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+condSect2(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ return XML_ROLE_IGNORE_SECT;
+ }
+ return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static int PTRCALL
+declClose(PROLOG_STATE *state,
+ int tok,
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return state->role_none;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return state->role_none;
+ }
+ return common(state, tok);
+}
+
+static int PTRCALL
+error(PROLOG_STATE *UNUSED_P(state),
+ int UNUSED_P(tok),
+ const char *UNUSED_P(ptr),
+ const char *UNUSED_P(end),
+ const ENCODING *UNUSED_P(enc))
+{
+ return XML_ROLE_NONE;
+}
+
+static int FASTCALL
+common(PROLOG_STATE *state, int tok)
+{
+#ifdef XML_DTD
+ if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
+ return XML_ROLE_INNER_PARAM_ENTITY_REF;
+#endif
+ state->handler = error;
+ return XML_ROLE_ERROR;
+}
+
+void
+XmlPrologStateInit(PROLOG_STATE *state)
+{
+ state->handler = prolog0;
+#ifdef XML_DTD
+ state->documentEntity = 1;
+ state->includeLevel = 0;
+ state->inEntityValue = 0;
+#endif /* XML_DTD */
+}
+
+#ifdef XML_DTD
+
+void
+XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
+{
+ state->handler = externalSubset0;
+ state->documentEntity = 0;
+ state->includeLevel = 0;
+}
+
+#endif /* XML_DTD */
diff --git a/parser/expat/lib/xmlrole.h b/parser/expat/lib/xmlrole.h
new file mode 100644
index 0000000000..4dd9f06f97
--- /dev/null
+++ b/parser/expat/lib/xmlrole.h
@@ -0,0 +1,114 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#ifdef __VMS
+/* 0 1 2 3 0 1 2 3
+ 1234567890123456789012345678901 1234567890123456789012345678901 */
+#define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt
+#endif
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ XML_ROLE_ERROR = -1,
+ XML_ROLE_NONE = 0,
+ XML_ROLE_XML_DECL,
+ XML_ROLE_INSTANCE_START,
+ XML_ROLE_DOCTYPE_NONE,
+ XML_ROLE_DOCTYPE_NAME,
+ XML_ROLE_DOCTYPE_SYSTEM_ID,
+ XML_ROLE_DOCTYPE_PUBLIC_ID,
+ XML_ROLE_DOCTYPE_INTERNAL_SUBSET,
+ XML_ROLE_DOCTYPE_CLOSE,
+ XML_ROLE_GENERAL_ENTITY_NAME,
+ XML_ROLE_PARAM_ENTITY_NAME,
+ XML_ROLE_ENTITY_NONE,
+ XML_ROLE_ENTITY_VALUE,
+ XML_ROLE_ENTITY_SYSTEM_ID,
+ XML_ROLE_ENTITY_PUBLIC_ID,
+ XML_ROLE_ENTITY_COMPLETE,
+ XML_ROLE_ENTITY_NOTATION_NAME,
+ XML_ROLE_NOTATION_NONE,
+ XML_ROLE_NOTATION_NAME,
+ XML_ROLE_NOTATION_SYSTEM_ID,
+ XML_ROLE_NOTATION_NO_SYSTEM_ID,
+ XML_ROLE_NOTATION_PUBLIC_ID,
+ XML_ROLE_ATTRIBUTE_NAME,
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+ XML_ROLE_ATTRIBUTE_TYPE_ID,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+ XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+ XML_ROLE_ATTLIST_NONE,
+ XML_ROLE_ATTLIST_ELEMENT_NAME,
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+ XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+ XML_ROLE_ELEMENT_NONE,
+ XML_ROLE_ELEMENT_NAME,
+ XML_ROLE_CONTENT_ANY,
+ XML_ROLE_CONTENT_EMPTY,
+ XML_ROLE_CONTENT_PCDATA,
+ XML_ROLE_GROUP_OPEN,
+ XML_ROLE_GROUP_CLOSE,
+ XML_ROLE_GROUP_CLOSE_REP,
+ XML_ROLE_GROUP_CLOSE_OPT,
+ XML_ROLE_GROUP_CLOSE_PLUS,
+ XML_ROLE_GROUP_CHOICE,
+ XML_ROLE_GROUP_SEQUENCE,
+ XML_ROLE_CONTENT_ELEMENT,
+ XML_ROLE_CONTENT_ELEMENT_REP,
+ XML_ROLE_CONTENT_ELEMENT_OPT,
+ XML_ROLE_CONTENT_ELEMENT_PLUS,
+ XML_ROLE_PI,
+ XML_ROLE_COMMENT,
+#ifdef XML_DTD
+ XML_ROLE_TEXT_DECL,
+ XML_ROLE_IGNORE_SECT,
+ XML_ROLE_INNER_PARAM_ENTITY_REF,
+#endif /* XML_DTD */
+ XML_ROLE_PARAM_ENTITY_REF
+};
+
+typedef struct prolog_state {
+ int (PTRCALL *handler) (struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+ unsigned level;
+ int role_none;
+#ifdef XML_DTD
+ unsigned includeLevel;
+ int documentEntity;
+ int inEntityValue;
+#endif /* XML_DTD */
+} PROLOG_STATE;
+
+void XmlPrologStateInit(PROLOG_STATE *);
+#ifdef XML_DTD
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *);
+#endif /* XML_DTD */
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
diff --git a/parser/expat/lib/xmltok.c b/parser/expat/lib/xmltok.c
new file mode 100644
index 0000000000..f01c2fa996
--- /dev/null
+++ b/parser/expat/lib/xmltok.c
@@ -0,0 +1,1766 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include "winconfig.h"
+#else
+#ifdef HAVE_EXPAT_CONFIG_H
+#include <expat_config.h>
+#endif
+#endif /* ndef _WIN32 */
+
+#include "expat_external.h"
+#include "internal.h"
+#include "xmltok.h"
+#include "nametab.h"
+
+#ifdef XML_DTD
+#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
+#else
+#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
+#endif
+
+#define VTABLE1 \
+ { PREFIX(prologTok), PREFIX(contentTok), \
+ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
+ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+ PREFIX(sameName), \
+ PREFIX(nameMatchesAscii), \
+ PREFIX(nameLength), \
+ PREFIX(skipS), \
+ PREFIX(getAtts), \
+ PREFIX(charRefNumber), \
+ PREFIX(predefinedEntityName), \
+ PREFIX(updatePosition), \
+ PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1u << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits between
+ the bottom 5 and 6 bits of the bytes. We need 8 bits to index into
+ pages, 3 bits to add to that index and 5 bits to generate the mask.
+*/
+#define UTF8_GET_NAMING2(pages, byte) \
+ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+ + ((((byte)[0]) & 3) << 1) \
+ + ((((byte)[1]) >> 5) & 1)] \
+ & (1u << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits between
+ the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index
+ into pages, 3 bits to add to that index and 5 bits to generate the
+ mask.
+*/
+#define UTF8_GET_NAMING3(pages, byte) \
+ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+ + ((((byte)[1]) >> 2) & 0xF)] \
+ << 3) \
+ + ((((byte)[1]) & 3) << 1) \
+ + ((((byte)[2]) >> 5) & 1)] \
+ & (1u << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+ ((n) == 2 \
+ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+ : ((n) == 3 \
+ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+ : 0))
+
+/* Detection of invalid UTF-8 sequences is based on Table 3.1B
+ of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
+ with the additional restriction of not allowing the Unicode
+ code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE).
+ Implementation details:
+ (A & 0x80) == 0 means A < 0x80
+ and
+ (A & 0xC0) == 0xC0 means A > 0xBF
+*/
+
+#define UTF8_INVALID2(p) \
+ ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
+
+#define UTF8_INVALID3(p) \
+ (((p)[2] & 0x80) == 0 \
+ || \
+ ((*p) == 0xEF && (p)[1] == 0xBF \
+ ? \
+ (p)[2] > 0xBD \
+ : \
+ ((p)[2] & 0xC0) == 0xC0) \
+ || \
+ ((*p) == 0xE0 \
+ ? \
+ (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \
+ : \
+ ((p)[1] & 0x80) == 0 \
+ || \
+ ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
+
+#define UTF8_INVALID4(p) \
+ (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 \
+ || \
+ ((p)[2] & 0x80) == 0 || ((p)[2] & 0xC0) == 0xC0 \
+ || \
+ ((*p) == 0xF0 \
+ ? \
+ (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \
+ : \
+ ((p)[1] & 0x80) == 0 \
+ || \
+ ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
+
+static int PTRFASTCALL
+isNever(const ENCODING *UNUSED_P(enc), const char *UNUSED_P(p))
+{
+ return 0;
+}
+
+static int PTRFASTCALL
+utf8_isName2(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isName3(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static int PTRFASTCALL
+utf8_isNmstrt2(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isNmstrt3(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+static int PTRFASTCALL
+utf8_isInvalid2(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_INVALID2((const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isInvalid3(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static int PTRFASTCALL
+utf8_isInvalid4(const ENCODING *UNUSED_P(enc), const char *p)
+{
+ return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+ ENCODING enc;
+ unsigned char type[256];
+#ifdef XML_MIN_SIZE
+ int (PTRFASTCALL *byteType)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
+ int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
+ int (PTRCALL *charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+ int (PTRFASTCALL *isName2)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isName3)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isName4)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
+ int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
+};
+
+#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *) (enc))
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+#define NULL_VTABLE \
+ /* isName2 */ NULL, \
+ /* isName3 */ NULL, \
+ /* isName4 */ NULL, \
+ /* isNmstrt2 */ NULL, \
+ /* isNmstrt3 */ NULL, \
+ /* isNmstrt4 */ NULL, \
+ /* isInvalid2 */ NULL, \
+ /* isInvalid3 */ NULL, \
+ /* isInvalid4 */ NULL
+
+static int FASTCALL checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+#include "ascii.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) 1
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static int PTRFASTCALL
+sb_byteType(const ENCODING *enc, const char *p)
+{
+ return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
+static int PTRFASTCALL
+sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*(p))
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
+static int PTRCALL
+sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#define XML_TOK_IMPL_C
+#include "xmltok_impl.c"
+#undef XML_TOK_IMPL_C
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
+ UTF8_cval1 = 0x00,
+ UTF8_cval2 = 0xc0,
+ UTF8_cval3 = 0xe0,
+ UTF8_cval4 = 0xf0
+};
+
+void
+align_limit_to_full_utf8_characters(const char * from, const char ** fromLimRef)
+{
+ const char * fromLim = *fromLimRef;
+ size_t walked = 0;
+ for (; fromLim > from; fromLim--, walked++) {
+ const unsigned char prev = (unsigned char)fromLim[-1];
+ if ((prev & 0xf8u) == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
+ if (walked + 1 >= 4) {
+ fromLim += 4 - 1;
+ break;
+ } else {
+ walked = 0;
+ }
+ } else if ((prev & 0xf0u) == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
+ if (walked + 1 >= 3) {
+ fromLim += 3 - 1;
+ break;
+ } else {
+ walked = 0;
+ }
+ } else if ((prev & 0xe0u) == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
+ if (walked + 1 >= 2) {
+ fromLim += 2 - 1;
+ break;
+ } else {
+ walked = 0;
+ }
+ } else if ((prev & 0x80u) == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
+ break;
+ }
+ }
+ *fromLimRef = fromLim;
+}
+
+static enum XML_Convert_Result PTRCALL
+utf8_toUtf8(const ENCODING *UNUSED_P(enc),
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char *to;
+ const char *from;
+ const char *fromLimInitial = fromLim;
+
+ /* Avoid copying partial characters. */
+ align_limit_to_full_utf8_characters(*fromP, &fromLim);
+
+ for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++)
+ *to = *from;
+ *fromP = from;
+ *toP = to;
+
+ if (fromLim < fromLimInitial)
+ return XML_CONVERT_INPUT_INCOMPLETE;
+ else if ((to == toLim) && (from < fromLim))
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ else
+ return XML_CONVERT_COMPLETED;
+}
+
+static enum XML_Convert_Result PTRCALL
+utf8_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
+ unsigned short *to = *toP;
+ const char *from = *fromP;
+ while (from < fromLim && to < toLim) {
+ switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+ case BT_LEAD2:
+ if (fromLim - from < 2) {
+ res = XML_CONVERT_INPUT_INCOMPLETE;
+ goto after;
+ }
+ *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
+ from += 2;
+ break;
+ case BT_LEAD3:
+ if (fromLim - from < 3) {
+ res = XML_CONVERT_INPUT_INCOMPLETE;
+ goto after;
+ }
+ *to++ = (unsigned short)(((from[0] & 0xf) << 12)
+ | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
+ from += 3;
+ break;
+ case BT_LEAD4:
+ {
+ unsigned long n;
+ if (toLim - to < 2) {
+ res = XML_CONVERT_OUTPUT_EXHAUSTED;
+ goto after;
+ }
+ if (fromLim - from < 4) {
+ res = XML_CONVERT_INPUT_INCOMPLETE;
+ goto after;
+ }
+ n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
+ | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+ n -= 0x10000;
+ to[0] = (unsigned short)((n >> 10) | 0xD800);
+ to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+ to += 2;
+ from += 4;
+ }
+ break;
+ default:
+ *to++ = *from++;
+ break;
+ }
+ }
+ if (from < fromLim)
+ res = XML_CONVERT_OUTPUT_EXHAUSTED;
+after:
+ *fromP = from;
+ *toP = to;
+ return res;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "iasciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static enum XML_Convert_Result PTRCALL
+latin1_toUtf8(const ENCODING *UNUSED_P(enc),
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ for (;;) {
+ unsigned char c;
+ if (*fromP == fromLim)
+ return XML_CONVERT_COMPLETED;
+ c = (unsigned char)**fromP;
+ if (c & 0x80) {
+ if (toLim - *toP < 2)
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ *(*toP)++ = (char)((c >> 6) | UTF8_cval2);
+ *(*toP)++ = (char)((c & 0x3f) | 0x80);
+ (*fromP)++;
+ }
+ else {
+ if (*toP == toLim)
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ *(*toP)++ = *(*fromP)++;
+ }
+ }
+}
+
+static enum XML_Convert_Result PTRCALL
+latin1_toUtf16(const ENCODING *UNUSED_P(enc),
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP < fromLim && *toP < toLim)
+ *(*toP)++ = (unsigned char)*(*fromP)++;
+
+ if ((*toP == toLim) && (*fromP < fromLim))
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ else
+ return XML_CONVERT_COMPLETED;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE
+};
+
+static enum XML_Convert_Result PTRCALL
+ascii_toUtf8(const ENCODING *UNUSED_P(enc),
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ while (*fromP < fromLim && *toP < toLim)
+ *(*toP)++ = *(*fromP)++;
+
+ if ((*toP == toLim) && (*fromP < fromLim))
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ else
+ return XML_CONVERT_COMPLETED;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE
+};
+
+static int PTRFASTCALL
+unicode_byte_type(char hi, char lo)
+{
+ switch ((unsigned char)hi) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ return BT_LEAD4;
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return BT_TRAIL;
+ case 0xFF:
+ switch ((unsigned char)lo) {
+ case 0xFF:
+ case 0xFE:
+ return BT_NONXML;
+ }
+ break;
+ }
+ return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static enum XML_Convert_Result PTRCALL \
+E ## toUtf8(const ENCODING *UNUSED_P(enc), \
+ const char **fromP, const char *fromLim, \
+ char **toP, const char *toLim) \
+{ \
+ const char *from = *fromP; \
+ fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */ \
+ for (; from < fromLim; from += 2) { \
+ int plane; \
+ unsigned char lo2; \
+ unsigned char lo = GET_LO(from); \
+ unsigned char hi = GET_HI(from); \
+ switch (hi) { \
+ case 0: \
+ if (lo < 0x80) { \
+ if (*toP == toLim) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ *(*toP)++ = lo; \
+ break; \
+ } \
+ /* fall through */ \
+ case 0x1: case 0x2: case 0x3: \
+ case 0x4: case 0x5: case 0x6: case 0x7: \
+ if (toLim - *toP < 2) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ default: \
+ if (toLim - *toP < 3) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+ if (toLim - *toP < 4) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ if (fromLim - from < 4) { \
+ *fromP = from; \
+ return XML_CONVERT_INPUT_INCOMPLETE; \
+ } \
+ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+ *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+ from += 2; \
+ lo2 = GET_LO(from); \
+ *(*toP)++ = (((lo & 0x3) << 4) \
+ | ((GET_HI(from) & 0x3) << 2) \
+ | (lo2 >> 6) \
+ | 0x80); \
+ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+ break; \
+ } \
+ } \
+ *fromP = from; \
+ if (from < fromLim) \
+ return XML_CONVERT_INPUT_INCOMPLETE; \
+ else \
+ return XML_CONVERT_COMPLETED; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static enum XML_Convert_Result PTRCALL \
+E ## toUtf16(const ENCODING *UNUSED_P(enc), \
+ const char **fromP, const char *fromLim, \
+ unsigned short **toP, const unsigned short *toLim) \
+{ \
+ enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
+ fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
+ /* Avoid copying first half only of surrogate */ \
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
+ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
+ fromLim -= 2; \
+ res = XML_CONVERT_INPUT_INCOMPLETE; \
+ } \
+ for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
+ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+ if ((*toP == toLim) && (*fromP < fromLim)) \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ else \
+ return res; \
+}
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+ : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static int PTRFASTCALL
+little2_byteType(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static int PTRFASTCALL
+little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static int PTRCALL
+little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static int PTRFASTCALL
+little2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static int PTRFASTCALL
+little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#define XML_TOK_IMPL_C
+#include "xmltok_impl.c"
+#undef XML_TOK_IMPL_C
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 1234
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 1234
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE
+};
+
+#if BYTEORDER != 4321
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+ : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static int PTRFASTCALL
+big2_byteType(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TYPE(enc, p);
+}
+
+static int PTRFASTCALL
+big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static int PTRCALL
+big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static int PTRFASTCALL
+big2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static int PTRFASTCALL
+big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#define XML_TOK_IMPL_C
+#include "xmltok_impl.c"
+#undef XML_TOK_IMPL_C
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 4321
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+ { VTABLE, 2, 0,
+#if BYTEORDER == 4321
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE
+};
+
+#if BYTEORDER != 1234
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE
+};
+
+#endif
+
+#undef PREFIX
+
+static int FASTCALL
+streqci(const char *s1, const char *s2)
+{
+ for (;;) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (ASCII_a <= c1 && c1 <= ASCII_z)
+ c1 += ASCII_A - ASCII_a;
+ if (ASCII_a <= c2 && c2 <= ASCII_z)
+ c2 += ASCII_A - ASCII_a;
+ if (c1 != c2)
+ return 0;
+ if (!c1)
+ break;
+ }
+ return 1;
+}
+
+static void PTRCALL
+initUpdatePosition(const ENCODING *UNUSED_P(enc), const char *ptr,
+ const char *end, POSITION *pos)
+{
+ normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static int
+toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+ char buf[1];
+ char *p = buf;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+ if (p == buf)
+ return -1;
+ else
+ return buf[0];
+}
+
+static int FASTCALL
+isSpace(int c)
+{
+ switch (c) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ case 0x9:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 if there's just optional white space or there's an S
+ followed by name=val.
+*/
+static int
+parsePseudoAttribute(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **namePtr,
+ const char **nameEndPtr,
+ const char **valPtr,
+ const char **nextTokPtr)
+{
+ int c;
+ char open;
+ if (ptr == end) {
+ *namePtr = NULL;
+ return 1;
+ }
+ if (!isSpace(toAscii(enc, ptr, end))) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(toAscii(enc, ptr, end)));
+ if (ptr == end) {
+ *namePtr = NULL;
+ return 1;
+ }
+ *namePtr = ptr;
+ for (;;) {
+ c = toAscii(enc, ptr, end);
+ if (c == -1) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ if (c == ASCII_EQUALS) {
+ *nameEndPtr = ptr;
+ break;
+ }
+ if (isSpace(c)) {
+ *nameEndPtr = ptr;
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(c = toAscii(enc, ptr, end)));
+ if (c != ASCII_EQUALS) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ ptr += enc->minBytesPerChar;
+ }
+ if (ptr == *namePtr) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ while (isSpace(c)) {
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ }
+ if (c != ASCII_QUOT && c != ASCII_APOS) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ open = (char)c;
+ ptr += enc->minBytesPerChar;
+ *valPtr = ptr;
+ for (;; ptr += enc->minBytesPerChar) {
+ c = toAscii(enc, ptr, end);
+ if (c == open)
+ break;
+ if (!(ASCII_a <= c && c <= ASCII_z)
+ && !(ASCII_A <= c && c <= ASCII_Z)
+ && !(ASCII_0 <= c && c <= ASCII_9)
+ && c != ASCII_PERIOD
+ && c != ASCII_MINUS
+ && c != ASCII_UNDERSCORE) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ }
+ *nextTokPtr = ptr + enc->minBytesPerChar;
+ return 1;
+}
+
+static const char KW_version[] = {
+ ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
+};
+
+static const char KW_encoding[] = {
+ ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
+};
+
+static const char KW_standalone[] = {
+ ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o,
+ ASCII_n, ASCII_e, '\0'
+};
+
+static const char KW_yes[] = {
+ ASCII_y, ASCII_e, ASCII_s, '\0'
+};
+
+static const char KW_no[] = {
+ ASCII_n, ASCII_o, '\0'
+};
+
+/* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=62157) */
+static const char KW_XML_1_0[] = {
+ ASCII_1, ASCII_PERIOD, ASCII_0, '\0'
+};
+/* END MOZILLA CHANGE */
+
+static int
+doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+ const char *,
+ const char *),
+ int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ const char *val = NULL;
+ const char *name = NULL;
+ const char *nameEnd = NULL;
+ ptr += 5 * enc->minBytesPerChar;
+ end -= 2 * enc->minBytesPerChar;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
+ || !name) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
+ if (!isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ }
+ else {
+ if (versionPtr)
+ *versionPtr = val;
+ if (versionEndPtr)
+ *versionEndPtr = ptr;
+/* BEGIN MOZILLA CHANGE (http://bugzilla.mozilla.org/show_bug.cgi?id=62157) */
+ /* Anything else but a version="1.0" is invalid for us, until we support later versions. */
+ if (!XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_XML_1_0)) {
+ *badPtr = val;
+ return 0;
+ }
+/* END MOZILLA CHANGE */
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name) {
+ if (isGeneralTextEntity) {
+ /* a TextDecl must have an EncodingDecl */
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
+ int c = toAscii(enc, val, end);
+ if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
+ *badPtr = val;
+ return 0;
+ }
+ if (encodingName)
+ *encodingName = val;
+ if (encoding)
+ *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name)
+ return 1;
+ }
+ if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
+ || isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
+ if (standalone)
+ *standalone = 1;
+ }
+ else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
+ if (standalone)
+ *standalone = 0;
+ }
+ else {
+ *badPtr = val;
+ return 0;
+ }
+ while (isSpace(toAscii(enc, ptr, end)))
+ ptr += enc->minBytesPerChar;
+ if (ptr != end) {
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+}
+
+static int FASTCALL
+checkCharRefNumber(int result)
+{
+ switch (result >> 8) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return -1;
+ case 0:
+ if (latin1_encoding.type[result] == BT_NONXML)
+ return -1;
+ break;
+ case 0xFF:
+ if (result == 0xFFFE || result == 0xFFFF)
+ return -1;
+ break;
+ }
+ return result;
+}
+
+int FASTCALL
+XmlUtf8Encode(int c, char *buf)
+{
+ enum {
+ /* minN is minimum legal resulting value for N byte sequence */
+ min2 = 0x80,
+ min3 = 0x800,
+ min4 = 0x10000
+ };
+
+ if (c < 0)
+ return 0;
+ if (c < min2) {
+ buf[0] = (char)(c | UTF8_cval1);
+ return 1;
+ }
+ if (c < min3) {
+ buf[0] = (char)((c >> 6) | UTF8_cval2);
+ buf[1] = (char)((c & 0x3f) | 0x80);
+ return 2;
+ }
+ if (c < min4) {
+ buf[0] = (char)((c >> 12) | UTF8_cval3);
+ buf[1] = (char)(((c >> 6) & 0x3f) | 0x80);
+ buf[2] = (char)((c & 0x3f) | 0x80);
+ return 3;
+ }
+ if (c < 0x110000) {
+ buf[0] = (char)((c >> 18) | UTF8_cval4);
+ buf[1] = (char)(((c >> 12) & 0x3f) | 0x80);
+ buf[2] = (char)(((c >> 6) & 0x3f) | 0x80);
+ buf[3] = (char)((c & 0x3f) | 0x80);
+ return 4;
+ }
+ return 0;
+}
+
+int FASTCALL
+XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+ if (charNum < 0)
+ return 0;
+ if (charNum < 0x10000) {
+ buf[0] = (unsigned short)charNum;
+ return 1;
+ }
+ if (charNum < 0x110000) {
+ charNum -= 0x10000;
+ buf[0] = (unsigned short)((charNum >> 10) + 0xD800);
+ buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00);
+ return 2;
+ }
+ return 0;
+}
+
+struct unknown_encoding {
+ struct normal_encoding normal;
+ CONVERTER convert;
+ void *userData;
+ unsigned short utf16[256];
+ char utf8[256][4];
+};
+
+#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *) (enc))
+
+int
+XmlSizeOfUnknownEncoding(void)
+{
+ return sizeof(struct unknown_encoding);
+}
+
+static int PTRFASTCALL
+unknown_isName(const ENCODING *enc, const char *p)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ int c = uenc->convert(uenc->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static int PTRFASTCALL
+unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ int c = uenc->convert(uenc->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static int PTRFASTCALL
+unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ int c = uenc->convert(uenc->userData, p);
+ return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static enum XML_Convert_Result PTRCALL
+unknown_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ char buf[XML_UTF8_ENCODE_MAX];
+ for (;;) {
+ const char *utf8;
+ int n;
+ if (*fromP == fromLim)
+ return XML_CONVERT_COMPLETED;
+ utf8 = uenc->utf8[(unsigned char)**fromP];
+ n = *utf8++;
+ if (n == 0) {
+ int c = uenc->convert(uenc->userData, *fromP);
+ n = XmlUtf8Encode(c, buf);
+ if (n > toLim - *toP)
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ utf8 = buf;
+ *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2));
+ }
+ else {
+ if (n > toLim - *toP)
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ (*fromP)++;
+ }
+ do {
+ *(*toP)++ = *utf8++;
+ } while (--n != 0);
+ }
+}
+
+static enum XML_Convert_Result PTRCALL
+unknown_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
+ while (*fromP < fromLim && *toP < toLim) {
+ unsigned short c = uenc->utf16[(unsigned char)**fromP];
+ if (c == 0) {
+ c = (unsigned short)
+ uenc->convert(uenc->userData, *fromP);
+ *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2));
+ }
+ else
+ (*fromP)++;
+ *(*toP)++ = c;
+ }
+
+ if ((*toP == toLim) && (*fromP < fromLim))
+ return XML_CONVERT_OUTPUT_EXHAUSTED;
+ else
+ return XML_CONVERT_COMPLETED;
+}
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData)
+{
+ int i;
+ struct unknown_encoding *e = (struct unknown_encoding *)mem;
+ for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
+ ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ for (i = 0; i < 128; i++)
+ if (latin1_encoding.type[i] != BT_OTHER
+ && latin1_encoding.type[i] != BT_NONXML
+ && table[i] != i)
+ return 0;
+ for (i = 0; i < 256; i++) {
+ int c = table[i];
+ if (c == -1) {
+ e->normal.type[i] = BT_MALFORM;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else if (c < 0) {
+ if (c < -4)
+ return 0;
+ e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
+ e->utf8[i][0] = 0;
+ e->utf16[i] = 0;
+ }
+ else if (c < 0x80) {
+ if (latin1_encoding.type[c] != BT_OTHER
+ && latin1_encoding.type[c] != BT_NONXML
+ && c != i)
+ return 0;
+ e->normal.type[i] = latin1_encoding.type[c];
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = (char)c;
+ e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
+ }
+ else if (checkCharRefNumber(c) < 0) {
+ e->normal.type[i] = BT_NONXML;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else {
+ if (c > 0xFFFF)
+ return 0;
+ if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NMSTRT;
+ else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NAME;
+ else
+ e->normal.type[i] = BT_OTHER;
+ e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+ e->utf16[i] = (unsigned short)c;
+ }
+ }
+ e->userData = userData;
+ e->convert = convert;
+ if (convert) {
+ e->normal.isName2 = unknown_isName;
+ e->normal.isName3 = unknown_isName;
+ e->normal.isName4 = unknown_isName;
+ e->normal.isNmstrt2 = unknown_isNmstrt;
+ e->normal.isNmstrt3 = unknown_isNmstrt;
+ e->normal.isNmstrt4 = unknown_isNmstrt;
+ e->normal.isInvalid2 = unknown_isInvalid;
+ e->normal.isInvalid3 = unknown_isInvalid;
+ e->normal.isInvalid4 = unknown_isInvalid;
+ }
+ e->normal.enc.utf8Convert = unknown_toUtf8;
+ e->normal.enc.utf16Convert = unknown_toUtf16;
+ return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+ UNKNOWN_ENC = -1,
+ ISO_8859_1_ENC = 0,
+ US_ASCII_ENC,
+ UTF_8_ENC,
+ UTF_16_ENC,
+ UTF_16BE_ENC,
+ UTF_16LE_ENC,
+ /* must match encodingNames up to here */
+ NO_ENC
+};
+
+static const char KW_ISO_8859_1[] = {
+ ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9,
+ ASCII_MINUS, ASCII_1, '\0'
+};
+static const char KW_US_ASCII[] = {
+ ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I,
+ '\0'
+};
+static const char KW_UTF_8[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'
+};
+static const char KW_UTF_16[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'
+};
+static const char KW_UTF_16BE[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E,
+ '\0'
+};
+static const char KW_UTF_16LE[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E,
+ '\0'
+};
+
+static int FASTCALL
+getEncodingIndex(const char *name)
+{
+ static const char * const encodingNames[] = {
+ KW_ISO_8859_1,
+ KW_US_ASCII,
+ KW_UTF_8,
+ KW_UTF_16,
+ KW_UTF_16BE,
+ KW_UTF_16LE,
+ };
+ int i;
+ if (name == NULL)
+ return NO_ENC;
+ for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++)
+ if (streqci(name, encodingNames[i]))
+ return i;
+ return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding
+ specified at initialization in the isUtf16 member.
+*/
+
+#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
+#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
+
+/* This is what detects the encoding. encodingTable maps from
+ encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of
+ the external (protocol) specified encoding; state is
+ XML_CONTENT_STATE if we're parsing an external text entity, and
+ XML_PROLOG_STATE otherwise.
+*/
+
+
+static int
+initScan(const ENCODING * const *encodingTable,
+ const INIT_ENCODING *enc,
+ int state,
+ const char *ptr,
+ const char *end,
+ const char **nextTokPtr)
+{
+ const ENCODING **encPtr;
+
+ if (ptr >= end)
+ return XML_TOK_NONE;
+ encPtr = enc->encPtr;
+ if (ptr + 1 == end) {
+ /* only a single byte available for auto-detection */
+#ifndef XML_DTD /* FIXME */
+ /* a well-formed document entity must have more than one byte */
+ if (state != XML_CONTENT_STATE)
+ return XML_TOK_PARTIAL;
+#endif
+ /* so we're parsing an external text entity... */
+ /* if UTF-16 was externally specified, then we need at least 2 bytes */
+ switch (INIT_ENC_INDEX(enc)) {
+ case UTF_16_ENC:
+ case UTF_16LE_ENC:
+ case UTF_16BE_ENC:
+ return XML_TOK_PARTIAL;
+ }
+ switch ((unsigned char)*ptr) {
+ case 0xFE:
+ case 0xFF:
+ case 0xEF: /* possibly first byte of UTF-8 BOM */
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ /* fall through */
+ case 0x00:
+ case 0x3C:
+ return XML_TOK_PARTIAL;
+ }
+ }
+ else {
+ switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+ case 0xFEFF:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XML_TOK_BOM;
+ /* 00 3C is handled in the default case */
+ case 0x3C00:
+ if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+ || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+ && state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ case 0xFFFE:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XML_TOK_BOM;
+ case 0xEFBB:
+ /* Maybe a UTF-8 BOM (EF BB BF) */
+ /* If there's an explicitly specified (external) encoding
+ of ISO-8859-1 or some flavour of UTF-16
+ and this is an external text entity,
+ don't look for the BOM,
+ because it might be a legal data.
+ */
+ if (state == XML_CONTENT_STATE) {
+ int e = INIT_ENC_INDEX(enc);
+ if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC
+ || e == UTF_16LE_ENC || e == UTF_16_ENC)
+ break;
+ }
+ if (ptr + 2 == end)
+ return XML_TOK_PARTIAL;
+ if ((unsigned char)ptr[2] == 0xBF) {
+ *nextTokPtr = ptr + 3;
+ *encPtr = encodingTable[UTF_8_ENC];
+ return XML_TOK_BOM;
+ }
+ break;
+ default:
+ if (ptr[0] == '\0') {
+ /* 0 isn't a legal data character. Furthermore a document
+ entity can only start with ASCII characters. So the only
+ way this can fail to be big-endian UTF-16 if it it's an
+ external parsed general entity that's labelled as
+ UTF-16LE.
+ */
+ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+ break;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ else if (ptr[1] == '\0') {
+ /* We could recover here in the case:
+ - parsing an external entity
+ - second byte is 0
+ - no externally specified encoding
+ - no encoding declaration
+ by assuming UTF-16LE. But we don't, because this would mean when
+ presented just with a single byte, we couldn't reliably determine
+ whether we needed further bytes.
+ */
+ if (state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ break;
+ }
+ }
+ *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#define XML_TOK_NS_C
+#include "xmltok_ns.c"
+#undef XML_TOK_NS_C
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#define XML_TOK_NS_C
+#include "xmltok_ns.c"
+#undef XML_TOK_NS_C
+
+#undef NS
+#undef ns
+
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData)
+{
+ ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
+ if (enc)
+ ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
+ return enc;
+}
+
+#endif /* XML_NS */
+
+/* BEGIN MOZILLA CHANGE (Mozilla extensions for QName checking) */
+#ifdef MOZILLA_CLIENT
+#include "moz_extensions.c"
+#endif /* MOZILLA_CLIENT */
+/* END MOZILLA CHANGE */
diff --git a/parser/expat/lib/xmltok.h b/parser/expat/lib/xmltok.h
new file mode 100644
index 0000000000..752007e8b9
--- /dev/null
+++ b/parser/expat/lib/xmltok.h
@@ -0,0 +1,322 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be
+ start of illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and
+ XmlContentTok.
+*/
+#define XML_TOK_NONE -4 /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+ might be part of CRLF sequence */
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+ returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok.
+*/
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10 /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and
+ XmlContentTok.
+*/
+#define XML_TOK_PI 11 /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14 /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok for a
+ name with a colon.
+*/
+#define XML_TOK_PREFIXED_NAME 41
+
+#ifdef XML_DTD
+#define XML_TOK_IGNORE_SECT 42
+#endif /* XML_DTD */
+
+#ifdef XML_DTD
+#define XML_N_STATES 4
+#else /* not XML_DTD */
+#define XML_N_STATES 3
+#endif /* not XML_DTD */
+
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+#ifdef XML_DTD
+#define XML_IGNORE_SECTION_STATE 3
+#endif /* XML_DTD */
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+ /* first line and first column are 0 not 1 */
+ XML_Size lineNumber;
+ XML_Size columnNumber;
+} POSITION;
+
+typedef struct {
+ const char *name;
+ const char *valuePtr;
+ const char *valueEnd;
+ char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+typedef int (PTRCALL *SCANNER)(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+
+enum XML_Convert_Result {
+ XML_CONVERT_COMPLETED = 0,
+ XML_CONVERT_INPUT_INCOMPLETE = 1,
+ XML_CONVERT_OUTPUT_EXHAUSTED = 2 /* and therefore potentially input remaining as well */
+};
+
+struct encoding {
+ SCANNER scanners[XML_N_STATES];
+ SCANNER literalScanners[XML_N_LITERAL_TYPES];
+ int (PTRCALL *sameName)(const ENCODING *,
+ const char *,
+ const char *);
+ int (PTRCALL *nameMatchesAscii)(const ENCODING *,
+ const char *,
+ const char *,
+ const char *);
+ int (PTRFASTCALL *nameLength)(const ENCODING *, const char *);
+ const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *);
+ int (PTRCALL *getAtts)(const ENCODING *enc,
+ const char *ptr,
+ int attsMax,
+ ATTRIBUTE *atts);
+ int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (PTRCALL *predefinedEntityName)(const ENCODING *,
+ const char *,
+ const char *);
+ void (PTRCALL *updatePosition)(const ENCODING *,
+ const char *ptr,
+ const char *end,
+ POSITION *);
+ int (PTRCALL *isPublicId)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr);
+ enum XML_Convert_Result (PTRCALL *utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ char **toP,
+ const char *toLim);
+ enum XML_Convert_Result (PTRCALL *utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
+ int minBytesPerChar;
+ char isUtf8;
+ char isUtf16;
+};
+
+/* Scan the string starting at ptr until the end of the next complete
+ token, but do not scan past eptr. Return an integer giving the
+ type of token.
+
+ Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+ Return XML_TOK_PARTIAL when the string does not contain a complete
+ token; nextTokPtr will not be set.
+
+ Return XML_TOK_INVALID when the string does not start a valid
+ token; nextTokPtr will be set to point to the character which made
+ the token invalid.
+
+ Otherwise the string starts with a valid token; nextTokPtr will be
+ set to point to the character following the end of that token.
+
+ Each data character counts as a single token, but adjacent data
+ characters may be returned together. Similarly for characters in
+ the prolog outside literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+#ifdef XML_DTD
+
+#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
+
+#endif /* XML_DTD */
+
+/* This is used for performing a 2nd-level tokenization on the content
+ of a literal that has already been returned by XmlTok.
+*/
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
+ (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+ (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+ (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+ (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+ (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+ (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+ (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+ (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+ ENCODING initEnc;
+ const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int XmlParseXmlDecl(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING *XmlGetUtf8InternalEncoding(void);
+const ENCODING *XmlGetUtf16InternalEncoding(void);
+int FASTCALL XmlUtf8Encode(int charNumber, char *buf);
+int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf);
+int XmlSizeOfUnknownEncoding(void);
+
+
+typedef int (XMLCALL *CONVERTER) (void *userData, const char *p);
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData);
+
+int XmlParseXmlDeclNS(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING *XmlGetUtf8InternalEncodingNS(void);
+const ENCODING *XmlGetUtf16InternalEncodingNS(void);
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ CONVERTER convert,
+ void *userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
diff --git a/parser/expat/lib/xmltok_impl.c b/parser/expat/lib/xmltok_impl.c
new file mode 100644
index 0000000000..5f779c0571
--- /dev/null
+++ b/parser/expat/lib/xmltok_impl.c
@@ -0,0 +1,1779 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* This file is included! */
+#ifdef XML_TOK_IMPL_C
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) (0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+ case BT_NONXML: \
+ case BT_MALFORM: \
+ case BT_TRAIL: \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NAME_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ case BT_DIGIT: \
+ case BT_NAME: \
+ case BT_MINUS: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+
+#define HAS_CHARS(enc, ptr, end, count) \
+ (end - ptr >= count * MINBPC(enc))
+
+#define HAS_CHAR(enc, ptr, end) \
+ HAS_CHARS(enc, ptr, end, 1)
+
+#define REQUIRE_CHARS(enc, ptr, end, count) \
+ { \
+ if (! HAS_CHARS(enc, ptr, end, count)) { \
+ return XML_TOK_PARTIAL; \
+ } \
+ }
+
+#define REQUIRE_CHAR(enc, ptr, end) \
+ REQUIRE_CHARS(enc, ptr, end, 1)
+
+
+/* ptr points to character following "<!-" */
+
+static int PTRCALL
+PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (HAS_CHAR(enc, ptr, end)) {
+ if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_MINUS:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMENT;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static int PTRCALL
+PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COND_SECT_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_PERCNT:
+ REQUIRE_CHARS(enc, ptr, end, 2);
+ /* don't allow <!ENTITY% foo "whatever"> */
+ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+ case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* fall through */
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DECL_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(checkPiTarget)(const ENCODING *UNUSED_P(enc), const char *ptr,
+ const char *end, int *tokPtr)
+{
+ int upper = 0;
+ *tokPtr = XML_TOK_PI;
+ if (end - ptr != MINBPC(enc)*3)
+ return 1;
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_x:
+ break;
+ case ASCII_X:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_m:
+ break;
+ case ASCII_M:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_l:
+ break;
+ case ASCII_L:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ if (upper)
+ return 0;
+ *tokPtr = XML_TOK_XML_DECL;
+ return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static int PTRCALL
+PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ int tok;
+ const char *target = ptr;
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUEST:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+ case BT_QUEST:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(scanCdataSection)(const ENCODING *UNUSED_P(enc), const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A,
+ ASCII_T, ASCII_A, ASCII_LSQB };
+ int i;
+ /* CDATA[ */
+ REQUIRE_CHARS(enc, ptr, end, 6);
+ for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+ if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static int PTRCALL
+PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (ptr >= end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ break;
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CDATA_SECT_CLOSE;
+ case BT_CR:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ case BT_RSQB:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static int PTRCALL
+PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ for (ptr += MINBPC(enc); HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ break;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+#ifdef XML_NS
+ case BT_COLON:
+ /* no need to check qname syntax here,
+ since end-tag must match exactly */
+ ptr += MINBPC(enc);
+ break;
+#endif
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static int PTRCALL
+PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static int PTRCALL
+PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ if (HAS_CHAR(enc, ptr, end)) {
+ if (CHAR_MATCHES(enc, ptr, ASCII_x))
+ return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static int PTRCALL
+PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_NUM:
+ return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static int PTRCALL
+PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon = 0;
+#endif
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ for (;;) {
+ int t;
+
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ t = BYTE_TYPE(enc, ptr);
+ if (t == BT_EQUALS)
+ break;
+ switch (t) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_EQUALS:
+ {
+ int open;
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ for (;;) {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ open = BYTE_TYPE(enc, ptr);
+ if (open == BT_QUOT || open == BT_APOS)
+ break;
+ switch (open) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ REQUIRE_CHAR(enc, ptr, end);
+ t = BYTE_TYPE(enc, ptr);
+ if (t == open)
+ break;
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_AMP:
+ {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
+ }
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ continue;
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static int PTRCALL
+PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon;
+#endif
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_EXCL:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc),
+ end, nextTokPtr);
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_SOL:
+ return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ /* we have a start-tag */
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ {
+ ptr += MINBPC(enc);
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S: case BT_CR: case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ }
+ return XML_TOK_PARTIAL;
+ }
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_NO_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr >= end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LT:
+ return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_AMP:
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ break;
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_RSQB:
+ if (HAS_CHARS(enc, ptr, end, 2)) {
+ if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ if (HAS_CHARS(enc, ptr, end, 3)) {
+ if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_AMP:
+ case BT_LT:
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static int PTRCALL
+PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_PERCENT;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_PARAM_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_POUND_NAME;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return -XML_TOK_POUND_NAME;
+}
+
+static int PTRCALL
+PREFIX(scanLit)(int open, const ENCODING *enc,
+ const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ while (HAS_CHAR(enc, ptr, end)) {
+ int t = BYTE_TYPE(enc, ptr);
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUOT:
+ case BT_APOS:
+ ptr += MINBPC(enc);
+ if (t != open)
+ break;
+ if (! HAS_CHAR(enc, ptr, end))
+ return -XML_TOK_LITERAL;
+ *nextTokPtr = ptr;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ case BT_GT: case BT_PERCNT: case BT_LSQB:
+ return XML_TOK_LITERAL;
+ default:
+ return XML_TOK_INVALID;
+ }
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static int PTRCALL
+PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ if (ptr >= end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_QUOT:
+ return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_APOS:
+ return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LT:
+ {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_EXCL:
+ return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_NONASCII:
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ *nextTokPtr = ptr - MINBPC(enc);
+ return XML_TOK_INSTANCE_START;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ case BT_CR:
+ if (ptr + MINBPC(enc) == end) {
+ *nextTokPtr = end;
+ /* indicate that this might be part of a CR/LF pair */
+ return -XML_TOK_PROLOG_S;
+ }
+ /* fall through */
+ case BT_S: case BT_LF:
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ break;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_LF:
+ break;
+ case BT_CR:
+ /* don't split CR/LF pair */
+ if (ptr + MINBPC(enc) != end)
+ break;
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ case BT_PERCNT:
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_COMMA:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMA;
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_BRACKET;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return -XML_TOK_CLOSE_BRACKET;
+ if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+ REQUIRE_CHARS(enc, ptr, end, 2);
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_COND_SECT_CLOSE;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_BRACKET;
+ case BT_LPAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_PAREN;
+ case BT_RPAR:
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return -XML_TOK_CLOSE_PAREN;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_AST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_ASTERISK;
+ case BT_QUEST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_QUESTION;
+ case BT_PLUS:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_PLUS;
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_GT: case BT_COMMA: case BT_VERBAR:
+ case BT_RPAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_PAREN;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_VERBAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OR;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DECL_CLOSE;
+ case BT_NUM:
+ return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NAME; \
+ break; \
+ } \
+ if (IS_NAME_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NMTOKEN; \
+ break; \
+ } \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NMSTRT:
+ case BT_HEX:
+ tok = XML_TOK_NAME;
+ ptr += MINBPC(enc);
+ break;
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ tok = XML_TOK_NMTOKEN;
+ ptr += MINBPC(enc);
+ break;
+ case BT_NONASCII:
+ if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NAME;
+ break;
+ }
+ if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT: case BT_RPAR: case BT_COMMA:
+ case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return tok;
+#ifdef XML_NS
+ case BT_COLON:
+ ptr += MINBPC(enc);
+ switch (tok) {
+ case XML_TOK_NAME:
+ REQUIRE_CHAR(enc, ptr, end);
+ tok = XML_TOK_PREFIXED_NAME;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+ case XML_TOK_PREFIXED_NAME:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+#endif
+ case BT_PLUS:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_PLUS;
+ case BT_AST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_ASTERISK;
+ case BT_QUEST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_QUESTION;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return -tok;
+}
+
+static int PTRCALL
+PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr >= end)
+ return XML_TOK_NONE;
+ else if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_PARTIAL;
+ start = ptr;
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LT:
+ /* this is for inside entity references */
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_S:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ATTRIBUTE_VALUE_S;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static int PTRCALL
+PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr >= end)
+ return XML_TOK_NONE;
+ else if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_PARTIAL;
+ start = ptr;
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_PERCNT:
+ if (ptr == start) {
+ int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc),
+ end, nextTokPtr);
+ return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+#ifdef XML_DTD
+
+static int PTRCALL
+PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **nextTokPtr)
+{
+ int level = 0;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ end = ptr + n;
+ }
+ }
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_LT:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) {
+ ++level;
+ ptr += MINBPC(enc);
+ }
+ }
+ break;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr += MINBPC(enc);
+ if (level == 0) {
+ *nextTokPtr = ptr;
+ return XML_TOK_IGNORE_SECT;
+ }
+ --level;
+ }
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+#endif /* XML_DTD */
+
+static int PTRCALL
+PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr)
+{
+ ptr += MINBPC(enc);
+ end -= MINBPC(enc);
+ for (; HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ case BT_MINUS:
+ case BT_APOS:
+ case BT_LPAR:
+ case BT_RPAR:
+ case BT_PLUS:
+ case BT_COMMA:
+ case BT_SOL:
+ case BT_EQUALS:
+ case BT_QUEST:
+ case BT_CR:
+ case BT_LF:
+ case BT_SEMI:
+ case BT_EXCL:
+ case BT_AST:
+ case BT_PERCNT:
+ case BT_NUM:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ break;
+ case BT_S:
+ if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ case BT_NAME:
+ case BT_NMSTRT:
+ if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+ break;
+ default:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 0x24: /* $ */
+ case 0x40: /* @ */
+ break;
+ default:
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty
+ element tag. Returns the number of attributes. Pointers to the
+ first attsMax attributes are stored in atts.
+*/
+
+static int PTRCALL
+PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts)
+{
+ enum { other, inName, inValue } state = inName;
+ int nAtts = 0;
+ int open = 0; /* defined when state == inValue;
+ initialization just to shut up compilers */
+
+ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+ if (state == other) { \
+ if (nAtts < attsMax) { \
+ atts[nAtts].name = ptr; \
+ atts[nAtts].normalized = 1; \
+ } \
+ state = inName; \
+ }
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+ case BT_HEX:
+ START_NAME
+ break;
+#undef START_NAME
+ case BT_QUOT:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ open = BT_QUOT;
+ }
+ else if (open == BT_QUOT) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_APOS:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ open = BT_APOS;
+ }
+ else if (open == BT_APOS) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_AMP:
+ if (nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_S:
+ if (state == inName)
+ state = other;
+ else if (state == inValue
+ && nAtts < attsMax
+ && atts[nAtts].normalized
+ && (ptr == atts[nAtts].valuePtr
+ || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
+ || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
+ || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_CR: case BT_LF:
+ /* This case ensures that the first attribute name is counted
+ Apart from that we could just change state on the quote. */
+ if (state == inName)
+ state = other;
+ else if (state == inValue && nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_GT:
+ case BT_SOL:
+ if (state != inValue)
+ return nAtts;
+ break;
+ default:
+ break;
+ }
+ }
+ /* not reached */
+}
+
+static int PTRFASTCALL
+PREFIX(charRefNumber)(const ENCODING *UNUSED_P(enc), const char *ptr)
+{
+ int result = 0;
+ /* skip &# */
+ ptr += 2*MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
+ for (ptr += MINBPC(enc);
+ !CHAR_MATCHES(enc, ptr, ASCII_SEMI);
+ ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ switch (c) {
+ case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
+ case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
+ result <<= 4;
+ result |= (c - ASCII_0);
+ break;
+ case ASCII_A: case ASCII_B: case ASCII_C:
+ case ASCII_D: case ASCII_E: case ASCII_F:
+ result <<= 4;
+ result += 10 + (c - ASCII_A);
+ break;
+ case ASCII_a: case ASCII_b: case ASCII_c:
+ case ASCII_d: case ASCII_e: case ASCII_f:
+ result <<= 4;
+ result += 10 + (c - ASCII_a);
+ break;
+ }
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ else {
+ for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ result *= 10;
+ result += (c - ASCII_0);
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ return checkCharRefNumber(result);
+}
+
+static int PTRCALL
+PREFIX(predefinedEntityName)(const ENCODING *UNUSED_P(enc), const char *ptr,
+ const char *end)
+{
+ switch ((end - ptr)/MINBPC(enc)) {
+ case 2:
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_l:
+ return ASCII_LT;
+ case ASCII_g:
+ return ASCII_GT;
+ }
+ }
+ break;
+ case 3:
+ if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_p))
+ return ASCII_AMP;
+ }
+ }
+ break;
+ case 4:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_q:
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_t))
+ return ASCII_QUOT;
+ }
+ }
+ break;
+ case ASCII_a:
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_s))
+ return ASCII_APOS;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static int PTRCALL
+PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (*ptr1++ != *ptr2++) \
+ return 0;
+ LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+ /* fall through */
+ if (*ptr1++ != *ptr2++)
+ return 0;
+ break;
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 1) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 2) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 3) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+ return 1;
+ switch (BYTE_TYPE(enc, ptr2)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+ }
+ /* not reached */
+}
+
+static int PTRCALL
+PREFIX(nameMatchesAscii)(const ENCODING *UNUSED_P(enc), const char *ptr1,
+ const char *end1, const char *ptr2)
+{
+ for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+ if (end1 - ptr1 < MINBPC(enc))
+ return 0;
+ if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+ return 0;
+ }
+ return ptr1 == end1;
+}
+
+static int PTRFASTCALL
+PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+ const char *start = ptr;
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return (int)(ptr - start);
+ }
+ }
+}
+
+static const char * PTRFASTCALL
+PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LF:
+ case BT_CR:
+ case BT_S:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr;
+ }
+ }
+}
+
+static void PTRCALL
+PREFIX(updatePosition)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ POSITION *pos)
+{
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_LF:
+ pos->columnNumber = (XML_Size)-1;
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ break;
+ case BT_CR:
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ if (HAS_CHAR(enc, ptr, end) && BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ pos->columnNumber = (XML_Size)-1;
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ pos->columnNumber++;
+ }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
+
+#endif /* XML_TOK_IMPL_C */
diff --git a/parser/expat/lib/xmltok_impl.h b/parser/expat/lib/xmltok_impl.h
new file mode 100644
index 0000000000..da0ea60a65
--- /dev/null
+++ b/parser/expat/lib/xmltok_impl.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+enum {
+ BT_NONXML,
+ BT_MALFORM,
+ BT_LT,
+ BT_AMP,
+ BT_RSQB,
+ BT_LEAD2,
+ BT_LEAD3,
+ BT_LEAD4,
+ BT_TRAIL,
+ BT_CR,
+ BT_LF,
+ BT_GT,
+ BT_QUOT,
+ BT_APOS,
+ BT_EQUALS,
+ BT_QUEST,
+ BT_EXCL,
+ BT_SOL,
+ BT_SEMI,
+ BT_NUM,
+ BT_LSQB,
+ BT_S,
+ BT_NMSTRT,
+ BT_COLON,
+ BT_HEX,
+ BT_DIGIT,
+ BT_NAME,
+ BT_MINUS,
+ BT_OTHER, /* known not to be a name or name start character */
+ BT_NONASCII, /* might be a name or name start character */
+ BT_PERCNT,
+ BT_LPAR,
+ BT_RPAR,
+ BT_AST,
+ BT_PLUS,
+ BT_COMMA,
+ BT_VERBAR
+};
+
+#include <stddef.h>
diff --git a/parser/expat/lib/xmltok_ns.c b/parser/expat/lib/xmltok_ns.c
new file mode 100644
index 0000000000..c3b88fdf4e
--- /dev/null
+++ b/parser/expat/lib/xmltok_ns.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+ See the file COPYING for copying permission.
+*/
+
+/* This file is included! */
+#ifdef XML_TOK_NS_C
+
+const ENCODING *
+NS(XmlGetUtf8InternalEncoding)(void)
+{
+ return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *
+NS(XmlGetUtf16InternalEncoding)(void)
+{
+#if BYTEORDER == 1234
+ return &ns(internal_little2_encoding).enc;
+#elif BYTEORDER == 4321
+ return &ns(internal_big2_encoding).enc;
+#else
+ const short n = 1;
+ return (*(const char *)&n
+ ? &ns(internal_little2_encoding).enc
+ : &ns(internal_big2_encoding).enc);
+#endif
+}
+
+static const ENCODING * const NS(encodings)[] = {
+ &ns(latin1_encoding).enc,
+ &ns(ascii_encoding).enc,
+ &ns(utf8_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(little2_encoding).enc,
+ &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static int PTRCALL
+NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc,
+ XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static int PTRCALL
+NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc,
+ XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int
+NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr,
+ const char *name)
+{
+ int i = getEncodingIndex(name);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ SET_INIT_ENC_INDEX(p, i);
+ p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+ p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+ p->initEnc.updatePosition = initUpdatePosition;
+ p->encPtr = encPtr;
+ *encPtr = &(p->initEnc);
+ return 1;
+}
+
+static const ENCODING *
+NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+ char buf[ENCODING_MAX];
+ char *p = buf;
+ int i;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+ if (ptr != end)
+ return 0;
+ *p = 0;
+ if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
+ return enc;
+ i = getEncodingIndex(buf);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ return NS(encodings)[i];
+}
+
+int
+NS(XmlParseXmlDecl)(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ return doParseXmlDecl(NS(findEncoding),
+ isGeneralTextEntity,
+ enc,
+ ptr,
+ end,
+ badPtr,
+ versionPtr,
+ versionEndPtr,
+ encodingName,
+ encoding,
+ standalone);
+}
+
+#endif /* XML_TOK_NS_C */
diff --git a/parser/expat/moz.build b/parser/expat/moz.build
new file mode 100644
index 0000000000..f79e8a9083
--- /dev/null
+++ b/parser/expat/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files('**'):
+ BUG_COMPONENT = ('Core', 'XML')
+
+DIRS += ['lib']
+
+EXPORTS += [
+ 'expat_config.h',
+ 'expat_config_moz.h',
+ 'expat_config_rlbox.h',
+ 'rlbox_expat.h',
+ 'rlbox_expat_types.h',
+]
+
+LOCAL_INCLUDES += [
+ '!/security/rlbox',
+]
diff --git a/parser/expat/rlbox_expat.h b/parser/expat/rlbox_expat.h
new file mode 100644
index 0000000000..38afe93814
--- /dev/null
+++ b/parser/expat/rlbox_expat.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef PARSER_HTML_RLBOX_EXPAT_H_
+#define PARSER_HTML_RLBOX_EXPAT_H_
+
+#include "rlbox_expat_types.h"
+
+// Load general firefox configuration of RLBox
+#include "mozilla/rlbox/rlbox_config.h"
+
+#ifdef MOZ_WASM_SANDBOXING_EXPAT
+// Include the generated header file so that we are able to resolve the symbols
+// in the wasm binary
+# include "rlbox.wasm.h"
+# define RLBOX_USE_STATIC_CALLS() rlbox_wasm2c_sandbox_lookup_symbol
+# include "mozilla/rlbox/rlbox_wasm2c_sandbox.hpp"
+#else
+// Extra configuration for no-op sandbox
+# define RLBOX_USE_STATIC_CALLS() rlbox_noop_sandbox_lookup_symbol
+# include "mozilla/rlbox/rlbox_noop_sandbox.hpp"
+#endif
+
+#include "mozilla/rlbox/rlbox.hpp"
+
+#endif
diff --git a/parser/expat/rlbox_expat_types.h b/parser/expat/rlbox_expat_types.h
new file mode 100644
index 0000000000..8596a213c7
--- /dev/null
+++ b/parser/expat/rlbox_expat_types.h
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef PARSER_HTML_RLBOX_EXPAT_TYPES_H_
+#define PARSER_HTML_RLBOX_EXPAT_TYPES_H_
+
+#include <stddef.h>
+#include "mozilla/rlbox/rlbox_types.hpp"
+
+#ifdef MOZ_WASM_SANDBOXING_EXPAT
+RLBOX_DEFINE_BASE_TYPES_FOR(expat, wasm2c)
+#else
+RLBOX_DEFINE_BASE_TYPES_FOR(expat, noop)
+#endif
+
+#endif
diff --git a/parser/html/jArray.h b/parser/html/jArray.h
new file mode 100644
index 0000000000..a5429e6fd7
--- /dev/null
+++ b/parser/html/jArray.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2008-2015 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef jArray_h
+#define jArray_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/BinarySearch.h"
+#include "nsDebug.h"
+
+template <class T, class L>
+struct staticJArray {
+ const T* arr;
+ const L length;
+ operator T*() { return arr; }
+ T& operator[](L const index) {
+ MOZ_ASSERT(index >= 0, "Array access with negative index.");
+ MOZ_ASSERT(index < length, "Array index out of bounds.");
+ return ((T*)arr)[index];
+ }
+ L binarySearch(T const elem) {
+ size_t idx;
+ bool found = mozilla::BinarySearch(arr, 0, length, elem, &idx);
+ return found ? idx : -1;
+ }
+};
+
+template <class T, class L>
+class autoJArray;
+
+template <class T, class L>
+class jArray {
+ friend class autoJArray<T, L>;
+
+ private:
+ T* arr;
+
+ public:
+ L length;
+ static jArray<T, L> newJArray(L const len) {
+ MOZ_ASSERT(len >= 0, "Negative length.");
+ jArray<T, L> newArray = {new T[size_t(len)], len};
+ return newArray;
+ }
+ static jArray<T, L> newFallibleJArray(L const len) {
+ MOZ_ASSERT(len >= 0, "Negative length.");
+ T* a = new (mozilla::fallible) T[size_t(len)];
+ jArray<T, L> newArray = {a, a ? len : 0};
+ return newArray;
+ }
+ operator T*() { return arr; }
+ T& operator[](L const index) {
+ MOZ_ASSERT(index >= 0, "Array access with negative index.");
+ MOZ_ASSERT(index < length, "Array index out of bounds.");
+ return arr[index];
+ }
+ void operator=(staticJArray<T, L>& other) {
+ arr = (T*)other.arr;
+ length = other.length;
+ }
+ MOZ_IMPLICIT jArray(decltype(nullptr)) : arr(nullptr), length(0) {}
+ jArray() : arr(nullptr), length(0) {}
+
+ private:
+ jArray(T* aArr, L aLength) : arr(aArr), length(aLength) {}
+};
+
+template <class T, class L>
+class autoJArray {
+ private:
+ T* arr;
+
+ public:
+ L length;
+ autoJArray() : arr(0), length(0) {}
+ MOZ_IMPLICIT autoJArray(const jArray<T, L>& other)
+ : arr(other.arr), length(other.length) {}
+ ~autoJArray() { delete[] arr; }
+ operator T*() { return arr; }
+ T& operator[](L const index) {
+ MOZ_ASSERT(index >= 0, "Array access with negative index.");
+ MOZ_ASSERT(index < length, "Array index out of bounds.");
+ return arr[index];
+ }
+ operator jArray<T, L>() {
+ // WARNING! This makes it possible to goof with buffer ownership!
+ // This is needed for the getStack and getListOfActiveFormattingElements
+ // methods to work sensibly.
+ jArray<T, L> newArray = {arr, length};
+ return newArray;
+ }
+ void operator=(const jArray<T, L>& other) {
+ delete[] arr;
+ arr = other.arr;
+ length = other.length;
+ }
+ void operator=(decltype(nullptr)) {
+ // Make assigning null to an array in Java delete the buffer in C++
+ delete[] arr;
+ arr = nullptr;
+ length = 0;
+ }
+};
+
+#endif // jArray_h
diff --git a/parser/html/java/Makefile b/parser/html/java/Makefile
new file mode 100644
index 0000000000..5dd7d6bb0a
--- /dev/null
+++ b/parser/html/java/Makefile
@@ -0,0 +1,52 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+libs:: translator
+
+translator:: javaparser \
+; mkdir -p htmlparser/bin && \
+ find htmlparser/translator-src/nu/validator/htmlparser -name "*.java" | \
+ xargs javac -cp javaparser.jar -g -d htmlparser/bin && \
+ jar cfm translator.jar manifest.txt -C htmlparser/bin .
+
+javaparser:: \
+; mkdir -p javaparser/bin && \
+ find javaparser/src -name "*.java" | \
+ xargs javac -encoding ISO-8859-1 -g -d javaparser/bin && \
+ jar cf javaparser.jar -C javaparser/bin .
+
+sync_javaparser:: \
+; if [ ! -d javaparser/.git ] ; \
+ then rm -rf javaparser ; \
+ git clone https://github.com/javaparser/javaparser.git ; \
+ fi ; \
+ cd javaparser ; git checkout javaparser-1.0.6 ; cd ..
+
+sync_htmlparser:: \
+; if [ -d htmlparser/.hg ] ; \
+ then echo "The htmlparser repo has move to GitHub. Please remove the htmlparser directory and resync." ; exit ; \
+ elif [ ! -d htmlparser/.git ] ; \
+ then rm -rf htmlparser ; \
+ git clone https://github.com/validator/htmlparser.git ; \
+ cd htmlparser ; git checkout master ; cd .. ; \
+ fi
+
+sync:: sync_javaparser sync_htmlparser
+
+translate:: translator \
+; mkdir -p ../javasrc ; \
+ java -jar translator.jar \
+ htmlparser/src/nu/validator/htmlparser/impl \
+ .. ../../../xpcom/ds/StaticAtoms.py ../../../xpcom/ds/HTMLAtoms.py
+
+translate_from_snapshot:: translator \
+; mkdir -p ../javasrc ; \
+ java -jar translator.jar \
+ ../javasrc \
+ .. ../../../xpcom/ds/StaticAtoms.py ../../../xpcom/ds/HTMLAtoms.py
+
+named_characters:: translator \
+; java -cp translator.jar \
+ nu.validator.htmlparser.generator.GenerateNamedCharactersCpp \
+ named-character-references.html ../
diff --git a/parser/html/java/README.txt b/parser/html/java/README.txt
new file mode 100644
index 0000000000..13eeb9a5cf
--- /dev/null
+++ b/parser/html/java/README.txt
@@ -0,0 +1,86 @@
+If this is your first time building the HTML5 parser, you need to execute the
+following commands (from this directory) to bootstrap the translation:
+
+ make sync # fetch remote source files and licenses
+ make translate # perform the Java-to-C++ translation from the remote
+ # sources
+ make named_characters # Generate tables for named character tokenization
+
+If you make changes to the translator or the javaparser, you can rebuild by
+retyping 'make' in this directory. If you make changes to the HTML5 Java
+implementation, you can retranslate the Java sources from the htmlparser
+repository by retyping 'make translate' in this directory.
+
+The makefile supports the following targets:
+
+sync_htmlparser:
+ Retrieves the HTML parser and Java to C++ translator sources from GitHub.
+sync_javaparser:
+ Retrieves the javaparser sources from GitHub.
+sync:
+ Runs both sync_javaparser and sync_htmlparser.
+javaparser:
+ Builds the javaparser library retrieved earlier by sync_javaparser.
+translator:
+ Runs the javaparser target and then builds the Java to C++ translator from
+ sources retrieved earlier by sync_htmlparser.
+libs:
+ The default target. Alias for translator
+translate:
+ Runs the translator target and then translates the HTML parser sources
+ retrieved by sync_htmlparser copying the Java sources to ../javasrc.
+translate_from_snapshot:
+ Runs the translator target and then translates the HTML parser sources
+ stored in ../javasrc.
+named_characters:
+ Generates data tables for named character tokenization.
+
+## How to add an attribute
+
+# starting from the root of a mozilla-central checkout
+cd parser/html/java/
+make sync
+# now you have a clone of https://github.com/validator/htmlparser/tree/master in parser/html/java/htmlparser/
+cd htmlparser/src/
+$EDITOR nu/validator/htmlparser/impl/AttributeName.java
+# Search for the word "uncomment" and uncomment stuff according to the comments that talk about uncommenting
+# Duplicate the declaration a normal attribute (nothings special in SVG mode, etc.). Let's use "alt", since it's the first one.
+# In the duplicate, replace ALT with the new name in all caps and "alt" with the new name in quotes in lower case.
+# Search for "ALT,", duplicate that line and change the duplicate to say the new name in all caps followed by comma.
+# Save.
+javac nu/validator/htmlparser/impl/AttributeName.java
+java nu.validator.htmlparser.impl.AttributeName
+# Copy and paste the output into nu/validator/htmlparser/impl/AttributeName.java replacing the text below the comment "START GENERATED CODE" and above the very last "}".
+# Recomment the bits that you uncommented earlier.
+# Save.
+cd ../.. # Back to parser/html/java/
+make translate
+cd ../../..
+./mach clang-format
+
+## How to add an element
+
+# First, add an entry to parser/htmlparser/nsHTMLTagList.h or dom/svg/SVGTagList.h!
+# Then, starting from the root of a mozilla-central checkout
+cd parser/html/java/
+make sync
+# now you have a clone of https://github.com/validator/htmlparser/tree/master in parser/html/java/htmlparser/
+cd htmlparser/src/
+$EDITOR nu/validator/htmlparser/impl/ElementName.java
+# Search for the word "uncomment" and uncomment stuff according to the comments that talk about uncommenting
+# Duplicate the declaration a normal element. Let's use "bdo", since it's the first normal one.
+# In the duplicate, replace BDO with the new name in all caps and "bdo" with the new name in quotes in lower case (twice).
+# Search for "BDO,", duplicate that line and change the duplicate to say the new name in all caps followed by comma.
+# Save.
+javac nu/validator/htmlparser/impl/ElementName.java
+java nu.validator.htmlparser.impl.ElementName ../../../../../parser/htmlparser/nsHTMLTagList.h ../../../../../dom/svg/SVGTagList.h
+# Copy and paste the output into nu/validator/htmlparser/impl/ElementName.java replacing the text below the comment "START GENERATED CODE" and above the very last "}".
+# Recomment the bits that you uncommented earlier.
+# Save.
+cd ../.. # Back to parser/html/java/
+make translate
+cd ../../..
+./mach clang-format
+
+Ben Newman (23 September 2009)
+Henri Sivonen (10 August 2017, 10 February 2020)
diff --git a/parser/html/java/manifest.txt b/parser/html/java/manifest.txt
new file mode 100644
index 0000000000..14cd9d0819
--- /dev/null
+++ b/parser/html/java/manifest.txt
@@ -0,0 +1,2 @@
+Main-Class: nu.validator.htmlparser.cpptranslate.Main
+Class-Path: javaparser.jar
diff --git a/parser/html/java/named-character-references.html b/parser/html/java/named-character-references.html
new file mode 100644
index 0000000000..c8d1e08daf
--- /dev/null
+++ b/parser/html/java/named-character-references.html
@@ -0,0 +1,7 @@
+<!--
+Spec rev 4381
+-->
+
+ <table><thead><tr><th> Name </th> <th> Character </th> <tbody><tr><td> <code title="">AElig;</code> </td> <td> U+000C6 </td> <tr><td> <code title="">AElig</code> </td> <td> U+000C6 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">AMP;</code> </td> <td> U+00026 </td> <tr><td> <code title="">AMP</code> </td> <td> U+00026 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Aacute;</code> </td> <td> U+000C1 </td> <tr><td> <code title="">Aacute</code> </td> <td> U+000C1 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Abreve;</code> </td> <td> U+00102 </td> <tr><td> <code title="">Acirc;</code> </td> <td> U+000C2 </td> <tr><td> <code title="">Acirc</code> </td> <td> U+000C2 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Acy;</code> </td> <td> U+00410 </td> <tr><td> <code title="">Afr;</code> </td> <td> U+1D504 </td> <tr><td> <code title="">Agrave;</code> </td> <td> U+000C0 </td> <tr><td> <code title="">Agrave</code> </td> <td> U+000C0 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Alpha;</code> </td> <td> U+00391 </td> <tr><td> <code title="">Amacr;</code> </td> <td> U+00100 </td> <tr><td> <code title="">And;</code> </td> <td> U+02A53 </td> <tr><td> <code title="">Aogon;</code> </td> <td> U+00104 </td> <tr><td> <code title="">Aopf;</code> </td> <td> U+1D538 </td> <tr><td> <code title="">ApplyFunction;</code> </td> <td> U+02061 </td> <tr><td> <code title="">Aring;</code> </td> <td> U+000C5 </td> <tr><td> <code title="">Aring</code> </td> <td> U+000C5 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ascr;</code> </td> <td> U+1D49C </td> <tr><td> <code title="">Assign;</code> </td> <td> U+02254 </td> <tr><td> <code title="">Atilde;</code> </td> <td> U+000C3 </td> <tr><td> <code title="">Atilde</code> </td> <td> U+000C3 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Auml;</code> </td> <td> U+000C4 </td> <tr><td> <code title="">Auml</code> </td> <td> U+000C4 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Backslash;</code> </td> <td> U+02216 </td> <tr><td> <code title="">Barv;</code> </td> <td> U+02AE7 </td> <tr><td> <code title="">Barwed;</code> </td> <td> U+02306 </td> <tr><td> <code title="">Bcy;</code> </td> <td> U+00411 </td> <tr><td> <code title="">Because;</code> </td> <td> U+02235 </td> <tr><td> <code title="">Bernoullis;</code> </td> <td> U+0212C </td> <tr><td> <code title="">Beta;</code> </td> <td> U+00392 </td> <tr><td> <code title="">Bfr;</code> </td> <td> U+1D505 </td> <tr><td> <code title="">Bopf;</code> </td> <td> U+1D539 </td> <tr><td> <code title="">Breve;</code> </td> <td> U+002D8 </td> <tr><td> <code title="">Bscr;</code> </td> <td> U+0212C </td> <tr><td> <code title="">Bumpeq;</code> </td> <td> U+0224E </td> <tr><td> <code title="">CHcy;</code> </td> <td> U+00427 </td> <tr><td> <code title="">COPY;</code> </td> <td> U+000A9 </td> <tr><td> <code title="">COPY</code> </td> <td> U+000A9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Cacute;</code> </td> <td> U+00106 </td> <tr><td> <code title="">Cap;</code> </td> <td> U+022D2 </td> <tr><td> <code title="">CapitalDifferentialD;</code> </td> <td> U+02145 </td> <tr><td> <code title="">Cayleys;</code> </td> <td> U+0212D </td> <tr><td> <code title="">Ccaron;</code> </td> <td> U+0010C </td> <tr><td> <code title="">Ccedil;</code> </td> <td> U+000C7 </td> <tr><td> <code title="">Ccedil</code> </td> <td> U+000C7 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ccirc;</code> </td> <td> U+00108 </td> <tr><td> <code title="">Cconint;</code> </td> <td> U+02230 </td> <tr><td> <code title="">Cdot;</code> </td> <td> U+0010A </td> <tr><td> <code title="">Cedilla;</code> </td> <td> U+000B8 </td> <tr><td> <code title="">CenterDot;</code> </td> <td> U+000B7 </td> <tr><td> <code title="">Cfr;</code> </td> <td> U+0212D </td> <tr><td> <code title="">Chi;</code> </td> <td> U+003A7 </td> <tr><td> <code title="">CircleDot;</code> </td> <td> U+02299 </td> <tr><td> <code title="">CircleMinus;</code> </td> <td> U+02296 </td> <tr><td> <code title="">CirclePlus;</code> </td> <td> U+02295 </td> <tr><td> <code title="">CircleTimes;</code> </td> <td> U+02297 </td> <tr><td> <code title="">ClockwiseContourIntegral;</code> </td> <td> U+02232 </td> <tr><td> <code title="">CloseCurlyDoubleQuote;</code> </td> <td> U+0201D </td> <tr><td> <code title="">CloseCurlyQuote;</code> </td> <td> U+02019 </td> <tr><td> <code title="">Colon;</code> </td> <td> U+02237 </td> <tr><td> <code title="">Colone;</code> </td> <td> U+02A74 </td> <tr><td> <code title="">Congruent;</code> </td> <td> U+02261 </td> <tr><td> <code title="">Conint;</code> </td> <td> U+0222F </td> <tr><td> <code title="">ContourIntegral;</code> </td> <td> U+0222E </td> <tr><td> <code title="">Copf;</code> </td> <td> U+02102 </td> <tr><td> <code title="">Coproduct;</code> </td> <td> U+02210 </td> <tr><td> <code title="">CounterClockwiseContourIntegral;</code> </td> <td> U+02233 </td> <tr><td> <code title="">Cross;</code> </td> <td> U+02A2F </td> <tr><td> <code title="">Cscr;</code> </td> <td> U+1D49E </td> <tr><td> <code title="">Cup;</code> </td> <td> U+022D3 </td> <tr><td> <code title="">CupCap;</code> </td> <td> U+0224D </td> <tr><td> <code title="">DD;</code> </td> <td> U+02145 </td> <tr><td> <code title="">DDotrahd;</code> </td> <td> U+02911 </td> <tr><td> <code title="">DJcy;</code> </td> <td> U+00402 </td> <tr><td> <code title="">DScy;</code> </td> <td> U+00405 </td> <tr><td> <code title="">DZcy;</code> </td> <td> U+0040F </td> <tr><td> <code title="">Dagger;</code> </td> <td> U+02021 </td> <tr><td> <code title="">Darr;</code> </td> <td> U+021A1 </td> <tr><td> <code title="">Dashv;</code> </td> <td> U+02AE4 </td> <tr><td> <code title="">Dcaron;</code> </td> <td> U+0010E </td> <tr><td> <code title="">Dcy;</code> </td> <td> U+00414 </td> <tr><td> <code title="">Del;</code> </td> <td> U+02207 </td> <tr><td> <code title="">Delta;</code> </td> <td> U+00394 </td> <tr><td> <code title="">Dfr;</code> </td> <td> U+1D507 </td> <tr><td> <code title="">DiacriticalAcute;</code> </td> <td> U+000B4 </td> <tr><td> <code title="">DiacriticalDot;</code> </td> <td> U+002D9 </td> <tr><td> <code title="">DiacriticalDoubleAcute;</code> </td> <td> U+002DD </td> <tr><td> <code title="">DiacriticalGrave;</code> </td> <td> U+00060 </td> <tr><td> <code title="">DiacriticalTilde;</code> </td> <td> U+002DC </td> <tr><td> <code title="">Diamond;</code> </td> <td> U+022C4 </td> <tr><td> <code title="">DifferentialD;</code> </td> <td> U+02146 </td> <tr><td> <code title="">Dopf;</code> </td> <td> U+1D53B </td> <tr><td> <code title="">Dot;</code> </td> <td> U+000A8 </td> <tr><td> <code title="">DotDot;</code> </td> <td> U+020DC </td> <tr><td> <code title="">DotEqual;</code> </td> <td> U+02250 </td> <tr><td> <code title="">DoubleContourIntegral;</code> </td> <td> U+0222F </td> <tr><td> <code title="">DoubleDot;</code> </td> <td> U+000A8 </td> <tr><td> <code title="">DoubleDownArrow;</code> </td> <td> U+021D3 </td> <tr><td> <code title="">DoubleLeftArrow;</code> </td> <td> U+021D0 </td> <tr><td> <code title="">DoubleLeftRightArrow;</code> </td> <td> U+021D4 </td> <tr><td> <code title="">DoubleLeftTee;</code> </td> <td> U+02AE4 </td> <tr><td> <code title="">DoubleLongLeftArrow;</code> </td> <td> U+027F8 </td> <tr><td> <code title="">DoubleLongLeftRightArrow;</code> </td> <td> U+027FA </td> <tr><td> <code title="">DoubleLongRightArrow;</code> </td> <td> U+027F9 </td> <tr><td> <code title="">DoubleRightArrow;</code> </td> <td> U+021D2 </td> <tr><td> <code title="">DoubleRightTee;</code> </td> <td> U+022A8 </td> <tr><td> <code title="">DoubleUpArrow;</code> </td> <td> U+021D1 </td> <tr><td> <code title="">DoubleUpDownArrow;</code> </td> <td> U+021D5 </td> <tr><td> <code title="">DoubleVerticalBar;</code> </td> <td> U+02225 </td> <tr><td> <code title="">DownArrow;</code> </td> <td> U+02193 </td> <tr><td> <code title="">DownArrowBar;</code> </td> <td> U+02913 </td> <tr><td> <code title="">DownArrowUpArrow;</code> </td> <td> U+021F5 </td> <tr><td> <code title="">DownBreve;</code> </td> <td> U+00311 </td> <tr><td> <code title="">DownLeftRightVector;</code> </td> <td> U+02950 </td> <tr><td> <code title="">DownLeftTeeVector;</code> </td> <td> U+0295E </td> <tr><td> <code title="">DownLeftVector;</code> </td> <td> U+021BD </td> <tr><td> <code title="">DownLeftVectorBar;</code> </td> <td> U+02956 </td> <tr><td> <code title="">DownRightTeeVector;</code> </td> <td> U+0295F </td> <tr><td> <code title="">DownRightVector;</code> </td> <td> U+021C1 </td> <tr><td> <code title="">DownRightVectorBar;</code> </td> <td> U+02957 </td> <tr><td> <code title="">DownTee;</code> </td> <td> U+022A4 </td> <tr><td> <code title="">DownTeeArrow;</code> </td> <td> U+021A7 </td> <tr><td> <code title="">Downarrow;</code> </td> <td> U+021D3 </td> <tr><td> <code title="">Dscr;</code> </td> <td> U+1D49F </td> <tr><td> <code title="">Dstrok;</code> </td> <td> U+00110 </td> <tr><td> <code title="">ENG;</code> </td> <td> U+0014A </td> <tr><td> <code title="">ETH;</code> </td> <td> U+000D0 </td> <tr><td> <code title="">ETH</code> </td> <td> U+000D0 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Eacute;</code> </td> <td> U+000C9 </td> <tr><td> <code title="">Eacute</code> </td> <td> U+000C9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ecaron;</code> </td> <td> U+0011A </td> <tr><td> <code title="">Ecirc;</code> </td> <td> U+000CA </td> <tr><td> <code title="">Ecirc</code> </td> <td> U+000CA </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ecy;</code> </td> <td> U+0042D </td> <tr><td> <code title="">Edot;</code> </td> <td> U+00116 </td> <tr><td> <code title="">Efr;</code> </td> <td> U+1D508 </td> <tr><td> <code title="">Egrave;</code> </td> <td> U+000C8 </td> <tr><td> <code title="">Egrave</code> </td> <td> U+000C8 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Element;</code> </td> <td> U+02208 </td> <tr><td> <code title="">Emacr;</code> </td> <td> U+00112 </td> <tr><td> <code title="">EmptySmallSquare;</code> </td> <td> U+025FB </td> <tr><td> <code title="">EmptyVerySmallSquare;</code> </td> <td> U+025AB </td> <tr><td> <code title="">Eogon;</code> </td> <td> U+00118 </td> <tr><td> <code title="">Eopf;</code> </td> <td> U+1D53C </td> <tr><td> <code title="">Epsilon;</code> </td> <td> U+00395 </td> <tr><td> <code title="">Equal;</code> </td> <td> U+02A75 </td> <tr><td> <code title="">EqualTilde;</code> </td> <td> U+02242 </td> <tr><td> <code title="">Equilibrium;</code> </td> <td> U+021CC </td> <tr><td> <code title="">Escr;</code> </td> <td> U+02130 </td> <tr><td> <code title="">Esim;</code> </td> <td> U+02A73 </td> <tr><td> <code title="">Eta;</code> </td> <td> U+00397 </td> <tr><td> <code title="">Euml;</code> </td> <td> U+000CB </td> <tr><td> <code title="">Euml</code> </td> <td> U+000CB </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Exists;</code> </td> <td> U+02203 </td> <tr><td> <code title="">ExponentialE;</code> </td> <td> U+02147 </td> <tr><td> <code title="">Fcy;</code> </td> <td> U+00424 </td> <tr><td> <code title="">Ffr;</code> </td> <td> U+1D509 </td> <tr><td> <code title="">FilledSmallSquare;</code> </td> <td> U+025FC </td> <tr><td> <code title="">FilledVerySmallSquare;</code> </td> <td> U+025AA </td> <tr><td> <code title="">Fopf;</code> </td> <td> U+1D53D </td> <tr><td> <code title="">ForAll;</code> </td> <td> U+02200 </td> <tr><td> <code title="">Fouriertrf;</code> </td> <td> U+02131 </td> <tr><td> <code title="">Fscr;</code> </td> <td> U+02131 </td> <tr><td> <code title="">GJcy;</code> </td> <td> U+00403 </td> <tr><td> <code title="">GT;</code> </td> <td> U+0003E </td> <tr><td> <code title="">GT</code> </td> <td> U+0003E </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Gamma;</code> </td> <td> U+00393 </td> <tr><td> <code title="">Gammad;</code> </td> <td> U+003DC </td> <tr><td> <code title="">Gbreve;</code> </td> <td> U+0011E </td> <tr><td> <code title="">Gcedil;</code> </td> <td> U+00122 </td> <tr><td> <code title="">Gcirc;</code> </td> <td> U+0011C </td> <tr><td> <code title="">Gcy;</code> </td> <td> U+00413 </td> <tr><td> <code title="">Gdot;</code> </td> <td> U+00120 </td> <tr><td> <code title="">Gfr;</code> </td> <td> U+1D50A </td> <tr><td> <code title="">Gg;</code> </td> <td> U+022D9 </td> <tr><td> <code title="">Gopf;</code> </td> <td> U+1D53E </td> <tr><td> <code title="">GreaterEqual;</code> </td> <td> U+02265 </td> <tr><td> <code title="">GreaterEqualLess;</code> </td> <td> U+022DB </td> <tr><td> <code title="">GreaterFullEqual;</code> </td> <td> U+02267 </td> <tr><td> <code title="">GreaterGreater;</code> </td> <td> U+02AA2 </td> <tr><td> <code title="">GreaterLess;</code> </td> <td> U+02277 </td> <tr><td> <code title="">GreaterSlantEqual;</code> </td> <td> U+02A7E </td> <tr><td> <code title="">GreaterTilde;</code> </td> <td> U+02273 </td> <tr><td> <code title="">Gscr;</code> </td> <td> U+1D4A2 </td> <tr><td> <code title="">Gt;</code> </td> <td> U+0226B </td> <tr><td> <code title="">HARDcy;</code> </td> <td> U+0042A </td> <tr><td> <code title="">Hacek;</code> </td> <td> U+002C7 </td> <tr><td> <code title="">Hat;</code> </td> <td> U+0005E </td> <tr><td> <code title="">Hcirc;</code> </td> <td> U+00124 </td> <tr><td> <code title="">Hfr;</code> </td> <td> U+0210C </td> <tr><td> <code title="">HilbertSpace;</code> </td> <td> U+0210B </td> <tr><td> <code title="">Hopf;</code> </td> <td> U+0210D </td> <tr><td> <code title="">HorizontalLine;</code> </td> <td> U+02500 </td> <tr><td> <code title="">Hscr;</code> </td> <td> U+0210B </td> <tr><td> <code title="">Hstrok;</code> </td> <td> U+00126 </td> <tr><td> <code title="">HumpDownHump;</code> </td> <td> U+0224E </td> <tr><td> <code title="">HumpEqual;</code> </td> <td> U+0224F </td> <tr><td> <code title="">IEcy;</code> </td> <td> U+00415 </td> <tr><td> <code title="">IJlig;</code> </td> <td> U+00132 </td> <tr><td> <code title="">IOcy;</code> </td> <td> U+00401 </td> <tr><td> <code title="">Iacute;</code> </td> <td> U+000CD </td> <tr><td> <code title="">Iacute</code> </td> <td> U+000CD </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Icirc;</code> </td> <td> U+000CE </td> <tr><td> <code title="">Icirc</code> </td> <td> U+000CE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Icy;</code> </td> <td> U+00418 </td> <tr><td> <code title="">Idot;</code> </td> <td> U+00130 </td> <tr><td> <code title="">Ifr;</code> </td> <td> U+02111 </td> <tr><td> <code title="">Igrave;</code> </td> <td> U+000CC </td> <tr><td> <code title="">Igrave</code> </td> <td> U+000CC </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Im;</code> </td> <td> U+02111 </td> <tr><td> <code title="">Imacr;</code> </td> <td> U+0012A </td> <tr><td> <code title="">ImaginaryI;</code> </td> <td> U+02148 </td> <tr><td> <code title="">Implies;</code> </td> <td> U+021D2 </td> <tr><td> <code title="">Int;</code> </td> <td> U+0222C </td> <tr><td> <code title="">Integral;</code> </td> <td> U+0222B </td> <tr><td> <code title="">Intersection;</code> </td> <td> U+022C2 </td> <tr><td> <code title="">InvisibleComma;</code> </td> <td> U+02063 </td> <tr><td> <code title="">InvisibleTimes;</code> </td> <td> U+02062 </td> <tr><td> <code title="">Iogon;</code> </td> <td> U+0012E </td> <tr><td> <code title="">Iopf;</code> </td> <td> U+1D540 </td> <tr><td> <code title="">Iota;</code> </td> <td> U+00399 </td> <tr><td> <code title="">Iscr;</code> </td> <td> U+02110 </td> <tr><td> <code title="">Itilde;</code> </td> <td> U+00128 </td> <tr><td> <code title="">Iukcy;</code> </td> <td> U+00406 </td> <tr><td> <code title="">Iuml;</code> </td> <td> U+000CF </td> <tr><td> <code title="">Iuml</code> </td> <td> U+000CF </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Jcirc;</code> </td> <td> U+00134 </td> <tr><td> <code title="">Jcy;</code> </td> <td> U+00419 </td> <tr><td> <code title="">Jfr;</code> </td> <td> U+1D50D </td> <tr><td> <code title="">Jopf;</code> </td> <td> U+1D541 </td> <tr><td> <code title="">Jscr;</code> </td> <td> U+1D4A5 </td> <tr><td> <code title="">Jsercy;</code> </td> <td> U+00408 </td> <tr><td> <code title="">Jukcy;</code> </td> <td> U+00404 </td> <tr><td> <code title="">KHcy;</code> </td> <td> U+00425 </td> <tr><td> <code title="">KJcy;</code> </td> <td> U+0040C </td> <tr><td> <code title="">Kappa;</code> </td> <td> U+0039A </td> <tr><td> <code title="">Kcedil;</code> </td> <td> U+00136 </td> <tr><td> <code title="">Kcy;</code> </td> <td> U+0041A </td> <tr><td> <code title="">Kfr;</code> </td> <td> U+1D50E </td> <tr><td> <code title="">Kopf;</code> </td> <td> U+1D542 </td> <tr><td> <code title="">Kscr;</code> </td> <td> U+1D4A6 </td> <tr><td> <code title="">LJcy;</code> </td> <td> U+00409 </td> <tr><td> <code title="">LT;</code> </td> <td> U+0003C </td> <tr><td> <code title="">LT</code> </td> <td> U+0003C </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Lacute;</code> </td> <td> U+00139 </td> <tr><td> <code title="">Lambda;</code> </td> <td> U+0039B </td> <tr><td> <code title="">Lang;</code> </td> <td> U+027EA </td> <tr><td> <code title="">Laplacetrf;</code> </td> <td> U+02112 </td> <tr><td> <code title="">Larr;</code> </td> <td> U+0219E </td> <tr><td> <code title="">Lcaron;</code> </td> <td> U+0013D </td> <tr><td> <code title="">Lcedil;</code> </td> <td> U+0013B </td> <tr><td> <code title="">Lcy;</code> </td> <td> U+0041B </td> <tr><td> <code title="">LeftAngleBracket;</code> </td> <td> U+027E8 </td> <tr><td> <code title="">LeftArrow;</code> </td> <td> U+02190 </td> <tr><td> <code title="">LeftArrowBar;</code> </td> <td> U+021E4 </td> <tr><td> <code title="">LeftArrowRightArrow;</code> </td> <td> U+021C6 </td> <tr><td> <code title="">LeftCeiling;</code> </td> <td> U+02308 </td> <tr><td> <code title="">LeftDoubleBracket;</code> </td> <td> U+027E6 </td> <tr><td> <code title="">LeftDownTeeVector;</code> </td> <td> U+02961 </td> <tr><td> <code title="">LeftDownVector;</code> </td> <td> U+021C3 </td> <tr><td> <code title="">LeftDownVectorBar;</code> </td> <td> U+02959 </td> <tr><td> <code title="">LeftFloor;</code> </td> <td> U+0230A </td> <tr><td> <code title="">LeftRightArrow;</code> </td> <td> U+02194 </td> <tr><td> <code title="">LeftRightVector;</code> </td> <td> U+0294E </td> <tr><td> <code title="">LeftTee;</code> </td> <td> U+022A3 </td> <tr><td> <code title="">LeftTeeArrow;</code> </td> <td> U+021A4 </td> <tr><td> <code title="">LeftTeeVector;</code> </td> <td> U+0295A </td> <tr><td> <code title="">LeftTriangle;</code> </td> <td> U+022B2 </td> <tr><td> <code title="">LeftTriangleBar;</code> </td> <td> U+029CF </td> <tr><td> <code title="">LeftTriangleEqual;</code> </td> <td> U+022B4 </td> <tr><td> <code title="">LeftUpDownVector;</code> </td> <td> U+02951 </td> <tr><td> <code title="">LeftUpTeeVector;</code> </td> <td> U+02960 </td> <tr><td> <code title="">LeftUpVector;</code> </td> <td> U+021BF </td> <tr><td> <code title="">LeftUpVectorBar;</code> </td> <td> U+02958 </td> <tr><td> <code title="">LeftVector;</code> </td> <td> U+021BC </td> <tr><td> <code title="">LeftVectorBar;</code> </td> <td> U+02952 </td> <tr><td> <code title="">Leftarrow;</code> </td> <td> U+021D0 </td> <tr><td> <code title="">Leftrightarrow;</code> </td> <td> U+021D4 </td> <tr><td> <code title="">LessEqualGreater;</code> </td> <td> U+022DA </td> <tr><td> <code title="">LessFullEqual;</code> </td> <td> U+02266 </td> <tr><td> <code title="">LessGreater;</code> </td> <td> U+02276 </td> <tr><td> <code title="">LessLess;</code> </td> <td> U+02AA1 </td> <tr><td> <code title="">LessSlantEqual;</code> </td> <td> U+02A7D </td> <tr><td> <code title="">LessTilde;</code> </td> <td> U+02272 </td> <tr><td> <code title="">Lfr;</code> </td> <td> U+1D50F </td> <tr><td> <code title="">Ll;</code> </td> <td> U+022D8 </td> <tr><td> <code title="">Lleftarrow;</code> </td> <td> U+021DA </td> <tr><td> <code title="">Lmidot;</code> </td> <td> U+0013F </td> <tr><td> <code title="">LongLeftArrow;</code> </td> <td> U+027F5 </td> <tr><td> <code title="">LongLeftRightArrow;</code> </td> <td> U+027F7 </td> <tr><td> <code title="">LongRightArrow;</code> </td> <td> U+027F6 </td> <tr><td> <code title="">Longleftarrow;</code> </td> <td> U+027F8 </td> <tr><td> <code title="">Longleftrightarrow;</code> </td> <td> U+027FA </td> <tr><td> <code title="">Longrightarrow;</code> </td> <td> U+027F9 </td> <tr><td> <code title="">Lopf;</code> </td> <td> U+1D543 </td> <tr><td> <code title="">LowerLeftArrow;</code> </td> <td> U+02199 </td> <tr><td> <code title="">LowerRightArrow;</code> </td> <td> U+02198 </td> <tr><td> <code title="">Lscr;</code> </td> <td> U+02112 </td> <tr><td> <code title="">Lsh;</code> </td> <td> U+021B0 </td> <tr><td> <code title="">Lstrok;</code> </td> <td> U+00141 </td> <tr><td> <code title="">Lt;</code> </td> <td> U+0226A </td> <tr><td> <code title="">Map;</code> </td> <td> U+02905 </td> <tr><td> <code title="">Mcy;</code> </td> <td> U+0041C </td> <tr><td> <code title="">MediumSpace;</code> </td> <td> U+0205F </td> <tr><td> <code title="">Mellintrf;</code> </td> <td> U+02133 </td> <tr><td> <code title="">Mfr;</code> </td> <td> U+1D510 </td> <tr><td> <code title="">MinusPlus;</code> </td> <td> U+02213 </td> <tr><td> <code title="">Mopf;</code> </td> <td> U+1D544 </td> <tr><td> <code title="">Mscr;</code> </td> <td> U+02133 </td> <tr><td> <code title="">Mu;</code> </td> <td> U+0039C </td> <tr><td> <code title="">NJcy;</code> </td> <td> U+0040A </td> <tr><td> <code title="">Nacute;</code> </td> <td> U+00143 </td> <tr><td> <code title="">Ncaron;</code> </td> <td> U+00147 </td> <tr><td> <code title="">Ncedil;</code> </td> <td> U+00145 </td> <tr><td> <code title="">Ncy;</code> </td> <td> U+0041D </td> <tr><td> <code title="">NegativeMediumSpace;</code> </td> <td> U+0200B </td> <tr><td> <code title="">NegativeThickSpace;</code> </td> <td> U+0200B </td> <tr><td> <code title="">NegativeThinSpace;</code> </td> <td> U+0200B </td> <tr><td> <code title="">NegativeVeryThinSpace;</code> </td> <td> U+0200B </td> <tr><td> <code title="">NestedGreaterGreater;</code> </td> <td> U+0226B </td> <tr><td> <code title="">NestedLessLess;</code> </td> <td> U+0226A </td> <tr><td> <code title="">NewLine;</code> </td> <td> U+0000A </td> <tr><td> <code title="">Nfr;</code> </td> <td> U+1D511 </td> <tr><td> <code title="">NoBreak;</code> </td> <td> U+02060 </td> <tr><td> <code title="">NonBreakingSpace;</code> </td> <td> U+000A0 </td> <tr><td> <code title="">Nopf;</code> </td> <td> U+02115 </td> <tr><td> <code title="">Not;</code> </td> <td> U+02AEC </td> <tr><td> <code title="">NotCongruent;</code> </td> <td> U+02262 </td> <tr><td> <code title="">NotCupCap;</code> </td> <td> U+0226D </td> <tr><td> <code title="">NotDoubleVerticalBar;</code> </td> <td> U+02226 </td> <tr><td> <code title="">NotElement;</code> </td> <td> U+02209 </td> <tr><td> <code title="">NotEqual;</code> </td> <td> U+02260 </td> <tr><td> <code title="">NotExists;</code> </td> <td> U+02204 </td> <tr><td> <code title="">NotGreater;</code> </td> <td> U+0226F </td> <tr><td> <code title="">NotGreaterEqual;</code> </td> <td> U+02271 </td> <tr><td> <code title="">NotGreaterLess;</code> </td> <td> U+02279 </td> <tr><td> <code title="">NotGreaterTilde;</code> </td> <td> U+02275 </td> <tr><td> <code title="">NotLeftTriangle;</code> </td> <td> U+022EA </td> <tr><td> <code title="">NotLeftTriangleEqual;</code> </td> <td> U+022EC </td> <tr><td> <code title="">NotLess;</code> </td> <td> U+0226E </td> <tr><td> <code title="">NotLessEqual;</code> </td> <td> U+02270 </td> <tr><td> <code title="">NotLessGreater;</code> </td> <td> U+02278 </td> <tr><td> <code title="">NotLessTilde;</code> </td> <td> U+02274 </td> <tr><td> <code title="">NotPrecedes;</code> </td> <td> U+02280 </td> <tr><td> <code title="">NotPrecedesSlantEqual;</code> </td> <td> U+022E0 </td> <tr><td> <code title="">NotReverseElement;</code> </td> <td> U+0220C </td> <tr><td> <code title="">NotRightTriangle;</code> </td> <td> U+022EB </td> <tr><td> <code title="">NotRightTriangleEqual;</code> </td> <td> U+022ED </td> <tr><td> <code title="">NotSquareSubsetEqual;</code> </td> <td> U+022E2 </td> <tr><td> <code title="">NotSquareSupersetEqual;</code> </td> <td> U+022E3 </td> <tr><td> <code title="">NotSubsetEqual;</code> </td> <td> U+02288 </td> <tr><td> <code title="">NotSucceeds;</code> </td> <td> U+02281 </td> <tr><td> <code title="">NotSucceedsSlantEqual;</code> </td> <td> U+022E1 </td> <tr><td> <code title="">NotSupersetEqual;</code> </td> <td> U+02289 </td> <tr><td> <code title="">NotTilde;</code> </td> <td> U+02241 </td> <tr><td> <code title="">NotTildeEqual;</code> </td> <td> U+02244 </td> <tr><td> <code title="">NotTildeFullEqual;</code> </td> <td> U+02247 </td> <tr><td> <code title="">NotTildeTilde;</code> </td> <td> U+02249 </td> <tr><td> <code title="">NotVerticalBar;</code> </td> <td> U+02224 </td> <tr><td> <code title="">Nscr;</code> </td> <td> U+1D4A9 </td> <tr><td> <code title="">Ntilde;</code> </td> <td> U+000D1 </td> <tr><td> <code title="">Ntilde</code> </td> <td> U+000D1 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Nu;</code> </td> <td> U+0039D </td> <tr><td> <code title="">OElig;</code> </td> <td> U+00152 </td> <tr><td> <code title="">Oacute;</code> </td> <td> U+000D3 </td> <tr><td> <code title="">Oacute</code> </td> <td> U+000D3 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ocirc;</code> </td> <td> U+000D4 </td> <tr><td> <code title="">Ocirc</code> </td> <td> U+000D4 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ocy;</code> </td> <td> U+0041E </td> <tr><td> <code title="">Odblac;</code> </td> <td> U+00150 </td> <tr><td> <code title="">Ofr;</code> </td> <td> U+1D512 </td> <tr><td> <code title="">Ograve;</code> </td> <td> U+000D2 </td> <tr><td> <code title="">Ograve</code> </td> <td> U+000D2 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Omacr;</code> </td> <td> U+0014C </td> <tr><td> <code title="">Omega;</code> </td> <td> U+003A9 </td> <tr><td> <code title="">Omicron;</code> </td> <td> U+0039F </td> <tr><td> <code title="">Oopf;</code> </td> <td> U+1D546 </td> <tr><td> <code title="">OpenCurlyDoubleQuote;</code> </td> <td> U+0201C </td> <tr><td> <code title="">OpenCurlyQuote;</code> </td> <td> U+02018 </td> <tr><td> <code title="">Or;</code> </td> <td> U+02A54 </td> <tr><td> <code title="">Oscr;</code> </td> <td> U+1D4AA </td> <tr><td> <code title="">Oslash;</code> </td> <td> U+000D8 </td> <tr><td> <code title="">Oslash</code> </td> <td> U+000D8 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Otilde;</code> </td> <td> U+000D5 </td> <tr><td> <code title="">Otilde</code> </td> <td> U+000D5 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Otimes;</code> </td> <td> U+02A37 </td> <tr><td> <code title="">Ouml;</code> </td> <td> U+000D6 </td> <tr><td> <code title="">Ouml</code> </td> <td> U+000D6 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">OverBar;</code> </td> <td> U+0203E </td> <tr><td> <code title="">OverBrace;</code> </td> <td> U+023DE </td> <tr><td> <code title="">OverBracket;</code> </td> <td> U+023B4 </td> <tr><td> <code title="">OverParenthesis;</code> </td> <td> U+023DC </td> <tr><td> <code title="">PartialD;</code> </td> <td> U+02202 </td> <tr><td> <code title="">Pcy;</code> </td> <td> U+0041F </td> <tr><td> <code title="">Pfr;</code> </td> <td> U+1D513 </td> <tr><td> <code title="">Phi;</code> </td> <td> U+003A6 </td> <tr><td> <code title="">Pi;</code> </td> <td> U+003A0 </td> <tr><td> <code title="">PlusMinus;</code> </td> <td> U+000B1 </td> <tr><td> <code title="">Poincareplane;</code> </td> <td> U+0210C </td> <tr><td> <code title="">Popf;</code> </td> <td> U+02119 </td> <tr><td> <code title="">Pr;</code> </td> <td> U+02ABB </td> <tr><td> <code title="">Precedes;</code> </td> <td> U+0227A </td> <tr><td> <code title="">PrecedesEqual;</code> </td> <td> U+02AAF </td> <tr><td> <code title="">PrecedesSlantEqual;</code> </td> <td> U+0227C </td> <tr><td> <code title="">PrecedesTilde;</code> </td> <td> U+0227E </td> <tr><td> <code title="">Prime;</code> </td> <td> U+02033 </td> <tr><td> <code title="">Product;</code> </td> <td> U+0220F </td> <tr><td> <code title="">Proportion;</code> </td> <td> U+02237 </td> <tr><td> <code title="">Proportional;</code> </td> <td> U+0221D </td> <tr><td> <code title="">Pscr;</code> </td> <td> U+1D4AB </td> <tr><td> <code title="">Psi;</code> </td> <td> U+003A8 </td> <tr><td> <code title="">QUOT;</code> </td> <td> U+00022 </td> <tr><td> <code title="">QUOT</code> </td> <td> U+00022 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Qfr;</code> </td> <td> U+1D514 </td> <tr><td> <code title="">Qopf;</code> </td> <td> U+0211A </td> <tr><td> <code title="">Qscr;</code> </td> <td> U+1D4AC </td> <tr><td> <code title="">RBarr;</code> </td> <td> U+02910 </td> <tr><td> <code title="">REG;</code> </td> <td> U+000AE </td> <tr><td> <code title="">REG</code> </td> <td> U+000AE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Racute;</code> </td> <td> U+00154 </td> <tr><td> <code title="">Rang;</code> </td> <td> U+027EB </td> <tr><td> <code title="">Rarr;</code> </td> <td> U+021A0 </td> <tr><td> <code title="">Rarrtl;</code> </td> <td> U+02916 </td> <tr><td> <code title="">Rcaron;</code> </td> <td> U+00158 </td> <tr><td> <code title="">Rcedil;</code> </td> <td> U+00156 </td> <tr><td> <code title="">Rcy;</code> </td> <td> U+00420 </td> <tr><td> <code title="">Re;</code> </td> <td> U+0211C </td> <tr><td> <code title="">ReverseElement;</code> </td> <td> U+0220B </td> <tr><td> <code title="">ReverseEquilibrium;</code> </td> <td> U+021CB </td> <tr><td> <code title="">ReverseUpEquilibrium;</code> </td> <td> U+0296F </td> <tr><td> <code title="">Rfr;</code> </td> <td> U+0211C </td> <tr><td> <code title="">Rho;</code> </td> <td> U+003A1 </td> <tr><td> <code title="">RightAngleBracket;</code> </td> <td> U+027E9 </td> <tr><td> <code title="">RightArrow;</code> </td> <td> U+02192 </td> <tr><td> <code title="">RightArrowBar;</code> </td> <td> U+021E5 </td> <tr><td> <code title="">RightArrowLeftArrow;</code> </td> <td> U+021C4 </td> <tr><td> <code title="">RightCeiling;</code> </td> <td> U+02309 </td> <tr><td> <code title="">RightDoubleBracket;</code> </td> <td> U+027E7 </td> <tr><td> <code title="">RightDownTeeVector;</code> </td> <td> U+0295D </td> <tr><td> <code title="">RightDownVector;</code> </td> <td> U+021C2 </td> <tr><td> <code title="">RightDownVectorBar;</code> </td> <td> U+02955 </td> <tr><td> <code title="">RightFloor;</code> </td> <td> U+0230B </td> <tr><td> <code title="">RightTee;</code> </td> <td> U+022A2 </td> <tr><td> <code title="">RightTeeArrow;</code> </td> <td> U+021A6 </td> <tr><td> <code title="">RightTeeVector;</code> </td> <td> U+0295B </td> <tr><td> <code title="">RightTriangle;</code> </td> <td> U+022B3 </td> <tr><td> <code title="">RightTriangleBar;</code> </td> <td> U+029D0 </td> <tr><td> <code title="">RightTriangleEqual;</code> </td> <td> U+022B5 </td> <tr><td> <code title="">RightUpDownVector;</code> </td> <td> U+0294F </td> <tr><td> <code title="">RightUpTeeVector;</code> </td> <td> U+0295C </td> <tr><td> <code title="">RightUpVector;</code> </td> <td> U+021BE </td> <tr><td> <code title="">RightUpVectorBar;</code> </td> <td> U+02954 </td> <tr><td> <code title="">RightVector;</code> </td> <td> U+021C0 </td> <tr><td> <code title="">RightVectorBar;</code> </td> <td> U+02953 </td> <tr><td> <code title="">Rightarrow;</code> </td> <td> U+021D2 </td> <tr><td> <code title="">Ropf;</code> </td> <td> U+0211D </td> <tr><td> <code title="">RoundImplies;</code> </td> <td> U+02970 </td> <tr><td> <code title="">Rrightarrow;</code> </td> <td> U+021DB </td> <tr><td> <code title="">Rscr;</code> </td> <td> U+0211B </td> <tr><td> <code title="">Rsh;</code> </td> <td> U+021B1 </td> <tr><td> <code title="">RuleDelayed;</code> </td> <td> U+029F4 </td> <tr><td> <code title="">SHCHcy;</code> </td> <td> U+00429 </td> <tr><td> <code title="">SHcy;</code> </td> <td> U+00428 </td> <tr><td> <code title="">SOFTcy;</code> </td> <td> U+0042C </td> <tr><td> <code title="">Sacute;</code> </td> <td> U+0015A </td> <tr><td> <code title="">Sc;</code> </td> <td> U+02ABC </td> <tr><td> <code title="">Scaron;</code> </td> <td> U+00160 </td> <tr><td> <code title="">Scedil;</code> </td> <td> U+0015E </td> <tr><td> <code title="">Scirc;</code> </td> <td> U+0015C </td> <tr><td> <code title="">Scy;</code> </td> <td> U+00421 </td> <tr><td> <code title="">Sfr;</code> </td> <td> U+1D516 </td> <tr><td> <code title="">ShortDownArrow;</code> </td> <td> U+02193 </td> <tr><td> <code title="">ShortLeftArrow;</code> </td> <td> U+02190 </td> <tr><td> <code title="">ShortRightArrow;</code> </td> <td> U+02192 </td> <tr><td> <code title="">ShortUpArrow;</code> </td> <td> U+02191 </td> <tr><td> <code title="">Sigma;</code> </td> <td> U+003A3 </td> <tr><td> <code title="">SmallCircle;</code> </td> <td> U+02218 </td> <tr><td> <code title="">Sopf;</code> </td> <td> U+1D54A </td> <tr><td> <code title="">Sqrt;</code> </td> <td> U+0221A </td> <tr><td> <code title="">Square;</code> </td> <td> U+025A1 </td> <tr><td> <code title="">SquareIntersection;</code> </td> <td> U+02293 </td> <tr><td> <code title="">SquareSubset;</code> </td> <td> U+0228F </td> <tr><td> <code title="">SquareSubsetEqual;</code> </td> <td> U+02291 </td> <tr><td> <code title="">SquareSuperset;</code> </td> <td> U+02290 </td> <tr><td> <code title="">SquareSupersetEqual;</code> </td> <td> U+02292 </td> <tr><td> <code title="">SquareUnion;</code> </td> <td> U+02294 </td> <tr><td> <code title="">Sscr;</code> </td> <td> U+1D4AE </td> <tr><td> <code title="">Star;</code> </td> <td> U+022C6 </td> <tr><td> <code title="">Sub;</code> </td> <td> U+022D0 </td> <tr><td> <code title="">Subset;</code> </td> <td> U+022D0 </td> <tr><td> <code title="">SubsetEqual;</code> </td> <td> U+02286 </td> <tr><td> <code title="">Succeeds;</code> </td> <td> U+0227B </td> <tr><td> <code title="">SucceedsEqual;</code> </td> <td> U+02AB0 </td> <tr><td> <code title="">SucceedsSlantEqual;</code> </td> <td> U+0227D </td> <tr><td> <code title="">SucceedsTilde;</code> </td> <td> U+0227F </td> <tr><td> <code title="">SuchThat;</code> </td> <td> U+0220B </td> <tr><td> <code title="">Sum;</code> </td> <td> U+02211 </td> <tr><td> <code title="">Sup;</code> </td> <td> U+022D1 </td> <tr><td> <code title="">Superset;</code> </td> <td> U+02283 </td> <tr><td> <code title="">SupersetEqual;</code> </td> <td> U+02287 </td> <tr><td> <code title="">Supset;</code> </td> <td> U+022D1 </td> <tr><td> <code title="">THORN;</code> </td> <td> U+000DE </td> <tr><td> <code title="">THORN</code> </td> <td> U+000DE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">TRADE;</code> </td> <td> U+02122 </td> <tr><td> <code title="">TSHcy;</code> </td> <td> U+0040B </td> <tr><td> <code title="">TScy;</code> </td> <td> U+00426 </td> <tr><td> <code title="">Tab;</code> </td> <td> U+00009 </td> <tr><td> <code title="">Tau;</code> </td> <td> U+003A4 </td> <tr><td> <code title="">Tcaron;</code> </td> <td> U+00164 </td> <tr><td> <code title="">Tcedil;</code> </td> <td> U+00162 </td> <tr><td> <code title="">Tcy;</code> </td> <td> U+00422 </td> <tr><td> <code title="">Tfr;</code> </td> <td> U+1D517 </td> <tr><td> <code title="">Therefore;</code> </td> <td> U+02234 </td> <tr><td> <code title="">Theta;</code> </td> <td> U+00398 </td> <tr><td> <code title="">ThinSpace;</code> </td> <td> U+02009 </td> <tr><td> <code title="">Tilde;</code> </td> <td> U+0223C </td> <tr><td> <code title="">TildeEqual;</code> </td> <td> U+02243 </td> <tr><td> <code title="">TildeFullEqual;</code> </td> <td> U+02245 </td> <tr><td> <code title="">TildeTilde;</code> </td> <td> U+02248 </td> <tr><td> <code title="">Topf;</code> </td> <td> U+1D54B </td> <tr><td> <code title="">TripleDot;</code> </td> <td> U+020DB </td> <tr><td> <code title="">Tscr;</code> </td> <td> U+1D4AF </td> <tr><td> <code title="">Tstrok;</code> </td> <td> U+00166 </td> <tr><td> <code title="">Uacute;</code> </td> <td> U+000DA </td> <tr><td> <code title="">Uacute</code> </td> <td> U+000DA </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Uarr;</code> </td> <td> U+0219F </td> <tr><td> <code title="">Uarrocir;</code> </td> <td> U+02949 </td> <tr><td> <code title="">Ubrcy;</code> </td> <td> U+0040E </td> <tr><td> <code title="">Ubreve;</code> </td> <td> U+0016C </td> <tr><td> <code title="">Ucirc;</code> </td> <td> U+000DB </td> <tr><td> <code title="">Ucirc</code> </td> <td> U+000DB </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ucy;</code> </td> <td> U+00423 </td> <tr><td> <code title="">Udblac;</code> </td> <td> U+00170 </td> <tr><td> <code title="">Ufr;</code> </td> <td> U+1D518 </td> <tr><td> <code title="">Ugrave;</code> </td> <td> U+000D9 </td> <tr><td> <code title="">Ugrave</code> </td> <td> U+000D9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Umacr;</code> </td> <td> U+0016A </td> <tr><td> <code title="">UnderBar;</code> </td> <td> U+0005F </td> <tr><td> <code title="">UnderBrace;</code> </td> <td> U+023DF </td> <tr><td> <code title="">UnderBracket;</code> </td> <td> U+023B5 </td> <tr><td> <code title="">UnderParenthesis;</code> </td> <td> U+023DD </td> <tr><td> <code title="">Union;</code> </td> <td> U+022C3 </td> <tr><td> <code title="">UnionPlus;</code> </td> <td> U+0228E </td> <tr><td> <code title="">Uogon;</code> </td> <td> U+00172 </td> <tr><td> <code title="">Uopf;</code> </td> <td> U+1D54C </td> <tr><td> <code title="">UpArrow;</code> </td> <td> U+02191 </td> <tr><td> <code title="">UpArrowBar;</code> </td> <td> U+02912 </td> <tr><td> <code title="">UpArrowDownArrow;</code> </td> <td> U+021C5 </td> <tr><td> <code title="">UpDownArrow;</code> </td> <td> U+02195 </td> <tr><td> <code title="">UpEquilibrium;</code> </td> <td> U+0296E </td> <tr><td> <code title="">UpTee;</code> </td> <td> U+022A5 </td> <tr><td> <code title="">UpTeeArrow;</code> </td> <td> U+021A5 </td> <tr><td> <code title="">Uparrow;</code> </td> <td> U+021D1 </td> <tr><td> <code title="">Updownarrow;</code> </td> <td> U+021D5 </td> <tr><td> <code title="">UpperLeftArrow;</code> </td> <td> U+02196 </td> <tr><td> <code title="">UpperRightArrow;</code> </td> <td> U+02197 </td> <tr><td> <code title="">Upsi;</code> </td> <td> U+003D2 </td> <tr><td> <code title="">Upsilon;</code> </td> <td> U+003A5 </td> <tr><td> <code title="">Uring;</code> </td> <td> U+0016E </td> <tr><td> <code title="">Uscr;</code> </td> <td> U+1D4B0 </td> <tr><td> <code title="">Utilde;</code> </td> <td> U+00168 </td> <tr><td> <code title="">Uuml;</code> </td> <td> U+000DC </td> <tr><td> <code title="">Uuml</code> </td> <td> U+000DC </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">VDash;</code> </td> <td> U+022AB </td> <tr><td> <code title="">Vbar;</code> </td> <td> U+02AEB </td> <tr><td> <code title="">Vcy;</code> </td> <td> U+00412 </td> <tr><td> <code title="">Vdash;</code> </td> <td> U+022A9 </td> <tr><td> <code title="">Vdashl;</code> </td> <td> U+02AE6 </td> <tr><td> <code title="">Vee;</code> </td> <td> U+022C1 </td> <tr><td> <code title="">Verbar;</code> </td> <td> U+02016 </td> <tr><td> <code title="">Vert;</code> </td> <td> U+02016 </td> <tr><td> <code title="">VerticalBar;</code> </td> <td> U+02223 </td> <tr><td> <code title="">VerticalLine;</code> </td> <td> U+0007C </td> <tr><td> <code title="">VerticalSeparator;</code> </td> <td> U+02758 </td> <tr><td> <code title="">VerticalTilde;</code> </td> <td> U+02240 </td> <tr><td> <code title="">VeryThinSpace;</code> </td> <td> U+0200A </td> <tr><td> <code title="">Vfr;</code> </td> <td> U+1D519 </td> <tr><td> <code title="">Vopf;</code> </td> <td> U+1D54D </td> <tr><td> <code title="">Vscr;</code> </td> <td> U+1D4B1 </td> <tr><td> <code title="">Vvdash;</code> </td> <td> U+022AA </td> <tr><td> <code title="">Wcirc;</code> </td> <td> U+00174 </td> <tr><td> <code title="">Wedge;</code> </td> <td> U+022C0 </td> <tr><td> <code title="">Wfr;</code> </td> <td> U+1D51A </td> <tr><td> <code title="">Wopf;</code> </td> <td> U+1D54E </td> <tr><td> <code title="">Wscr;</code> </td> <td> U+1D4B2 </td> <tr><td> <code title="">Xfr;</code> </td> <td> U+1D51B </td> <tr><td> <code title="">Xi;</code> </td> <td> U+0039E </td> <tr><td> <code title="">Xopf;</code> </td> <td> U+1D54F </td> <tr><td> <code title="">Xscr;</code> </td> <td> U+1D4B3 </td> <tr><td> <code title="">YAcy;</code> </td> <td> U+0042F </td> <tr><td> <code title="">YIcy;</code> </td> <td> U+00407 </td> <tr><td> <code title="">YUcy;</code> </td> <td> U+0042E </td> <tr><td> <code title="">Yacute;</code> </td> <td> U+000DD </td> <tr><td> <code title="">Yacute</code> </td> <td> U+000DD </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">Ycirc;</code> </td> <td> U+00176 </td> <tr><td> <code title="">Ycy;</code> </td> <td> U+0042B </td> <tr><td> <code title="">Yfr;</code> </td> <td> U+1D51C </td> <tr><td> <code title="">Yopf;</code> </td> <td> U+1D550 </td> <tr><td> <code title="">Yscr;</code> </td> <td> U+1D4B4 </td> <tr><td> <code title="">Yuml;</code> </td> <td> U+00178 </td> <tr><td> <code title="">ZHcy;</code> </td> <td> U+00416 </td> <tr><td> <code title="">Zacute;</code> </td> <td> U+00179 </td> <tr><td> <code title="">Zcaron;</code> </td> <td> U+0017D </td> <tr><td> <code title="">Zcy;</code> </td> <td> U+00417 </td> <tr><td> <code title="">Zdot;</code> </td> <td> U+0017B </td> <tr><td> <code title="">ZeroWidthSpace;</code> </td> <td> U+0200B </td> <tr><td> <code title="">Zeta;</code> </td> <td> U+00396 </td> <tr><td> <code title="">Zfr;</code> </td> <td> U+02128 </td> <tr><td> <code title="">Zopf;</code> </td> <td> U+02124 </td> <tr><td> <code title="">Zscr;</code> </td> <td> U+1D4B5 </td> <tr><td> <code title="">aacute;</code> </td> <td> U+000E1 </td> <tr><td> <code title="">aacute</code> </td> <td> U+000E1 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">abreve;</code> </td> <td> U+00103 </td> <tr><td> <code title="">ac;</code> </td> <td> U+0223E </td> <tr><td> <code title="">acd;</code> </td> <td> U+0223F </td> <tr><td> <code title="">acirc;</code> </td> <td> U+000E2 </td> <tr><td> <code title="">acirc</code> </td> <td> U+000E2 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">acute;</code> </td> <td> U+000B4 </td> <tr><td> <code title="">acute</code> </td> <td> U+000B4 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">acy;</code> </td> <td> U+00430 </td> <tr><td> <code title="">aelig;</code> </td> <td> U+000E6 </td> <tr><td> <code title="">aelig</code> </td> <td> U+000E6 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">af;</code> </td> <td> U+02061 </td> <tr><td> <code title="">afr;</code> </td> <td> U+1D51E </td> <tr><td> <code title="">agrave;</code> </td> <td> U+000E0 </td> <tr><td> <code title="">agrave</code> </td> <td> U+000E0 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">alefsym;</code> </td> <td> U+02135 </td> <tr><td> <code title="">aleph;</code> </td> <td> U+02135 </td> <tr><td> <code title="">alpha;</code> </td> <td> U+003B1 </td> <tr><td> <code title="">amacr;</code> </td> <td> U+00101 </td> <tr><td> <code title="">amalg;</code> </td> <td> U+02A3F </td> <tr><td> <code title="">amp;</code> </td> <td> U+00026 </td> <tr><td> <code title="">amp</code> </td> <td> U+00026 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">and;</code> </td> <td> U+02227 </td> <tr><td> <code title="">andand;</code> </td> <td> U+02A55 </td> <tr><td> <code title="">andd;</code> </td> <td> U+02A5C </td> <tr><td> <code title="">andslope;</code> </td> <td> U+02A58 </td> <tr><td> <code title="">andv;</code> </td> <td> U+02A5A </td> <tr><td> <code title="">ang;</code> </td> <td> U+02220 </td> <tr><td> <code title="">ange;</code> </td> <td> U+029A4 </td> <tr><td> <code title="">angle;</code> </td> <td> U+02220 </td> <tr><td> <code title="">angmsd;</code> </td> <td> U+02221 </td> <tr><td> <code title="">angmsdaa;</code> </td> <td> U+029A8 </td> <tr><td> <code title="">angmsdab;</code> </td> <td> U+029A9 </td> <tr><td> <code title="">angmsdac;</code> </td> <td> U+029AA </td> <tr><td> <code title="">angmsdad;</code> </td> <td> U+029AB </td> <tr><td> <code title="">angmsdae;</code> </td> <td> U+029AC </td> <tr><td> <code title="">angmsdaf;</code> </td> <td> U+029AD </td> <tr><td> <code title="">angmsdag;</code> </td> <td> U+029AE </td> <tr><td> <code title="">angmsdah;</code> </td> <td> U+029AF </td> <tr><td> <code title="">angrt;</code> </td> <td> U+0221F </td> <tr><td> <code title="">angrtvb;</code> </td> <td> U+022BE </td> <tr><td> <code title="">angrtvbd;</code> </td> <td> U+0299D </td> <tr><td> <code title="">angsph;</code> </td> <td> U+02222 </td> <tr><td> <code title="">angst;</code> </td> <td> U+000C5 </td> <tr><td> <code title="">angzarr;</code> </td> <td> U+0237C </td> <tr><td> <code title="">aogon;</code> </td> <td> U+00105 </td> <tr><td> <code title="">aopf;</code> </td> <td> U+1D552 </td> <tr><td> <code title="">ap;</code> </td> <td> U+02248 </td> <tr><td> <code title="">apE;</code> </td> <td> U+02A70 </td> <tr><td> <code title="">apacir;</code> </td> <td> U+02A6F </td> <tr><td> <code title="">ape;</code> </td> <td> U+0224A </td> <tr><td> <code title="">apid;</code> </td> <td> U+0224B </td> <tr><td> <code title="">apos;</code> </td> <td> U+00027 </td> <tr><td> <code title="">approx;</code> </td> <td> U+02248 </td> <tr><td> <code title="">approxeq;</code> </td> <td> U+0224A </td> <tr><td> <code title="">aring;</code> </td> <td> U+000E5 </td> <tr><td> <code title="">aring</code> </td> <td> U+000E5 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ascr;</code> </td> <td> U+1D4B6 </td> <tr><td> <code title="">ast;</code> </td> <td> U+0002A </td> <tr><td> <code title="">asymp;</code> </td> <td> U+02248 </td> <tr><td> <code title="">asympeq;</code> </td> <td> U+0224D </td> <tr><td> <code title="">atilde;</code> </td> <td> U+000E3 </td> <tr><td> <code title="">atilde</code> </td> <td> U+000E3 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">auml;</code> </td> <td> U+000E4 </td> <tr><td> <code title="">auml</code> </td> <td> U+000E4 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">awconint;</code> </td> <td> U+02233 </td> <tr><td> <code title="">awint;</code> </td> <td> U+02A11 </td> <tr><td> <code title="">bNot;</code> </td> <td> U+02AED </td> <tr><td> <code title="">backcong;</code> </td> <td> U+0224C </td> <tr><td> <code title="">backepsilon;</code> </td> <td> U+003F6 </td> <tr><td> <code title="">backprime;</code> </td> <td> U+02035 </td> <tr><td> <code title="">backsim;</code> </td> <td> U+0223D </td> <tr><td> <code title="">backsimeq;</code> </td> <td> U+022CD </td> <tr><td> <code title="">barvee;</code> </td> <td> U+022BD </td> <tr><td> <code title="">barwed;</code> </td> <td> U+02305 </td> <tr><td> <code title="">barwedge;</code> </td> <td> U+02305 </td> <tr><td> <code title="">bbrk;</code> </td> <td> U+023B5 </td> <tr><td> <code title="">bbrktbrk;</code> </td> <td> U+023B6 </td> <tr><td> <code title="">bcong;</code> </td> <td> U+0224C </td> <tr><td> <code title="">bcy;</code> </td> <td> U+00431 </td> <tr><td> <code title="">bdquo;</code> </td> <td> U+0201E </td> <tr><td> <code title="">becaus;</code> </td> <td> U+02235 </td> <tr><td> <code title="">because;</code> </td> <td> U+02235 </td> <tr><td> <code title="">bemptyv;</code> </td> <td> U+029B0 </td> <tr><td> <code title="">bepsi;</code> </td> <td> U+003F6 </td> <tr><td> <code title="">bernou;</code> </td> <td> U+0212C </td> <tr><td> <code title="">beta;</code> </td> <td> U+003B2 </td> <tr><td> <code title="">beth;</code> </td> <td> U+02136 </td> <tr><td> <code title="">between;</code> </td> <td> U+0226C </td> <tr><td> <code title="">bfr;</code> </td> <td> U+1D51F </td> <tr><td> <code title="">bigcap;</code> </td> <td> U+022C2 </td> <tr><td> <code title="">bigcirc;</code> </td> <td> U+025EF </td> <tr><td> <code title="">bigcup;</code> </td> <td> U+022C3 </td> <tr><td> <code title="">bigodot;</code> </td> <td> U+02A00 </td> <tr><td> <code title="">bigoplus;</code> </td> <td> U+02A01 </td> <tr><td> <code title="">bigotimes;</code> </td> <td> U+02A02 </td> <tr><td> <code title="">bigsqcup;</code> </td> <td> U+02A06 </td> <tr><td> <code title="">bigstar;</code> </td> <td> U+02605 </td> <tr><td> <code title="">bigtriangledown;</code> </td> <td> U+025BD </td> <tr><td> <code title="">bigtriangleup;</code> </td> <td> U+025B3 </td> <tr><td> <code title="">biguplus;</code> </td> <td> U+02A04 </td> <tr><td> <code title="">bigvee;</code> </td> <td> U+022C1 </td> <tr><td> <code title="">bigwedge;</code> </td> <td> U+022C0 </td> <tr><td> <code title="">bkarow;</code> </td> <td> U+0290D </td> <tr><td> <code title="">blacklozenge;</code> </td> <td> U+029EB </td> <tr><td> <code title="">blacksquare;</code> </td> <td> U+025AA </td> <tr><td> <code title="">blacktriangle;</code> </td> <td> U+025B4 </td> <tr><td> <code title="">blacktriangledown;</code> </td> <td> U+025BE </td> <tr><td> <code title="">blacktriangleleft;</code> </td> <td> U+025C2 </td> <tr><td> <code title="">blacktriangleright;</code> </td> <td> U+025B8 </td> <tr><td> <code title="">blank;</code> </td> <td> U+02423 </td> <tr><td> <code title="">blk12;</code> </td> <td> U+02592 </td> <tr><td> <code title="">blk14;</code> </td> <td> U+02591 </td> <tr><td> <code title="">blk34;</code> </td> <td> U+02593 </td> <tr><td> <code title="">block;</code> </td> <td> U+02588 </td> <tr><td> <code title="">bnot;</code> </td> <td> U+02310 </td> <tr><td> <code title="">bopf;</code> </td> <td> U+1D553 </td> <tr><td> <code title="">bot;</code> </td> <td> U+022A5 </td> <tr><td> <code title="">bottom;</code> </td> <td> U+022A5 </td> <tr><td> <code title="">bowtie;</code> </td> <td> U+022C8 </td> <tr><td> <code title="">boxDL;</code> </td> <td> U+02557 </td> <tr><td> <code title="">boxDR;</code> </td> <td> U+02554 </td> <tr><td> <code title="">boxDl;</code> </td> <td> U+02556 </td> <tr><td> <code title="">boxDr;</code> </td> <td> U+02553 </td> <tr><td> <code title="">boxH;</code> </td> <td> U+02550 </td> <tr><td> <code title="">boxHD;</code> </td> <td> U+02566 </td> <tr><td> <code title="">boxHU;</code> </td> <td> U+02569 </td> <tr><td> <code title="">boxHd;</code> </td> <td> U+02564 </td> <tr><td> <code title="">boxHu;</code> </td> <td> U+02567 </td> <tr><td> <code title="">boxUL;</code> </td> <td> U+0255D </td> <tr><td> <code title="">boxUR;</code> </td> <td> U+0255A </td> <tr><td> <code title="">boxUl;</code> </td> <td> U+0255C </td> <tr><td> <code title="">boxUr;</code> </td> <td> U+02559 </td> <tr><td> <code title="">boxV;</code> </td> <td> U+02551 </td> <tr><td> <code title="">boxVH;</code> </td> <td> U+0256C </td> <tr><td> <code title="">boxVL;</code> </td> <td> U+02563 </td> <tr><td> <code title="">boxVR;</code> </td> <td> U+02560 </td> <tr><td> <code title="">boxVh;</code> </td> <td> U+0256B </td> <tr><td> <code title="">boxVl;</code> </td> <td> U+02562 </td> <tr><td> <code title="">boxVr;</code> </td> <td> U+0255F </td> <tr><td> <code title="">boxbox;</code> </td> <td> U+029C9 </td> <tr><td> <code title="">boxdL;</code> </td> <td> U+02555 </td> <tr><td> <code title="">boxdR;</code> </td> <td> U+02552 </td> <tr><td> <code title="">boxdl;</code> </td> <td> U+02510 </td> <tr><td> <code title="">boxdr;</code> </td> <td> U+0250C </td> <tr><td> <code title="">boxh;</code> </td> <td> U+02500 </td> <tr><td> <code title="">boxhD;</code> </td> <td> U+02565 </td> <tr><td> <code title="">boxhU;</code> </td> <td> U+02568 </td> <tr><td> <code title="">boxhd;</code> </td> <td> U+0252C </td> <tr><td> <code title="">boxhu;</code> </td> <td> U+02534 </td> <tr><td> <code title="">boxminus;</code> </td> <td> U+0229F </td> <tr><td> <code title="">boxplus;</code> </td> <td> U+0229E </td> <tr><td> <code title="">boxtimes;</code> </td> <td> U+022A0 </td> <tr><td> <code title="">boxuL;</code> </td> <td> U+0255B </td> <tr><td> <code title="">boxuR;</code> </td> <td> U+02558 </td> <tr><td> <code title="">boxul;</code> </td> <td> U+02518 </td> <tr><td> <code title="">boxur;</code> </td> <td> U+02514 </td> <tr><td> <code title="">boxv;</code> </td> <td> U+02502 </td> <tr><td> <code title="">boxvH;</code> </td> <td> U+0256A </td> <tr><td> <code title="">boxvL;</code> </td> <td> U+02561 </td> <tr><td> <code title="">boxvR;</code> </td> <td> U+0255E </td> <tr><td> <code title="">boxvh;</code> </td> <td> U+0253C </td> <tr><td> <code title="">boxvl;</code> </td> <td> U+02524 </td> <tr><td> <code title="">boxvr;</code> </td> <td> U+0251C </td> <tr><td> <code title="">bprime;</code> </td> <td> U+02035 </td> <tr><td> <code title="">breve;</code> </td> <td> U+002D8 </td> <tr><td> <code title="">brvbar;</code> </td> <td> U+000A6 </td> <tr><td> <code title="">brvbar</code> </td> <td> U+000A6 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">bscr;</code> </td> <td> U+1D4B7 </td> <tr><td> <code title="">bsemi;</code> </td> <td> U+0204F </td> <tr><td> <code title="">bsim;</code> </td> <td> U+0223D </td> <tr><td> <code title="">bsime;</code> </td> <td> U+022CD </td> <tr><td> <code title="">bsol;</code> </td> <td> U+0005C </td> <tr><td> <code title="">bsolb;</code> </td> <td> U+029C5 </td> <tr><td> <code title="">bsolhsub;</code> </td> <td> U+027C8 </td> <tr><td> <code title="">bull;</code> </td> <td> U+02022 </td> <tr><td> <code title="">bullet;</code> </td> <td> U+02022 </td> <tr><td> <code title="">bump;</code> </td> <td> U+0224E </td> <tr><td> <code title="">bumpE;</code> </td> <td> U+02AAE </td> <tr><td> <code title="">bumpe;</code> </td> <td> U+0224F </td> <tr><td> <code title="">bumpeq;</code> </td> <td> U+0224F </td> <tr><td> <code title="">cacute;</code> </td> <td> U+00107 </td> <tr><td> <code title="">cap;</code> </td> <td> U+02229 </td> <tr><td> <code title="">capand;</code> </td> <td> U+02A44 </td> <tr><td> <code title="">capbrcup;</code> </td> <td> U+02A49 </td> <tr><td> <code title="">capcap;</code> </td> <td> U+02A4B </td> <tr><td> <code title="">capcup;</code> </td> <td> U+02A47 </td> <tr><td> <code title="">capdot;</code> </td> <td> U+02A40 </td> <tr><td> <code title="">caret;</code> </td> <td> U+02041 </td> <tr><td> <code title="">caron;</code> </td> <td> U+002C7 </td> <tr><td> <code title="">ccaps;</code> </td> <td> U+02A4D </td> <tr><td> <code title="">ccaron;</code> </td> <td> U+0010D </td> <tr><td> <code title="">ccedil;</code> </td> <td> U+000E7 </td> <tr><td> <code title="">ccedil</code> </td> <td> U+000E7 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ccirc;</code> </td> <td> U+00109 </td> <tr><td> <code title="">ccups;</code> </td> <td> U+02A4C </td> <tr><td> <code title="">ccupssm;</code> </td> <td> U+02A50 </td> <tr><td> <code title="">cdot;</code> </td> <td> U+0010B </td> <tr><td> <code title="">cedil;</code> </td> <td> U+000B8 </td> <tr><td> <code title="">cedil</code> </td> <td> U+000B8 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">cemptyv;</code> </td> <td> U+029B2 </td> <tr><td> <code title="">cent;</code> </td> <td> U+000A2 </td> <tr><td> <code title="">cent</code> </td> <td> U+000A2 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">centerdot;</code> </td> <td> U+000B7 </td> <tr><td> <code title="">cfr;</code> </td> <td> U+1D520 </td> <tr><td> <code title="">chcy;</code> </td> <td> U+00447 </td> <tr><td> <code title="">check;</code> </td> <td> U+02713 </td> <tr><td> <code title="">checkmark;</code> </td> <td> U+02713 </td> <tr><td> <code title="">chi;</code> </td> <td> U+003C7 </td> <tr><td> <code title="">cir;</code> </td> <td> U+025CB </td> <tr><td> <code title="">cirE;</code> </td> <td> U+029C3 </td> <tr><td> <code title="">circ;</code> </td> <td> U+002C6 </td> <tr><td> <code title="">circeq;</code> </td> <td> U+02257 </td> <tr><td> <code title="">circlearrowleft;</code> </td> <td> U+021BA </td> <tr><td> <code title="">circlearrowright;</code> </td> <td> U+021BB </td> <tr><td> <code title="">circledR;</code> </td> <td> U+000AE </td> <tr><td> <code title="">circledS;</code> </td> <td> U+024C8 </td> <tr><td> <code title="">circledast;</code> </td> <td> U+0229B </td> <tr><td> <code title="">circledcirc;</code> </td> <td> U+0229A </td> <tr><td> <code title="">circleddash;</code> </td> <td> U+0229D </td> <tr><td> <code title="">cire;</code> </td> <td> U+02257 </td> <tr><td> <code title="">cirfnint;</code> </td> <td> U+02A10 </td> <tr><td> <code title="">cirmid;</code> </td> <td> U+02AEF </td> <tr><td> <code title="">cirscir;</code> </td> <td> U+029C2 </td> <tr><td> <code title="">clubs;</code> </td> <td> U+02663 </td> <tr><td> <code title="">clubsuit;</code> </td> <td> U+02663 </td> <tr><td> <code title="">colon;</code> </td> <td> U+0003A </td> <tr><td> <code title="">colone;</code> </td> <td> U+02254 </td> <tr><td> <code title="">coloneq;</code> </td> <td> U+02254 </td> <tr><td> <code title="">comma;</code> </td> <td> U+0002C </td> <tr><td> <code title="">commat;</code> </td> <td> U+00040 </td> <tr><td> <code title="">comp;</code> </td> <td> U+02201 </td> <tr><td> <code title="">compfn;</code> </td> <td> U+02218 </td> <tr><td> <code title="">complement;</code> </td> <td> U+02201 </td> <tr><td> <code title="">complexes;</code> </td> <td> U+02102 </td> <tr><td> <code title="">cong;</code> </td> <td> U+02245 </td> <tr><td> <code title="">congdot;</code> </td> <td> U+02A6D </td> <tr><td> <code title="">conint;</code> </td> <td> U+0222E </td> <tr><td> <code title="">copf;</code> </td> <td> U+1D554 </td> <tr><td> <code title="">coprod;</code> </td> <td> U+02210 </td> <tr><td> <code title="">copy;</code> </td> <td> U+000A9 </td> <tr><td> <code title="">copy</code> </td> <td> U+000A9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">copysr;</code> </td> <td> U+02117 </td> <tr><td> <code title="">crarr;</code> </td> <td> U+021B5 </td> <tr><td> <code title="">cross;</code> </td> <td> U+02717 </td> <tr><td> <code title="">cscr;</code> </td> <td> U+1D4B8 </td> <tr><td> <code title="">csub;</code> </td> <td> U+02ACF </td> <tr><td> <code title="">csube;</code> </td> <td> U+02AD1 </td> <tr><td> <code title="">csup;</code> </td> <td> U+02AD0 </td> <tr><td> <code title="">csupe;</code> </td> <td> U+02AD2 </td> <tr><td> <code title="">ctdot;</code> </td> <td> U+022EF </td> <tr><td> <code title="">cudarrl;</code> </td> <td> U+02938 </td> <tr><td> <code title="">cudarrr;</code> </td> <td> U+02935 </td> <tr><td> <code title="">cuepr;</code> </td> <td> U+022DE </td> <tr><td> <code title="">cuesc;</code> </td> <td> U+022DF </td> <tr><td> <code title="">cularr;</code> </td> <td> U+021B6 </td> <tr><td> <code title="">cularrp;</code> </td> <td> U+0293D </td> <tr><td> <code title="">cup;</code> </td> <td> U+0222A </td> <tr><td> <code title="">cupbrcap;</code> </td> <td> U+02A48 </td> <tr><td> <code title="">cupcap;</code> </td> <td> U+02A46 </td> <tr><td> <code title="">cupcup;</code> </td> <td> U+02A4A </td> <tr><td> <code title="">cupdot;</code> </td> <td> U+0228D </td> <tr><td> <code title="">cupor;</code> </td> <td> U+02A45 </td> <tr><td> <code title="">curarr;</code> </td> <td> U+021B7 </td> <tr><td> <code title="">curarrm;</code> </td> <td> U+0293C </td> <tr><td> <code title="">curlyeqprec;</code> </td> <td> U+022DE </td> <tr><td> <code title="">curlyeqsucc;</code> </td> <td> U+022DF </td> <tr><td> <code title="">curlyvee;</code> </td> <td> U+022CE </td> <tr><td> <code title="">curlywedge;</code> </td> <td> U+022CF </td> <tr><td> <code title="">curren;</code> </td> <td> U+000A4 </td> <tr><td> <code title="">curren</code> </td> <td> U+000A4 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">curvearrowleft;</code> </td> <td> U+021B6 </td> <tr><td> <code title="">curvearrowright;</code> </td> <td> U+021B7 </td> <tr><td> <code title="">cuvee;</code> </td> <td> U+022CE </td> <tr><td> <code title="">cuwed;</code> </td> <td> U+022CF </td> <tr><td> <code title="">cwconint;</code> </td> <td> U+02232 </td> <tr><td> <code title="">cwint;</code> </td> <td> U+02231 </td> <tr><td> <code title="">cylcty;</code> </td> <td> U+0232D </td> <tr><td> <code title="">dArr;</code> </td> <td> U+021D3 </td> <tr><td> <code title="">dHar;</code> </td> <td> U+02965 </td> <tr><td> <code title="">dagger;</code> </td> <td> U+02020 </td> <tr><td> <code title="">daleth;</code> </td> <td> U+02138 </td> <tr><td> <code title="">darr;</code> </td> <td> U+02193 </td> <tr><td> <code title="">dash;</code> </td> <td> U+02010 </td> <tr><td> <code title="">dashv;</code> </td> <td> U+022A3 </td> <tr><td> <code title="">dbkarow;</code> </td> <td> U+0290F </td> <tr><td> <code title="">dblac;</code> </td> <td> U+002DD </td> <tr><td> <code title="">dcaron;</code> </td> <td> U+0010F </td> <tr><td> <code title="">dcy;</code> </td> <td> U+00434 </td> <tr><td> <code title="">dd;</code> </td> <td> U+02146 </td> <tr><td> <code title="">ddagger;</code> </td> <td> U+02021 </td> <tr><td> <code title="">ddarr;</code> </td> <td> U+021CA </td> <tr><td> <code title="">ddotseq;</code> </td> <td> U+02A77 </td> <tr><td> <code title="">deg;</code> </td> <td> U+000B0 </td> <tr><td> <code title="">deg</code> </td> <td> U+000B0 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">delta;</code> </td> <td> U+003B4 </td> <tr><td> <code title="">demptyv;</code> </td> <td> U+029B1 </td> <tr><td> <code title="">dfisht;</code> </td> <td> U+0297F </td> <tr><td> <code title="">dfr;</code> </td> <td> U+1D521 </td> <tr><td> <code title="">dharl;</code> </td> <td> U+021C3 </td> <tr><td> <code title="">dharr;</code> </td> <td> U+021C2 </td> <tr><td> <code title="">diam;</code> </td> <td> U+022C4 </td> <tr><td> <code title="">diamond;</code> </td> <td> U+022C4 </td> <tr><td> <code title="">diamondsuit;</code> </td> <td> U+02666 </td> <tr><td> <code title="">diams;</code> </td> <td> U+02666 </td> <tr><td> <code title="">die;</code> </td> <td> U+000A8 </td> <tr><td> <code title="">digamma;</code> </td> <td> U+003DD </td> <tr><td> <code title="">disin;</code> </td> <td> U+022F2 </td> <tr><td> <code title="">div;</code> </td> <td> U+000F7 </td> <tr><td> <code title="">divide;</code> </td> <td> U+000F7 </td> <tr><td> <code title="">divide</code> </td> <td> U+000F7 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">divideontimes;</code> </td> <td> U+022C7 </td> <tr><td> <code title="">divonx;</code> </td> <td> U+022C7 </td> <tr><td> <code title="">djcy;</code> </td> <td> U+00452 </td> <tr><td> <code title="">dlcorn;</code> </td> <td> U+0231E </td> <tr><td> <code title="">dlcrop;</code> </td> <td> U+0230D </td> <tr><td> <code title="">dollar;</code> </td> <td> U+00024 </td> <tr><td> <code title="">dopf;</code> </td> <td> U+1D555 </td> <tr><td> <code title="">dot;</code> </td> <td> U+002D9 </td> <tr><td> <code title="">doteq;</code> </td> <td> U+02250 </td> <tr><td> <code title="">doteqdot;</code> </td> <td> U+02251 </td> <tr><td> <code title="">dotminus;</code> </td> <td> U+02238 </td> <tr><td> <code title="">dotplus;</code> </td> <td> U+02214 </td> <tr><td> <code title="">dotsquare;</code> </td> <td> U+022A1 </td> <tr><td> <code title="">doublebarwedge;</code> </td> <td> U+02306 </td> <tr><td> <code title="">downarrow;</code> </td> <td> U+02193 </td> <tr><td> <code title="">downdownarrows;</code> </td> <td> U+021CA </td> <tr><td> <code title="">downharpoonleft;</code> </td> <td> U+021C3 </td> <tr><td> <code title="">downharpoonright;</code> </td> <td> U+021C2 </td> <tr><td> <code title="">drbkarow;</code> </td> <td> U+02910 </td> <tr><td> <code title="">drcorn;</code> </td> <td> U+0231F </td> <tr><td> <code title="">drcrop;</code> </td> <td> U+0230C </td> <tr><td> <code title="">dscr;</code> </td> <td> U+1D4B9 </td> <tr><td> <code title="">dscy;</code> </td> <td> U+00455 </td> <tr><td> <code title="">dsol;</code> </td> <td> U+029F6 </td> <tr><td> <code title="">dstrok;</code> </td> <td> U+00111 </td> <tr><td> <code title="">dtdot;</code> </td> <td> U+022F1 </td> <tr><td> <code title="">dtri;</code> </td> <td> U+025BF </td> <tr><td> <code title="">dtrif;</code> </td> <td> U+025BE </td> <tr><td> <code title="">duarr;</code> </td> <td> U+021F5 </td> <tr><td> <code title="">duhar;</code> </td> <td> U+0296F </td> <tr><td> <code title="">dwangle;</code> </td> <td> U+029A6 </td> <tr><td> <code title="">dzcy;</code> </td> <td> U+0045F </td> <tr><td> <code title="">dzigrarr;</code> </td> <td> U+027FF </td> <tr><td> <code title="">eDDot;</code> </td> <td> U+02A77 </td> <tr><td> <code title="">eDot;</code> </td> <td> U+02251 </td> <tr><td> <code title="">eacute;</code> </td> <td> U+000E9 </td> <tr><td> <code title="">eacute</code> </td> <td> U+000E9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">easter;</code> </td> <td> U+02A6E </td> <tr><td> <code title="">ecaron;</code> </td> <td> U+0011B </td> <tr><td> <code title="">ecir;</code> </td> <td> U+02256 </td> <tr><td> <code title="">ecirc;</code> </td> <td> U+000EA </td> <tr><td> <code title="">ecirc</code> </td> <td> U+000EA </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ecolon;</code> </td> <td> U+02255 </td> <tr><td> <code title="">ecy;</code> </td> <td> U+0044D </td> <tr><td> <code title="">edot;</code> </td> <td> U+00117 </td> <tr><td> <code title="">ee;</code> </td> <td> U+02147 </td> <tr><td> <code title="">efDot;</code> </td> <td> U+02252 </td> <tr><td> <code title="">efr;</code> </td> <td> U+1D522 </td> <tr><td> <code title="">eg;</code> </td> <td> U+02A9A </td> <tr><td> <code title="">egrave;</code> </td> <td> U+000E8 </td> <tr><td> <code title="">egrave</code> </td> <td> U+000E8 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">egs;</code> </td> <td> U+02A96 </td> <tr><td> <code title="">egsdot;</code> </td> <td> U+02A98 </td> <tr><td> <code title="">el;</code> </td> <td> U+02A99 </td> <tr><td> <code title="">elinters;</code> </td> <td> U+023E7 </td> <tr><td> <code title="">ell;</code> </td> <td> U+02113 </td> <tr><td> <code title="">els;</code> </td> <td> U+02A95 </td> <tr><td> <code title="">elsdot;</code> </td> <td> U+02A97 </td> <tr><td> <code title="">emacr;</code> </td> <td> U+00113 </td> <tr><td> <code title="">empty;</code> </td> <td> U+02205 </td> <tr><td> <code title="">emptyset;</code> </td> <td> U+02205 </td> <tr><td> <code title="">emptyv;</code> </td> <td> U+02205 </td> <tr><td> <code title="">emsp13;</code> </td> <td> U+02004 </td> <tr><td> <code title="">emsp14;</code> </td> <td> U+02005 </td> <tr><td> <code title="">emsp;</code> </td> <td> U+02003 </td> <tr><td> <code title="">eng;</code> </td> <td> U+0014B </td> <tr><td> <code title="">ensp;</code> </td> <td> U+02002 </td> <tr><td> <code title="">eogon;</code> </td> <td> U+00119 </td> <tr><td> <code title="">eopf;</code> </td> <td> U+1D556 </td> <tr><td> <code title="">epar;</code> </td> <td> U+022D5 </td> <tr><td> <code title="">eparsl;</code> </td> <td> U+029E3 </td> <tr><td> <code title="">eplus;</code> </td> <td> U+02A71 </td> <tr><td> <code title="">epsi;</code> </td> <td> U+003B5 </td> <tr><td> <code title="">epsilon;</code> </td> <td> U+003B5 </td> <tr><td> <code title="">epsiv;</code> </td> <td> U+003F5 </td> <tr><td> <code title="">eqcirc;</code> </td> <td> U+02256 </td> <tr><td> <code title="">eqcolon;</code> </td> <td> U+02255 </td> <tr><td> <code title="">eqsim;</code> </td> <td> U+02242 </td> <tr><td> <code title="">eqslantgtr;</code> </td> <td> U+02A96 </td> <tr><td> <code title="">eqslantless;</code> </td> <td> U+02A95 </td> <tr><td> <code title="">equals;</code> </td> <td> U+0003D </td> <tr><td> <code title="">equest;</code> </td> <td> U+0225F </td> <tr><td> <code title="">equiv;</code> </td> <td> U+02261 </td> <tr><td> <code title="">equivDD;</code> </td> <td> U+02A78 </td> <tr><td> <code title="">eqvparsl;</code> </td> <td> U+029E5 </td> <tr><td> <code title="">erDot;</code> </td> <td> U+02253 </td> <tr><td> <code title="">erarr;</code> </td> <td> U+02971 </td> <tr><td> <code title="">escr;</code> </td> <td> U+0212F </td> <tr><td> <code title="">esdot;</code> </td> <td> U+02250 </td> <tr><td> <code title="">esim;</code> </td> <td> U+02242 </td> <tr><td> <code title="">eta;</code> </td> <td> U+003B7 </td> <tr><td> <code title="">eth;</code> </td> <td> U+000F0 </td> <tr><td> <code title="">eth</code> </td> <td> U+000F0 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">euml;</code> </td> <td> U+000EB </td> <tr><td> <code title="">euml</code> </td> <td> U+000EB </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">euro;</code> </td> <td> U+020AC </td> <tr><td> <code title="">excl;</code> </td> <td> U+00021 </td> <tr><td> <code title="">exist;</code> </td> <td> U+02203 </td> <tr><td> <code title="">expectation;</code> </td> <td> U+02130 </td> <tr><td> <code title="">exponentiale;</code> </td> <td> U+02147 </td> <tr><td> <code title="">fallingdotseq;</code> </td> <td> U+02252 </td> <tr><td> <code title="">fcy;</code> </td> <td> U+00444 </td> <tr><td> <code title="">female;</code> </td> <td> U+02640 </td> <tr><td> <code title="">ffilig;</code> </td> <td> U+0FB03 </td> <tr><td> <code title="">fflig;</code> </td> <td> U+0FB00 </td> <tr><td> <code title="">ffllig;</code> </td> <td> U+0FB04 </td> <tr><td> <code title="">ffr;</code> </td> <td> U+1D523 </td> <tr><td> <code title="">filig;</code> </td> <td> U+0FB01 </td> <tr><td> <code title="">flat;</code> </td> <td> U+0266D </td> <tr><td> <code title="">fllig;</code> </td> <td> U+0FB02 </td> <tr><td> <code title="">fltns;</code> </td> <td> U+025B1 </td> <tr><td> <code title="">fnof;</code> </td> <td> U+00192 </td> <tr><td> <code title="">fopf;</code> </td> <td> U+1D557 </td> <tr><td> <code title="">forall;</code> </td> <td> U+02200 </td> <tr><td> <code title="">fork;</code> </td> <td> U+022D4 </td> <tr><td> <code title="">forkv;</code> </td> <td> U+02AD9 </td> <tr><td> <code title="">fpartint;</code> </td> <td> U+02A0D </td> <tr><td> <code title="">frac12;</code> </td> <td> U+000BD </td> <tr><td> <code title="">frac12</code> </td> <td> U+000BD </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">frac13;</code> </td> <td> U+02153 </td> <tr><td> <code title="">frac14;</code> </td> <td> U+000BC </td> <tr><td> <code title="">frac14</code> </td> <td> U+000BC </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">frac15;</code> </td> <td> U+02155 </td> <tr><td> <code title="">frac16;</code> </td> <td> U+02159 </td> <tr><td> <code title="">frac18;</code> </td> <td> U+0215B </td> <tr><td> <code title="">frac23;</code> </td> <td> U+02154 </td> <tr><td> <code title="">frac25;</code> </td> <td> U+02156 </td> <tr><td> <code title="">frac34;</code> </td> <td> U+000BE </td> <tr><td> <code title="">frac34</code> </td> <td> U+000BE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">frac35;</code> </td> <td> U+02157 </td> <tr><td> <code title="">frac38;</code> </td> <td> U+0215C </td> <tr><td> <code title="">frac45;</code> </td> <td> U+02158 </td> <tr><td> <code title="">frac56;</code> </td> <td> U+0215A </td> <tr><td> <code title="">frac58;</code> </td> <td> U+0215D </td> <tr><td> <code title="">frac78;</code> </td> <td> U+0215E </td> <tr><td> <code title="">frasl;</code> </td> <td> U+02044 </td> <tr><td> <code title="">frown;</code> </td> <td> U+02322 </td> <tr><td> <code title="">fscr;</code> </td> <td> U+1D4BB </td> <tr><td> <code title="">gE;</code> </td> <td> U+02267 </td> <tr><td> <code title="">gEl;</code> </td> <td> U+02A8C </td> <tr><td> <code title="">gacute;</code> </td> <td> U+001F5 </td> <tr><td> <code title="">gamma;</code> </td> <td> U+003B3 </td> <tr><td> <code title="">gammad;</code> </td> <td> U+003DD </td> <tr><td> <code title="">gap;</code> </td> <td> U+02A86 </td> <tr><td> <code title="">gbreve;</code> </td> <td> U+0011F </td> <tr><td> <code title="">gcirc;</code> </td> <td> U+0011D </td> <tr><td> <code title="">gcy;</code> </td> <td> U+00433 </td> <tr><td> <code title="">gdot;</code> </td> <td> U+00121 </td> <tr><td> <code title="">ge;</code> </td> <td> U+02265 </td> <tr><td> <code title="">gel;</code> </td> <td> U+022DB </td> <tr><td> <code title="">geq;</code> </td> <td> U+02265 </td> <tr><td> <code title="">geqq;</code> </td> <td> U+02267 </td> <tr><td> <code title="">geqslant;</code> </td> <td> U+02A7E </td> <tr><td> <code title="">ges;</code> </td> <td> U+02A7E </td> <tr><td> <code title="">gescc;</code> </td> <td> U+02AA9 </td> <tr><td> <code title="">gesdot;</code> </td> <td> U+02A80 </td> <tr><td> <code title="">gesdoto;</code> </td> <td> U+02A82 </td> <tr><td> <code title="">gesdotol;</code> </td> <td> U+02A84 </td> <tr><td> <code title="">gesles;</code> </td> <td> U+02A94 </td> <tr><td> <code title="">gfr;</code> </td> <td> U+1D524 </td> <tr><td> <code title="">gg;</code> </td> <td> U+0226B </td> <tr><td> <code title="">ggg;</code> </td> <td> U+022D9 </td> <tr><td> <code title="">gimel;</code> </td> <td> U+02137 </td> <tr><td> <code title="">gjcy;</code> </td> <td> U+00453 </td> <tr><td> <code title="">gl;</code> </td> <td> U+02277 </td> <tr><td> <code title="">glE;</code> </td> <td> U+02A92 </td> <tr><td> <code title="">gla;</code> </td> <td> U+02AA5 </td> <tr><td> <code title="">glj;</code> </td> <td> U+02AA4 </td> <tr><td> <code title="">gnE;</code> </td> <td> U+02269 </td> <tr><td> <code title="">gnap;</code> </td> <td> U+02A8A </td> <tr><td> <code title="">gnapprox;</code> </td> <td> U+02A8A </td> <tr><td> <code title="">gne;</code> </td> <td> U+02A88 </td> <tr><td> <code title="">gneq;</code> </td> <td> U+02A88 </td> <tr><td> <code title="">gneqq;</code> </td> <td> U+02269 </td> <tr><td> <code title="">gnsim;</code> </td> <td> U+022E7 </td> <tr><td> <code title="">gopf;</code> </td> <td> U+1D558 </td> <tr><td> <code title="">grave;</code> </td> <td> U+00060 </td> <tr><td> <code title="">gscr;</code> </td> <td> U+0210A </td> <tr><td> <code title="">gsim;</code> </td> <td> U+02273 </td> <tr><td> <code title="">gsime;</code> </td> <td> U+02A8E </td> <tr><td> <code title="">gsiml;</code> </td> <td> U+02A90 </td> <tr><td> <code title="">gt;</code> </td> <td> U+0003E </td> <tr><td> <code title="">gt</code> </td> <td> U+0003E </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">gtcc;</code> </td> <td> U+02AA7 </td> <tr><td> <code title="">gtcir;</code> </td> <td> U+02A7A </td> <tr><td> <code title="">gtdot;</code> </td> <td> U+022D7 </td> <tr><td> <code title="">gtlPar;</code> </td> <td> U+02995 </td> <tr><td> <code title="">gtquest;</code> </td> <td> U+02A7C </td> <tr><td> <code title="">gtrapprox;</code> </td> <td> U+02A86 </td> <tr><td> <code title="">gtrarr;</code> </td> <td> U+02978 </td> <tr><td> <code title="">gtrdot;</code> </td> <td> U+022D7 </td> <tr><td> <code title="">gtreqless;</code> </td> <td> U+022DB </td> <tr><td> <code title="">gtreqqless;</code> </td> <td> U+02A8C </td> <tr><td> <code title="">gtrless;</code> </td> <td> U+02277 </td> <tr><td> <code title="">gtrsim;</code> </td> <td> U+02273 </td> <tr><td> <code title="">hArr;</code> </td> <td> U+021D4 </td> <tr><td> <code title="">hairsp;</code> </td> <td> U+0200A </td> <tr><td> <code title="">half;</code> </td> <td> U+000BD </td> <tr><td> <code title="">hamilt;</code> </td> <td> U+0210B </td> <tr><td> <code title="">hardcy;</code> </td> <td> U+0044A </td> <tr><td> <code title="">harr;</code> </td> <td> U+02194 </td> <tr><td> <code title="">harrcir;</code> </td> <td> U+02948 </td> <tr><td> <code title="">harrw;</code> </td> <td> U+021AD </td> <tr><td> <code title="">hbar;</code> </td> <td> U+0210F </td> <tr><td> <code title="">hcirc;</code> </td> <td> U+00125 </td> <tr><td> <code title="">hearts;</code> </td> <td> U+02665 </td> <tr><td> <code title="">heartsuit;</code> </td> <td> U+02665 </td> <tr><td> <code title="">hellip;</code> </td> <td> U+02026 </td> <tr><td> <code title="">hercon;</code> </td> <td> U+022B9 </td> <tr><td> <code title="">hfr;</code> </td> <td> U+1D525 </td> <tr><td> <code title="">hksearow;</code> </td> <td> U+02925 </td> <tr><td> <code title="">hkswarow;</code> </td> <td> U+02926 </td> <tr><td> <code title="">hoarr;</code> </td> <td> U+021FF </td> <tr><td> <code title="">homtht;</code> </td> <td> U+0223B </td> <tr><td> <code title="">hookleftarrow;</code> </td> <td> U+021A9 </td> <tr><td> <code title="">hookrightarrow;</code> </td> <td> U+021AA </td> <tr><td> <code title="">hopf;</code> </td> <td> U+1D559 </td> <tr><td> <code title="">horbar;</code> </td> <td> U+02015 </td> <tr><td> <code title="">hscr;</code> </td> <td> U+1D4BD </td> <tr><td> <code title="">hslash;</code> </td> <td> U+0210F </td> <tr><td> <code title="">hstrok;</code> </td> <td> U+00127 </td> <tr><td> <code title="">hybull;</code> </td> <td> U+02043 </td> <tr><td> <code title="">hyphen;</code> </td> <td> U+02010 </td> <tr><td> <code title="">iacute;</code> </td> <td> U+000ED </td> <tr><td> <code title="">iacute</code> </td> <td> U+000ED </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ic;</code> </td> <td> U+02063 </td> <tr><td> <code title="">icirc;</code> </td> <td> U+000EE </td> <tr><td> <code title="">icirc</code> </td> <td> U+000EE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">icy;</code> </td> <td> U+00438 </td> <tr><td> <code title="">iecy;</code> </td> <td> U+00435 </td> <tr><td> <code title="">iexcl;</code> </td> <td> U+000A1 </td> <tr><td> <code title="">iexcl</code> </td> <td> U+000A1 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">iff;</code> </td> <td> U+021D4 </td> <tr><td> <code title="">ifr;</code> </td> <td> U+1D526 </td> <tr><td> <code title="">igrave;</code> </td> <td> U+000EC </td> <tr><td> <code title="">igrave</code> </td> <td> U+000EC </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ii;</code> </td> <td> U+02148 </td> <tr><td> <code title="">iiiint;</code> </td> <td> U+02A0C </td> <tr><td> <code title="">iiint;</code> </td> <td> U+0222D </td> <tr><td> <code title="">iinfin;</code> </td> <td> U+029DC </td> <tr><td> <code title="">iiota;</code> </td> <td> U+02129 </td> <tr><td> <code title="">ijlig;</code> </td> <td> U+00133 </td> <tr><td> <code title="">imacr;</code> </td> <td> U+0012B </td> <tr><td> <code title="">image;</code> </td> <td> U+02111 </td> <tr><td> <code title="">imagline;</code> </td> <td> U+02110 </td> <tr><td> <code title="">imagpart;</code> </td> <td> U+02111 </td> <tr><td> <code title="">imath;</code> </td> <td> U+00131 </td> <tr><td> <code title="">imof;</code> </td> <td> U+022B7 </td> <tr><td> <code title="">imped;</code> </td> <td> U+001B5 </td> <tr><td> <code title="">in;</code> </td> <td> U+02208 </td> <tr><td> <code title="">incare;</code> </td> <td> U+02105 </td> <tr><td> <code title="">infin;</code> </td> <td> U+0221E </td> <tr><td> <code title="">infintie;</code> </td> <td> U+029DD </td> <tr><td> <code title="">inodot;</code> </td> <td> U+00131 </td> <tr><td> <code title="">int;</code> </td> <td> U+0222B </td> <tr><td> <code title="">intcal;</code> </td> <td> U+022BA </td> <tr><td> <code title="">integers;</code> </td> <td> U+02124 </td> <tr><td> <code title="">intercal;</code> </td> <td> U+022BA </td> <tr><td> <code title="">intlarhk;</code> </td> <td> U+02A17 </td> <tr><td> <code title="">intprod;</code> </td> <td> U+02A3C </td> <tr><td> <code title="">iocy;</code> </td> <td> U+00451 </td> <tr><td> <code title="">iogon;</code> </td> <td> U+0012F </td> <tr><td> <code title="">iopf;</code> </td> <td> U+1D55A </td> <tr><td> <code title="">iota;</code> </td> <td> U+003B9 </td> <tr><td> <code title="">iprod;</code> </td> <td> U+02A3C </td> <tr><td> <code title="">iquest;</code> </td> <td> U+000BF </td> <tr><td> <code title="">iquest</code> </td> <td> U+000BF </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">iscr;</code> </td> <td> U+1D4BE </td> <tr><td> <code title="">isin;</code> </td> <td> U+02208 </td> <tr><td> <code title="">isinE;</code> </td> <td> U+022F9 </td> <tr><td> <code title="">isindot;</code> </td> <td> U+022F5 </td> <tr><td> <code title="">isins;</code> </td> <td> U+022F4 </td> <tr><td> <code title="">isinsv;</code> </td> <td> U+022F3 </td> <tr><td> <code title="">isinv;</code> </td> <td> U+02208 </td> <tr><td> <code title="">it;</code> </td> <td> U+02062 </td> <tr><td> <code title="">itilde;</code> </td> <td> U+00129 </td> <tr><td> <code title="">iukcy;</code> </td> <td> U+00456 </td> <tr><td> <code title="">iuml;</code> </td> <td> U+000EF </td> <tr><td> <code title="">iuml</code> </td> <td> U+000EF </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">jcirc;</code> </td> <td> U+00135 </td> <tr><td> <code title="">jcy;</code> </td> <td> U+00439 </td> <tr><td> <code title="">jfr;</code> </td> <td> U+1D527 </td> <tr><td> <code title="">jmath;</code> </td> <td> U+00237 </td> <tr><td> <code title="">jopf;</code> </td> <td> U+1D55B </td> <tr><td> <code title="">jscr;</code> </td> <td> U+1D4BF </td> <tr><td> <code title="">jsercy;</code> </td> <td> U+00458 </td> <tr><td> <code title="">jukcy;</code> </td> <td> U+00454 </td> <tr><td> <code title="">kappa;</code> </td> <td> U+003BA </td> <tr><td> <code title="">kappav;</code> </td> <td> U+003F0 </td> <tr><td> <code title="">kcedil;</code> </td> <td> U+00137 </td> <tr><td> <code title="">kcy;</code> </td> <td> U+0043A </td> <tr><td> <code title="">kfr;</code> </td> <td> U+1D528 </td> <tr><td> <code title="">kgreen;</code> </td> <td> U+00138 </td> <tr><td> <code title="">khcy;</code> </td> <td> U+00445 </td> <tr><td> <code title="">kjcy;</code> </td> <td> U+0045C </td> <tr><td> <code title="">kopf;</code> </td> <td> U+1D55C </td> <tr><td> <code title="">kscr;</code> </td> <td> U+1D4C0 </td> <tr><td> <code title="">lAarr;</code> </td> <td> U+021DA </td> <tr><td> <code title="">lArr;</code> </td> <td> U+021D0 </td> <tr><td> <code title="">lAtail;</code> </td> <td> U+0291B </td> <tr><td> <code title="">lBarr;</code> </td> <td> U+0290E </td> <tr><td> <code title="">lE;</code> </td> <td> U+02266 </td> <tr><td> <code title="">lEg;</code> </td> <td> U+02A8B </td> <tr><td> <code title="">lHar;</code> </td> <td> U+02962 </td> <tr><td> <code title="">lacute;</code> </td> <td> U+0013A </td> <tr><td> <code title="">laemptyv;</code> </td> <td> U+029B4 </td> <tr><td> <code title="">lagran;</code> </td> <td> U+02112 </td> <tr><td> <code title="">lambda;</code> </td> <td> U+003BB </td> <tr><td> <code title="">lang;</code> </td> <td> U+027E8 </td> <tr><td> <code title="">langd;</code> </td> <td> U+02991 </td> <tr><td> <code title="">langle;</code> </td> <td> U+027E8 </td> <tr><td> <code title="">lap;</code> </td> <td> U+02A85 </td> <tr><td> <code title="">laquo;</code> </td> <td> U+000AB </td> <tr><td> <code title="">laquo</code> </td> <td> U+000AB </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">larr;</code> </td> <td> U+02190 </td> <tr><td> <code title="">larrb;</code> </td> <td> U+021E4 </td> <tr><td> <code title="">larrbfs;</code> </td> <td> U+0291F </td> <tr><td> <code title="">larrfs;</code> </td> <td> U+0291D </td> <tr><td> <code title="">larrhk;</code> </td> <td> U+021A9 </td> <tr><td> <code title="">larrlp;</code> </td> <td> U+021AB </td> <tr><td> <code title="">larrpl;</code> </td> <td> U+02939 </td> <tr><td> <code title="">larrsim;</code> </td> <td> U+02973 </td> <tr><td> <code title="">larrtl;</code> </td> <td> U+021A2 </td> <tr><td> <code title="">lat;</code> </td> <td> U+02AAB </td> <tr><td> <code title="">latail;</code> </td> <td> U+02919 </td> <tr><td> <code title="">late;</code> </td> <td> U+02AAD </td> <tr><td> <code title="">lbarr;</code> </td> <td> U+0290C </td> <tr><td> <code title="">lbbrk;</code> </td> <td> U+02772 </td> <tr><td> <code title="">lbrace;</code> </td> <td> U+0007B </td> <tr><td> <code title="">lbrack;</code> </td> <td> U+0005B </td> <tr><td> <code title="">lbrke;</code> </td> <td> U+0298B </td> <tr><td> <code title="">lbrksld;</code> </td> <td> U+0298F </td> <tr><td> <code title="">lbrkslu;</code> </td> <td> U+0298D </td> <tr><td> <code title="">lcaron;</code> </td> <td> U+0013E </td> <tr><td> <code title="">lcedil;</code> </td> <td> U+0013C </td> <tr><td> <code title="">lceil;</code> </td> <td> U+02308 </td> <tr><td> <code title="">lcub;</code> </td> <td> U+0007B </td> <tr><td> <code title="">lcy;</code> </td> <td> U+0043B </td> <tr><td> <code title="">ldca;</code> </td> <td> U+02936 </td> <tr><td> <code title="">ldquo;</code> </td> <td> U+0201C </td> <tr><td> <code title="">ldquor;</code> </td> <td> U+0201E </td> <tr><td> <code title="">ldrdhar;</code> </td> <td> U+02967 </td> <tr><td> <code title="">ldrushar;</code> </td> <td> U+0294B </td> <tr><td> <code title="">ldsh;</code> </td> <td> U+021B2 </td> <tr><td> <code title="">le;</code> </td> <td> U+02264 </td> <tr><td> <code title="">leftarrow;</code> </td> <td> U+02190 </td> <tr><td> <code title="">leftarrowtail;</code> </td> <td> U+021A2 </td> <tr><td> <code title="">leftharpoondown;</code> </td> <td> U+021BD </td> <tr><td> <code title="">leftharpoonup;</code> </td> <td> U+021BC </td> <tr><td> <code title="">leftleftarrows;</code> </td> <td> U+021C7 </td> <tr><td> <code title="">leftrightarrow;</code> </td> <td> U+02194 </td> <tr><td> <code title="">leftrightarrows;</code> </td> <td> U+021C6 </td> <tr><td> <code title="">leftrightharpoons;</code> </td> <td> U+021CB </td> <tr><td> <code title="">leftrightsquigarrow;</code> </td> <td> U+021AD </td> <tr><td> <code title="">leftthreetimes;</code> </td> <td> U+022CB </td> <tr><td> <code title="">leg;</code> </td> <td> U+022DA </td> <tr><td> <code title="">leq;</code> </td> <td> U+02264 </td> <tr><td> <code title="">leqq;</code> </td> <td> U+02266 </td> <tr><td> <code title="">leqslant;</code> </td> <td> U+02A7D </td> <tr><td> <code title="">les;</code> </td> <td> U+02A7D </td> <tr><td> <code title="">lescc;</code> </td> <td> U+02AA8 </td> <tr><td> <code title="">lesdot;</code> </td> <td> U+02A7F </td> <tr><td> <code title="">lesdoto;</code> </td> <td> U+02A81 </td> <tr><td> <code title="">lesdotor;</code> </td> <td> U+02A83 </td> <tr><td> <code title="">lesges;</code> </td> <td> U+02A93 </td> <tr><td> <code title="">lessapprox;</code> </td> <td> U+02A85 </td> <tr><td> <code title="">lessdot;</code> </td> <td> U+022D6 </td> <tr><td> <code title="">lesseqgtr;</code> </td> <td> U+022DA </td> <tr><td> <code title="">lesseqqgtr;</code> </td> <td> U+02A8B </td> <tr><td> <code title="">lessgtr;</code> </td> <td> U+02276 </td> <tr><td> <code title="">lesssim;</code> </td> <td> U+02272 </td> <tr><td> <code title="">lfisht;</code> </td> <td> U+0297C </td> <tr><td> <code title="">lfloor;</code> </td> <td> U+0230A </td> <tr><td> <code title="">lfr;</code> </td> <td> U+1D529 </td> <tr><td> <code title="">lg;</code> </td> <td> U+02276 </td> <tr><td> <code title="">lgE;</code> </td> <td> U+02A91 </td> <tr><td> <code title="">lhard;</code> </td> <td> U+021BD </td> <tr><td> <code title="">lharu;</code> </td> <td> U+021BC </td> <tr><td> <code title="">lharul;</code> </td> <td> U+0296A </td> <tr><td> <code title="">lhblk;</code> </td> <td> U+02584 </td> <tr><td> <code title="">ljcy;</code> </td> <td> U+00459 </td> <tr><td> <code title="">ll;</code> </td> <td> U+0226A </td> <tr><td> <code title="">llarr;</code> </td> <td> U+021C7 </td> <tr><td> <code title="">llcorner;</code> </td> <td> U+0231E </td> <tr><td> <code title="">llhard;</code> </td> <td> U+0296B </td> <tr><td> <code title="">lltri;</code> </td> <td> U+025FA </td> <tr><td> <code title="">lmidot;</code> </td> <td> U+00140 </td> <tr><td> <code title="">lmoust;</code> </td> <td> U+023B0 </td> <tr><td> <code title="">lmoustache;</code> </td> <td> U+023B0 </td> <tr><td> <code title="">lnE;</code> </td> <td> U+02268 </td> <tr><td> <code title="">lnap;</code> </td> <td> U+02A89 </td> <tr><td> <code title="">lnapprox;</code> </td> <td> U+02A89 </td> <tr><td> <code title="">lne;</code> </td> <td> U+02A87 </td> <tr><td> <code title="">lneq;</code> </td> <td> U+02A87 </td> <tr><td> <code title="">lneqq;</code> </td> <td> U+02268 </td> <tr><td> <code title="">lnsim;</code> </td> <td> U+022E6 </td> <tr><td> <code title="">loang;</code> </td> <td> U+027EC </td> <tr><td> <code title="">loarr;</code> </td> <td> U+021FD </td> <tr><td> <code title="">lobrk;</code> </td> <td> U+027E6 </td> <tr><td> <code title="">longleftarrow;</code> </td> <td> U+027F5 </td> <tr><td> <code title="">longleftrightarrow;</code> </td> <td> U+027F7 </td> <tr><td> <code title="">longmapsto;</code> </td> <td> U+027FC </td> <tr><td> <code title="">longrightarrow;</code> </td> <td> U+027F6 </td> <tr><td> <code title="">looparrowleft;</code> </td> <td> U+021AB </td> <tr><td> <code title="">looparrowright;</code> </td> <td> U+021AC </td> <tr><td> <code title="">lopar;</code> </td> <td> U+02985 </td> <tr><td> <code title="">lopf;</code> </td> <td> U+1D55D </td> <tr><td> <code title="">loplus;</code> </td> <td> U+02A2D </td> <tr><td> <code title="">lotimes;</code> </td> <td> U+02A34 </td> <tr><td> <code title="">lowast;</code> </td> <td> U+02217 </td> <tr><td> <code title="">lowbar;</code> </td> <td> U+0005F </td> <tr><td> <code title="">loz;</code> </td> <td> U+025CA </td> <tr><td> <code title="">lozenge;</code> </td> <td> U+025CA </td> <tr><td> <code title="">lozf;</code> </td> <td> U+029EB </td> <tr><td> <code title="">lpar;</code> </td> <td> U+00028 </td> <tr><td> <code title="">lparlt;</code> </td> <td> U+02993 </td> <tr><td> <code title="">lrarr;</code> </td> <td> U+021C6 </td> <tr><td> <code title="">lrcorner;</code> </td> <td> U+0231F </td> <tr><td> <code title="">lrhar;</code> </td> <td> U+021CB </td> <tr><td> <code title="">lrhard;</code> </td> <td> U+0296D </td> <tr><td> <code title="">lrm;</code> </td> <td> U+0200E </td> <tr><td> <code title="">lrtri;</code> </td> <td> U+022BF </td> <tr><td> <code title="">lsaquo;</code> </td> <td> U+02039 </td> <tr><td> <code title="">lscr;</code> </td> <td> U+1D4C1 </td> <tr><td> <code title="">lsh;</code> </td> <td> U+021B0 </td> <tr><td> <code title="">lsim;</code> </td> <td> U+02272 </td> <tr><td> <code title="">lsime;</code> </td> <td> U+02A8D </td> <tr><td> <code title="">lsimg;</code> </td> <td> U+02A8F </td> <tr><td> <code title="">lsqb;</code> </td> <td> U+0005B </td> <tr><td> <code title="">lsquo;</code> </td> <td> U+02018 </td> <tr><td> <code title="">lsquor;</code> </td> <td> U+0201A </td> <tr><td> <code title="">lstrok;</code> </td> <td> U+00142 </td> <tr><td> <code title="">lt;</code> </td> <td> U+0003C </td> <tr><td> <code title="">lt</code> </td> <td> U+0003C </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ltcc;</code> </td> <td> U+02AA6 </td> <tr><td> <code title="">ltcir;</code> </td> <td> U+02A79 </td> <tr><td> <code title="">ltdot;</code> </td> <td> U+022D6 </td> <tr><td> <code title="">lthree;</code> </td> <td> U+022CB </td> <tr><td> <code title="">ltimes;</code> </td> <td> U+022C9 </td> <tr><td> <code title="">ltlarr;</code> </td> <td> U+02976 </td> <tr><td> <code title="">ltquest;</code> </td> <td> U+02A7B </td> <tr><td> <code title="">ltrPar;</code> </td> <td> U+02996 </td> <tr><td> <code title="">ltri;</code> </td> <td> U+025C3 </td> <tr><td> <code title="">ltrie;</code> </td> <td> U+022B4 </td> <tr><td> <code title="">ltrif;</code> </td> <td> U+025C2 </td> <tr><td> <code title="">lurdshar;</code> </td> <td> U+0294A </td> <tr><td> <code title="">luruhar;</code> </td> <td> U+02966 </td> <tr><td> <code title="">mDDot;</code> </td> <td> U+0223A </td> <tr><td> <code title="">macr;</code> </td> <td> U+000AF </td> <tr><td> <code title="">macr</code> </td> <td> U+000AF </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">male;</code> </td> <td> U+02642 </td> <tr><td> <code title="">malt;</code> </td> <td> U+02720 </td> <tr><td> <code title="">maltese;</code> </td> <td> U+02720 </td> <tr><td> <code title="">map;</code> </td> <td> U+021A6 </td> <tr><td> <code title="">mapsto;</code> </td> <td> U+021A6 </td> <tr><td> <code title="">mapstodown;</code> </td> <td> U+021A7 </td> <tr><td> <code title="">mapstoleft;</code> </td> <td> U+021A4 </td> <tr><td> <code title="">mapstoup;</code> </td> <td> U+021A5 </td> <tr><td> <code title="">marker;</code> </td> <td> U+025AE </td> <tr><td> <code title="">mcomma;</code> </td> <td> U+02A29 </td> <tr><td> <code title="">mcy;</code> </td> <td> U+0043C </td> <tr><td> <code title="">mdash;</code> </td> <td> U+02014 </td> <tr><td> <code title="">measuredangle;</code> </td> <td> U+02221 </td> <tr><td> <code title="">mfr;</code> </td> <td> U+1D52A </td> <tr><td> <code title="">mho;</code> </td> <td> U+02127 </td> <tr><td> <code title="">micro;</code> </td> <td> U+000B5 </td> <tr><td> <code title="">micro</code> </td> <td> U+000B5 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">mid;</code> </td> <td> U+02223 </td> <tr><td> <code title="">midast;</code> </td> <td> U+0002A </td> <tr><td> <code title="">midcir;</code> </td> <td> U+02AF0 </td> <tr><td> <code title="">middot;</code> </td> <td> U+000B7 </td> <tr><td> <code title="">middot</code> </td> <td> U+000B7 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">minus;</code> </td> <td> U+02212 </td> <tr><td> <code title="">minusb;</code> </td> <td> U+0229F </td> <tr><td> <code title="">minusd;</code> </td> <td> U+02238 </td> <tr><td> <code title="">minusdu;</code> </td> <td> U+02A2A </td> <tr><td> <code title="">mlcp;</code> </td> <td> U+02ADB </td> <tr><td> <code title="">mldr;</code> </td> <td> U+02026 </td> <tr><td> <code title="">mnplus;</code> </td> <td> U+02213 </td> <tr><td> <code title="">models;</code> </td> <td> U+022A7 </td> <tr><td> <code title="">mopf;</code> </td> <td> U+1D55E </td> <tr><td> <code title="">mp;</code> </td> <td> U+02213 </td> <tr><td> <code title="">mscr;</code> </td> <td> U+1D4C2 </td> <tr><td> <code title="">mstpos;</code> </td> <td> U+0223E </td> <tr><td> <code title="">mu;</code> </td> <td> U+003BC </td> <tr><td> <code title="">multimap;</code> </td> <td> U+022B8 </td> <tr><td> <code title="">mumap;</code> </td> <td> U+022B8 </td> <tr><td> <code title="">nLeftarrow;</code> </td> <td> U+021CD </td> <tr><td> <code title="">nLeftrightarrow;</code> </td> <td> U+021CE </td> <tr><td> <code title="">nRightarrow;</code> </td> <td> U+021CF </td> <tr><td> <code title="">nVDash;</code> </td> <td> U+022AF </td> <tr><td> <code title="">nVdash;</code> </td> <td> U+022AE </td> <tr><td> <code title="">nabla;</code> </td> <td> U+02207 </td> <tr><td> <code title="">nacute;</code> </td> <td> U+00144 </td> <tr><td> <code title="">nap;</code> </td> <td> U+02249 </td> <tr><td> <code title="">napos;</code> </td> <td> U+00149 </td> <tr><td> <code title="">napprox;</code> </td> <td> U+02249 </td> <tr><td> <code title="">natur;</code> </td> <td> U+0266E </td> <tr><td> <code title="">natural;</code> </td> <td> U+0266E </td> <tr><td> <code title="">naturals;</code> </td> <td> U+02115 </td> <tr><td> <code title="">nbsp;</code> </td> <td> U+000A0 </td> <tr><td> <code title="">nbsp</code> </td> <td> U+000A0 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ncap;</code> </td> <td> U+02A43 </td> <tr><td> <code title="">ncaron;</code> </td> <td> U+00148 </td> <tr><td> <code title="">ncedil;</code> </td> <td> U+00146 </td> <tr><td> <code title="">ncong;</code> </td> <td> U+02247 </td> <tr><td> <code title="">ncup;</code> </td> <td> U+02A42 </td> <tr><td> <code title="">ncy;</code> </td> <td> U+0043D </td> <tr><td> <code title="">ndash;</code> </td> <td> U+02013 </td> <tr><td> <code title="">ne;</code> </td> <td> U+02260 </td> <tr><td> <code title="">neArr;</code> </td> <td> U+021D7 </td> <tr><td> <code title="">nearhk;</code> </td> <td> U+02924 </td> <tr><td> <code title="">nearr;</code> </td> <td> U+02197 </td> <tr><td> <code title="">nearrow;</code> </td> <td> U+02197 </td> <tr><td> <code title="">nequiv;</code> </td> <td> U+02262 </td> <tr><td> <code title="">nesear;</code> </td> <td> U+02928 </td> <tr><td> <code title="">nexist;</code> </td> <td> U+02204 </td> <tr><td> <code title="">nexists;</code> </td> <td> U+02204 </td> <tr><td> <code title="">nfr;</code> </td> <td> U+1D52B </td> <tr><td> <code title="">nge;</code> </td> <td> U+02271 </td> <tr><td> <code title="">ngeq;</code> </td> <td> U+02271 </td> <tr><td> <code title="">ngsim;</code> </td> <td> U+02275 </td> <tr><td> <code title="">ngt;</code> </td> <td> U+0226F </td> <tr><td> <code title="">ngtr;</code> </td> <td> U+0226F </td> <tr><td> <code title="">nhArr;</code> </td> <td> U+021CE </td> <tr><td> <code title="">nharr;</code> </td> <td> U+021AE </td> <tr><td> <code title="">nhpar;</code> </td> <td> U+02AF2 </td> <tr><td> <code title="">ni;</code> </td> <td> U+0220B </td> <tr><td> <code title="">nis;</code> </td> <td> U+022FC </td> <tr><td> <code title="">nisd;</code> </td> <td> U+022FA </td> <tr><td> <code title="">niv;</code> </td> <td> U+0220B </td> <tr><td> <code title="">njcy;</code> </td> <td> U+0045A </td> <tr><td> <code title="">nlArr;</code> </td> <td> U+021CD </td> <tr><td> <code title="">nlarr;</code> </td> <td> U+0219A </td> <tr><td> <code title="">nldr;</code> </td> <td> U+02025 </td> <tr><td> <code title="">nle;</code> </td> <td> U+02270 </td> <tr><td> <code title="">nleftarrow;</code> </td> <td> U+0219A </td> <tr><td> <code title="">nleftrightarrow;</code> </td> <td> U+021AE </td> <tr><td> <code title="">nleq;</code> </td> <td> U+02270 </td> <tr><td> <code title="">nless;</code> </td> <td> U+0226E </td> <tr><td> <code title="">nlsim;</code> </td> <td> U+02274 </td> <tr><td> <code title="">nlt;</code> </td> <td> U+0226E </td> <tr><td> <code title="">nltri;</code> </td> <td> U+022EA </td> <tr><td> <code title="">nltrie;</code> </td> <td> U+022EC </td> <tr><td> <code title="">nmid;</code> </td> <td> U+02224 </td> <tr><td> <code title="">nopf;</code> </td> <td> U+1D55F </td> <tr><td> <code title="">not;</code> </td> <td> U+000AC </td> <tr><td> <code title="">not</code> </td> <td> U+000AC </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">notin;</code> </td> <td> U+02209 </td> <tr><td> <code title="">notinva;</code> </td> <td> U+02209 </td> <tr><td> <code title="">notinvb;</code> </td> <td> U+022F7 </td> <tr><td> <code title="">notinvc;</code> </td> <td> U+022F6 </td> <tr><td> <code title="">notni;</code> </td> <td> U+0220C </td> <tr><td> <code title="">notniva;</code> </td> <td> U+0220C </td> <tr><td> <code title="">notnivb;</code> </td> <td> U+022FE </td> <tr><td> <code title="">notnivc;</code> </td> <td> U+022FD </td> <tr><td> <code title="">npar;</code> </td> <td> U+02226 </td> <tr><td> <code title="">nparallel;</code> </td> <td> U+02226 </td> <tr><td> <code title="">npolint;</code> </td> <td> U+02A14 </td> <tr><td> <code title="">npr;</code> </td> <td> U+02280 </td> <tr><td> <code title="">nprcue;</code> </td> <td> U+022E0 </td> <tr><td> <code title="">nprec;</code> </td> <td> U+02280 </td> <tr><td> <code title="">nrArr;</code> </td> <td> U+021CF </td> <tr><td> <code title="">nrarr;</code> </td> <td> U+0219B </td> <tr><td> <code title="">nrightarrow;</code> </td> <td> U+0219B </td> <tr><td> <code title="">nrtri;</code> </td> <td> U+022EB </td> <tr><td> <code title="">nrtrie;</code> </td> <td> U+022ED </td> <tr><td> <code title="">nsc;</code> </td> <td> U+02281 </td> <tr><td> <code title="">nsccue;</code> </td> <td> U+022E1 </td> <tr><td> <code title="">nscr;</code> </td> <td> U+1D4C3 </td> <tr><td> <code title="">nshortmid;</code> </td> <td> U+02224 </td> <tr><td> <code title="">nshortparallel;</code> </td> <td> U+02226 </td> <tr><td> <code title="">nsim;</code> </td> <td> U+02241 </td> <tr><td> <code title="">nsime;</code> </td> <td> U+02244 </td> <tr><td> <code title="">nsimeq;</code> </td> <td> U+02244 </td> <tr><td> <code title="">nsmid;</code> </td> <td> U+02224 </td> <tr><td> <code title="">nspar;</code> </td> <td> U+02226 </td> <tr><td> <code title="">nsqsube;</code> </td> <td> U+022E2 </td> <tr><td> <code title="">nsqsupe;</code> </td> <td> U+022E3 </td> <tr><td> <code title="">nsub;</code> </td> <td> U+02284 </td> <tr><td> <code title="">nsube;</code> </td> <td> U+02288 </td> <tr><td> <code title="">nsubseteq;</code> </td> <td> U+02288 </td> <tr><td> <code title="">nsucc;</code> </td> <td> U+02281 </td> <tr><td> <code title="">nsup;</code> </td> <td> U+02285 </td> <tr><td> <code title="">nsupe;</code> </td> <td> U+02289 </td> <tr><td> <code title="">nsupseteq;</code> </td> <td> U+02289 </td> <tr><td> <code title="">ntgl;</code> </td> <td> U+02279 </td> <tr><td> <code title="">ntilde;</code> </td> <td> U+000F1 </td> <tr><td> <code title="">ntilde</code> </td> <td> U+000F1 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ntlg;</code> </td> <td> U+02278 </td> <tr><td> <code title="">ntriangleleft;</code> </td> <td> U+022EA </td> <tr><td> <code title="">ntrianglelefteq;</code> </td> <td> U+022EC </td> <tr><td> <code title="">ntriangleright;</code> </td> <td> U+022EB </td> <tr><td> <code title="">ntrianglerighteq;</code> </td> <td> U+022ED </td> <tr><td> <code title="">nu;</code> </td> <td> U+003BD </td> <tr><td> <code title="">num;</code> </td> <td> U+00023 </td> <tr><td> <code title="">numero;</code> </td> <td> U+02116 </td> <tr><td> <code title="">numsp;</code> </td> <td> U+02007 </td> <tr><td> <code title="">nvDash;</code> </td> <td> U+022AD </td> <tr><td> <code title="">nvHarr;</code> </td> <td> U+02904 </td> <tr><td> <code title="">nvdash;</code> </td> <td> U+022AC </td> <tr><td> <code title="">nvinfin;</code> </td> <td> U+029DE </td> <tr><td> <code title="">nvlArr;</code> </td> <td> U+02902 </td> <tr><td> <code title="">nvrArr;</code> </td> <td> U+02903 </td> <tr><td> <code title="">nwArr;</code> </td> <td> U+021D6 </td> <tr><td> <code title="">nwarhk;</code> </td> <td> U+02923 </td> <tr><td> <code title="">nwarr;</code> </td> <td> U+02196 </td> <tr><td> <code title="">nwarrow;</code> </td> <td> U+02196 </td> <tr><td> <code title="">nwnear;</code> </td> <td> U+02927 </td> <tr><td> <code title="">oS;</code> </td> <td> U+024C8 </td> <tr><td> <code title="">oacute;</code> </td> <td> U+000F3 </td> <tr><td> <code title="">oacute</code> </td> <td> U+000F3 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">oast;</code> </td> <td> U+0229B </td> <tr><td> <code title="">ocir;</code> </td> <td> U+0229A </td> <tr><td> <code title="">ocirc;</code> </td> <td> U+000F4 </td> <tr><td> <code title="">ocirc</code> </td> <td> U+000F4 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ocy;</code> </td> <td> U+0043E </td> <tr><td> <code title="">odash;</code> </td> <td> U+0229D </td> <tr><td> <code title="">odblac;</code> </td> <td> U+00151 </td> <tr><td> <code title="">odiv;</code> </td> <td> U+02A38 </td> <tr><td> <code title="">odot;</code> </td> <td> U+02299 </td> <tr><td> <code title="">odsold;</code> </td> <td> U+029BC </td> <tr><td> <code title="">oelig;</code> </td> <td> U+00153 </td> <tr><td> <code title="">ofcir;</code> </td> <td> U+029BF </td> <tr><td> <code title="">ofr;</code> </td> <td> U+1D52C </td> <tr><td> <code title="">ogon;</code> </td> <td> U+002DB </td> <tr><td> <code title="">ograve;</code> </td> <td> U+000F2 </td> <tr><td> <code title="">ograve</code> </td> <td> U+000F2 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ogt;</code> </td> <td> U+029C1 </td> <tr><td> <code title="">ohbar;</code> </td> <td> U+029B5 </td> <tr><td> <code title="">ohm;</code> </td> <td> U+003A9 </td> <tr><td> <code title="">oint;</code> </td> <td> U+0222E </td> <tr><td> <code title="">olarr;</code> </td> <td> U+021BA </td> <tr><td> <code title="">olcir;</code> </td> <td> U+029BE </td> <tr><td> <code title="">olcross;</code> </td> <td> U+029BB </td> <tr><td> <code title="">oline;</code> </td> <td> U+0203E </td> <tr><td> <code title="">olt;</code> </td> <td> U+029C0 </td> <tr><td> <code title="">omacr;</code> </td> <td> U+0014D </td> <tr><td> <code title="">omega;</code> </td> <td> U+003C9 </td> <tr><td> <code title="">omicron;</code> </td> <td> U+003BF </td> <tr><td> <code title="">omid;</code> </td> <td> U+029B6 </td> <tr><td> <code title="">ominus;</code> </td> <td> U+02296 </td> <tr><td> <code title="">oopf;</code> </td> <td> U+1D560 </td> <tr><td> <code title="">opar;</code> </td> <td> U+029B7 </td> <tr><td> <code title="">operp;</code> </td> <td> U+029B9 </td> <tr><td> <code title="">oplus;</code> </td> <td> U+02295 </td> <tr><td> <code title="">or;</code> </td> <td> U+02228 </td> <tr><td> <code title="">orarr;</code> </td> <td> U+021BB </td> <tr><td> <code title="">ord;</code> </td> <td> U+02A5D </td> <tr><td> <code title="">order;</code> </td> <td> U+02134 </td> <tr><td> <code title="">orderof;</code> </td> <td> U+02134 </td> <tr><td> <code title="">ordf;</code> </td> <td> U+000AA </td> <tr><td> <code title="">ordf</code> </td> <td> U+000AA </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ordm;</code> </td> <td> U+000BA </td> <tr><td> <code title="">ordm</code> </td> <td> U+000BA </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">origof;</code> </td> <td> U+022B6 </td> <tr><td> <code title="">oror;</code> </td> <td> U+02A56 </td> <tr><td> <code title="">orslope;</code> </td> <td> U+02A57 </td> <tr><td> <code title="">orv;</code> </td> <td> U+02A5B </td> <tr><td> <code title="">oscr;</code> </td> <td> U+02134 </td> <tr><td> <code title="">oslash;</code> </td> <td> U+000F8 </td> <tr><td> <code title="">oslash</code> </td> <td> U+000F8 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">osol;</code> </td> <td> U+02298 </td> <tr><td> <code title="">otilde;</code> </td> <td> U+000F5 </td> <tr><td> <code title="">otilde</code> </td> <td> U+000F5 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">otimes;</code> </td> <td> U+02297 </td> <tr><td> <code title="">otimesas;</code> </td> <td> U+02A36 </td> <tr><td> <code title="">ouml;</code> </td> <td> U+000F6 </td> <tr><td> <code title="">ouml</code> </td> <td> U+000F6 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ovbar;</code> </td> <td> U+0233D </td> <tr><td> <code title="">par;</code> </td> <td> U+02225 </td> <tr><td> <code title="">para;</code> </td> <td> U+000B6 </td> <tr><td> <code title="">para</code> </td> <td> U+000B6 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">parallel;</code> </td> <td> U+02225 </td> <tr><td> <code title="">parsim;</code> </td> <td> U+02AF3 </td> <tr><td> <code title="">parsl;</code> </td> <td> U+02AFD </td> <tr><td> <code title="">part;</code> </td> <td> U+02202 </td> <tr><td> <code title="">pcy;</code> </td> <td> U+0043F </td> <tr><td> <code title="">percnt;</code> </td> <td> U+00025 </td> <tr><td> <code title="">period;</code> </td> <td> U+0002E </td> <tr><td> <code title="">permil;</code> </td> <td> U+02030 </td> <tr><td> <code title="">perp;</code> </td> <td> U+022A5 </td> <tr><td> <code title="">pertenk;</code> </td> <td> U+02031 </td> <tr><td> <code title="">pfr;</code> </td> <td> U+1D52D </td> <tr><td> <code title="">phi;</code> </td> <td> U+003C6 </td> <tr><td> <code title="">phiv;</code> </td> <td> U+003D5 </td> <tr><td> <code title="">phmmat;</code> </td> <td> U+02133 </td> <tr><td> <code title="">phone;</code> </td> <td> U+0260E </td> <tr><td> <code title="">pi;</code> </td> <td> U+003C0 </td> <tr><td> <code title="">pitchfork;</code> </td> <td> U+022D4 </td> <tr><td> <code title="">piv;</code> </td> <td> U+003D6 </td> <tr><td> <code title="">planck;</code> </td> <td> U+0210F </td> <tr><td> <code title="">planckh;</code> </td> <td> U+0210E </td> <tr><td> <code title="">plankv;</code> </td> <td> U+0210F </td> <tr><td> <code title="">plus;</code> </td> <td> U+0002B </td> <tr><td> <code title="">plusacir;</code> </td> <td> U+02A23 </td> <tr><td> <code title="">plusb;</code> </td> <td> U+0229E </td> <tr><td> <code title="">pluscir;</code> </td> <td> U+02A22 </td> <tr><td> <code title="">plusdo;</code> </td> <td> U+02214 </td> <tr><td> <code title="">plusdu;</code> </td> <td> U+02A25 </td> <tr><td> <code title="">pluse;</code> </td> <td> U+02A72 </td> <tr><td> <code title="">plusmn;</code> </td> <td> U+000B1 </td> <tr><td> <code title="">plusmn</code> </td> <td> U+000B1 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">plussim;</code> </td> <td> U+02A26 </td> <tr><td> <code title="">plustwo;</code> </td> <td> U+02A27 </td> <tr><td> <code title="">pm;</code> </td> <td> U+000B1 </td> <tr><td> <code title="">pointint;</code> </td> <td> U+02A15 </td> <tr><td> <code title="">popf;</code> </td> <td> U+1D561 </td> <tr><td> <code title="">pound;</code> </td> <td> U+000A3 </td> <tr><td> <code title="">pound</code> </td> <td> U+000A3 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">pr;</code> </td> <td> U+0227A </td> <tr><td> <code title="">prE;</code> </td> <td> U+02AB3 </td> <tr><td> <code title="">prap;</code> </td> <td> U+02AB7 </td> <tr><td> <code title="">prcue;</code> </td> <td> U+0227C </td> <tr><td> <code title="">pre;</code> </td> <td> U+02AAF </td> <tr><td> <code title="">prec;</code> </td> <td> U+0227A </td> <tr><td> <code title="">precapprox;</code> </td> <td> U+02AB7 </td> <tr><td> <code title="">preccurlyeq;</code> </td> <td> U+0227C </td> <tr><td> <code title="">preceq;</code> </td> <td> U+02AAF </td> <tr><td> <code title="">precnapprox;</code> </td> <td> U+02AB9 </td> <tr><td> <code title="">precneqq;</code> </td> <td> U+02AB5 </td> <tr><td> <code title="">precnsim;</code> </td> <td> U+022E8 </td> <tr><td> <code title="">precsim;</code> </td> <td> U+0227E </td> <tr><td> <code title="">prime;</code> </td> <td> U+02032 </td> <tr><td> <code title="">primes;</code> </td> <td> U+02119 </td> <tr><td> <code title="">prnE;</code> </td> <td> U+02AB5 </td> <tr><td> <code title="">prnap;</code> </td> <td> U+02AB9 </td> <tr><td> <code title="">prnsim;</code> </td> <td> U+022E8 </td> <tr><td> <code title="">prod;</code> </td> <td> U+0220F </td> <tr><td> <code title="">profalar;</code> </td> <td> U+0232E </td> <tr><td> <code title="">profline;</code> </td> <td> U+02312 </td> <tr><td> <code title="">profsurf;</code> </td> <td> U+02313 </td> <tr><td> <code title="">prop;</code> </td> <td> U+0221D </td> <tr><td> <code title="">propto;</code> </td> <td> U+0221D </td> <tr><td> <code title="">prsim;</code> </td> <td> U+0227E </td> <tr><td> <code title="">prurel;</code> </td> <td> U+022B0 </td> <tr><td> <code title="">pscr;</code> </td> <td> U+1D4C5 </td> <tr><td> <code title="">psi;</code> </td> <td> U+003C8 </td> <tr><td> <code title="">puncsp;</code> </td> <td> U+02008 </td> <tr><td> <code title="">qfr;</code> </td> <td> U+1D52E </td> <tr><td> <code title="">qint;</code> </td> <td> U+02A0C </td> <tr><td> <code title="">qopf;</code> </td> <td> U+1D562 </td> <tr><td> <code title="">qprime;</code> </td> <td> U+02057 </td> <tr><td> <code title="">qscr;</code> </td> <td> U+1D4C6 </td> <tr><td> <code title="">quaternions;</code> </td> <td> U+0210D </td> <tr><td> <code title="">quatint;</code> </td> <td> U+02A16 </td> <tr><td> <code title="">quest;</code> </td> <td> U+0003F </td> <tr><td> <code title="">questeq;</code> </td> <td> U+0225F </td> <tr><td> <code title="">quot;</code> </td> <td> U+00022 </td> <tr><td> <code title="">quot</code> </td> <td> U+00022 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">rAarr;</code> </td> <td> U+021DB </td> <tr><td> <code title="">rArr;</code> </td> <td> U+021D2 </td> <tr><td> <code title="">rAtail;</code> </td> <td> U+0291C </td> <tr><td> <code title="">rBarr;</code> </td> <td> U+0290F </td> <tr><td> <code title="">rHar;</code> </td> <td> U+02964 </td> <tr><td> <code title="">racute;</code> </td> <td> U+00155 </td> <tr><td> <code title="">radic;</code> </td> <td> U+0221A </td> <tr><td> <code title="">raemptyv;</code> </td> <td> U+029B3 </td> <tr><td> <code title="">rang;</code> </td> <td> U+027E9 </td> <tr><td> <code title="">rangd;</code> </td> <td> U+02992 </td> <tr><td> <code title="">range;</code> </td> <td> U+029A5 </td> <tr><td> <code title="">rangle;</code> </td> <td> U+027E9 </td> <tr><td> <code title="">raquo;</code> </td> <td> U+000BB </td> <tr><td> <code title="">raquo</code> </td> <td> U+000BB </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">rarr;</code> </td> <td> U+02192 </td> <tr><td> <code title="">rarrap;</code> </td> <td> U+02975 </td> <tr><td> <code title="">rarrb;</code> </td> <td> U+021E5 </td> <tr><td> <code title="">rarrbfs;</code> </td> <td> U+02920 </td> <tr><td> <code title="">rarrc;</code> </td> <td> U+02933 </td> <tr><td> <code title="">rarrfs;</code> </td> <td> U+0291E </td> <tr><td> <code title="">rarrhk;</code> </td> <td> U+021AA </td> <tr><td> <code title="">rarrlp;</code> </td> <td> U+021AC </td> <tr><td> <code title="">rarrpl;</code> </td> <td> U+02945 </td> <tr><td> <code title="">rarrsim;</code> </td> <td> U+02974 </td> <tr><td> <code title="">rarrtl;</code> </td> <td> U+021A3 </td> <tr><td> <code title="">rarrw;</code> </td> <td> U+0219D </td> <tr><td> <code title="">ratail;</code> </td> <td> U+0291A </td> <tr><td> <code title="">ratio;</code> </td> <td> U+02236 </td> <tr><td> <code title="">rationals;</code> </td> <td> U+0211A </td> <tr><td> <code title="">rbarr;</code> </td> <td> U+0290D </td> <tr><td> <code title="">rbbrk;</code> </td> <td> U+02773 </td> <tr><td> <code title="">rbrace;</code> </td> <td> U+0007D </td> <tr><td> <code title="">rbrack;</code> </td> <td> U+0005D </td> <tr><td> <code title="">rbrke;</code> </td> <td> U+0298C </td> <tr><td> <code title="">rbrksld;</code> </td> <td> U+0298E </td> <tr><td> <code title="">rbrkslu;</code> </td> <td> U+02990 </td> <tr><td> <code title="">rcaron;</code> </td> <td> U+00159 </td> <tr><td> <code title="">rcedil;</code> </td> <td> U+00157 </td> <tr><td> <code title="">rceil;</code> </td> <td> U+02309 </td> <tr><td> <code title="">rcub;</code> </td> <td> U+0007D </td> <tr><td> <code title="">rcy;</code> </td> <td> U+00440 </td> <tr><td> <code title="">rdca;</code> </td> <td> U+02937 </td> <tr><td> <code title="">rdldhar;</code> </td> <td> U+02969 </td> <tr><td> <code title="">rdquo;</code> </td> <td> U+0201D </td> <tr><td> <code title="">rdquor;</code> </td> <td> U+0201D </td> <tr><td> <code title="">rdsh;</code> </td> <td> U+021B3 </td> <tr><td> <code title="">real;</code> </td> <td> U+0211C </td> <tr><td> <code title="">realine;</code> </td> <td> U+0211B </td> <tr><td> <code title="">realpart;</code> </td> <td> U+0211C </td> <tr><td> <code title="">reals;</code> </td> <td> U+0211D </td> <tr><td> <code title="">rect;</code> </td> <td> U+025AD </td> <tr><td> <code title="">reg;</code> </td> <td> U+000AE </td> <tr><td> <code title="">reg</code> </td> <td> U+000AE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">rfisht;</code> </td> <td> U+0297D </td> <tr><td> <code title="">rfloor;</code> </td> <td> U+0230B </td> <tr><td> <code title="">rfr;</code> </td> <td> U+1D52F </td> <tr><td> <code title="">rhard;</code> </td> <td> U+021C1 </td> <tr><td> <code title="">rharu;</code> </td> <td> U+021C0 </td> <tr><td> <code title="">rharul;</code> </td> <td> U+0296C </td> <tr><td> <code title="">rho;</code> </td> <td> U+003C1 </td> <tr><td> <code title="">rhov;</code> </td> <td> U+003F1 </td> <tr><td> <code title="">rightarrow;</code> </td> <td> U+02192 </td> <tr><td> <code title="">rightarrowtail;</code> </td> <td> U+021A3 </td> <tr><td> <code title="">rightharpoondown;</code> </td> <td> U+021C1 </td> <tr><td> <code title="">rightharpoonup;</code> </td> <td> U+021C0 </td> <tr><td> <code title="">rightleftarrows;</code> </td> <td> U+021C4 </td> <tr><td> <code title="">rightleftharpoons;</code> </td> <td> U+021CC </td> <tr><td> <code title="">rightrightarrows;</code> </td> <td> U+021C9 </td> <tr><td> <code title="">rightsquigarrow;</code> </td> <td> U+0219D </td> <tr><td> <code title="">rightthreetimes;</code> </td> <td> U+022CC </td> <tr><td> <code title="">ring;</code> </td> <td> U+002DA </td> <tr><td> <code title="">risingdotseq;</code> </td> <td> U+02253 </td> <tr><td> <code title="">rlarr;</code> </td> <td> U+021C4 </td> <tr><td> <code title="">rlhar;</code> </td> <td> U+021CC </td> <tr><td> <code title="">rlm;</code> </td> <td> U+0200F </td> <tr><td> <code title="">rmoust;</code> </td> <td> U+023B1 </td> <tr><td> <code title="">rmoustache;</code> </td> <td> U+023B1 </td> <tr><td> <code title="">rnmid;</code> </td> <td> U+02AEE </td> <tr><td> <code title="">roang;</code> </td> <td> U+027ED </td> <tr><td> <code title="">roarr;</code> </td> <td> U+021FE </td> <tr><td> <code title="">robrk;</code> </td> <td> U+027E7 </td> <tr><td> <code title="">ropar;</code> </td> <td> U+02986 </td> <tr><td> <code title="">ropf;</code> </td> <td> U+1D563 </td> <tr><td> <code title="">roplus;</code> </td> <td> U+02A2E </td> <tr><td> <code title="">rotimes;</code> </td> <td> U+02A35 </td> <tr><td> <code title="">rpar;</code> </td> <td> U+00029 </td> <tr><td> <code title="">rpargt;</code> </td> <td> U+02994 </td> <tr><td> <code title="">rppolint;</code> </td> <td> U+02A12 </td> <tr><td> <code title="">rrarr;</code> </td> <td> U+021C9 </td> <tr><td> <code title="">rsaquo;</code> </td> <td> U+0203A </td> <tr><td> <code title="">rscr;</code> </td> <td> U+1D4C7 </td> <tr><td> <code title="">rsh;</code> </td> <td> U+021B1 </td> <tr><td> <code title="">rsqb;</code> </td> <td> U+0005D </td> <tr><td> <code title="">rsquo;</code> </td> <td> U+02019 </td> <tr><td> <code title="">rsquor;</code> </td> <td> U+02019 </td> <tr><td> <code title="">rthree;</code> </td> <td> U+022CC </td> <tr><td> <code title="">rtimes;</code> </td> <td> U+022CA </td> <tr><td> <code title="">rtri;</code> </td> <td> U+025B9 </td> <tr><td> <code title="">rtrie;</code> </td> <td> U+022B5 </td> <tr><td> <code title="">rtrif;</code> </td> <td> U+025B8 </td> <tr><td> <code title="">rtriltri;</code> </td> <td> U+029CE </td> <tr><td> <code title="">ruluhar;</code> </td> <td> U+02968 </td> <tr><td> <code title="">rx;</code> </td> <td> U+0211E </td> <tr><td> <code title="">sacute;</code> </td> <td> U+0015B </td> <tr><td> <code title="">sbquo;</code> </td> <td> U+0201A </td> <tr><td> <code title="">sc;</code> </td> <td> U+0227B </td> <tr><td> <code title="">scE;</code> </td> <td> U+02AB4 </td> <tr><td> <code title="">scap;</code> </td> <td> U+02AB8 </td> <tr><td> <code title="">scaron;</code> </td> <td> U+00161 </td> <tr><td> <code title="">sccue;</code> </td> <td> U+0227D </td> <tr><td> <code title="">sce;</code> </td> <td> U+02AB0 </td> <tr><td> <code title="">scedil;</code> </td> <td> U+0015F </td> <tr><td> <code title="">scirc;</code> </td> <td> U+0015D </td> <tr><td> <code title="">scnE;</code> </td> <td> U+02AB6 </td> <tr><td> <code title="">scnap;</code> </td> <td> U+02ABA </td> <tr><td> <code title="">scnsim;</code> </td> <td> U+022E9 </td> <tr><td> <code title="">scpolint;</code> </td> <td> U+02A13 </td> <tr><td> <code title="">scsim;</code> </td> <td> U+0227F </td> <tr><td> <code title="">scy;</code> </td> <td> U+00441 </td> <tr><td> <code title="">sdot;</code> </td> <td> U+022C5 </td> <tr><td> <code title="">sdotb;</code> </td> <td> U+022A1 </td> <tr><td> <code title="">sdote;</code> </td> <td> U+02A66 </td> <tr><td> <code title="">seArr;</code> </td> <td> U+021D8 </td> <tr><td> <code title="">searhk;</code> </td> <td> U+02925 </td> <tr><td> <code title="">searr;</code> </td> <td> U+02198 </td> <tr><td> <code title="">searrow;</code> </td> <td> U+02198 </td> <tr><td> <code title="">sect;</code> </td> <td> U+000A7 </td> <tr><td> <code title="">sect</code> </td> <td> U+000A7 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">semi;</code> </td> <td> U+0003B </td> <tr><td> <code title="">seswar;</code> </td> <td> U+02929 </td> <tr><td> <code title="">setminus;</code> </td> <td> U+02216 </td> <tr><td> <code title="">setmn;</code> </td> <td> U+02216 </td> <tr><td> <code title="">sext;</code> </td> <td> U+02736 </td> <tr><td> <code title="">sfr;</code> </td> <td> U+1D530 </td> <tr><td> <code title="">sfrown;</code> </td> <td> U+02322 </td> <tr><td> <code title="">sharp;</code> </td> <td> U+0266F </td> <tr><td> <code title="">shchcy;</code> </td> <td> U+00449 </td> <tr><td> <code title="">shcy;</code> </td> <td> U+00448 </td> <tr><td> <code title="">shortmid;</code> </td> <td> U+02223 </td> <tr><td> <code title="">shortparallel;</code> </td> <td> U+02225 </td> <tr><td> <code title="">shy;</code> </td> <td> U+000AD </td> <tr><td> <code title="">shy</code> </td> <td> U+000AD </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">sigma;</code> </td> <td> U+003C3 </td> <tr><td> <code title="">sigmaf;</code> </td> <td> U+003C2 </td> <tr><td> <code title="">sigmav;</code> </td> <td> U+003C2 </td> <tr><td> <code title="">sim;</code> </td> <td> U+0223C </td> <tr><td> <code title="">simdot;</code> </td> <td> U+02A6A </td> <tr><td> <code title="">sime;</code> </td> <td> U+02243 </td> <tr><td> <code title="">simeq;</code> </td> <td> U+02243 </td> <tr><td> <code title="">simg;</code> </td> <td> U+02A9E </td> <tr><td> <code title="">simgE;</code> </td> <td> U+02AA0 </td> <tr><td> <code title="">siml;</code> </td> <td> U+02A9D </td> <tr><td> <code title="">simlE;</code> </td> <td> U+02A9F </td> <tr><td> <code title="">simne;</code> </td> <td> U+02246 </td> <tr><td> <code title="">simplus;</code> </td> <td> U+02A24 </td> <tr><td> <code title="">simrarr;</code> </td> <td> U+02972 </td> <tr><td> <code title="">slarr;</code> </td> <td> U+02190 </td> <tr><td> <code title="">smallsetminus;</code> </td> <td> U+02216 </td> <tr><td> <code title="">smashp;</code> </td> <td> U+02A33 </td> <tr><td> <code title="">smeparsl;</code> </td> <td> U+029E4 </td> <tr><td> <code title="">smid;</code> </td> <td> U+02223 </td> <tr><td> <code title="">smile;</code> </td> <td> U+02323 </td> <tr><td> <code title="">smt;</code> </td> <td> U+02AAA </td> <tr><td> <code title="">smte;</code> </td> <td> U+02AAC </td> <tr><td> <code title="">softcy;</code> </td> <td> U+0044C </td> <tr><td> <code title="">sol;</code> </td> <td> U+0002F </td> <tr><td> <code title="">solb;</code> </td> <td> U+029C4 </td> <tr><td> <code title="">solbar;</code> </td> <td> U+0233F </td> <tr><td> <code title="">sopf;</code> </td> <td> U+1D564 </td> <tr><td> <code title="">spades;</code> </td> <td> U+02660 </td> <tr><td> <code title="">spadesuit;</code> </td> <td> U+02660 </td> <tr><td> <code title="">spar;</code> </td> <td> U+02225 </td> <tr><td> <code title="">sqcap;</code> </td> <td> U+02293 </td> <tr><td> <code title="">sqcup;</code> </td> <td> U+02294 </td> <tr><td> <code title="">sqsub;</code> </td> <td> U+0228F </td> <tr><td> <code title="">sqsube;</code> </td> <td> U+02291 </td> <tr><td> <code title="">sqsubset;</code> </td> <td> U+0228F </td> <tr><td> <code title="">sqsubseteq;</code> </td> <td> U+02291 </td> <tr><td> <code title="">sqsup;</code> </td> <td> U+02290 </td> <tr><td> <code title="">sqsupe;</code> </td> <td> U+02292 </td> <tr><td> <code title="">sqsupset;</code> </td> <td> U+02290 </td> <tr><td> <code title="">sqsupseteq;</code> </td> <td> U+02292 </td> <tr><td> <code title="">squ;</code> </td> <td> U+025A1 </td> <tr><td> <code title="">square;</code> </td> <td> U+025A1 </td> <tr><td> <code title="">squarf;</code> </td> <td> U+025AA </td> <tr><td> <code title="">squf;</code> </td> <td> U+025AA </td> <tr><td> <code title="">srarr;</code> </td> <td> U+02192 </td> <tr><td> <code title="">sscr;</code> </td> <td> U+1D4C8 </td> <tr><td> <code title="">ssetmn;</code> </td> <td> U+02216 </td> <tr><td> <code title="">ssmile;</code> </td> <td> U+02323 </td> <tr><td> <code title="">sstarf;</code> </td> <td> U+022C6 </td> <tr><td> <code title="">star;</code> </td> <td> U+02606 </td> <tr><td> <code title="">starf;</code> </td> <td> U+02605 </td> <tr><td> <code title="">straightepsilon;</code> </td> <td> U+003F5 </td> <tr><td> <code title="">straightphi;</code> </td> <td> U+003D5 </td> <tr><td> <code title="">strns;</code> </td> <td> U+000AF </td> <tr><td> <code title="">sub;</code> </td> <td> U+02282 </td> <tr><td> <code title="">subE;</code> </td> <td> U+02AC5 </td> <tr><td> <code title="">subdot;</code> </td> <td> U+02ABD </td> <tr><td> <code title="">sube;</code> </td> <td> U+02286 </td> <tr><td> <code title="">subedot;</code> </td> <td> U+02AC3 </td> <tr><td> <code title="">submult;</code> </td> <td> U+02AC1 </td> <tr><td> <code title="">subnE;</code> </td> <td> U+02ACB </td> <tr><td> <code title="">subne;</code> </td> <td> U+0228A </td> <tr><td> <code title="">subplus;</code> </td> <td> U+02ABF </td> <tr><td> <code title="">subrarr;</code> </td> <td> U+02979 </td> <tr><td> <code title="">subset;</code> </td> <td> U+02282 </td> <tr><td> <code title="">subseteq;</code> </td> <td> U+02286 </td> <tr><td> <code title="">subseteqq;</code> </td> <td> U+02AC5 </td> <tr><td> <code title="">subsetneq;</code> </td> <td> U+0228A </td> <tr><td> <code title="">subsetneqq;</code> </td> <td> U+02ACB </td> <tr><td> <code title="">subsim;</code> </td> <td> U+02AC7 </td> <tr><td> <code title="">subsub;</code> </td> <td> U+02AD5 </td> <tr><td> <code title="">subsup;</code> </td> <td> U+02AD3 </td> <tr><td> <code title="">succ;</code> </td> <td> U+0227B </td> <tr><td> <code title="">succapprox;</code> </td> <td> U+02AB8 </td> <tr><td> <code title="">succcurlyeq;</code> </td> <td> U+0227D </td> <tr><td> <code title="">succeq;</code> </td> <td> U+02AB0 </td> <tr><td> <code title="">succnapprox;</code> </td> <td> U+02ABA </td> <tr><td> <code title="">succneqq;</code> </td> <td> U+02AB6 </td> <tr><td> <code title="">succnsim;</code> </td> <td> U+022E9 </td> <tr><td> <code title="">succsim;</code> </td> <td> U+0227F </td> <tr><td> <code title="">sum;</code> </td> <td> U+02211 </td> <tr><td> <code title="">sung;</code> </td> <td> U+0266A </td> <tr><td> <code title="">sup1;</code> </td> <td> U+000B9 </td> <tr><td> <code title="">sup1</code> </td> <td> U+000B9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">sup2;</code> </td> <td> U+000B2 </td> <tr><td> <code title="">sup2</code> </td> <td> U+000B2 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">sup3;</code> </td> <td> U+000B3 </td> <tr><td> <code title="">sup3</code> </td> <td> U+000B3 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">sup;</code> </td> <td> U+02283 </td> <tr><td> <code title="">supE;</code> </td> <td> U+02AC6 </td> <tr><td> <code title="">supdot;</code> </td> <td> U+02ABE </td> <tr><td> <code title="">supdsub;</code> </td> <td> U+02AD8 </td> <tr><td> <code title="">supe;</code> </td> <td> U+02287 </td> <tr><td> <code title="">supedot;</code> </td> <td> U+02AC4 </td> <tr><td> <code title="">suphsol;</code> </td> <td> U+027C9 </td> <tr><td> <code title="">suphsub;</code> </td> <td> U+02AD7 </td> <tr><td> <code title="">suplarr;</code> </td> <td> U+0297B </td> <tr><td> <code title="">supmult;</code> </td> <td> U+02AC2 </td> <tr><td> <code title="">supnE;</code> </td> <td> U+02ACC </td> <tr><td> <code title="">supne;</code> </td> <td> U+0228B </td> <tr><td> <code title="">supplus;</code> </td> <td> U+02AC0 </td> <tr><td> <code title="">supset;</code> </td> <td> U+02283 </td> <tr><td> <code title="">supseteq;</code> </td> <td> U+02287 </td> <tr><td> <code title="">supseteqq;</code> </td> <td> U+02AC6 </td> <tr><td> <code title="">supsetneq;</code> </td> <td> U+0228B </td> <tr><td> <code title="">supsetneqq;</code> </td> <td> U+02ACC </td> <tr><td> <code title="">supsim;</code> </td> <td> U+02AC8 </td> <tr><td> <code title="">supsub;</code> </td> <td> U+02AD4 </td> <tr><td> <code title="">supsup;</code> </td> <td> U+02AD6 </td> <tr><td> <code title="">swArr;</code> </td> <td> U+021D9 </td> <tr><td> <code title="">swarhk;</code> </td> <td> U+02926 </td> <tr><td> <code title="">swarr;</code> </td> <td> U+02199 </td> <tr><td> <code title="">swarrow;</code> </td> <td> U+02199 </td> <tr><td> <code title="">swnwar;</code> </td> <td> U+0292A </td> <tr><td> <code title="">szlig;</code> </td> <td> U+000DF </td> <tr><td> <code title="">szlig</code> </td> <td> U+000DF </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">target;</code> </td> <td> U+02316 </td> <tr><td> <code title="">tau;</code> </td> <td> U+003C4 </td> <tr><td> <code title="">tbrk;</code> </td> <td> U+023B4 </td> <tr><td> <code title="">tcaron;</code> </td> <td> U+00165 </td> <tr><td> <code title="">tcedil;</code> </td> <td> U+00163 </td> <tr><td> <code title="">tcy;</code> </td> <td> U+00442 </td> <tr><td> <code title="">tdot;</code> </td> <td> U+020DB </td> <tr><td> <code title="">telrec;</code> </td> <td> U+02315 </td> <tr><td> <code title="">tfr;</code> </td> <td> U+1D531 </td> <tr><td> <code title="">there4;</code> </td> <td> U+02234 </td> <tr><td> <code title="">therefore;</code> </td> <td> U+02234 </td> <tr><td> <code title="">theta;</code> </td> <td> U+003B8 </td> <tr><td> <code title="">thetasym;</code> </td> <td> U+003D1 </td> <tr><td> <code title="">thetav;</code> </td> <td> U+003D1 </td> <tr><td> <code title="">thickapprox;</code> </td> <td> U+02248 </td> <tr><td> <code title="">thicksim;</code> </td> <td> U+0223C </td> <tr><td> <code title="">thinsp;</code> </td> <td> U+02009 </td> <tr><td> <code title="">thkap;</code> </td> <td> U+02248 </td> <tr><td> <code title="">thksim;</code> </td> <td> U+0223C </td> <tr><td> <code title="">thorn;</code> </td> <td> U+000FE </td> <tr><td> <code title="">thorn</code> </td> <td> U+000FE </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">tilde;</code> </td> <td> U+002DC </td> <tr><td> <code title="">times;</code> </td> <td> U+000D7 </td> <tr><td> <code title="">times</code> </td> <td> U+000D7 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">timesb;</code> </td> <td> U+022A0 </td> <tr><td> <code title="">timesbar;</code> </td> <td> U+02A31 </td> <tr><td> <code title="">timesd;</code> </td> <td> U+02A30 </td> <tr><td> <code title="">tint;</code> </td> <td> U+0222D </td> <tr><td> <code title="">toea;</code> </td> <td> U+02928 </td> <tr><td> <code title="">top;</code> </td> <td> U+022A4 </td> <tr><td> <code title="">topbot;</code> </td> <td> U+02336 </td> <tr><td> <code title="">topcir;</code> </td> <td> U+02AF1 </td> <tr><td> <code title="">topf;</code> </td> <td> U+1D565 </td> <tr><td> <code title="">topfork;</code> </td> <td> U+02ADA </td> <tr><td> <code title="">tosa;</code> </td> <td> U+02929 </td> <tr><td> <code title="">tprime;</code> </td> <td> U+02034 </td> <tr><td> <code title="">trade;</code> </td> <td> U+02122 </td> <tr><td> <code title="">triangle;</code> </td> <td> U+025B5 </td> <tr><td> <code title="">triangledown;</code> </td> <td> U+025BF </td> <tr><td> <code title="">triangleleft;</code> </td> <td> U+025C3 </td> <tr><td> <code title="">trianglelefteq;</code> </td> <td> U+022B4 </td> <tr><td> <code title="">triangleq;</code> </td> <td> U+0225C </td> <tr><td> <code title="">triangleright;</code> </td> <td> U+025B9 </td> <tr><td> <code title="">trianglerighteq;</code> </td> <td> U+022B5 </td> <tr><td> <code title="">tridot;</code> </td> <td> U+025EC </td> <tr><td> <code title="">trie;</code> </td> <td> U+0225C </td> <tr><td> <code title="">triminus;</code> </td> <td> U+02A3A </td> <tr><td> <code title="">triplus;</code> </td> <td> U+02A39 </td> <tr><td> <code title="">trisb;</code> </td> <td> U+029CD </td> <tr><td> <code title="">tritime;</code> </td> <td> U+02A3B </td> <tr><td> <code title="">trpezium;</code> </td> <td> U+023E2 </td> <tr><td> <code title="">tscr;</code> </td> <td> U+1D4C9 </td> <tr><td> <code title="">tscy;</code> </td> <td> U+00446 </td> <tr><td> <code title="">tshcy;</code> </td> <td> U+0045B </td> <tr><td> <code title="">tstrok;</code> </td> <td> U+00167 </td> <tr><td> <code title="">twixt;</code> </td> <td> U+0226C </td> <tr><td> <code title="">twoheadleftarrow;</code> </td> <td> U+0219E </td> <tr><td> <code title="">twoheadrightarrow;</code> </td> <td> U+021A0 </td> <tr><td> <code title="">uArr;</code> </td> <td> U+021D1 </td> <tr><td> <code title="">uHar;</code> </td> <td> U+02963 </td> <tr><td> <code title="">uacute;</code> </td> <td> U+000FA </td> <tr><td> <code title="">uacute</code> </td> <td> U+000FA </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">uarr;</code> </td> <td> U+02191 </td> <tr><td> <code title="">ubrcy;</code> </td> <td> U+0045E </td> <tr><td> <code title="">ubreve;</code> </td> <td> U+0016D </td> <tr><td> <code title="">ucirc;</code> </td> <td> U+000FB </td> <tr><td> <code title="">ucirc</code> </td> <td> U+000FB </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">ucy;</code> </td> <td> U+00443 </td> <tr><td> <code title="">udarr;</code> </td> <td> U+021C5 </td> <tr><td> <code title="">udblac;</code> </td> <td> U+00171 </td> <tr><td> <code title="">udhar;</code> </td> <td> U+0296E </td> <tr><td> <code title="">ufisht;</code> </td> <td> U+0297E </td> <tr><td> <code title="">ufr;</code> </td> <td> U+1D532 </td> <tr><td> <code title="">ugrave;</code> </td> <td> U+000F9 </td> <tr><td> <code title="">ugrave</code> </td> <td> U+000F9 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">uharl;</code> </td> <td> U+021BF </td> <tr><td> <code title="">uharr;</code> </td> <td> U+021BE </td> <tr><td> <code title="">uhblk;</code> </td> <td> U+02580 </td> <tr><td> <code title="">ulcorn;</code> </td> <td> U+0231C </td> <tr><td> <code title="">ulcorner;</code> </td> <td> U+0231C </td> <tr><td> <code title="">ulcrop;</code> </td> <td> U+0230F </td> <tr><td> <code title="">ultri;</code> </td> <td> U+025F8 </td> <tr><td> <code title="">umacr;</code> </td> <td> U+0016B </td> <tr><td> <code title="">uml;</code> </td> <td> U+000A8 </td> <tr><td> <code title="">uml</code> </td> <td> U+000A8 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">uogon;</code> </td> <td> U+00173 </td> <tr><td> <code title="">uopf;</code> </td> <td> U+1D566 </td> <tr><td> <code title="">uparrow;</code> </td> <td> U+02191 </td> <tr><td> <code title="">updownarrow;</code> </td> <td> U+02195 </td> <tr><td> <code title="">upharpoonleft;</code> </td> <td> U+021BF </td> <tr><td> <code title="">upharpoonright;</code> </td> <td> U+021BE </td> <tr><td> <code title="">uplus;</code> </td> <td> U+0228E </td> <tr><td> <code title="">upsi;</code> </td> <td> U+003C5 </td> <tr><td> <code title="">upsih;</code> </td> <td> U+003D2 </td> <tr><td> <code title="">upsilon;</code> </td> <td> U+003C5 </td> <tr><td> <code title="">upuparrows;</code> </td> <td> U+021C8 </td> <tr><td> <code title="">urcorn;</code> </td> <td> U+0231D </td> <tr><td> <code title="">urcorner;</code> </td> <td> U+0231D </td> <tr><td> <code title="">urcrop;</code> </td> <td> U+0230E </td> <tr><td> <code title="">uring;</code> </td> <td> U+0016F </td> <tr><td> <code title="">urtri;</code> </td> <td> U+025F9 </td> <tr><td> <code title="">uscr;</code> </td> <td> U+1D4CA </td> <tr><td> <code title="">utdot;</code> </td> <td> U+022F0 </td> <tr><td> <code title="">utilde;</code> </td> <td> U+00169 </td> <tr><td> <code title="">utri;</code> </td> <td> U+025B5 </td> <tr><td> <code title="">utrif;</code> </td> <td> U+025B4 </td> <tr><td> <code title="">uuarr;</code> </td> <td> U+021C8 </td> <tr><td> <code title="">uuml;</code> </td> <td> U+000FC </td> <tr><td> <code title="">uuml</code> </td> <td> U+000FC </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">uwangle;</code> </td> <td> U+029A7 </td> <tr><td> <code title="">vArr;</code> </td> <td> U+021D5 </td> <tr><td> <code title="">vBar;</code> </td> <td> U+02AE8 </td> <tr><td> <code title="">vBarv;</code> </td> <td> U+02AE9 </td> <tr><td> <code title="">vDash;</code> </td> <td> U+022A8 </td> <tr><td> <code title="">vangrt;</code> </td> <td> U+0299C </td> <tr><td> <code title="">varepsilon;</code> </td> <td> U+003F5 </td> <tr><td> <code title="">varkappa;</code> </td> <td> U+003F0 </td> <tr><td> <code title="">varnothing;</code> </td> <td> U+02205 </td> <tr><td> <code title="">varphi;</code> </td> <td> U+003D5 </td> <tr><td> <code title="">varpi;</code> </td> <td> U+003D6 </td> <tr><td> <code title="">varpropto;</code> </td> <td> U+0221D </td> <tr><td> <code title="">varr;</code> </td> <td> U+02195 </td> <tr><td> <code title="">varrho;</code> </td> <td> U+003F1 </td> <tr><td> <code title="">varsigma;</code> </td> <td> U+003C2 </td> <tr><td> <code title="">vartheta;</code> </td> <td> U+003D1 </td> <tr><td> <code title="">vartriangleleft;</code> </td> <td> U+022B2 </td> <tr><td> <code title="">vartriangleright;</code> </td> <td> U+022B3 </td> <tr><td> <code title="">vcy;</code> </td> <td> U+00432 </td> <tr><td> <code title="">vdash;</code> </td> <td> U+022A2 </td> <tr><td> <code title="">vee;</code> </td> <td> U+02228 </td> <tr><td> <code title="">veebar;</code> </td> <td> U+022BB </td> <tr><td> <code title="">veeeq;</code> </td> <td> U+0225A </td> <tr><td> <code title="">vellip;</code> </td> <td> U+022EE </td> <tr><td> <code title="">verbar;</code> </td> <td> U+0007C </td> <tr><td> <code title="">vert;</code> </td> <td> U+0007C </td> <tr><td> <code title="">vfr;</code> </td> <td> U+1D533 </td> <tr><td> <code title="">vltri;</code> </td> <td> U+022B2 </td> <tr><td> <code title="">vopf;</code> </td> <td> U+1D567 </td> <tr><td> <code title="">vprop;</code> </td> <td> U+0221D </td> <tr><td> <code title="">vrtri;</code> </td> <td> U+022B3 </td> <tr><td> <code title="">vscr;</code> </td> <td> U+1D4CB </td> <tr><td> <code title="">vzigzag;</code> </td> <td> U+0299A </td> <tr><td> <code title="">wcirc;</code> </td> <td> U+00175 </td> <tr><td> <code title="">wedbar;</code> </td> <td> U+02A5F </td> <tr><td> <code title="">wedge;</code> </td> <td> U+02227 </td> <tr><td> <code title="">wedgeq;</code> </td> <td> U+02259 </td> <tr><td> <code title="">weierp;</code> </td> <td> U+02118 </td> <tr><td> <code title="">wfr;</code> </td> <td> U+1D534 </td> <tr><td> <code title="">wopf;</code> </td> <td> U+1D568 </td> <tr><td> <code title="">wp;</code> </td> <td> U+02118 </td> <tr><td> <code title="">wr;</code> </td> <td> U+02240 </td> <tr><td> <code title="">wreath;</code> </td> <td> U+02240 </td> <tr><td> <code title="">wscr;</code> </td> <td> U+1D4CC </td> <tr><td> <code title="">xcap;</code> </td> <td> U+022C2 </td> <tr><td> <code title="">xcirc;</code> </td> <td> U+025EF </td> <tr><td> <code title="">xcup;</code> </td> <td> U+022C3 </td> <tr><td> <code title="">xdtri;</code> </td> <td> U+025BD </td> <tr><td> <code title="">xfr;</code> </td> <td> U+1D535 </td> <tr><td> <code title="">xhArr;</code> </td> <td> U+027FA </td> <tr><td> <code title="">xharr;</code> </td> <td> U+027F7 </td> <tr><td> <code title="">xi;</code> </td> <td> U+003BE </td> <tr><td> <code title="">xlArr;</code> </td> <td> U+027F8 </td> <tr><td> <code title="">xlarr;</code> </td> <td> U+027F5 </td> <tr><td> <code title="">xmap;</code> </td> <td> U+027FC </td> <tr><td> <code title="">xnis;</code> </td> <td> U+022FB </td> <tr><td> <code title="">xodot;</code> </td> <td> U+02A00 </td> <tr><td> <code title="">xopf;</code> </td> <td> U+1D569 </td> <tr><td> <code title="">xoplus;</code> </td> <td> U+02A01 </td> <tr><td> <code title="">xotime;</code> </td> <td> U+02A02 </td> <tr><td> <code title="">xrArr;</code> </td> <td> U+027F9 </td> <tr><td> <code title="">xrarr;</code> </td> <td> U+027F6 </td> <tr><td> <code title="">xscr;</code> </td> <td> U+1D4CD </td> <tr><td> <code title="">xsqcup;</code> </td> <td> U+02A06 </td> <tr><td> <code title="">xuplus;</code> </td> <td> U+02A04 </td> <tr><td> <code title="">xutri;</code> </td> <td> U+025B3 </td> <tr><td> <code title="">xvee;</code> </td> <td> U+022C1 </td> <tr><td> <code title="">xwedge;</code> </td> <td> U+022C0 </td> <tr><td> <code title="">yacute;</code> </td> <td> U+000FD </td> <tr><td> <code title="">yacute</code> </td> <td> U+000FD </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">yacy;</code> </td> <td> U+0044F </td> <tr><td> <code title="">ycirc;</code> </td> <td> U+00177 </td> <tr><td> <code title="">ycy;</code> </td> <td> U+0044B </td> <tr><td> <code title="">yen;</code> </td> <td> U+000A5 </td> <tr><td> <code title="">yen</code> </td> <td> U+000A5 </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">yfr;</code> </td> <td> U+1D536 </td> <tr><td> <code title="">yicy;</code> </td> <td> U+00457 </td> <tr><td> <code title="">yopf;</code> </td> <td> U+1D56A </td> <tr><td> <code title="">yscr;</code> </td> <td> U+1D4CE </td> <tr><td> <code title="">yucy;</code> </td> <td> U+0044E </td> <tr><td> <code title="">yuml;</code> </td> <td> U+000FF </td> <tr><td> <code title="">yuml</code> </td> <td> U+000FF </td> </tr><!-- (invalid entity with missing semicolon for legacy support only) --><tr><td> <code title="">zacute;</code> </td> <td> U+0017A </td> <tr><td> <code title="">zcaron;</code> </td> <td> U+0017E </td> <tr><td> <code title="">zcy;</code> </td> <td> U+00437 </td> <tr><td> <code title="">zdot;</code> </td> <td> U+0017C </td> <tr><td> <code title="">zeetrf;</code> </td> <td> U+02128 </td> <tr><td> <code title="">zeta;</code> </td> <td> U+003B6 </td> <tr><td> <code title="">zfr;</code> </td> <td> U+1D537 </td> <tr><td> <code title="">zhcy;</code> </td> <td> U+00436 </td> <tr><td> <code title="">zigrarr;</code> </td> <td> U+021DD </td> <tr><td> <code title="">zopf;</code> </td> <td> U+1D56B </td> <tr><td> <code title="">zscr;</code> </td> <td> U+1D4CF </td> <tr><td> <code title="">zwj;</code> </td> <td> U+0200D </td> <tr><td> <code title="">zwnj;</code> </td> <td> U+0200C </td> </table>
+
+ \ No newline at end of file
diff --git a/parser/html/javasrc/AttributeName.java b/parser/html/javasrc/AttributeName.java
new file mode 100644
index 0000000000..8014cd8043
--- /dev/null
+++ b/parser/html/javasrc/AttributeName.java
@@ -0,0 +1,2278 @@
+/*
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.impl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import nu.validator.htmlparser.annotation.Inline;
+import nu.validator.htmlparser.annotation.Local;
+import nu.validator.htmlparser.annotation.NoLength;
+import nu.validator.htmlparser.annotation.NsUri;
+import nu.validator.htmlparser.annotation.Prefix;
+import nu.validator.htmlparser.annotation.QName;
+import nu.validator.htmlparser.annotation.Unsigned;
+import nu.validator.htmlparser.common.Interner;
+
+public final class AttributeName
+// Uncomment to regenerate
+// implements Comparable<AttributeName>
+{
+ // [NOCPP[
+
+ public static final int NCNAME_HTML = 1;
+
+ public static final int NCNAME_FOREIGN = (1 << 1) | (1 << 2);
+
+ public static final int NCNAME_LANG = (1 << 3);
+
+ public static final int IS_XMLNS = (1 << 4);
+
+ public static final int CASE_FOLDED = (1 << 5);
+
+ public static final int BOOLEAN = (1 << 6);
+
+ // ]NOCPP]
+
+ /**
+ * An array representing no namespace regardless of namespace mode (HTML,
+ * SVG, MathML, lang-mapping HTML) used.
+ */
+ static final @NoLength @NsUri String[] ALL_NO_NS = { "", "", "",
+ // [NOCPP[
+ ""
+ // ]NOCPP]
+ };
+
+ /**
+ * An array that has no namespace for the HTML mode but the XMLNS namespace
+ * for the SVG and MathML modes.
+ */
+ private static final @NoLength @NsUri String[] XMLNS_NS = { "",
+ "http://www.w3.org/2000/xmlns/", "http://www.w3.org/2000/xmlns/",
+ // [NOCPP[
+ ""
+ // ]NOCPP]
+ };
+
+ /**
+ * An array that has no namespace for the HTML mode but the XML namespace
+ * for the SVG and MathML modes.
+ */
+ private static final @NoLength @NsUri String[] XML_NS = { "",
+ "http://www.w3.org/XML/1998/namespace",
+ "http://www.w3.org/XML/1998/namespace",
+ // [NOCPP[
+ ""
+ // ]NOCPP]
+ };
+
+ /**
+ * An array that has no namespace for the HTML mode but the XLink namespace
+ * for the SVG and MathML modes.
+ */
+ private static final @NoLength @NsUri String[] XLINK_NS = { "",
+ "http://www.w3.org/1999/xlink", "http://www.w3.org/1999/xlink",
+ // [NOCPP[
+ ""
+ // ]NOCPP]
+ };
+
+ // [NOCPP[
+ /**
+ * An array that has no namespace for the HTML, SVG and MathML modes but has
+ * the XML namespace for the lang-mapping HTML mode.
+ */
+ private static final @NoLength @NsUri String[] LANG_NS = { "", "", "",
+ "http://www.w3.org/XML/1998/namespace" };
+
+ // ]NOCPP]
+
+ /**
+ * An array for no prefixes in any mode.
+ */
+ static final @NoLength @Prefix String[] ALL_NO_PREFIX = { null, null, null,
+ // [NOCPP[
+ null
+ // ]NOCPP]
+ };
+
+ /**
+ * An array for no prefixe in the HTML mode and the <code>xmlns</code>
+ * prefix in the SVG and MathML modes.
+ */
+ private static final @NoLength @Prefix String[] XMLNS_PREFIX = { null,
+ "xmlns", "xmlns",
+ // [NOCPP[
+ null
+ // ]NOCPP]
+ };
+
+ /**
+ * An array for no prefixe in the HTML mode and the <code>xlink</code>
+ * prefix in the SVG and MathML modes.
+ */
+ private static final @NoLength @Prefix String[] XLINK_PREFIX = { null,
+ "xlink", "xlink",
+ // [NOCPP[
+ null
+ // ]NOCPP]
+ };
+
+ /**
+ * An array for no prefixe in the HTML mode and the <code>xml</code> prefix
+ * in the SVG and MathML modes.
+ */
+ private static final @NoLength @Prefix String[] XML_PREFIX = { null, "xml",
+ "xml",
+ // [NOCPP[
+ null
+ // ]NOCPP]
+ };
+
+ // [NOCPP[
+
+ private static final @NoLength @Prefix String[] LANG_PREFIX = { null, null,
+ null, "xml" };
+
+ private static @QName String[] COMPUTE_QNAME(String[] local, String[] prefix) {
+ @QName String[] arr = new String[4];
+ for (int i = 0; i < arr.length; i++) {
+ if (prefix[i] == null) {
+ arr[i] = local[i];
+ } else {
+ arr[i] = (prefix[i] + ':' + local[i]).intern();
+ }
+ }
+ return arr;
+ }
+
+ // ]NOCPP]
+
+ /**
+ * An initialization helper for having a one name in the SVG mode and
+ * another name in the other modes.
+ *
+ * @param name
+ * the name for the non-SVG modes
+ * @param camel
+ * the name for the SVG mode
+ * @return the initialized name array
+ */
+ private static @NoLength @Local String[] SVG_DIFFERENT(@Local String name,
+ @Local String camel) {
+ @NoLength @Local String[] arr = new String[4];
+ arr[0] = name;
+ arr[1] = name;
+ arr[2] = camel;
+ // [NOCPP[
+ arr[3] = name;
+ // ]NOCPP]
+ return arr;
+ }
+
+ /**
+ * An initialization helper for having a one name in the MathML mode and
+ * another name in the other modes.
+ *
+ * @param name
+ * the name for the non-MathML modes
+ * @param camel
+ * the name for the MathML mode
+ * @return the initialized name array
+ */
+ private static @NoLength @Local String[] MATH_DIFFERENT(@Local String name,
+ @Local String camel) {
+ @NoLength @Local String[] arr = new String[4];
+ arr[0] = name;
+ arr[1] = camel;
+ arr[2] = name;
+ // [NOCPP[
+ arr[3] = name;
+ // ]NOCPP]
+ return arr;
+ }
+
+ /**
+ * An initialization helper for having a different local name in the HTML
+ * mode and the SVG and MathML modes.
+ *
+ * @param name
+ * the name for the HTML mode
+ * @param suffix
+ * the name for the SVG and MathML modes
+ * @return the initialized name array
+ */
+ private static @NoLength @Local String[] COLONIFIED_LOCAL(
+ @Local String name, @Local String suffix) {
+ @NoLength @Local String[] arr = new String[4];
+ arr[0] = name;
+ arr[1] = suffix;
+ arr[2] = suffix;
+ // [NOCPP[
+ arr[3] = name;
+ // ]NOCPP]
+ return arr;
+ }
+
+ /**
+ * An initialization helper for having the same local name in all modes.
+ *
+ * @param name
+ * the name
+ * @return the initialized name array
+ */
+ static @NoLength @Local String[] SAME_LOCAL(@Local String name) {
+ @NoLength @Local String[] arr = new String[4];
+ arr[0] = name;
+ arr[1] = name;
+ arr[2] = name;
+ // [NOCPP[
+ arr[3] = name;
+ // ]NOCPP]
+ return arr;
+ }
+
+ @Inline static int levelOrderBinarySearch(int[] data, int key) {
+ int n = data.length;
+ int i = 0;
+
+ while (i < n) {
+ int val = data[i];
+ if (val < key) {
+ i = 2 * i + 2;
+ } else if (val > key) {
+ i = 2 * i + 1;
+ } else {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns an attribute name by buffer.
+ *
+ * <p>
+ * C++ ownership: The return value is either released by the caller if the
+ * attribute is a duplicate or the ownership is transferred to
+ * HtmlAttributes and released upon clearing or destroying that object.
+ *
+ * @param buf
+ * the buffer
+ * @param offset
+ * ignored
+ * @param length
+ * length of data
+ * @param checkNcName
+ * whether to check ncnameness
+ * @return an <code>AttributeName</code> corresponding to the argument data
+ */
+ @Inline static AttributeName nameByBuffer(@NoLength char[] buf,
+ int length, Interner interner) {
+ // XXX deal with offset
+ @Unsigned int hash = AttributeName.bufToHash(buf, length);
+ int[] hashes;
+ hashes = AttributeName.ATTRIBUTE_HASHES;
+ int index = levelOrderBinarySearch(hashes, hash);
+ if (index < 0) {
+ return null;
+ }
+ AttributeName attributeName = AttributeName.ATTRIBUTE_NAMES[index];
+ @Local String name = attributeName.getLocal(0);
+ if (!Portability.localEqualsBuffer(name, buf, length)) {
+ return null;
+ }
+ return attributeName;
+ }
+
+ /**
+ * This method has to return a unique positive integer for each well-known
+ * lower-cased attribute name.
+ *
+ * @param buf
+ * @param len
+ * @return
+ */
+ @Inline private static @Unsigned int bufToHash(@NoLength char[] buf, int length) {
+ @Unsigned int len = length;
+ @Unsigned int first = buf[0];
+ first <<= 19;
+ @Unsigned int second = 1 << 23;
+ @Unsigned int third = 0;
+ @Unsigned int fourth = 0;
+ @Unsigned int fifth = 0;
+ @Unsigned int sixth = 0;
+ if (length >= 4) {
+ second = buf[length - 4];
+ second <<= 4;
+ third = buf[1];
+ third <<= 9;
+ fourth = buf[length - 2];
+ fourth <<= 14;
+ fifth = buf[3];
+ fifth <<= 24;
+ sixth = buf[length - 1];
+ sixth <<= 11;
+ } else if (length == 3) {
+ second = buf[1];
+ second <<= 4;
+ third = buf[2];
+ third <<= 9;
+ } else if (length == 2) {
+ second = buf[1];
+ second <<= 24;
+ }
+ return len + first + second + third + fourth + fifth + sixth;
+ }
+
+ /**
+ * The mode value for HTML.
+ */
+ public static final int HTML = 0;
+
+ /**
+ * The mode value for MathML.
+ */
+ public static final int MATHML = 1;
+
+ /**
+ * The mode value for SVG.
+ */
+ public static final int SVG = 2;
+
+ // [NOCPP[
+
+ /**
+ * The mode value for lang-mapping HTML.
+ */
+ public static final int HTML_LANG = 3;
+
+ // ]NOCPP]
+
+ /**
+ * The namespaces indexable by mode.
+ */
+ private final @NsUri @NoLength String[] uri;
+
+ /**
+ * The local names indexable by mode.
+ */
+ private final @Local @NoLength String[] local;
+
+ /**
+ * The prefixes indexably by mode.
+ */
+ private final @Prefix @NoLength String[] prefix;
+
+ // CPPONLY: private final boolean custom;
+
+ // [NOCPP[
+
+ private final int flags;
+
+ /**
+ * The qnames indexable by mode.
+ */
+ private final @QName @NoLength String[] qName;
+
+ // ]NOCPP]
+
+ /**
+ * The startup-time constructor.
+ *
+ * @param uri
+ * the namespace
+ * @param local
+ * the local name
+ * @param prefix
+ * the prefix
+ * @param ncname
+ * the ncnameness
+ * @param xmlns
+ * whether this is an xmlns attribute
+ */
+ private AttributeName(@NsUri @NoLength String[] uri,
+ @Local @NoLength String[] local, @Prefix @NoLength String[] prefix
+ // [NOCPP[
+ , int flags
+ // ]NOCPP]
+ ) {
+ this.uri = uri;
+ this.local = local;
+ this.prefix = prefix;
+ // [NOCPP[
+ this.qName = COMPUTE_QNAME(local, prefix);
+ this.flags = flags;
+ // ]NOCPP]
+ // CPPONLY: this.custom = false;
+ }
+
+ // CPPONLY: public AttributeName() {
+ // CPPONLY: this.uri = AttributeName.ALL_NO_NS;
+ // CPPONLY: this.local = AttributeName.SAME_LOCAL(null);
+ // CPPONLY: this.prefix = ALL_NO_PREFIX;
+ // CPPONLY: this.custom = true;
+ // CPPONLY: }
+ // CPPONLY:
+ // CPPONLY: @Inline public boolean isInterned() {
+ // CPPONLY: return !custom;
+ // CPPONLY: }
+ // CPPONLY:
+ // CPPONLY: @Inline public void setNameForNonInterned(@Local String name) {
+ // CPPONLY: assert custom;
+ // CPPONLY: local[0] = name;
+ // CPPONLY: local[1] = name;
+ // CPPONLY: local[2] = name;
+ // CPPONLY: }
+
+ /**
+ * Creates an <code>AttributeName</code> for a local name.
+ *
+ * @param name
+ * the name
+ * @param checkNcName
+ * whether to check ncnameness
+ * @return an <code>AttributeName</code>
+ */
+ static AttributeName createAttributeName(@Local String name
+ // [NOCPP[
+ , boolean checkNcName
+ // ]NOCPP]
+ ) {
+ // [NOCPP[
+ int flags = NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG;
+ if (name.startsWith("xmlns:")) {
+ flags = IS_XMLNS;
+ } else if (checkNcName && !NCName.isNCName(name)) {
+ flags = 0;
+ }
+ // ]NOCPP]
+ return new AttributeName(AttributeName.ALL_NO_NS,
+ AttributeName.SAME_LOCAL(name), ALL_NO_PREFIX, flags);
+ }
+
+ /**
+ * The C++ destructor.
+ */
+ @SuppressWarnings("unused") private void destructor() {
+ Portability.deleteArray(local);
+ }
+
+ // [NOCPP[
+ /**
+ * Creator for use when the XML violation policy requires an attribute name
+ * to be changed.
+ *
+ * @param name
+ * the name of the attribute to create
+ */
+ static AttributeName create(@Local String name) {
+ return new AttributeName(AttributeName.ALL_NO_NS,
+ AttributeName.SAME_LOCAL(name), ALL_NO_PREFIX,
+ NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ }
+
+ /**
+ * Queries whether this name is an XML 1.0 4th ed. NCName.
+ *
+ * @param mode
+ * the SVG/MathML/HTML mode
+ * @return <code>true</code> if this is an NCName in the given mode
+ */
+ public boolean isNcName(int mode) {
+ return (flags & (1 << mode)) != 0;
+ }
+
+ /**
+ * Queries whether this is an <code>xmlns</code> attribute.
+ *
+ * @return <code>true</code> if this is an <code>xmlns</code> attribute
+ */
+ public boolean isXmlns() {
+ return (flags & IS_XMLNS) != 0;
+ }
+
+ /**
+ * Queries whether this attribute has a case-folded value in the HTML4 mode
+ * of the parser.
+ *
+ * @return <code>true</code> if the value is case-folded
+ */
+ boolean isCaseFolded() {
+ return (flags & CASE_FOLDED) != 0;
+ }
+
+ boolean isBoolean() {
+ return (flags & BOOLEAN) != 0;
+ }
+
+ public @QName String getQName(int mode) {
+ return qName[mode];
+ }
+
+ // ]NOCPP]
+
+ public @NsUri String getUri(int mode) {
+ return uri[mode];
+ }
+
+ public @Local String getLocal(int mode) {
+ return local[mode];
+ }
+
+ public @Prefix String getPrefix(int mode) {
+ return prefix[mode];
+ }
+
+ boolean equalsAnother(AttributeName another) {
+ return this.getLocal(AttributeName.HTML) == another.getLocal(AttributeName.HTML);
+ }
+
+ // START CODE ONLY USED FOR GENERATING CODE uncomment to regenerate
+
+// /**
+// * @see java.lang.Object#toString()
+// */
+// @Override public String toString() {
+// return "(" + formatNs() + ", " + formatLocal() + ", " + formatPrefix()
+// + ", " + formatFlags() + ")";
+// }
+//
+// private String formatFlags() {
+// StringBuilder builder = new StringBuilder();
+// if ((flags & NCNAME_HTML) != 0) {
+// if (builder.length() != 0) {
+// builder.append(" | ");
+// }
+// builder.append("NCNAME_HTML");
+// }
+// if ((flags & NCNAME_FOREIGN) != 0) {
+// if (builder.length() != 0) {
+// builder.append(" | ");
+// }
+// builder.append("NCNAME_FOREIGN");
+// }
+// if ((flags & NCNAME_LANG) != 0) {
+// if (builder.length() != 0) {
+// builder.append(" | ");
+// }
+// builder.append("NCNAME_LANG");
+// }
+// if (isXmlns()) {
+// if (builder.length() != 0) {
+// builder.append(" | ");
+// }
+// builder.append("IS_XMLNS");
+// }
+// if (isCaseFolded()) {
+// if (builder.length() != 0) {
+// builder.append(" | ");
+// }
+// builder.append("CASE_FOLDED");
+// }
+// if (isBoolean()) {
+// if (builder.length() != 0) {
+// builder.append(" | ");
+// }
+// builder.append("BOOLEAN");
+// }
+// if (builder.length() == 0) {
+// return "0";
+// }
+// return builder.toString();
+// }
+//
+// public int compareTo(AttributeName other) {
+// int thisHash = this.hash();
+// int otherHash = other.hash();
+// if (thisHash < otherHash) {
+// return -1;
+// } else if (thisHash == otherHash) {
+// return 0;
+// } else {
+// return 1;
+// }
+// }
+//
+// private String formatPrefix() {
+// if (prefix[0] == null && prefix[1] == null && prefix[2] == null
+// && prefix[3] == null) {
+// return "ALL_NO_PREFIX";
+// } else if (prefix[0] == null && prefix[1] == prefix[2]
+// && prefix[3] == null) {
+// if ("xmlns".equals(prefix[1])) {
+// return "XMLNS_PREFIX";
+// } else if ("xml".equals(prefix[1])) {
+// return "XML_PREFIX";
+// } else if ("xlink".equals(prefix[1])) {
+// return "XLINK_PREFIX";
+// } else {
+// throw new IllegalStateException();
+// }
+// } else if (prefix[0] == null && prefix[1] == null && prefix[2] == null
+// && prefix[3] == "xml") {
+// return "LANG_PREFIX";
+// } else {
+// throw new IllegalStateException();
+// }
+// }
+//
+// private String formatLocal() {
+// if (local[0] == local[1] && local[0] == local[3]
+// && local[0] != local[2]) {
+// return "SVG_DIFFERENT(\"" + local[0] + "\", \"" + local[2] + "\")";
+// }
+// if (local[0] == local[2] && local[0] == local[3]
+// && local[0] != local[1]) {
+// return "MATH_DIFFERENT(\"" + local[0] + "\", \"" + local[1] + "\")";
+// }
+// if (local[0] == local[3] && local[1] == local[2]
+// && local[0] != local[1]) {
+// return "COLONIFIED_LOCAL(\"" + local[0] + "\", \"" + local[1]
+// + "\")";
+// }
+// for (int i = 1; i < local.length; i++) {
+// if (local[0] != local[i]) {
+// throw new IllegalStateException();
+// }
+// }
+// return "SAME_LOCAL(\"" + local[0] + "\")";
+// }
+//
+// private String formatNs() {
+// if (uri[0] == "" && uri[1] == "" && uri[2] == "" && uri[3] == "") {
+// return "ALL_NO_NS";
+// } else if (uri[0] == "" && uri[1] == uri[2] && uri[3] == "") {
+// if ("http://www.w3.org/2000/xmlns/".equals(uri[1])) {
+// return "XMLNS_NS";
+// } else if ("http://www.w3.org/XML/1998/namespace".equals(uri[1])) {
+// return "XML_NS";
+// } else if ("http://www.w3.org/1999/xlink".equals(uri[1])) {
+// return "XLINK_NS";
+// } else {
+// throw new IllegalStateException();
+// }
+// } else if (uri[0] == "" && uri[1] == "" && uri[2] == ""
+// && uri[3] == "http://www.w3.org/XML/1998/namespace") {
+// return "LANG_NS";
+// } else {
+// throw new IllegalStateException();
+// }
+// }
+//
+// private String constName() {
+// String name = getLocal(HTML);
+// char[] buf = new char[name.length()];
+// for (int i = 0; i < name.length(); i++) {
+// char c = name.charAt(i);
+// if (c == '-' || c == ':') {
+// buf[i] = '_';
+// } else if (c >= 'a' && c <= 'z') {
+// buf[i] = (char) (c - 0x20);
+// } else {
+// buf[i] = c;
+// }
+// }
+// return new String(buf);
+// }
+//
+// private int hash() {
+// String name = getLocal(HTML);
+// return bufToHash(name.toCharArray(), name.length());
+// }
+//
+// private static void fillLevelOrderArray(List<AttributeName> sorted, int depth,
+// int rootIdx, AttributeName[] levelOrder) {
+// if (rootIdx >= levelOrder.length) {
+// return;
+// }
+//
+// if (depth > 0) {
+// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 1, levelOrder);
+// }
+//
+// if (!sorted.isEmpty()) {
+// levelOrder[rootIdx] = sorted.remove(0);
+// }
+//
+// if (depth > 0) {
+// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 2, levelOrder);
+// }
+// }
+//
+// /**
+// * Regenerate self
+// *
+// * @param args
+// */
+// public static void main(String[] args) {
+// Arrays.sort(ATTRIBUTE_NAMES);
+// for (int i = 0; i < ATTRIBUTE_NAMES.length; i++) {
+// int hash = ATTRIBUTE_NAMES[i].hash();
+// if (hash < 0) {
+// System.err.println("Negative hash: " + ATTRIBUTE_NAMES[i].local[0]);
+// return;
+// }
+// for (int j = i + 1; j < ATTRIBUTE_NAMES.length; j++) {
+// if (hash == ATTRIBUTE_NAMES[j].hash()) {
+// System.err.println(
+// "Hash collision: " + ATTRIBUTE_NAMES[i].local[0] + ", "
+// + ATTRIBUTE_NAMES[j].local[0]);
+// return;
+// }
+// }
+// }
+// for (int i = 0; i < ATTRIBUTE_NAMES.length; i++) {
+// AttributeName att = ATTRIBUTE_NAMES[i];
+// System.out.println("public static final AttributeName "
+// + att.constName() + " = new AttributeName" + att.toString()
+// + ";");
+// }
+//
+// LinkedList<AttributeName> sortedNames = new LinkedList<AttributeName>();
+// Collections.addAll(sortedNames, ATTRIBUTE_NAMES);
+// AttributeName[] levelOrder = new AttributeName[ATTRIBUTE_NAMES.length];
+// int bstDepth = (int) Math.ceil(Math.log(ATTRIBUTE_NAMES.length) / Math.log(2));
+// fillLevelOrderArray(sortedNames, bstDepth, 0, levelOrder);
+//
+// System.out.println("private final static @NoLength AttributeName[] ATTRIBUTE_NAMES = {");
+// for (int i = 0; i < levelOrder.length; i++) {
+// AttributeName att = levelOrder[i];
+// System.out.println(att.constName() + ",");
+// }
+// System.out.println("};");
+// System.out.println("private final static int[] ATTRIBUTE_HASHES = {");
+// for (int i = 0; i < levelOrder.length; i++) {
+// AttributeName att = levelOrder[i];
+// System.out.println(Integer.toString(att.hash()) + ",");
+// }
+// System.out.println("};");
+// }
+
+ // START GENERATED CODE
+ public static final AttributeName ALT = new AttributeName(ALL_NO_NS, SAME_LOCAL("alt"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DIR = new AttributeName(ALL_NO_NS, SAME_LOCAL("dir"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName DUR = new AttributeName(ALL_NO_NS, SAME_LOCAL("dur"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName END = new AttributeName(ALL_NO_NS, SAME_LOCAL("end"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("for"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName IN2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("in2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LOW = new AttributeName(ALL_NO_NS, SAME_LOCAL("low"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("min"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MAX = new AttributeName(ALL_NO_NS, SAME_LOCAL("max"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REL = new AttributeName(ALL_NO_NS, SAME_LOCAL("rel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REV = new AttributeName(ALL_NO_NS, SAME_LOCAL("rev"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SRC = new AttributeName(ALL_NO_NS, SAME_LOCAL("src"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName D = new AttributeName(ALL_NO_NS, SAME_LOCAL("d"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName R = new AttributeName(ALL_NO_NS, SAME_LOCAL("r"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName X = new AttributeName(ALL_NO_NS, SAME_LOCAL("x"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName Y = new AttributeName(ALL_NO_NS, SAME_LOCAL("y"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName Z = new AttributeName(ALL_NO_NS, SAME_LOCAL("z"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName K1 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k1"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName X1 = new AttributeName(ALL_NO_NS, SAME_LOCAL("x1"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName Y1 = new AttributeName(ALL_NO_NS, SAME_LOCAL("y1"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName K2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName X2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("x2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName Y2 = new AttributeName(ALL_NO_NS, SAME_LOCAL("y2"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName K3 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k3"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName K4 = new AttributeName(ALL_NO_NS, SAME_LOCAL("k4"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName XML_SPACE = new AttributeName(XML_NS, COLONIFIED_LOCAL("xml:space", "space"), XML_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XML_LANG = new AttributeName(XML_NS, COLONIFIED_LOCAL("xml:lang", "lang"), XML_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName ARIA_GRAB = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-grab"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_VALUEMAX = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-valuemax"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_LABELLEDBY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-labelledby"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_DESCRIBEDBY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-describedby"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_DISABLED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-disabled"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_CHECKED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-checked"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_SELECTED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-selected"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_DROPEFFECT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-dropeffect"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_REQUIRED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-required"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_EXPANDED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-expanded"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_PRESSED = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-pressed"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_LEVEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-level"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_CHANNEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-channel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_HIDDEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-hidden"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_SECRET = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-secret"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_POSINSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-posinset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_ATOMIC = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-atomic"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_INVALID = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-invalid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_TEMPLATEID = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-templateid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_VALUEMIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-valuemin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_MULTISELECTABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-multiselectable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_CONTROLS = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-controls"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_MULTILINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-multiline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_READONLY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-readonly"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_OWNS = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-owns"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_ACTIVEDESCENDANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-activedescendant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_RELEVANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-relevant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_DATATYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-datatype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_VALUENOW = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-valuenow"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_SORT = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-sort"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_AUTOCOMPLETE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-autocomplete"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_FLOWTO = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-flowto"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_BUSY = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-busy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_LIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-live"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_HASPOPUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-haspopup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARIA_SETSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("aria-setsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLEAR = new AttributeName(ALL_NO_NS, SAME_LOCAL("clear"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName DISABLED = new AttributeName(ALL_NO_NS, SAME_LOCAL("disabled"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName DEFAULT = new AttributeName(ALL_NO_NS, SAME_LOCAL("default"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName DATA = new AttributeName(ALL_NO_NS, SAME_LOCAL("data"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName EQUALCOLUMNS = new AttributeName(ALL_NO_NS, SAME_LOCAL("equalcolumns"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName EQUALROWS = new AttributeName(ALL_NO_NS, SAME_LOCAL("equalrows"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("hspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ISMAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("ismap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName LOCAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("local"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("lspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MOVABLELIMITS = new AttributeName(ALL_NO_NS, SAME_LOCAL("movablelimits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NOTATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("notation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDATAAVAILABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondataavailable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONPASTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onpaste"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("rspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ROWALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ROTATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("rotate"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SEPARATOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("separator"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SEPARATORS = new AttributeName(ALL_NO_NS, SAME_LOCAL("separators"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VSPACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("vspace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName XCHANNELSELECTOR = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("xchannelselector", "xChannelSelector"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName YCHANNELSELECTOR = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("ychannelselector", "yChannelSelector"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ENABLE_BACKGROUND = new AttributeName(ALL_NO_NS, SAME_LOCAL("enable-background"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDBLCLICK = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondblclick"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONABORT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onabort"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CALCMODE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("calcmode", "calcMode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CHECKED = new AttributeName(ALL_NO_NS, SAME_LOCAL("checked"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName FENCE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fence"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONSCROLL = new AttributeName(ALL_NO_NS, SAME_LOCAL("onscroll"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONACTIVATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onactivate"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("spacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SPECULAREXPONENT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("specularexponent", "specularExponent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SPECULARCONSTANT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("specularconstant", "specularConstant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BORDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("border"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ID = new AttributeName(ALL_NO_NS, SAME_LOCAL("id"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName GRADIENTTRANSFORM = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("gradienttransform", "gradientTransform"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName GRADIENTUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("gradientunits", "gradientUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HIDDEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("hidden"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HEADERS = new AttributeName(ALL_NO_NS, SAME_LOCAL("headers"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LOADING = new AttributeName(ALL_NO_NS, SAME_LOCAL("loading"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName READONLY = new AttributeName(ALL_NO_NS, SAME_LOCAL("readonly"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName RENDERING_INTENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("rendering-intent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SEED = new AttributeName(ALL_NO_NS, SAME_LOCAL("seed"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SRCDOC = new AttributeName(ALL_NO_NS, SAME_LOCAL("srcdoc"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STDDEVIATION = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("stddeviation", "stdDeviation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SANDBOX = new AttributeName(ALL_NO_NS, SAME_LOCAL("sandbox"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName WORD_SPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("word-spacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACCENTUNDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("accentunder"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACCEPT_CHARSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("accept-charset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACCESSKEY = new AttributeName(ALL_NO_NS, SAME_LOCAL("accesskey"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACCENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("accent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACCEPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("accept"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BEVELLED = new AttributeName(ALL_NO_NS, SAME_LOCAL("bevelled"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BASEFREQUENCY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("basefrequency", "baseFrequency"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BASELINE_SHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("baseline-shift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BASEPROFILE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("baseprofile", "baseProfile"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BASELINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("baseline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BASE = new AttributeName(ALL_NO_NS, SAME_LOCAL("base"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("code"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CODETYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("codetype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CODEBASE = new AttributeName(ALL_NO_NS, SAME_LOCAL("codebase"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CITE = new AttributeName(ALL_NO_NS, SAME_LOCAL("cite"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DEFER = new AttributeName(ALL_NO_NS, SAME_LOCAL("defer"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName DATETIME = new AttributeName(ALL_NO_NS, SAME_LOCAL("datetime"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DIRECTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("direction"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName EDGEMODE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("edgemode", "edgeMode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName EDGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("edge"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ENTERKEYHINT = new AttributeName(ALL_NO_NS, SAME_LOCAL("enterkeyhint"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("face"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName INDEX = new AttributeName(ALL_NO_NS, SAME_LOCAL("index"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName INTERCEPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("intercept"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName INTEGRITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("integrity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LINEBREAK = new AttributeName(ALL_NO_NS, SAME_LOCAL("linebreak"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LABEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("label"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LINETHICKNESS = new AttributeName(ALL_NO_NS, SAME_LOCAL("linethickness"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("mode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NAME = new AttributeName(ALL_NO_NS, SAME_LOCAL("name"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NORESIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("noresize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName ONBEFOREUNLOAD = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforeunload"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONREPEAT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onrepeat"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OBJECT = new AttributeName(ALL_NO_NS, SAME_LOCAL("object"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONSELECT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onselect"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ORDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("order"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OTHER = new AttributeName(ALL_NO_NS, SAME_LOCAL("other"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONRESET = new AttributeName(ALL_NO_NS, SAME_LOCAL("onreset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONREADYSTATECHANGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onreadystatechange"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMESSAGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmessage"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONBEGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbegin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONBEFOREPRINT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforeprint"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ORIENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("orient"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ORIENTATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("orientation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONBEFORECOPY = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforecopy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONSELECTSTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("onselectstart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONBEFOREPASTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforepaste"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONKEYPRESS = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeypress"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONKEYUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeyup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONBEFORECUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onbeforecut"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONKEYDOWN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onkeydown"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONRESIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onresize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REPEAT = new AttributeName(ALL_NO_NS, SAME_LOCAL("repeat"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REFERRERPOLICY = new AttributeName(ALL_NO_NS, SAME_LOCAL("referrerpolicy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RULES = new AttributeName(ALL_NO_NS, SAME_LOCAL("rules"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName ROLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("role"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REPEATCOUNT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("repeatcount", "repeatCount"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REPEATDUR = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("repeatdur", "repeatDur"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SELECTED = new AttributeName(ALL_NO_NS, SAME_LOCAL("selected"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName SIZES = new AttributeName(ALL_NO_NS, SAME_LOCAL("sizes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SUPERSCRIPTSHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("superscriptshift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STRETCHY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stretchy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCHEME = new AttributeName(ALL_NO_NS, SAME_LOCAL("scheme"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SPREADMETHOD = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("spreadmethod", "spreadMethod"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SELECTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("selection"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("size"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("type"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName DIFFUSECONSTANT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("diffuseconstant", "diffuseConstant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HREF = new AttributeName(ALL_NO_NS, SAME_LOCAL("href"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HREFLANG = new AttributeName(ALL_NO_NS, SAME_LOCAL("hreflang"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONAFTERPRINT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onafterprint"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PROFILE = new AttributeName(ALL_NO_NS, SAME_LOCAL("profile"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SURFACESCALE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("surfacescale", "surfaceScale"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName XREF = new AttributeName(ALL_NO_NS, SAME_LOCAL("xref"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("align"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName ALIGNMENT_BASELINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("alignment-baseline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ALIGNMENTSCOPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("alignmentscope"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DRAGGABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("draggable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("height"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName IMAGESIZES = new AttributeName(ALL_NO_NS, SAME_LOCAL("imagesizes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName IMAGESRCSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("imagesrcset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName IMAGE_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("image-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LANGUAGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("language"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LANG = new AttributeName(LANG_NS, SAME_LOCAL("lang"), LANG_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LARGEOP = new AttributeName(ALL_NO_NS, SAME_LOCAL("largeop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LONGDESC = new AttributeName(ALL_NO_NS, SAME_LOCAL("longdesc"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LENGTHADJUST = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("lengthadjust", "lengthAdjust"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARGINHEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("marginheight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARGINWIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("marginwidth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ORIGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("origin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PING = new AttributeName(ALL_NO_NS, SAME_LOCAL("ping"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TARGET = new AttributeName(ALL_NO_NS, SAME_LOCAL("target"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TARGETX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("targetx", "targetX"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TARGETY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("targety", "targetY"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ARCHIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("archive"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HIGH = new AttributeName(ALL_NO_NS, SAME_LOCAL("high"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LIGHTING_COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("lighting-color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MATHBACKGROUND = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathbackground"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName METHOD = new AttributeName(ALL_NO_NS, SAME_LOCAL("method"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName MATHVARIANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathvariant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MATHCOLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathcolor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MATHSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("mathsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NOSHADE = new AttributeName(ALL_NO_NS, SAME_LOCAL("noshade"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName ONCHANGE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onchange"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PATHLENGTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pathlength", "pathLength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PATH = new AttributeName(ALL_NO_NS, SAME_LOCAL("path"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ALTIMG = new AttributeName(ALL_NO_NS, SAME_LOCAL("altimg"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACTIONTYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("actiontype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACTION = new AttributeName(ALL_NO_NS, SAME_LOCAL("action"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACTIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("active"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName ADDITIVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("additive"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BEGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("begin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DOMINANT_BASELINE = new AttributeName(ALL_NO_NS, SAME_LOCAL("dominant-baseline"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DIVISOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("divisor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DEFINITIONURL = new AttributeName(ALL_NO_NS, MATH_DIFFERENT("definitionurl", "definitionURL"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LIMITINGCONEANGLE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("limitingconeangle", "limitingConeAngle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MEDIA = new AttributeName(ALL_NO_NS, SAME_LOCAL("media"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MANIFEST = new AttributeName(ALL_NO_NS, SAME_LOCAL("manifest"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONFINISH = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfinish"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OPTIMUM = new AttributeName(ALL_NO_NS, SAME_LOCAL("optimum"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RADIOGROUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("radiogroup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RADIUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("radius"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCRIPTLEVEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("scriptlevel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCRIPTSIZEMULTIPLIER = new AttributeName(ALL_NO_NS, SAME_LOCAL("scriptsizemultiplier"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCRIPTMINSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("scriptminsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TABINDEX = new AttributeName(ALL_NO_NS, SAME_LOCAL("tabindex"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("valign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName VISIBILITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("visibility"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BACKGROUND = new AttributeName(ALL_NO_NS, SAME_LOCAL("background"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LINK = new AttributeName(ALL_NO_NS, SAME_LOCAL("link"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARKER_MID = new AttributeName(ALL_NO_NS, SAME_LOCAL("marker-mid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARKERHEIGHT = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("markerheight", "markerHeight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARKER_END = new AttributeName(ALL_NO_NS, SAME_LOCAL("marker-end"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MASK = new AttributeName(ALL_NO_NS, SAME_LOCAL("mask"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARKER_START = new AttributeName(ALL_NO_NS, SAME_LOCAL("marker-start"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARKERWIDTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("markerwidth", "markerWidth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MASKUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("maskunits", "maskUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MARKERUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("markerunits", "markerUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MASKCONTENTUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("maskcontentunits", "maskContentUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName AMPLITUDE = new AttributeName(ALL_NO_NS, SAME_LOCAL("amplitude"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CELLSPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("cellspacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CELLPADDING = new AttributeName(ALL_NO_NS, SAME_LOCAL("cellpadding"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DECLARE = new AttributeName(ALL_NO_NS, SAME_LOCAL("declare"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName FILL_RULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill-rule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FILL = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FILL_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("fill-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MAXLENGTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("maxlength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONCLICK = new AttributeName(ALL_NO_NS, SAME_LOCAL("onclick"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONBLUR = new AttributeName(ALL_NO_NS, SAME_LOCAL("onblur"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REPLACE = new AttributeName(ALL_NO_NS, SAME_LOCAL("replace"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName ROWLINES = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowlines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCALE = new AttributeName(ALL_NO_NS, SAME_LOCAL("scale"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("style"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TABLEVALUES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("tablevalues", "tableValues"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TITLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("title"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName AZIMUTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("azimuth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FORMAT = new AttributeName(ALL_NO_NS, SAME_LOCAL("format"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FRAMEBORDER = new AttributeName(ALL_NO_NS, SAME_LOCAL("frameborder"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FRAME = new AttributeName(ALL_NO_NS, SAME_LOCAL("frame"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName FRAMESPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("framespacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FROM = new AttributeName(ALL_NO_NS, SAME_LOCAL("from"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FORM = new AttributeName(ALL_NO_NS, SAME_LOCAL("form"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PROMPT = new AttributeName(ALL_NO_NS, SAME_LOCAL("prompt"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PRIMITIVEUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("primitiveunits", "primitiveUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SYMMETRIC = new AttributeName(ALL_NO_NS, SAME_LOCAL("symmetric"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SUMMARY = new AttributeName(ALL_NO_NS, SAME_LOCAL("summary"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName USEMAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("usemap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ZOOMANDPAN = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("zoomandpan", "zoomAndPan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ASYNC = new AttributeName(ALL_NO_NS, SAME_LOCAL("async"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName ALINK = new AttributeName(ALL_NO_NS, SAME_LOCAL("alink"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName IN = new AttributeName(ALL_NO_NS, SAME_LOCAL("in"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ICON = new AttributeName(ALL_NO_NS, SAME_LOCAL("icon"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KERNELMATRIX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("kernelmatrix", "kernelMatrix"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KERNING = new AttributeName(ALL_NO_NS, SAME_LOCAL("kerning"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KERNELUNITLENGTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("kernelunitlength", "kernelUnitLength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONUNLOAD = new AttributeName(ALL_NO_NS, SAME_LOCAL("onunload"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OPEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("open"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONINVALID = new AttributeName(ALL_NO_NS, SAME_LOCAL("oninvalid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("onend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONINPUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("oninput"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName POINTER_EVENTS = new AttributeName(ALL_NO_NS, SAME_LOCAL("pointer-events"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName POINTS = new AttributeName(ALL_NO_NS, SAME_LOCAL("points"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName POINTSATX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pointsatx", "pointsAtX"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName POINTSATY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pointsaty", "pointsAtY"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName POINTSATZ = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("pointsatz", "pointsAtZ"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("span"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STANDBY = new AttributeName(ALL_NO_NS, SAME_LOCAL("standby"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TRANSFORM_ORIGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("transform-origin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TRANSFORM = new AttributeName(ALL_NO_NS, SAME_LOCAL("transform"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VLINK = new AttributeName(ALL_NO_NS, SAME_LOCAL("vlink"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName WHEN = new AttributeName(ALL_NO_NS, SAME_LOCAL("when"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName XLINK_HREF = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:href", "href"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XLINK_TITLE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:title", "title"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XLINK_ROLE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:role", "role"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XLINK_ARCROLE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:arcrole", "arcrole"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XMLNS_XLINK = new AttributeName(XMLNS_NS, COLONIFIED_LOCAL("xmlns:xlink", "xlink"), XMLNS_PREFIX, IS_XMLNS);
+ public static final AttributeName XMLNS = new AttributeName(XMLNS_NS, SAME_LOCAL("xmlns"), ALL_NO_PREFIX, IS_XMLNS);
+ public static final AttributeName XLINK_TYPE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:type", "type"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XLINK_SHOW = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:show", "show"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName XLINK_ACTUATE = new AttributeName(XLINK_NS, COLONIFIED_LOCAL("xlink:actuate", "actuate"), XLINK_PREFIX, NCNAME_FOREIGN);
+ public static final AttributeName AUTOPLAY = new AttributeName(ALL_NO_NS, SAME_LOCAL("autoplay"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName AUTOCOMPLETE = new AttributeName(ALL_NO_NS, SAME_LOCAL("autocomplete"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName AUTOFOCUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("autofocus"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName AUTOCAPITALIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("autocapitalize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BGCOLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("bgcolor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLOR_PROFILE = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-profile"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLOR_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLOR_INTERPOLATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-interpolation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLOR_INTERPOLATION_FILTERS = new AttributeName(ALL_NO_NS, SAME_LOCAL("color-interpolation-filters"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ENCODING = new AttributeName(ALL_NO_NS, SAME_LOCAL("encoding"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName EXPONENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("exponent"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FLOOD_COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("flood-color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FLOOD_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("flood-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LQUOTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("lquote"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NUMOCTAVES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("numoctaves", "numOctaves"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NOMODULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("nomodule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName ONLOAD = new AttributeName(ALL_NO_NS, SAME_LOCAL("onload"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEWHEEL = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmousewheel"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEENTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseenter"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEOVER = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseover"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONFOCUSIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocusin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONCONTEXTMENU = new AttributeName(ALL_NO_NS, SAME_LOCAL("oncontextmenu"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONZOOM = new AttributeName(ALL_NO_NS, SAME_LOCAL("onzoom"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONCOPY = new AttributeName(ALL_NO_NS, SAME_LOCAL("oncopy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSELEAVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseleave"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEMOVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmousemove"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEUP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseup"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONFOCUS = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocus"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEOUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmouseout"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONFOCUSOUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onfocusout"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONMOUSEDOWN = new AttributeName(ALL_NO_NS, SAME_LOCAL("onmousedown"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TO = new AttributeName(ALL_NO_NS, SAME_LOCAL("to"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RQUOTE = new AttributeName(ALL_NO_NS, SAME_LOCAL("rquote"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE_LINECAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-linecap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE_DASHARRAY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-dasharray"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE_DASHOFFSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-dashoffset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE_LINEJOIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-linejoin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE_MITERLIMIT = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-miterlimit"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCROLLING = new AttributeName(ALL_NO_NS, SAME_LOCAL("scrolling"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName STROKE_WIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-width"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STROKE_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COMPACT = new AttributeName(ALL_NO_NS, SAME_LOCAL("compact"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName CLIP = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLIP_RULE = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip-rule"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLIP_PATH = new AttributeName(ALL_NO_NS, SAME_LOCAL("clip-path"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLIPPATHUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("clippathunits", "clipPathUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DISPLAY = new AttributeName(ALL_NO_NS, SAME_LOCAL("display"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DISPLAYSTYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("displaystyle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName GLYPH_ORIENTATION_VERTICAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("glyph-orientation-vertical"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName GLYPH_ORIENTATION_HORIZONTAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("glyph-orientation-horizontal"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName GLYPHREF = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("glyphref", "glyphRef"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName HTTP_EQUIV = new AttributeName(ALL_NO_NS, SAME_LOCAL("http-equiv"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KEYPOINTS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keypoints", "keyPoints"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LOOP = new AttributeName(ALL_NO_NS, SAME_LOCAL("loop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PROPERTY = new AttributeName(ALL_NO_NS, SAME_LOCAL("property"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCOPED = new AttributeName(ALL_NO_NS, SAME_LOCAL("scoped"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STEP = new AttributeName(ALL_NO_NS, SAME_LOCAL("step"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName SHAPE_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("shape-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SCOPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("scope"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName SHAPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("shape"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName SLOPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("slope"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STOP_COLOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("stop-color"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STOP_OPACITY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stop-opacity"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TEMPLATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("template"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName WRAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("wrap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ABBR = new AttributeName(ALL_NO_NS, SAME_LOCAL("abbr"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ATTRIBUTENAME = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("attributename", "attributeName"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ATTRIBUTETYPE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("attributetype", "attributeType"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CHAR = new AttributeName(ALL_NO_NS, SAME_LOCAL("char"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COORDS = new AttributeName(ALL_NO_NS, SAME_LOCAL("coords"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CHAROFF = new AttributeName(ALL_NO_NS, SAME_LOCAL("charoff"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CHARSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("charset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName NOWRAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("nowrap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName NOHREF = new AttributeName(ALL_NO_NS, SAME_LOCAL("nohref"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName ONDRAG = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondrag"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDRAGENTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragenter"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDRAGOVER = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragover"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDRAGEND = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragend"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDROP = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondrop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDRAGDROP = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragdrop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONERROR = new AttributeName(ALL_NO_NS, SAME_LOCAL("onerror"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OPERATOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("operator"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OVERFLOW = new AttributeName(ALL_NO_NS, SAME_LOCAL("overflow"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDRAGSTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragstart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONDRAGLEAVE = new AttributeName(ALL_NO_NS, SAME_LOCAL("ondragleave"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STARTOFFSET = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("startoffset", "startOffset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName START = new AttributeName(ALL_NO_NS, SAME_LOCAL("start"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName AS = new AttributeName(ALL_NO_NS, SAME_LOCAL("as"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName AXIS = new AttributeName(ALL_NO_NS, SAME_LOCAL("axis"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BIAS = new AttributeName(ALL_NO_NS, SAME_LOCAL("bias"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLSPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("colspan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLASSID = new AttributeName(ALL_NO_NS, SAME_LOCAL("classid"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CROSSORIGIN = new AttributeName(ALL_NO_NS, SAME_LOCAL("crossorigin"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLS = new AttributeName(ALL_NO_NS, SAME_LOCAL("cols"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CURSOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("cursor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLOSURE = new AttributeName(ALL_NO_NS, SAME_LOCAL("closure"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLOSE = new AttributeName(ALL_NO_NS, SAME_LOCAL("close"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CLASS = new AttributeName(ALL_NO_NS, SAME_LOCAL("class"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName IS = new AttributeName(ALL_NO_NS, SAME_LOCAL("is"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KEYSYSTEM = new AttributeName(ALL_NO_NS, SAME_LOCAL("keysystem"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KEYSPLINES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keysplines", "keySplines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LOWSRC = new AttributeName(ALL_NO_NS, SAME_LOCAL("lowsrc"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MAXSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("maxsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MINSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("minsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName OFFSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("offset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PRESERVEALPHA = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("preservealpha", "preserveAlpha"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PRESERVEASPECTRATIO = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("preserveaspectratio", "preserveAspectRatio"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ROWSPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowspan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ROWSPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowspacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ROWS = new AttributeName(ALL_NO_NS, SAME_LOCAL("rows"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SRCSET = new AttributeName(ALL_NO_NS, SAME_LOCAL("srcset"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SUBSCRIPTSHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("subscriptshift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VERSION = new AttributeName(ALL_NO_NS, SAME_LOCAL("version"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ALTTEXT = new AttributeName(ALL_NO_NS, SAME_LOCAL("alttext"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CONTENTEDITABLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("contenteditable"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CONTROLS = new AttributeName(ALL_NO_NS, SAME_LOCAL("controls"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CONTENT = new AttributeName(ALL_NO_NS, SAME_LOCAL("content"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CONTEXTMENU = new AttributeName(ALL_NO_NS, SAME_LOCAL("contextmenu"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DEPTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("depth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ENCTYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("enctype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName FONT_STRETCH = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-stretch"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FILTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("filter"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONTWEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontweight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONT_WEIGHT = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-weight"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONTSTYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontstyle"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONT_STYLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-style"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONTFAMILY = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontfamily"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONT_FAMILY = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-family"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONT_VARIANT = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-variant"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONT_SIZE_ADJUST = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-size-adjust"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FILTERUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("filterunits", "filterUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONTSIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("fontsize"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FONT_SIZE = new AttributeName(ALL_NO_NS, SAME_LOCAL("font-size"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName KEYTIMES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("keytimes", "keyTimes"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LETTER_SPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("letter-spacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName LIST = new AttributeName(ALL_NO_NS, SAME_LOCAL("list"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName MULTIPLE = new AttributeName(ALL_NO_NS, SAME_LOCAL("multiple"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName RT = new AttributeName(ALL_NO_NS, SAME_LOCAL("rt"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONSTOP = new AttributeName(ALL_NO_NS, SAME_LOCAL("onstop"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONSTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("onstart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName POSTER = new AttributeName(ALL_NO_NS, SAME_LOCAL("poster"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PATTERNTRANSFORM = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("patterntransform", "patternTransform"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PATTERN = new AttributeName(ALL_NO_NS, SAME_LOCAL("pattern"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PATTERNUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("patternunits", "patternUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName PATTERNCONTENTUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("patterncontentunits", "patternContentUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RESTART = new AttributeName(ALL_NO_NS, SAME_LOCAL("restart"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName STITCHTILES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("stitchtiles", "stitchTiles"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName SYSTEMLANGUAGE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("systemlanguage", "systemLanguage"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TEXT_RENDERING = new AttributeName(ALL_NO_NS, SAME_LOCAL("text-rendering"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TEXT_DECORATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("text-decoration"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TEXT_ANCHOR = new AttributeName(ALL_NO_NS, SAME_LOCAL("text-anchor"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TEXTLENGTH = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("textlength", "textLength"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName TEXT = new AttributeName(ALL_NO_NS, SAME_LOCAL("text"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName WRITING_MODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("writing-mode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName WIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("width"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ACCUMULATE = new AttributeName(ALL_NO_NS, SAME_LOCAL("accumulate"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLUMNSPAN = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnspan"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLUMNLINES = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnlines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLUMNALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLUMNSPACING = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnspacing"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName COLUMNWIDTH = new AttributeName(ALL_NO_NS, SAME_LOCAL("columnwidth"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName GROUPALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("groupalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName INPUTMODE = new AttributeName(ALL_NO_NS, SAME_LOCAL("inputmode"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONSUBMIT = new AttributeName(ALL_NO_NS, SAME_LOCAL("onsubmit"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ONCUT = new AttributeName(ALL_NO_NS, SAME_LOCAL("oncut"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REQUIRED = new AttributeName(ALL_NO_NS, SAME_LOCAL("required"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
+ public static final AttributeName REQUIREDFEATURES = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("requiredfeatures", "requiredFeatures"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RESULT = new AttributeName(ALL_NO_NS, SAME_LOCAL("result"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REQUIREDEXTENSIONS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("requiredextensions", "requiredExtensions"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VALUES = new AttributeName(ALL_NO_NS, SAME_LOCAL("values"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VALUETYPE = new AttributeName(ALL_NO_NS, SAME_LOCAL("valuetype"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED);
+ public static final AttributeName VALUE = new AttributeName(ALL_NO_NS, SAME_LOCAL("value"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName ELEVATION = new AttributeName(ALL_NO_NS, SAME_LOCAL("elevation"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VIEWTARGET = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("viewtarget", "viewTarget"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName VIEWBOX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("viewbox", "viewBox"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CX = new AttributeName(ALL_NO_NS, SAME_LOCAL("cx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DX = new AttributeName(ALL_NO_NS, SAME_LOCAL("dx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FX = new AttributeName(ALL_NO_NS, SAME_LOCAL("fx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RX = new AttributeName(ALL_NO_NS, SAME_LOCAL("rx"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REFX = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("refx", "refX"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName BY = new AttributeName(ALL_NO_NS, SAME_LOCAL("by"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName CY = new AttributeName(ALL_NO_NS, SAME_LOCAL("cy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName DY = new AttributeName(ALL_NO_NS, SAME_LOCAL("dy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName FY = new AttributeName(ALL_NO_NS, SAME_LOCAL("fy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName RY = new AttributeName(ALL_NO_NS, SAME_LOCAL("ry"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ public static final AttributeName REFY = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("refy", "refY"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
+ private final static @NoLength AttributeName[] ATTRIBUTE_NAMES = {
+ FILL,
+ DATETIME,
+ CHAROFF,
+ CLEAR,
+ IMAGESRCSET,
+ COLOR,
+ LETTER_SPACING,
+ ARIA_DISABLED,
+ SPECULAREXPONENT,
+ ONKEYUP,
+ DOMINANT_BASELINE,
+ OPEN,
+ SCROLLING,
+ MAXSIZE,
+ REQUIREDFEATURES,
+ Y,
+ ARIA_MULTISELECTABLE,
+ ROTATE,
+ ACCENTUNDER,
+ ONREPEAT,
+ SELECTION,
+ LIGHTING_COLOR,
+ BACKGROUND,
+ FROM,
+ XLINK_TITLE,
+ ONCOPY,
+ PROPERTY,
+ START,
+ DEPTH,
+ TEXT_ANCHOR,
+ RX,
+ MIN,
+ K3,
+ ARIA_CHANNEL,
+ ARIA_VALUENOW,
+ LOCAL,
+ ONABORT,
+ LOADING,
+ BASEPROFILE,
+ INTEGRITY,
+ ONBEGIN,
+ REPEATCOUNT,
+ SURFACESCALE,
+ MARGINWIDTH,
+ PATHLENGTH,
+ RADIOGROUP,
+ MASKUNITS,
+ STYLE,
+ ASYNC,
+ POINTSATZ,
+ AUTOPLAY,
+ NOMODULE,
+ TO,
+ DISPLAY,
+ STOP_OPACITY,
+ ONDROP,
+ CURSOR,
+ SRCSET,
+ FONTFAMILY,
+ PATTERN,
+ COLUMNALIGN,
+ VIEWBOX,
+ DY,
+ END,
+ SRC,
+ Y1,
+ ARIA_GRAB,
+ ARIA_REQUIRED,
+ ARIA_ATOMIC,
+ ARIA_OWNS,
+ ARIA_BUSY,
+ EQUALCOLUMNS,
+ ONDATAAVAILABLE,
+ XCHANNELSELECTOR,
+ ONSCROLL,
+ GRADIENTTRANSFORM,
+ SRCDOC,
+ ACCEPT,
+ CODETYPE,
+ ENTERKEYHINT,
+ MODE,
+ OTHER,
+ ONBEFORECOPY,
+ REPEAT,
+ SUPERSCRIPTSHIFT,
+ HREF,
+ ALIGNMENTSCOPE,
+ LARGEOP,
+ TARGETX,
+ MATHCOLOR,
+ ACTION,
+ MEDIA,
+ SCRIPTMINSIZE,
+ MARKER_END,
+ CELLSPACING,
+ ONBLUR,
+ FORMAT,
+ SYMMETRIC,
+ KERNELMATRIX,
+ POINTER_EVENTS,
+ TRANSFORM,
+ XMLNS,
+ BGCOLOR,
+ FLOOD_COLOR,
+ ONMOUSEOVER,
+ ONFOCUS,
+ STROKE_DASHOFFSET,
+ CLIP,
+ GLYPHREF,
+ SCOPE,
+ ATTRIBUTENAME,
+ ONDRAG,
+ OVERFLOW,
+ COLSPAN,
+ IS,
+ PRESERVEASPECTRATIO,
+ CONTENTEDITABLE,
+ FONTWEIGHT,
+ FILTERUNITS,
+ ONSTOP,
+ STITCHTILES,
+ WIDTH,
+ INPUTMODE,
+ VALUETYPE,
+ DX,
+ BY,
+ RY,
+ DIR,
+ IN2,
+ REL,
+ R,
+ K1,
+ X2,
+ XML_SPACE,
+ ARIA_LABELLEDBY,
+ ARIA_SELECTED,
+ ARIA_PRESSED,
+ ARIA_SECRET,
+ ARIA_TEMPLATEID,
+ ARIA_MULTILINE,
+ ARIA_RELEVANT,
+ ARIA_AUTOCOMPLETE,
+ ARIA_HASPOPUP,
+ DEFAULT,
+ HSPACE,
+ MOVABLELIMITS,
+ RSPACE,
+ SEPARATORS,
+ ENABLE_BACKGROUND,
+ CHECKED,
+ OPACITY,
+ BORDER,
+ HIDDEN,
+ RENDERING_INTENT,
+ SANDBOX,
+ ACCESSKEY,
+ BASEFREQUENCY,
+ BASE,
+ CITE,
+ EDGEMODE,
+ INDEX,
+ LABEL,
+ NORESIZE,
+ ONSELECT,
+ ONREADYSTATECHANGE,
+ ORIENT,
+ ONBEFOREPASTE,
+ ONKEYDOWN,
+ RULES,
+ SELECTED,
+ SCHEME,
+ TYPE,
+ ONAFTERPRINT,
+ ALIGN,
+ HEIGHT,
+ LANGUAGE,
+ LENGTHADJUST,
+ PING,
+ ARCHIVE,
+ METHOD,
+ NOSHADE,
+ ALTIMG,
+ ADDITIVE,
+ DEFINITIONURL,
+ ONFINISH,
+ SCRIPTLEVEL,
+ VALIGN,
+ MARKER_MID,
+ MARKER_START,
+ MASKCONTENTUNITS,
+ DECLARE,
+ MAXLENGTH,
+ ROWLINES,
+ TITLE,
+ FRAME,
+ PROMPT,
+ USEMAP,
+ IN,
+ KERNELUNITLENGTH,
+ ONEND,
+ POINTSATX,
+ STANDBY,
+ WHEN,
+ XLINK_ARCROLE,
+ XLINK_SHOW,
+ AUTOFOCUS,
+ COLOR_RENDERING,
+ ENCODING,
+ LQUOTE,
+ ONMOUSEWHEEL,
+ ONCONTEXTMENU,
+ ONMOUSEMOVE,
+ ONFOCUSOUT,
+ STROKE_LINECAP,
+ STROKE_MITERLIMIT,
+ STROKE_OPACITY,
+ CLIP_PATH,
+ GLYPH_ORIENTATION_VERTICAL,
+ KEYPOINTS,
+ STEP,
+ SLOPE,
+ WRAP,
+ CHAR,
+ NOWRAP,
+ ONDRAGOVER,
+ ONERROR,
+ ONDRAGLEAVE,
+ AXIS,
+ CROSSORIGIN,
+ CLOSE,
+ KEYSPLINES,
+ OFFSET,
+ ROWSPACING,
+ VERSION,
+ CONTENT,
+ FONT_STRETCH,
+ FONTSTYLE,
+ FONT_VARIANT,
+ FONT_SIZE,
+ MULTIPLE,
+ POSTER,
+ PATTERNCONTENTUNITS,
+ TEXT_RENDERING,
+ TEXT,
+ COLUMNSPAN,
+ COLUMNWIDTH,
+ ONCUT,
+ REQUIREDEXTENSIONS,
+ ELEVATION,
+ CX,
+ FX,
+ REFX,
+ CY,
+ FY,
+ REFY,
+ ALT,
+ DUR,
+ FOR,
+ LOW,
+ MAX,
+ REV,
+ D,
+ X,
+ Z,
+ X1,
+ K2,
+ Y2,
+ K4,
+ XML_LANG,
+ ARIA_VALUEMAX,
+ ARIA_DESCRIBEDBY,
+ ARIA_CHECKED,
+ ARIA_DROPEFFECT,
+ ARIA_EXPANDED,
+ ARIA_LEVEL,
+ ARIA_HIDDEN,
+ ARIA_POSINSET,
+ ARIA_INVALID,
+ ARIA_VALUEMIN,
+ ARIA_CONTROLS,
+ ARIA_READONLY,
+ ARIA_ACTIVEDESCENDANT,
+ ARIA_DATATYPE,
+ ARIA_SORT,
+ ARIA_FLOWTO,
+ ARIA_LIVE,
+ ARIA_SETSIZE,
+ DISABLED,
+ DATA,
+ EQUALROWS,
+ ISMAP,
+ LSPACE,
+ NOTATION,
+ ONPASTE,
+ ROWALIGN,
+ SEPARATOR,
+ VSPACE,
+ YCHANNELSELECTOR,
+ ONDBLCLICK,
+ CALCMODE,
+ FENCE,
+ ONACTIVATE,
+ SPACING,
+ SPECULARCONSTANT,
+ ID,
+ GRADIENTUNITS,
+ HEADERS,
+ READONLY,
+ SEED,
+ STDDEVIATION,
+ WORD_SPACING,
+ ACCEPT_CHARSET,
+ ACCENT,
+ BEVELLED,
+ BASELINE_SHIFT,
+ BASELINE,
+ CODE,
+ CODEBASE,
+ DEFER,
+ DIRECTION,
+ EDGE,
+ FACE,
+ INTERCEPT,
+ LINEBREAK,
+ LINETHICKNESS,
+ NAME,
+ ONBEFOREUNLOAD,
+ OBJECT,
+ ORDER,
+ ONRESET,
+ ONMESSAGE,
+ ONBEFOREPRINT,
+ ORIENTATION,
+ ONSELECTSTART,
+ ONKEYPRESS,
+ ONBEFORECUT,
+ ONRESIZE,
+ REFERRERPOLICY,
+ ROLE,
+ REPEATDUR,
+ SIZES,
+ STRETCHY,
+ SPREADMETHOD,
+ SIZE,
+ DIFFUSECONSTANT,
+ HREFLANG,
+ PROFILE,
+ XREF,
+ ALIGNMENT_BASELINE,
+ DRAGGABLE,
+ IMAGESIZES,
+ IMAGE_RENDERING,
+ LANG,
+ LONGDESC,
+ MARGINHEIGHT,
+ ORIGIN,
+ TARGET,
+ TARGETY,
+ HIGH,
+ MATHBACKGROUND,
+ MATHVARIANT,
+ MATHSIZE,
+ ONCHANGE,
+ PATH,
+ ACTIONTYPE,
+ ACTIVE,
+ BEGIN,
+ DIVISOR,
+ LIMITINGCONEANGLE,
+ MANIFEST,
+ OPTIMUM,
+ RADIUS,
+ SCRIPTSIZEMULTIPLIER,
+ TABINDEX,
+ VISIBILITY,
+ LINK,
+ MARKERHEIGHT,
+ MASK,
+ MARKERWIDTH,
+ MARKERUNITS,
+ AMPLITUDE,
+ CELLPADDING,
+ FILL_RULE,
+ FILL_OPACITY,
+ ONCLICK,
+ REPLACE,
+ SCALE,
+ TABLEVALUES,
+ AZIMUTH,
+ FRAMEBORDER,
+ FRAMESPACING,
+ FORM,
+ PRIMITIVEUNITS,
+ SUMMARY,
+ ZOOMANDPAN,
+ ALINK,
+ ICON,
+ KERNING,
+ ONUNLOAD,
+ ONINVALID,
+ ONINPUT,
+ POINTS,
+ POINTSATY,
+ SPAN,
+ TRANSFORM_ORIGIN,
+ VLINK,
+ XLINK_HREF,
+ XLINK_ROLE,
+ XMLNS_XLINK,
+ XLINK_TYPE,
+ XLINK_ACTUATE,
+ AUTOCOMPLETE,
+ AUTOCAPITALIZE,
+ COLOR_PROFILE,
+ COLOR_INTERPOLATION,
+ COLOR_INTERPOLATION_FILTERS,
+ EXPONENT,
+ FLOOD_OPACITY,
+ NUMOCTAVES,
+ ONLOAD,
+ ONMOUSEENTER,
+ ONFOCUSIN,
+ ONZOOM,
+ ONMOUSELEAVE,
+ ONMOUSEUP,
+ ONMOUSEOUT,
+ ONMOUSEDOWN,
+ RQUOTE,
+ STROKE_DASHARRAY,
+ STROKE_LINEJOIN,
+ STROKE,
+ STROKE_WIDTH,
+ COMPACT,
+ CLIP_RULE,
+ CLIPPATHUNITS,
+ DISPLAYSTYLE,
+ GLYPH_ORIENTATION_HORIZONTAL,
+ HTTP_EQUIV,
+ LOOP,
+ SCOPED,
+ SHAPE_RENDERING,
+ SHAPE,
+ STOP_COLOR,
+ TEMPLATE,
+ ABBR,
+ ATTRIBUTETYPE,
+ COORDS,
+ CHARSET,
+ NOHREF,
+ ONDRAGENTER,
+ ONDRAGEND,
+ ONDRAGDROP,
+ OPERATOR,
+ ONDRAGSTART,
+ STARTOFFSET,
+ AS,
+ BIAS,
+ CLASSID,
+ COLS,
+ CLOSURE,
+ CLASS,
+ KEYSYSTEM,
+ LOWSRC,
+ MINSIZE,
+ PRESERVEALPHA,
+ ROWSPAN,
+ ROWS,
+ SUBSCRIPTSHIFT,
+ ALTTEXT,
+ CONTROLS,
+ CONTEXTMENU,
+ ENCTYPE,
+ FILTER,
+ FONT_WEIGHT,
+ FONT_STYLE,
+ FONT_FAMILY,
+ FONT_SIZE_ADJUST,
+ FONTSIZE,
+ KEYTIMES,
+ LIST,
+ RT,
+ ONSTART,
+ PATTERNTRANSFORM,
+ PATTERNUNITS,
+ RESTART,
+ SYSTEMLANGUAGE,
+ TEXT_DECORATION,
+ TEXTLENGTH,
+ WRITING_MODE,
+ ACCUMULATE,
+ COLUMNLINES,
+ COLUMNSPACING,
+ GROUPALIGN,
+ ONSUBMIT,
+ REQUIRED,
+ RESULT,
+ VALUES,
+ VALUE,
+ VIEWTARGET,
+ };
+ private final static int[] ATTRIBUTE_HASHES = {
+ 1867462756,
+ 1748971848,
+ 1966442279,
+ 1681174213,
+ 1785053243,
+ 1916286197,
+ 2004846654,
+ 1680165421,
+ 1723336432,
+ 1754899031,
+ 1816104145,
+ 1905628916,
+ 1924629705,
+ 1988784439,
+ 2024647008,
+ 71827457,
+ 1680282148,
+ 1689324870,
+ 1747295467,
+ 1754579720,
+ 1756889417,
+ 1803561214,
+ 1848600826,
+ 1884295780,
+ 1910441627,
+ 1922607670,
+ 1939976792,
+ 1975062341,
+ 2000752725,
+ 2009079867,
+ 2073034754,
+ 57205395,
+ 911736834,
+ 1680181996,
+ 1680368221,
+ 1685882101,
+ 1704526375,
+ 1736416327,
+ 1747906667,
+ 1751755561,
+ 1754698327,
+ 1756360955,
+ 1773606972,
+ 1787365531,
+ 1805715690,
+ 1823574314,
+ 1854497001,
+ 1874270021,
+ 1898415413,
+ 1906423097,
+ 1915025672,
+ 1921977416,
+ 1923088386,
+ 1933369607,
+ 1941550652,
+ 1972904518,
+ 1983398182,
+ 1991625270,
+ 2001710298,
+ 2007021895,
+ 2016810187,
+ 2060474743,
+ 2082471938,
+ 53006051,
+ 60345635,
+ 885522434,
+ 1680095865,
+ 1680165533,
+ 1680229115,
+ 1680343801,
+ 1680437801,
+ 1682440540,
+ 1687620127,
+ 1692408896,
+ 1721189160,
+ 1733874289,
+ 1740096054,
+ 1747479606,
+ 1748503880,
+ 1749549708,
+ 1753550036,
+ 1754644293,
+ 1754835516,
+ 1756147974,
+ 1756762256,
+ 1767725700,
+ 1781007934,
+ 1786775671,
+ 1791068279,
+ 1804081401,
+ 1814560070,
+ 1820727381,
+ 1824159037,
+ 1854366938,
+ 1865910331,
+ 1872343590,
+ 1884079398,
+ 1890996553,
+ 1903612236,
+ 1906408542,
+ 1908462185,
+ 1910503637,
+ 1915757815,
+ 1917857531,
+ 1922413307,
+ 1922677495,
+ 1924517489,
+ 1932959284,
+ 1934970504,
+ 1941435445,
+ 1965512429,
+ 1972656710,
+ 1972922984,
+ 1983157559,
+ 1984430082,
+ 1990107683,
+ 2000096287,
+ 2001634458,
+ 2001826027,
+ 2006459190,
+ 2008401563,
+ 2010716309,
+ 2019887833,
+ 2026893641,
+ 2065694722,
+ 2081423362,
+ 2089811970,
+ 52488851,
+ 55077603,
+ 59825747,
+ 68157441,
+ 878182402,
+ 901775362,
+ 1037879561,
+ 1680159327,
+ 1680165437,
+ 1680165692,
+ 1680198203,
+ 1680231247,
+ 1680315086,
+ 1680345965,
+ 1680413393,
+ 1680452349,
+ 1681879063,
+ 1683805446,
+ 1686731997,
+ 1689048326,
+ 1689839946,
+ 1699185409,
+ 1714763319,
+ 1721347639,
+ 1731048742,
+ 1734182982,
+ 1739583824,
+ 1740130375,
+ 1747309881,
+ 1747800157,
+ 1748021284,
+ 1748566068,
+ 1749350104,
+ 1751507685,
+ 1753049109,
+ 1754434872,
+ 1754612424,
+ 1754647074,
+ 1754794646,
+ 1754860061,
+ 1754927689,
+ 1756219733,
+ 1756704824,
+ 1756836998,
+ 1757421892,
+ 1771569964,
+ 1780879045,
+ 1784574102,
+ 1786622296,
+ 1786851500,
+ 1788842244,
+ 1797886599,
+ 1804054854,
+ 1804405895,
+ 1814517574,
+ 1814656840,
+ 1816178925,
+ 1821958888,
+ 1823829083,
+ 1825437894,
+ 1854285018,
+ 1854466380,
+ 1854497008,
+ 1866496199,
+ 1871251689,
+ 1873656984,
+ 1874788501,
+ 1884246821,
+ 1889569526,
+ 1891937366,
+ 1900544002,
+ 1903759600,
+ 1905754853,
+ 1906419001,
+ 1907701479,
+ 1909819252,
+ 1910441773,
+ 1910527802,
+ 1915341049,
+ 1916247343,
+ 1917295176,
+ 1921061206,
+ 1922400908,
+ 1922566877,
+ 1922665179,
+ 1922679610,
+ 1924443742,
+ 1924583073,
+ 1924773438,
+ 1933123337,
+ 1934917290,
+ 1937336473,
+ 1941286708,
+ 1941440197,
+ 1943317364,
+ 1966384692,
+ 1972151670,
+ 1972744954,
+ 1972908839,
+ 1972996699,
+ 1982254612,
+ 1983290011,
+ 1983432389,
+ 1987422362,
+ 1989522022,
+ 1991220282,
+ 1993343287,
+ 2000160071,
+ 2001527900,
+ 2001669449,
+ 2001732764,
+ 2001898809,
+ 2005342360,
+ 2006824246,
+ 2007064819,
+ 2009041198,
+ 2009231684,
+ 2016711994,
+ 2017010843,
+ 2023342821,
+ 2024794274,
+ 2034765641,
+ 2065170434,
+ 2066743298,
+ 2075005220,
+ 2081947650,
+ 2083520514,
+ 2091784484,
+ 50917059,
+ 52489043,
+ 53537523,
+ 56685811,
+ 57210387,
+ 59830867,
+ 60817409,
+ 71303169,
+ 72351745,
+ 884998146,
+ 894959618,
+ 902299650,
+ 928514050,
+ 1038063816,
+ 1680140893,
+ 1680159328,
+ 1680165436,
+ 1680165487,
+ 1680165613,
+ 1680181850,
+ 1680185931,
+ 1680198381,
+ 1680230940,
+ 1680251485,
+ 1680311085,
+ 1680323325,
+ 1680345685,
+ 1680347981,
+ 1680411449,
+ 1680433915,
+ 1680446153,
+ 1680511804,
+ 1681733672,
+ 1681969220,
+ 1682587945,
+ 1684319541,
+ 1685902598,
+ 1687164232,
+ 1687751191,
+ 1689130184,
+ 1689788441,
+ 1691145478,
+ 1692933184,
+ 1704262346,
+ 1714745560,
+ 1716303957,
+ 1721305962,
+ 1723309623,
+ 1723336528,
+ 1732771842,
+ 1733919469,
+ 1734404167,
+ 1739561208,
+ 1739927860,
+ 1740119884,
+ 1742183484,
+ 1747299630,
+ 1747446838,
+ 1747792072,
+ 1747839118,
+ 1747939528,
+ 1748306996,
+ 1748552744,
+ 1748869205,
+ 1749027145,
+ 1749399124,
+ 1749856356,
+ 1751679545,
+ 1752985897,
+ 1753297133,
+ 1754214628,
+ 1754546894,
+ 1754606246,
+ 1754643237,
+ 1754645079,
+ 1754647353,
+ 1754792749,
+ 1754798923,
+ 1754858317,
+ 1754872618,
+ 1754907227,
+ 1754958648,
+ 1756190926,
+ 1756302628,
+ 1756471625,
+ 1756737685,
+ 1756804936,
+ 1756874572,
+ 1757053236,
+ 1765800271,
+ 1767875272,
+ 1772032615,
+ 1776114564,
+ 1780975314,
+ 1782518297,
+ 1785051290,
+ 1785174319,
+ 1786740932,
+ 1786821704,
+ 1787193500,
+ 1788254870,
+ 1790814502,
+ 1791070327,
+ 1801312388,
+ 1804036350,
+ 1804069019,
+ 1804235064,
+ 1804978712,
+ 1805715716,
+ 1814558026,
+ 1814656326,
+ 1814986837,
+ 1816144023,
+ 1820262641,
+ 1820928104,
+ 1822002839,
+ 1823580230,
+ 1823841492,
+ 1824377064,
+ 1825677514,
+ 1853862084,
+ 1854302364,
+ 1854464212,
+ 1854474395,
+ 1854497003,
+ 1864698185,
+ 1865910347,
+ 1867448617,
+ 1867620412,
+ 1872034503,
+ 1873590471,
+ 1874261045,
+ 1874698443,
+ 1881750231,
+ 1884142379,
+ 1884267068,
+ 1884343396,
+ 1889633006,
+ 1891186903,
+ 1894552650,
+ 1898428101,
+ 1902640276,
+ 1903659239,
+ 1905541832,
+ 1905672729,
+ 1905902311,
+ 1906408598,
+ 1906421049,
+ 1907660596,
+ 1908316832,
+ 1909438149,
+ 1910328970,
+ 1910441770,
+ 1910487243,
+ 1910507338,
+ 1910572893,
+ 1915295948,
+ 1915394254,
+ 1916210285,
+ 1916278099,
+ 1916337499,
+ 1917327080,
+ 1917953597,
+ 1921894426,
+ 1922319046,
+ 1922413292,
+ 1922470745,
+ 1922567078,
+ 1922665052,
+ 1922671417,
+ 1922679386,
+ 1922699851,
+ 1924206934,
+ 1924462384,
+ 1924570799,
+ 1924585254,
+ 1924738716,
+ 1932870919,
+ 1932986153,
+ 1933145837,
+ 1933508940,
+ 1934917372,
+ 1935597338,
+ 1937777860,
+ 1941253366,
+ 1941409583,
+ 1941438085,
+ 1941454586,
+ 1942026440,
+ 1965349396,
+ 1965561677,
+ 1966439670,
+ 1966454567,
+ 1972196486,
+ 1972744939,
+ 1972863609,
+ 1972904522,
+ 1972909592,
+ 1972962123,
+ 1974849131,
+ 1980235778,
+ 1982640164,
+ 1983266615,
+ 1983347764,
+ 1983416119,
+ 1983461061,
+ 1987410233,
+ 1988132214,
+ 1988788535,
+ 1990062797,
+ 1991021879,
+ 1991392548,
+ 1991643278,
+ 1999273799,
+ 2000125224,
+ 2000162011,
+ 2001210183,
+ 2001578182,
+ 2001634459,
+ 2001669450,
+ 2001710299,
+ 2001814704,
+ 2001898808,
+ 2004199576,
+ 2004957380,
+ 2005925890,
+ 2006516551,
+ 2007019632,
+ 2007064812,
+ 2008084807,
+ 2008408414,
+ 2009071951,
+ 2009141482,
+ 2010452700,
+ 2015950026,
+ 2016787611,
+ 2016910397,
+ 2018908874,
+ 2023146024,
+ 2024616088,
+ 2024763702,
+ 2026741958,
+ 2026975253,
+ 2060302634,
+ };
+}
diff --git a/parser/html/javasrc/ElementName.java b/parser/html/javasrc/ElementName.java
new file mode 100644
index 0000000000..9ee2ad0152
--- /dev/null
+++ b/parser/html/javasrc/ElementName.java
@@ -0,0 +1,1896 @@
+/*
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.impl;
+
+// uncomment to regenerate self
+//import java.io.BufferedReader;
+//import java.io.File;
+//import java.io.FileInputStream;
+//import java.io.IOException;
+//import java.io.InputStreamReader;
+//import java.util.Arrays;
+//import java.util.Collections;
+//import java.util.HashMap;
+//import java.util.LinkedList;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Map.Entry;
+//import java.util.regex.Matcher;
+//import java.util.regex.Pattern;
+
+import nu.validator.htmlparser.annotation.Inline;
+import nu.validator.htmlparser.annotation.Local;
+import nu.validator.htmlparser.annotation.NoLength;
+import nu.validator.htmlparser.annotation.Unsigned;
+import nu.validator.htmlparser.common.Interner;
+
+public final class ElementName
+ // uncomment when regenerating self
+// implements Comparable<ElementName>
+{
+
+ /**
+ * The mask for extracting the dispatch group.
+ */
+ public static final int GROUP_MASK = 127;
+
+ /**
+ * Indicates that the element is not a pre-interned element. Forbidden on
+ * preinterned elements.
+ */
+ public static final int NOT_INTERNED = (1 << 30);
+
+ /**
+ * Indicates that the element is in the "special" category. This bit should
+ * not be pre-set on MathML or SVG specials--only on HTML specials.
+ */
+ public static final int SPECIAL = (1 << 29);
+
+ /**
+ * The element is foster-parenting. This bit should be pre-set on elements
+ * that are foster-parenting as HTML.
+ */
+ public static final int FOSTER_PARENTING = (1 << 28);
+
+ /**
+ * The element is scoping. This bit should be pre-set on elements that are
+ * scoping as HTML.
+ */
+ public static final int SCOPING = (1 << 27);
+
+ /**
+ * The element is scoping as SVG.
+ */
+ public static final int SCOPING_AS_SVG = (1 << 26);
+
+ /**
+ * The element is scoping as MathML.
+ */
+ public static final int SCOPING_AS_MATHML = (1 << 25);
+
+ /**
+ * The element is an HTML integration point.
+ */
+ public static final int HTML_INTEGRATION_POINT = (1 << 24);
+
+ /**
+ * The element has an optional end tag.
+ */
+ public static final int OPTIONAL_END_TAG = (1 << 23);
+
+ private @Local String name;
+
+ private @Local String camelCaseName;
+
+ // CPPONLY: private @HtmlCreator Object htmlCreator;
+
+ // CPPONLY: private @SvgCreator Object svgCreator;
+
+ /**
+ * The lowest 7 bits are the dispatch group. The high bits are flags.
+ */
+ public final int flags;
+
+ @Inline public @Local String getName() {
+ return name;
+ }
+
+ @Inline public @Local String getCamelCaseName() {
+ return camelCaseName;
+ }
+
+ // CPPONLY: @Inline public @HtmlCreator Object getHtmlCreator() {
+ // CPPONLY: return htmlCreator;
+ // CPPONLY: }
+
+ // CPPONLY: @Inline public @SvgCreator Object getSvgCreator() {
+ // CPPONLY: return svgCreator;
+ // CPPONLY: }
+
+ @Inline public int getFlags() {
+ return flags;
+ }
+
+ @Inline public int getGroup() {
+ return flags & ElementName.GROUP_MASK;
+ }
+
+ @Inline public boolean isInterned() {
+ return (flags & ElementName.NOT_INTERNED) == 0;
+ }
+
+ @Inline static int levelOrderBinarySearch(int[] data, int key) {
+ int n = data.length;
+ int i = 0;
+
+ while (i < n) {
+ int val = data[i];
+ if (val < key) {
+ i = 2 * i + 2;
+ } else if (val > key) {
+ i = 2 * i + 1;
+ } else {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ @Inline static ElementName elementNameByBuffer(@NoLength char[] buf,
+ int length, Interner interner) {
+ @Unsigned int hash = ElementName.bufToHash(buf, length);
+ int[] hashes;
+ hashes = ElementName.ELEMENT_HASHES;
+ int index = levelOrderBinarySearch(hashes, hash);
+ if (index < 0) {
+ return null;
+ } else {
+ ElementName elementName = ElementName.ELEMENT_NAMES[index];
+ @Local String name = elementName.name;
+ if (!Portability.localEqualsBuffer(name, buf, length)) {
+ return null;
+ }
+ return elementName;
+ }
+ }
+
+ /**
+ * This method has to return a unique positive integer for each well-known
+ * lower-cased element name.
+ *
+ * @param buf
+ * @param len
+ * @return
+ */
+ @Inline private static @Unsigned int bufToHash(@NoLength char[] buf,
+ int length) {
+ @Unsigned int len = length;
+ @Unsigned int first = buf[0];
+ first <<= 19;
+ @Unsigned int second = 1 << 23;
+ @Unsigned int third = 0;
+ @Unsigned int fourth = 0;
+ @Unsigned int fifth = 0;
+ if (length >= 4) {
+ second = buf[length - 4];
+ second <<= 4;
+ third = buf[length - 3];
+ third <<= 9;
+ fourth = buf[length - 2];
+ fourth <<= 14;
+ fifth = buf[length - 1];
+ fifth <<= 24;
+ } else if (length == 3) {
+ second = buf[1];
+ second <<= 4;
+ third = buf[2];
+ third <<= 9;
+ } else if (length == 2) {
+ second = buf[1];
+ second <<= 24;
+ }
+ return len + first + second + third + fourth + fifth;
+ }
+
+ private ElementName(@Local String name, @Local String camelCaseName,
+ // CPPONLY: @HtmlCreator Object htmlCreator, @SvgCreator Object
+ // CPPONLY: svgCreator,
+ int flags) {
+ this.name = name;
+ this.camelCaseName = camelCaseName;
+ // CPPONLY: this.htmlCreator = htmlCreator;
+ // CPPONLY: this.svgCreator = svgCreator;
+ this.flags = flags;
+ }
+
+ public ElementName() {
+ this.name = null;
+ this.camelCaseName = null;
+ // CPPONLY: this.htmlCreator = NS_NewHTMLUnknownElement;
+ // CPPONLY: this.svgCreator = NS_NewSVGUnknownElement;
+ this.flags = TreeBuilder.OTHER | NOT_INTERNED;
+ }
+
+ public void destructor() {
+ // The translator adds refcount debug code here.
+ }
+
+ @Inline public void setNameForNonInterned(@Local String name
+ // CPPONLY: , boolean custom
+ ) {
+ // No need to worry about refcounting the local name, because in the
+ // C++ case the scoped atom table remembers its own atoms.
+ this.name = name;
+ this.camelCaseName = name;
+ // CPPONLY: if (custom) {
+ // CPPONLY: this.htmlCreator = NS_NewCustomElement;
+ // CPPONLY: } else {
+ // CPPONLY: this.htmlCreator = NS_NewHTMLUnknownElement;
+ // CPPONLY: }
+ // The assertion below relies on TreeBuilder.OTHER being zero!
+ // TreeBuilder.OTHER isn't referenced here, because it would create
+ // a circular C++ header dependency given that this method is inlined.
+ assert this.flags == ElementName.NOT_INTERNED;
+ }
+
+ // CPPONLY: @Inline public boolean isCustom() {
+ // CPPONLY: return this.htmlCreator == NS_NewCustomElement;
+ // CPPONLY: }
+
+ public static final ElementName ANNOTATION_XML = new ElementName(
+ "annotation-xml", "annotation-xml",
+ // CPPONLY: NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement,
+ TreeBuilder.ANNOTATION_XML | SCOPING_AS_MATHML);
+
+ // START CODE ONLY USED FOR GENERATING CODE uncomment and run to regenerate
+
+// private static final Pattern HTML_TAG_DEF = Pattern.compile(
+// "^HTML_TAG\\(([^,]+),\\s*([^,]+),\\s*[^,]+\\).*$");
+//
+// private static final Pattern HTML_HTMLELEMENT_TAG_DEF = Pattern.compile(
+// "^HTML_HTMLELEMENT_TAG\\(([^\\)]+)\\).*$");
+//
+// private static final Pattern SVG_TAG_DEF = Pattern.compile(
+// "^SVG_(?:FROM_PARSER_)?TAG\\(([^,]+),\\s*([^\\)]+)\\).*$");
+//
+// private static final Map<String, String> htmlMap = new HashMap<String, String>();
+//
+// private static final Map<String, String> svgMap = new HashMap<String, String>();
+//
+// private static void ingestHtmlTags(File htmlList) throws IOException {
+// // This doesn't need to be efficient, so let's make it easy to write.
+// BufferedReader htmlReader = new BufferedReader(
+// new InputStreamReader(new FileInputStream(htmlList), "utf-8"));
+// try {
+// String line;
+// while ((line = htmlReader.readLine()) != null) {
+// if (!line.startsWith("HTML_")) {
+// continue;
+// }
+// if (line.startsWith("HTML_OTHER")) {
+// continue;
+// }
+// Matcher m = HTML_TAG_DEF.matcher(line);
+// if (m.matches()) {
+// String iface = m.group(2);
+// if ("Unknown".equals(iface)) {
+// continue;
+// }
+// htmlMap.put(m.group(1), "NS_NewHTML" + iface + "Element");
+// } else {
+// m = HTML_HTMLELEMENT_TAG_DEF.matcher(line);
+// if (!m.matches()) {
+// throw new RuntimeException(
+// "Malformed HTML element definition: " + line);
+// }
+// htmlMap.put(m.group(1), "NS_NewHTMLElement");
+// }
+// }
+// } finally {
+// htmlReader.close();
+// }
+// }
+//
+// private static void ingestSvgTags(File svgList) throws IOException {
+// // This doesn't need to be efficient, so let's make it easy to write.
+// BufferedReader svgReader = new BufferedReader(
+// new InputStreamReader(new FileInputStream(svgList), "utf-8"));
+// try {
+// String line;
+// while ((line = svgReader.readLine()) != null) {
+// if (!line.startsWith("SVG_")) {
+// continue;
+// }
+// Matcher m = SVG_TAG_DEF.matcher(line);
+// if (!m.matches()) {
+// throw new RuntimeException(
+// "Malformed SVG element definition: " + line);
+// }
+// String name = m.group(1);
+// if ("svgSwitch".equals(name)) {
+// name = "switch";
+// }
+// svgMap.put(name, "NS_NewSVG" + m.group(2) + "Element");
+// }
+// } finally {
+// svgReader.close();
+// }
+// }
+//
+// private static String htmlCreator(String name) {
+// String creator = htmlMap.remove(name);
+// if (creator != null) {
+// return creator;
+// }
+// return "NS_NewHTMLUnknownElement";
+// }
+//
+// private static String svgCreator(String name) {
+// String creator = svgMap.remove(name);
+// if (creator != null) {
+// return creator;
+// }
+// return "NS_NewSVGUnknownElement";
+// }
+//
+// /**
+// * @see java.lang.Object#toString()
+// */
+// @Override public String toString() {
+// return "(\"" + name + "\", \"" + camelCaseName + "\", \n// CPP"
+// + "ONLY: " + htmlCreator(name) + ",\n// CPP" + "ONLY: "
+// + svgCreator(camelCaseName) + ", \n" + decomposedFlags() + ")";
+// }
+//
+// private String decomposedFlags() {
+// StringBuilder buf = new StringBuilder("TreeBuilder.");
+// buf.append(treeBuilderGroupToName());
+// if ((flags & SPECIAL) != 0) {
+// buf.append(" | SPECIAL");
+// }
+// if ((flags & FOSTER_PARENTING) != 0) {
+// buf.append(" | FOSTER_PARENTING");
+// }
+// if ((flags & SCOPING) != 0) {
+// buf.append(" | SCOPING");
+// }
+// if ((flags & SCOPING_AS_MATHML) != 0) {
+// buf.append(" | SCOPING_AS_MATHML");
+// }
+// if ((flags & SCOPING_AS_SVG) != 0) {
+// buf.append(" | SCOPING_AS_SVG");
+// }
+// if ((flags & OPTIONAL_END_TAG) != 0) {
+// buf.append(" | OPTIONAL_END_TAG");
+// }
+// return buf.toString();
+// }
+//
+// private String constName() {
+// char[] buf = new char[name.length()];
+// for (int i = 0; i < name.length(); i++) {
+// char c = name.charAt(i);
+// if (c == '-') {
+// if (!"annotation-xml".equals(name)) {
+// throw new RuntimeException(
+// "Non-annotation-xml element name with hyphen: "
+// + name);
+// }
+// buf[i] = '_';
+// } else if (c >= '0' && c <= '9') {
+// buf[i] = c;
+// } else {
+// buf[i] = (char) (c - 0x20);
+// }
+// }
+// return new String(buf);
+// }
+//
+// private int hash() {
+// return bufToHash(name.toCharArray(), name.length());
+// }
+//
+// public int compareTo(ElementName other) {
+// int thisHash = this.hash();
+// int otherHash = other.hash();
+// if (thisHash < otherHash) {
+// return -1;
+// } else if (thisHash == otherHash) {
+// return 0;
+// } else {
+// return 1;
+// }
+// }
+//
+// private String treeBuilderGroupToName() {
+// switch (getGroup()) {
+// case TreeBuilder.OTHER:
+// return "OTHER";
+// case TreeBuilder.A:
+// return "A";
+// case TreeBuilder.BASE:
+// return "BASE";
+// case TreeBuilder.BODY:
+// return "BODY";
+// case TreeBuilder.BR:
+// return "BR";
+// case TreeBuilder.BUTTON:
+// return "BUTTON";
+// case TreeBuilder.CAPTION:
+// return "CAPTION";
+// case TreeBuilder.COL:
+// return "COL";
+// case TreeBuilder.COLGROUP:
+// return "COLGROUP";
+// case TreeBuilder.FONT:
+// return "FONT";
+// case TreeBuilder.FORM:
+// return "FORM";
+// case TreeBuilder.FRAME:
+// return "FRAME";
+// case TreeBuilder.FRAMESET:
+// return "FRAMESET";
+// case TreeBuilder.IMAGE:
+// return "IMAGE";
+// case TreeBuilder.INPUT:
+// return "INPUT";
+// case TreeBuilder.LI:
+// return "LI";
+// case TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND:
+// return "LINK_OR_BASEFONT_OR_BGSOUND";
+// case TreeBuilder.MATH:
+// return "MATH";
+// case TreeBuilder.META:
+// return "META";
+// case TreeBuilder.SVG:
+// return "SVG";
+// case TreeBuilder.HEAD:
+// return "HEAD";
+// case TreeBuilder.HR:
+// return "HR";
+// case TreeBuilder.HTML:
+// return "HTML";
+// case TreeBuilder.KEYGEN:
+// return "KEYGEN";
+// case TreeBuilder.NOBR:
+// return "NOBR";
+// case TreeBuilder.NOFRAMES:
+// return "NOFRAMES";
+// case TreeBuilder.NOSCRIPT:
+// return "NOSCRIPT";
+// case TreeBuilder.OPTGROUP:
+// return "OPTGROUP";
+// case TreeBuilder.OPTION:
+// return "OPTION";
+// case TreeBuilder.P:
+// return "P";
+// case TreeBuilder.PLAINTEXT:
+// return "PLAINTEXT";
+// case TreeBuilder.SCRIPT:
+// return "SCRIPT";
+// case TreeBuilder.SELECT:
+// return "SELECT";
+// case TreeBuilder.STYLE:
+// return "STYLE";
+// case TreeBuilder.TABLE:
+// return "TABLE";
+// case TreeBuilder.TEXTAREA:
+// return "TEXTAREA";
+// case TreeBuilder.TITLE:
+// return "TITLE";
+// case TreeBuilder.TEMPLATE:
+// return "TEMPLATE";
+// case TreeBuilder.TR:
+// return "TR";
+// case TreeBuilder.XMP:
+// return "XMP";
+// case TreeBuilder.TBODY_OR_THEAD_OR_TFOOT:
+// return "TBODY_OR_THEAD_OR_TFOOT";
+// case TreeBuilder.TD_OR_TH:
+// return "TD_OR_TH";
+// case TreeBuilder.DD_OR_DT:
+// return "DD_OR_DT";
+// case TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
+// return "H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6";
+// case TreeBuilder.OBJECT:
+// return "OBJECT";
+// case TreeBuilder.OUTPUT:
+// return "OUTPUT";
+// case TreeBuilder.MARQUEE_OR_APPLET:
+// return "MARQUEE_OR_APPLET";
+// case TreeBuilder.PRE_OR_LISTING:
+// return "PRE_OR_LISTING";
+// case TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+// return "B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U";
+// case TreeBuilder.UL_OR_OL_OR_DL:
+// return "UL_OR_OL_OR_DL";
+// case TreeBuilder.IFRAME:
+// return "IFRAME";
+// case TreeBuilder.NOEMBED:
+// return "NOEMBED";
+// case TreeBuilder.EMBED:
+// return "EMBED";
+// case TreeBuilder.IMG:
+// return "IMG";
+// case TreeBuilder.AREA_OR_WBR:
+// return "AREA_OR_WBR";
+// case TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+// return "DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU";
+// case TreeBuilder.FIELDSET:
+// return "FIELDSET";
+// case TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY:
+// return "ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY";
+// case TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
+// return "RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR";
+// case TreeBuilder.RB_OR_RTC:
+// return "RB_OR_RTC";
+// case TreeBuilder.RT_OR_RP:
+// return "RT_OR_RP";
+// case TreeBuilder.PARAM_OR_SOURCE_OR_TRACK:
+// return "PARAM_OR_SOURCE_OR_TRACK";
+// case TreeBuilder.MGLYPH_OR_MALIGNMARK:
+// return "MGLYPH_OR_MALIGNMARK";
+// case TreeBuilder.MI_MO_MN_MS_MTEXT:
+// return "MI_MO_MN_MS_MTEXT";
+// case TreeBuilder.ANNOTATION_XML:
+// return "ANNOTATION_XML";
+// case TreeBuilder.FOREIGNOBJECT_OR_DESC:
+// return "FOREIGNOBJECT_OR_DESC";
+// }
+// return null;
+// }
+//
+// private static void fillLevelOrderArray(List<ElementName> sorted, int depth,
+// int rootIdx, ElementName[] levelOrder) {
+// if (rootIdx >= levelOrder.length) {
+// return;
+// }
+//
+// if (depth > 0) {
+// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 1, levelOrder);
+// }
+//
+// if (!sorted.isEmpty()) {
+// levelOrder[rootIdx] = sorted.remove(0);
+// }
+//
+// if (depth > 0) {
+// fillLevelOrderArray(sorted, depth - 1, rootIdx * 2 + 2, levelOrder);
+// }
+// }
+//
+// /**
+// * Regenerate self
+// *
+// * The args should be the paths to m-c files
+// * parser/htmlparser/nsHTMLTagList.h and dom/svg/SVGTagList.h.
+// */
+// public static void main(String[] args) {
+// File htmlList = new File(args[0]);
+// File svgList = new File(args[1]);
+// try {
+// ingestHtmlTags(htmlList);
+// } catch (IOException e) {
+// throw new RuntimeException(e);
+// }
+// try {
+// ingestSvgTags(svgList);
+// } catch (IOException e) {
+// throw new RuntimeException(e);
+// }
+//
+// Arrays.sort(ELEMENT_NAMES);
+// for (int i = 0; i < ELEMENT_NAMES.length; i++) {
+// int hash = ELEMENT_NAMES[i].hash();
+// if (hash < 0) {
+// System.err.println("Negative hash: " + ELEMENT_NAMES[i].name);
+// return;
+// }
+// for (int j = i + 1; j < ELEMENT_NAMES.length; j++) {
+// if (hash == ELEMENT_NAMES[j].hash()) {
+// System.err.println(
+// "Hash collision: " + ELEMENT_NAMES[i].name + ", "
+// + ELEMENT_NAMES[j].name);
+// return;
+// }
+// }
+// }
+// for (int i = 0; i < ELEMENT_NAMES.length; i++) {
+// ElementName el = ELEMENT_NAMES[i];
+// System.out.println(
+// "public static final ElementName " + el.constName()
+// + " = new ElementName" + el.toString() + ";");
+// }
+//
+// LinkedList<ElementName> sortedNames = new LinkedList<ElementName>();
+// Collections.addAll(sortedNames, ELEMENT_NAMES);
+// ElementName[] levelOrder = new ElementName[ELEMENT_NAMES.length];
+// int bstDepth = (int) Math.ceil(
+// Math.log(ELEMENT_NAMES.length) / Math.log(2));
+// fillLevelOrderArray(sortedNames, bstDepth, 0, levelOrder);
+//
+// System.out.println(
+// "private final static @NoLength ElementName[] ELEMENT_NAMES = {");
+// for (int i = 0; i < levelOrder.length; i++) {
+// ElementName el = levelOrder[i];
+// System.out.println(el.constName() + ",");
+// }
+// System.out.println("};");
+// System.out.println("private final static int[] ELEMENT_HASHES = {");
+// for (int i = 0; i < levelOrder.length; i++) {
+// ElementName el = levelOrder[i];
+// System.out.println(Integer.toString(el.hash()) + ",");
+// }
+// System.out.println("};");
+//
+// for (Entry<String, String> entry : htmlMap.entrySet()) {
+// System.err.println("Missing HTML element: " + entry.getKey());
+// }
+// for (Entry<String, String> entry : svgMap.entrySet()) {
+// System.err.println("Missing SVG element: " + entry.getKey());
+// }
+// }
+
+ // START GENERATED CODE
+public static final ElementName BIG = new ElementName("big", "big",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName BDI = new ElementName("bdi", "bdi",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName BDO = new ElementName("bdo", "bdo",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName COL = new ElementName("col", "col",
+// CPPONLY: NS_NewHTMLTableColElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.COL | SPECIAL);
+public static final ElementName DEL = new ElementName("del", "del",
+// CPPONLY: NS_NewHTMLModElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName DFN = new ElementName("dfn", "dfn",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName DIR = new ElementName("dir", "dir",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName DIV = new ElementName("div", "div",
+// CPPONLY: NS_NewHTMLDivElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+public static final ElementName IMG = new ElementName("img", "img",
+// CPPONLY: NS_NewHTMLImageElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.IMG | SPECIAL);
+public static final ElementName INS = new ElementName("ins", "ins",
+// CPPONLY: NS_NewHTMLModElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName KBD = new ElementName("kbd", "kbd",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName MAP = new ElementName("map", "map",
+// CPPONLY: NS_NewHTMLMapElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName NAV = new ElementName("nav", "nav",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName PRE = new ElementName("pre", "pre",
+// CPPONLY: NS_NewHTMLPreElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.PRE_OR_LISTING | SPECIAL);
+public static final ElementName A = new ElementName("a", "a",
+// CPPONLY: NS_NewHTMLAnchorElement,
+// CPPONLY: NS_NewSVGAElement,
+TreeBuilder.A);
+public static final ElementName B = new ElementName("b", "b",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName RTC = new ElementName("rtc", "rtc",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RB_OR_RTC | OPTIONAL_END_TAG);
+public static final ElementName SUB = new ElementName("sub", "sub",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+public static final ElementName SVG = new ElementName("svg", "svg",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGSVGElement,
+TreeBuilder.SVG);
+public static final ElementName SUP = new ElementName("sup", "sup",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+public static final ElementName SET = new ElementName("set", "set",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGSetElement,
+TreeBuilder.OTHER);
+public static final ElementName USE = new ElementName("use", "use",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUseElement,
+TreeBuilder.OTHER);
+public static final ElementName VAR = new ElementName("var", "var",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+public static final ElementName G = new ElementName("g", "g",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGGElement,
+TreeBuilder.OTHER);
+public static final ElementName WBR = new ElementName("wbr", "wbr",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.AREA_OR_WBR | SPECIAL);
+public static final ElementName XMP = new ElementName("xmp", "xmp",
+// CPPONLY: NS_NewHTMLPreElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.XMP | SPECIAL);
+public static final ElementName I = new ElementName("i", "i",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName P = new ElementName("p", "p",
+// CPPONLY: NS_NewHTMLParagraphElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.P | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName Q = new ElementName("q", "q",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName S = new ElementName("s", "s",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName U = new ElementName("u", "u",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName H1 = new ElementName("h1", "h1",
+// CPPONLY: NS_NewHTMLHeadingElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+public static final ElementName H2 = new ElementName("h2", "h2",
+// CPPONLY: NS_NewHTMLHeadingElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+public static final ElementName H3 = new ElementName("h3", "h3",
+// CPPONLY: NS_NewHTMLHeadingElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+public static final ElementName H4 = new ElementName("h4", "h4",
+// CPPONLY: NS_NewHTMLHeadingElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+public static final ElementName H5 = new ElementName("h5", "h5",
+// CPPONLY: NS_NewHTMLHeadingElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+public static final ElementName H6 = new ElementName("h6", "h6",
+// CPPONLY: NS_NewHTMLHeadingElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+public static final ElementName AREA = new ElementName("area", "area",
+// CPPONLY: NS_NewHTMLAreaElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.AREA_OR_WBR | SPECIAL);
+public static final ElementName DATA = new ElementName("data", "data",
+// CPPONLY: NS_NewHTMLDataElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName FEFUNCA = new ElementName("fefunca", "feFuncA",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEFuncAElement,
+TreeBuilder.OTHER);
+public static final ElementName METADATA = new ElementName("metadata", "metadata",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGMetadataElement,
+TreeBuilder.OTHER);
+public static final ElementName META = new ElementName("meta", "meta",
+// CPPONLY: NS_NewHTMLMetaElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.META | SPECIAL);
+public static final ElementName TEXTAREA = new ElementName("textarea", "textarea",
+// CPPONLY: NS_NewHTMLTextAreaElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TEXTAREA | SPECIAL);
+public static final ElementName FEFUNCB = new ElementName("fefuncb", "feFuncB",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEFuncBElement,
+TreeBuilder.OTHER);
+public static final ElementName RB = new ElementName("rb", "rb",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RB_OR_RTC | OPTIONAL_END_TAG);
+public static final ElementName DESC = new ElementName("desc", "desc",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGDescElement,
+TreeBuilder.FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG);
+public static final ElementName DD = new ElementName("dd", "dd",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.DD_OR_DT | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName BGSOUND = new ElementName("bgsound", "bgsound",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL);
+public static final ElementName EMBED = new ElementName("embed", "embed",
+// CPPONLY: NS_NewHTMLEmbedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.EMBED | SPECIAL);
+public static final ElementName FEBLEND = new ElementName("feblend", "feBlend",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEBlendElement,
+TreeBuilder.OTHER);
+public static final ElementName FEFLOOD = new ElementName("feflood", "feFlood",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEFloodElement,
+TreeBuilder.OTHER);
+public static final ElementName HEAD = new ElementName("head", "head",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.HEAD | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName LEGEND = new ElementName("legend", "legend",
+// CPPONLY: NS_NewHTMLLegendElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName NOEMBED = new ElementName("noembed", "noembed",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.NOEMBED | SPECIAL);
+public static final ElementName TD = new ElementName("td", "td",
+// CPPONLY: NS_NewHTMLTableCellElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG);
+public static final ElementName THEAD = new ElementName("thead", "thead",
+// CPPONLY: NS_NewHTMLTableSectionElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG);
+public static final ElementName ASIDE = new ElementName("aside", "aside",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName ARTICLE = new ElementName("article", "article",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName ANIMATE = new ElementName("animate", "animate",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGAnimateElement,
+TreeBuilder.OTHER);
+public static final ElementName BASE = new ElementName("base", "base",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.BASE | SPECIAL);
+public static final ElementName BLOCKQUOTE = new ElementName("blockquote", "blockquote",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+public static final ElementName CODE = new ElementName("code", "code",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName CIRCLE = new ElementName("circle", "circle",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGCircleElement,
+TreeBuilder.OTHER);
+public static final ElementName CITE = new ElementName("cite", "cite",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName ELLIPSE = new ElementName("ellipse", "ellipse",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGEllipseElement,
+TreeBuilder.OTHER);
+public static final ElementName FETURBULENCE = new ElementName("feturbulence", "feTurbulence",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFETurbulenceElement,
+TreeBuilder.OTHER);
+public static final ElementName FEMERGENODE = new ElementName("femergenode", "feMergeNode",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEMergeNodeElement,
+TreeBuilder.OTHER);
+public static final ElementName FEIMAGE = new ElementName("feimage", "feImage",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEImageElement,
+TreeBuilder.OTHER);
+public static final ElementName FEMERGE = new ElementName("femerge", "feMerge",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEMergeElement,
+TreeBuilder.OTHER);
+public static final ElementName FETILE = new ElementName("fetile", "feTile",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFETileElement,
+TreeBuilder.OTHER);
+public static final ElementName FRAME = new ElementName("frame", "frame",
+// CPPONLY: NS_NewHTMLFrameElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.FRAME | SPECIAL);
+public static final ElementName FIGURE = new ElementName("figure", "figure",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName FECOMPOSITE = new ElementName("fecomposite", "feComposite",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFECompositeElement,
+TreeBuilder.OTHER);
+public static final ElementName IMAGE = new ElementName("image", "image",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGImageElement,
+TreeBuilder.IMAGE);
+public static final ElementName IFRAME = new ElementName("iframe", "iframe",
+// CPPONLY: NS_NewHTMLIFrameElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.IFRAME | SPECIAL);
+public static final ElementName LINE = new ElementName("line", "line",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGLineElement,
+TreeBuilder.OTHER);
+public static final ElementName MARQUEE = new ElementName("marquee", "marquee",
+// CPPONLY: NS_NewHTMLMarqueeElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MARQUEE_OR_APPLET | SPECIAL | SCOPING);
+public static final ElementName POLYLINE = new ElementName("polyline", "polyline",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGPolylineElement,
+TreeBuilder.OTHER);
+public static final ElementName PICTURE = new ElementName("picture", "picture",
+// CPPONLY: NS_NewHTMLPictureElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName SOURCE = new ElementName("source", "source",
+// CPPONLY: NS_NewHTMLSourceElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.PARAM_OR_SOURCE_OR_TRACK);
+public static final ElementName STRIKE = new ElementName("strike", "strike",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName STYLE = new ElementName("style", "style",
+// CPPONLY: NS_NewHTMLStyleElement,
+// CPPONLY: NS_NewSVGStyleElement,
+TreeBuilder.STYLE | SPECIAL);
+public static final ElementName TABLE = new ElementName("table", "table",
+// CPPONLY: NS_NewHTMLTableElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TABLE | SPECIAL | FOSTER_PARENTING | SCOPING);
+public static final ElementName TITLE = new ElementName("title", "title",
+// CPPONLY: NS_NewHTMLTitleElement,
+// CPPONLY: NS_NewSVGTitleElement,
+TreeBuilder.TITLE | SPECIAL | SCOPING_AS_SVG);
+public static final ElementName TIME = new ElementName("time", "time",
+// CPPONLY: NS_NewHTMLTimeElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName TEMPLATE = new ElementName("template", "template",
+// CPPONLY: NS_NewHTMLTemplateElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TEMPLATE | SPECIAL | SCOPING);
+public static final ElementName ALTGLYPHDEF = new ElementName("altglyphdef", "altGlyphDef",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName GLYPHREF = new ElementName("glyphref", "glyphRef",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName DIALOG = new ElementName("dialog", "dialog",
+// CPPONLY: NS_NewHTMLDialogElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName FEFUNCG = new ElementName("fefuncg", "feFuncG",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEFuncGElement,
+TreeBuilder.OTHER);
+public static final ElementName FEDIFFUSELIGHTING = new ElementName("fediffuselighting", "feDiffuseLighting",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEDiffuseLightingElement,
+TreeBuilder.OTHER);
+public static final ElementName FESPECULARLIGHTING = new ElementName("fespecularlighting", "feSpecularLighting",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFESpecularLightingElement,
+TreeBuilder.OTHER);
+public static final ElementName LISTING = new ElementName("listing", "listing",
+// CPPONLY: NS_NewHTMLPreElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.PRE_OR_LISTING | SPECIAL);
+public static final ElementName STRONG = new ElementName("strong", "strong",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName ALTGLYPH = new ElementName("altglyph", "altGlyph",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName CLIPPATH = new ElementName("clippath", "clipPath",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGClipPathElement,
+TreeBuilder.OTHER);
+public static final ElementName MGLYPH = new ElementName("mglyph", "mglyph",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MGLYPH_OR_MALIGNMARK);
+public static final ElementName MATH = new ElementName("math", "math",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MATH);
+public static final ElementName MPATH = new ElementName("mpath", "mpath",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGMPathElement,
+TreeBuilder.OTHER);
+public static final ElementName PATH = new ElementName("path", "path",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGPathElement,
+TreeBuilder.OTHER);
+public static final ElementName TH = new ElementName("th", "th",
+// CPPONLY: NS_NewHTMLTableCellElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG);
+public static final ElementName SWITCH = new ElementName("switch", "switch",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGSwitchElement,
+TreeBuilder.OTHER);
+public static final ElementName TEXTPATH = new ElementName("textpath", "textPath",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGTextPathElement,
+TreeBuilder.OTHER);
+public static final ElementName LI = new ElementName("li", "li",
+// CPPONLY: NS_NewHTMLLIElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.LI | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName MI = new ElementName("mi", "mi",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+public static final ElementName LINK = new ElementName("link", "link",
+// CPPONLY: NS_NewHTMLLinkElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL);
+public static final ElementName MARK = new ElementName("mark", "mark",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName MALIGNMARK = new ElementName("malignmark", "malignmark",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MGLYPH_OR_MALIGNMARK);
+public static final ElementName MASK = new ElementName("mask", "mask",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGMaskElement,
+TreeBuilder.OTHER);
+public static final ElementName TRACK = new ElementName("track", "track",
+// CPPONLY: NS_NewHTMLTrackElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.PARAM_OR_SOURCE_OR_TRACK | SPECIAL);
+public static final ElementName DL = new ElementName("dl", "dl",
+// CPPONLY: NS_NewHTMLSharedListElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.UL_OR_OL_OR_DL | SPECIAL);
+public static final ElementName HTML = new ElementName("html", "html",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.HTML | SPECIAL | SCOPING | OPTIONAL_END_TAG);
+public static final ElementName OL = new ElementName("ol", "ol",
+// CPPONLY: NS_NewHTMLSharedListElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.UL_OR_OL_OR_DL | SPECIAL);
+public static final ElementName LABEL = new ElementName("label", "label",
+// CPPONLY: NS_NewHTMLLabelElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName UL = new ElementName("ul", "ul",
+// CPPONLY: NS_NewHTMLSharedListElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.UL_OR_OL_OR_DL | SPECIAL);
+public static final ElementName SMALL = new ElementName("small", "small",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName SYMBOL = new ElementName("symbol", "symbol",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGSymbolElement,
+TreeBuilder.OTHER);
+public static final ElementName ALTGLYPHITEM = new ElementName("altglyphitem", "altGlyphItem",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName ANIMATETRANSFORM = new ElementName("animatetransform", "animateTransform",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGAnimateTransformElement,
+TreeBuilder.OTHER);
+public static final ElementName ACRONYM = new ElementName("acronym", "acronym",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName EM = new ElementName("em", "em",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName FORM = new ElementName("form", "form",
+// CPPONLY: NS_NewHTMLFormElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.FORM | SPECIAL);
+public static final ElementName PARAM = new ElementName("param", "param",
+// CPPONLY: NS_NewHTMLSharedElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.PARAM_OR_SOURCE_OR_TRACK | SPECIAL);
+public static final ElementName ANIMATEMOTION = new ElementName("animatemotion", "animateMotion",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGAnimateMotionElement,
+TreeBuilder.OTHER);
+public static final ElementName BUTTON = new ElementName("button", "button",
+// CPPONLY: NS_NewHTMLButtonElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.BUTTON | SPECIAL);
+public static final ElementName CAPTION = new ElementName("caption", "caption",
+// CPPONLY: NS_NewHTMLTableCaptionElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.CAPTION | SPECIAL | SCOPING);
+public static final ElementName FIGCAPTION = new ElementName("figcaption", "figcaption",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName MN = new ElementName("mn", "mn",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+public static final ElementName KEYGEN = new ElementName("keygen", "keygen",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.KEYGEN | SPECIAL);
+public static final ElementName MAIN = new ElementName("main", "main",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName OPTION = new ElementName("option", "option",
+// CPPONLY: NS_NewHTMLOptionElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OPTION | OPTIONAL_END_TAG);
+public static final ElementName POLYGON = new ElementName("polygon", "polygon",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGPolygonElement,
+TreeBuilder.OTHER);
+public static final ElementName PATTERN = new ElementName("pattern", "pattern",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGPatternElement,
+TreeBuilder.OTHER);
+public static final ElementName SPAN = new ElementName("span", "span",
+// CPPONLY: NS_NewHTMLSpanElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+public static final ElementName SECTION = new ElementName("section", "section",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName TSPAN = new ElementName("tspan", "tspan",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGTSpanElement,
+TreeBuilder.OTHER);
+public static final ElementName AUDIO = new ElementName("audio", "audio",
+// CPPONLY: NS_NewHTMLAudioElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName MO = new ElementName("mo", "mo",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+public static final ElementName VIDEO = new ElementName("video", "video",
+// CPPONLY: NS_NewHTMLVideoElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName COLGROUP = new ElementName("colgroup", "colgroup",
+// CPPONLY: NS_NewHTMLTableColElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.COLGROUP | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName FEDISPLACEMENTMAP = new ElementName("fedisplacementmap", "feDisplacementMap",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEDisplacementMapElement,
+TreeBuilder.OTHER);
+public static final ElementName HGROUP = new ElementName("hgroup", "hgroup",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName RP = new ElementName("rp", "rp",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RT_OR_RP | OPTIONAL_END_TAG);
+public static final ElementName OPTGROUP = new ElementName("optgroup", "optgroup",
+// CPPONLY: NS_NewHTMLOptGroupElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OPTGROUP | OPTIONAL_END_TAG);
+public static final ElementName SAMP = new ElementName("samp", "samp",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName STOP = new ElementName("stop", "stop",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGStopElement,
+TreeBuilder.OTHER);
+public static final ElementName BR = new ElementName("br", "br",
+// CPPONLY: NS_NewHTMLBRElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.BR | SPECIAL);
+public static final ElementName ABBR = new ElementName("abbr", "abbr",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName ANIMATECOLOR = new ElementName("animatecolor", "animateColor",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName CENTER = new ElementName("center", "center",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+public static final ElementName HR = new ElementName("hr", "hr",
+// CPPONLY: NS_NewHTMLHRElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.HR | SPECIAL);
+public static final ElementName FEFUNCR = new ElementName("fefuncr", "feFuncR",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEFuncRElement,
+TreeBuilder.OTHER);
+public static final ElementName FECOMPONENTTRANSFER = new ElementName("fecomponenttransfer", "feComponentTransfer",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEComponentTransferElement,
+TreeBuilder.OTHER);
+public static final ElementName FILTER = new ElementName("filter", "filter",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFilterElement,
+TreeBuilder.OTHER);
+public static final ElementName FOOTER = new ElementName("footer", "footer",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName FEGAUSSIANBLUR = new ElementName("fegaussianblur", "feGaussianBlur",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEGaussianBlurElement,
+TreeBuilder.OTHER);
+public static final ElementName HEADER = new ElementName("header", "header",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName MARKER = new ElementName("marker", "marker",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGMarkerElement,
+TreeBuilder.OTHER);
+public static final ElementName METER = new ElementName("meter", "meter",
+// CPPONLY: NS_NewHTMLMeterElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName NOBR = new ElementName("nobr", "nobr",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.NOBR);
+public static final ElementName TR = new ElementName("tr", "tr",
+// CPPONLY: NS_NewHTMLTableRowElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TR | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG);
+public static final ElementName ADDRESS = new ElementName("address", "address",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName CANVAS = new ElementName("canvas", "canvas",
+// CPPONLY: NS_NewHTMLCanvasElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName DEFS = new ElementName("defs", "defs",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGDefsElement,
+TreeBuilder.OTHER);
+public static final ElementName DETAILS = new ElementName("details", "details",
+// CPPONLY: NS_NewHTMLDetailsElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName MS = new ElementName("ms", "ms",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+public static final ElementName NOFRAMES = new ElementName("noframes", "noframes",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.NOFRAMES | SPECIAL);
+public static final ElementName PROGRESS = new ElementName("progress", "progress",
+// CPPONLY: NS_NewHTMLProgressElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName DT = new ElementName("dt", "dt",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.DD_OR_DT | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName APPLET = new ElementName("applet", "applet",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MARQUEE_OR_APPLET | SPECIAL | SCOPING);
+public static final ElementName BASEFONT = new ElementName("basefont", "basefont",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL);
+public static final ElementName DATALIST = new ElementName("datalist", "datalist",
+// CPPONLY: NS_NewHTMLDataListElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName FOREIGNOBJECT = new ElementName("foreignobject", "foreignObject",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGForeignObjectElement,
+TreeBuilder.FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG);
+public static final ElementName FIELDSET = new ElementName("fieldset", "fieldset",
+// CPPONLY: NS_NewHTMLFieldSetElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.FIELDSET | SPECIAL);
+public static final ElementName FRAMESET = new ElementName("frameset", "frameset",
+// CPPONLY: NS_NewHTMLFrameSetElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.FRAMESET | SPECIAL);
+public static final ElementName FEOFFSET = new ElementName("feoffset", "feOffset",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEOffsetElement,
+TreeBuilder.OTHER);
+public static final ElementName FESPOTLIGHT = new ElementName("fespotlight", "feSpotLight",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFESpotLightElement,
+TreeBuilder.OTHER);
+public static final ElementName FEPOINTLIGHT = new ElementName("fepointlight", "fePointLight",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEPointLightElement,
+TreeBuilder.OTHER);
+public static final ElementName FEDISTANTLIGHT = new ElementName("fedistantlight", "feDistantLight",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEDistantLightElement,
+TreeBuilder.OTHER);
+public static final ElementName FONT = new ElementName("font", "font",
+// CPPONLY: NS_NewHTMLFontElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.FONT);
+public static final ElementName INPUT = new ElementName("input", "input",
+// CPPONLY: NS_NewHTMLInputElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.INPUT | SPECIAL);
+public static final ElementName LINEARGRADIENT = new ElementName("lineargradient", "linearGradient",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGLinearGradientElement,
+TreeBuilder.OTHER);
+public static final ElementName MTEXT = new ElementName("mtext", "mtext",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+public static final ElementName NOSCRIPT = new ElementName("noscript", "noscript",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.NOSCRIPT | SPECIAL);
+public static final ElementName RT = new ElementName("rt", "rt",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RT_OR_RP | OPTIONAL_END_TAG);
+public static final ElementName OBJECT = new ElementName("object", "object",
+// CPPONLY: NS_NewHTMLObjectElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OBJECT | SPECIAL | SCOPING);
+public static final ElementName OUTPUT = new ElementName("output", "output",
+// CPPONLY: NS_NewHTMLOutputElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OUTPUT);
+public static final ElementName PLAINTEXT = new ElementName("plaintext", "plaintext",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.PLAINTEXT | SPECIAL);
+public static final ElementName TT = new ElementName("tt", "tt",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+public static final ElementName RECT = new ElementName("rect", "rect",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGRectElement,
+TreeBuilder.OTHER);
+public static final ElementName RADIALGRADIENT = new ElementName("radialgradient", "radialGradient",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGRadialGradientElement,
+TreeBuilder.OTHER);
+public static final ElementName SELECT = new ElementName("select", "select",
+// CPPONLY: NS_NewHTMLSelectElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.SELECT | SPECIAL);
+public static final ElementName SLOT = new ElementName("slot", "slot",
+// CPPONLY: NS_NewHTMLSlotElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.OTHER);
+public static final ElementName SCRIPT = new ElementName("script", "script",
+// CPPONLY: NS_NewHTMLScriptElement,
+// CPPONLY: NS_NewSVGScriptElement,
+TreeBuilder.SCRIPT | SPECIAL);
+public static final ElementName TFOOT = new ElementName("tfoot", "tfoot",
+// CPPONLY: NS_NewHTMLTableSectionElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG);
+public static final ElementName TEXT = new ElementName("text", "text",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGTextElement,
+TreeBuilder.OTHER);
+public static final ElementName MENU = new ElementName("menu", "menu",
+// CPPONLY: NS_NewHTMLMenuElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+public static final ElementName FEDROPSHADOW = new ElementName("fedropshadow", "feDropShadow",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEDropShadowElement,
+TreeBuilder.OTHER);
+public static final ElementName VIEW = new ElementName("view", "view",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGViewElement,
+TreeBuilder.OTHER);
+public static final ElementName FECOLORMATRIX = new ElementName("fecolormatrix", "feColorMatrix",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEColorMatrixElement,
+TreeBuilder.OTHER);
+public static final ElementName FECONVOLVEMATRIX = new ElementName("feconvolvematrix", "feConvolveMatrix",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEConvolveMatrixElement,
+TreeBuilder.OTHER);
+public static final ElementName BODY = new ElementName("body", "body",
+// CPPONLY: NS_NewHTMLBodyElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.BODY | SPECIAL | OPTIONAL_END_TAG);
+public static final ElementName FEMORPHOLOGY = new ElementName("femorphology", "feMorphology",
+// CPPONLY: NS_NewHTMLUnknownElement,
+// CPPONLY: NS_NewSVGFEMorphologyElement,
+TreeBuilder.OTHER);
+public static final ElementName RUBY = new ElementName("ruby", "ruby",
+// CPPONLY: NS_NewHTMLElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+public static final ElementName SUMMARY = new ElementName("summary", "summary",
+// CPPONLY: NS_NewHTMLSummaryElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY | SPECIAL);
+public static final ElementName TBODY = new ElementName("tbody", "tbody",
+// CPPONLY: NS_NewHTMLTableSectionElement,
+// CPPONLY: NS_NewSVGUnknownElement,
+TreeBuilder.TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG);
+private final static @NoLength ElementName[] ELEMENT_NAMES = {
+MN,
+CITE,
+FRAMESET,
+H1,
+CLIPPATH,
+METER,
+RADIALGRADIENT,
+B,
+BGSOUND,
+SOURCE,
+HTML,
+OPTGROUP,
+NOFRAMES,
+MTEXT,
+VIEW,
+DIV,
+G,
+FEFUNCA,
+THEAD,
+FIGURE,
+GLYPHREF,
+LI,
+ACRONYM,
+TSPAN,
+FEFUNCR,
+CANVAS,
+BASEFONT,
+FEDISTANTLIGHT,
+OUTPUT,
+TFOOT,
+FEMORPHOLOGY,
+COL,
+MAP,
+SUP,
+P,
+H5,
+FEFUNCB,
+HEAD,
+BASE,
+FEIMAGE,
+LINE,
+TITLE,
+FESPECULARLIGHTING,
+PATH,
+MALIGNMARK,
+SMALL,
+ANIMATEMOTION,
+POLYGON,
+COLGROUP,
+ABBR,
+FEGAUSSIANBLUR,
+TR,
+DETAILS,
+DT,
+FOREIGNOBJECT,
+FESPOTLIGHT,
+INPUT,
+RT,
+TT,
+SLOT,
+MENU,
+FECONVOLVEMATRIX,
+SUMMARY,
+BDI,
+DFN,
+INS,
+PRE,
+SUB,
+USE,
+XMP,
+S,
+H3,
+AREA,
+META,
+DESC,
+FEBLEND,
+NOEMBED,
+ARTICLE,
+CODE,
+FETURBULENCE,
+FETILE,
+IMAGE,
+POLYLINE,
+STYLE,
+TEMPLATE,
+FEFUNCG,
+STRONG,
+MATH,
+SWITCH,
+LINK,
+TRACK,
+LABEL,
+ALTGLYPHITEM,
+FORM,
+CAPTION,
+MAIN,
+SPAN,
+MO,
+HGROUP,
+STOP,
+CENTER,
+FILTER,
+MARKER,
+NOBR,
+ADDRESS,
+DEFS,
+MS,
+PROGRESS,
+APPLET,
+DATALIST,
+FIELDSET,
+FEOFFSET,
+FEPOINTLIGHT,
+FONT,
+LINEARGRADIENT,
+NOSCRIPT,
+OBJECT,
+PLAINTEXT,
+RECT,
+SELECT,
+SCRIPT,
+TEXT,
+FEDROPSHADOW,
+FECOLORMATRIX,
+BODY,
+RUBY,
+TBODY,
+BIG,
+BDO,
+DEL,
+DIR,
+IMG,
+KBD,
+NAV,
+A,
+RTC,
+SVG,
+SET,
+VAR,
+WBR,
+I,
+Q,
+U,
+H2,
+H4,
+H6,
+DATA,
+METADATA,
+TEXTAREA,
+RB,
+DD,
+EMBED,
+FEFLOOD,
+LEGEND,
+TD,
+ASIDE,
+ANIMATE,
+BLOCKQUOTE,
+CIRCLE,
+ELLIPSE,
+FEMERGENODE,
+FEMERGE,
+FRAME,
+FECOMPOSITE,
+IFRAME,
+MARQUEE,
+PICTURE,
+STRIKE,
+TABLE,
+TIME,
+ALTGLYPHDEF,
+DIALOG,
+FEDIFFUSELIGHTING,
+LISTING,
+ALTGLYPH,
+MGLYPH,
+MPATH,
+TH,
+TEXTPATH,
+MI,
+MARK,
+MASK,
+DL,
+OL,
+UL,
+SYMBOL,
+ANIMATETRANSFORM,
+EM,
+PARAM,
+BUTTON,
+FIGCAPTION,
+KEYGEN,
+OPTION,
+PATTERN,
+SECTION,
+AUDIO,
+VIDEO,
+FEDISPLACEMENTMAP,
+RP,
+SAMP,
+BR,
+ANIMATECOLOR,
+HR,
+FECOMPONENTTRANSFER,
+FOOTER,
+HEADER,
+};
+private final static int[] ELEMENT_HASHES = {
+1902641154,
+1748359220,
+2001349720,
+876609538,
+1798686984,
+1971465813,
+2007781534,
+59768833,
+1730965751,
+1756474198,
+1868312196,
+1939219752,
+1988763672,
+2005324101,
+2060065124,
+52490899,
+62390273,
+1682547543,
+1740181637,
+1749905526,
+1766992520,
+1818230786,
+1881613047,
+1907959605,
+1967760215,
+1982935782,
+1999397992,
+2001392798,
+2006329158,
+2008851557,
+2085266636,
+51961587,
+57206291,
+60352339,
+67108865,
+943718402,
+1699324759,
+1733890180,
+1747814436,
+1749715159,
+1752979652,
+1757146773,
+1783388498,
+1805502724,
+1854228698,
+1874053333,
+1898223949,
+1906087319,
+1932928296,
+1965115924,
+1968053806,
+1973420034,
+1983633431,
+1998585858,
+2001309869,
+2001392795,
+2003183333,
+2005925890,
+2006974466,
+2008325940,
+2021937364,
+2068523856,
+2092255447,
+51435587,
+52486755,
+55110883,
+58773795,
+60345171,
+61395251,
+62973651,
+68681729,
+910163970,
+1679960596,
+1686491348,
+1715310660,
+1733054663,
+1737099991,
+1747176599,
+1748100148,
+1749656156,
+1749801286,
+1751288021,
+1755076808,
+1756625221,
+1757268168,
+1783210839,
+1790207270,
+1803929812,
+1806806678,
+1853642948,
+1857653029,
+1870268949,
+1881288348,
+1884120164,
+1899272519,
+1904412884,
+1907435316,
+1919418370,
+1935549734,
+1941221172,
+1966223078,
+1967795910,
+1971461414,
+1971938532,
+1982173479,
+1983533124,
+1986527234,
+1990037800,
+1998724870,
+2000525512,
+2001349704,
+2001349736,
+2001392796,
+2001495140,
+2004635806,
+2005719336,
+2006028454,
+2006896969,
+2007601444,
+2008125638,
+2008340774,
+2008994116,
+2051837468,
+2068523853,
+2083120164,
+2091479332,
+2092557349,
+51434643,
+51438659,
+52485715,
+52488851,
+55104723,
+56151587,
+57733651,
+59244545,
+59821379,
+60347747,
+60354131,
+61925907,
+62450211,
+63438849,
+67633153,
+69730305,
+893386754,
+926941186,
+960495618,
+1681770564,
+1686489160,
+1689922072,
+1703936002,
+1730150402,
+1732381397,
+1733076167,
+1736200310,
+1738539010,
+1747048757,
+1747306711,
+1747838298,
+1748225318,
+1749395095,
+1749673195,
+1749723735,
+1749813541,
+1749932347,
+1751386406,
+1753362711,
+1755148615,
+1756600614,
+1757137429,
+1757157700,
+1763839627,
+1782357526,
+1783388497,
+1786534215,
+1797585096,
+1803876550,
+1803929861,
+1805647874,
+1807599880,
+1818755074,
+1854228692,
+1854245076,
+1864368130,
+1870135298,
+1873281026,
+1874102998,
+1881498736,
+1881669634,
+1889085973,
+1898753862,
+1900845386,
+1903302038,
+1905563974,
+1906135367,
+1907661127,
+1914900309,
+1925844629,
+1934172497,
+1938817026,
+1941178676,
+1963982850,
+1965334268,
+1967128578,
+1967788867,
+1967795958,
+1968836118,
+};
+}
diff --git a/parser/html/javasrc/Portability.java b/parser/html/javasrc/Portability.java
new file mode 100644
index 0000000000..1d65894a86
--- /dev/null
+++ b/parser/html/javasrc/Portability.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2008-2015 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.impl;
+
+import org.xml.sax.SAXException;
+
+import nu.validator.htmlparser.annotation.Literal;
+import nu.validator.htmlparser.annotation.Local;
+import nu.validator.htmlparser.annotation.NoLength;
+import nu.validator.htmlparser.common.Interner;
+
+public final class Portability {
+
+ public static int checkedAdd(int a, int b) throws SAXException {
+ // This can't be translated code, because in C++ signed integer overflow is UB, so the below code would be wrong.
+ assert a >= 0;
+ assert b >= 0;
+ int sum = a + b;
+ if (sum < a || sum < b) {
+ throw new SAXException("Integer overflow");
+ }
+ return sum;
+ }
+
+ // Allocating methods
+
+ /**
+ * Allocates a new local name object. In C++, the refcount must be set up in such a way that
+ * calling <code>releaseLocal</code> on the return value balances the refcount set by this method.
+ */
+ public static @Local String newLocalNameFromBuffer(@NoLength char[] buf, int length, Interner interner) {
+ return new String(buf, 0, length).intern();
+ }
+
+ public static String newStringFromBuffer(@NoLength char[] buf, int offset, int length
+ // CPPONLY: , TreeBuilder treeBuilder, boolean maybeAtomize
+ ) {
+ return new String(buf, offset, length);
+ }
+
+ public static String newEmptyString() {
+ return "";
+ }
+
+ public static String newStringFromLiteral(@Literal String literal) {
+ return literal;
+ }
+
+ public static String newStringFromString(String string) {
+ return string;
+ }
+
+ // XXX get rid of this
+ public static char[] newCharArrayFromLocal(@Local String local) {
+ return local.toCharArray();
+ }
+
+ public static char[] newCharArrayFromString(String string) {
+ return string.toCharArray();
+ }
+
+ // Deallocation methods
+
+ public static void releaseString(String str) {
+ // No-op in Java
+ }
+
+ // Comparison methods
+
+ public static boolean localEqualsBuffer(@Local String local, @NoLength char[] buf, int length) {
+ if (local.length() != length) {
+ return false;
+ }
+ for (int i = 0; i < length; i++) {
+ if (local.charAt(i) != buf[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(@Literal String lowerCaseLiteral,
+ String string) {
+ if (string == null) {
+ return false;
+ }
+ if (lowerCaseLiteral.length() > string.length()) {
+ return false;
+ }
+ for (int i = 0; i < lowerCaseLiteral.length(); i++) {
+ char c0 = lowerCaseLiteral.charAt(i);
+ char c1 = string.charAt(i);
+ if (c1 >= 'A' && c1 <= 'Z') {
+ c1 += 0x20;
+ }
+ if (c0 != c1) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean lowerCaseLiteralEqualsIgnoreAsciiCaseString(@Literal String lowerCaseLiteral,
+ String string) {
+ if (string == null) {
+ return false;
+ }
+ if (lowerCaseLiteral.length() != string.length()) {
+ return false;
+ }
+ for (int i = 0; i < lowerCaseLiteral.length(); i++) {
+ char c0 = lowerCaseLiteral.charAt(i);
+ char c1 = string.charAt(i);
+ if (c1 >= 'A' && c1 <= 'Z') {
+ c1 += 0x20;
+ }
+ if (c0 != c1) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean literalEqualsString(@Literal String literal, String string) {
+ return literal.equals(string);
+ }
+
+ public static boolean stringEqualsString(String one, String other) {
+ return one.equals(other);
+ }
+
+ public static void delete(Object o) {
+
+ }
+
+ public static void deleteArray(Object o) {
+
+ }
+}
diff --git a/parser/html/javasrc/README.txt b/parser/html/javasrc/README.txt
new file mode 100644
index 0000000000..4555969cad
--- /dev/null
+++ b/parser/html/javasrc/README.txt
@@ -0,0 +1,6 @@
+The .java files in this directory were placed here by the Java-to-C++
+translator that lives in parser/html/java/translator. Together they represent
+a snapshot of the Java code that was translated to produce the corresponding
+.h and .cpp files in the parent directory. Changing these .java files is not
+worthwhile, as they will just be overwritten by the next translation. See
+parser/html/java/README.txt for information about performing the translation.
diff --git a/parser/html/javasrc/StackNode.java b/parser/html/javasrc/StackNode.java
new file mode 100644
index 0000000000..cfd570724e
--- /dev/null
+++ b/parser/html/javasrc/StackNode.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2007-2011 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.impl;
+
+import nu.validator.htmlparser.annotation.Inline;
+import nu.validator.htmlparser.annotation.Local;
+import nu.validator.htmlparser.annotation.NsUri;
+
+final class StackNode<T> {
+ // Index where this stack node is stored in the tree builder's list of stack nodes.
+ // A value of -1 indicates that the stack node is not owned by a tree builder and
+ // must delete itself when its refcount reaches 0.
+ final int idxInTreeBuilder;
+
+ int flags;
+
+ @Local String name;
+
+ @Local String popName;
+
+ @NsUri String ns;
+
+ T node;
+
+ // Only used on the list of formatting elements
+ HtmlAttributes attributes;
+
+ private int refcount = 0;
+
+ /*
+ * Only valid for formatting elements
+ */
+ // CPPONLY: private @HtmlCreator Object htmlCreator;
+
+ // [NOCPP[
+
+ private TaintableLocatorImpl locator;
+
+ public TaintableLocatorImpl getLocator() {
+ return locator;
+ }
+
+ // ]NOCPP]
+
+ @Inline public int getFlags() {
+ return flags;
+ }
+
+ public int getGroup() {
+ return flags & ElementName.GROUP_MASK;
+ }
+
+ public boolean isScoping() {
+ return (flags & ElementName.SCOPING) != 0;
+ }
+
+ public boolean isSpecial() {
+ return (flags & ElementName.SPECIAL) != 0;
+ }
+
+ public boolean isFosterParenting() {
+ return (flags & ElementName.FOSTER_PARENTING) != 0;
+ }
+
+ public boolean isHtmlIntegrationPoint() {
+ return (flags & ElementName.HTML_INTEGRATION_POINT) != 0;
+ }
+
+ // [NOCPP[
+
+ public boolean isOptionalEndTag() {
+ return (flags & ElementName.OPTIONAL_END_TAG) != 0;
+ }
+
+ // ]NOCPP]
+
+ StackNode(int idxInTreeBuilder) {
+ this.idxInTreeBuilder = idxInTreeBuilder;
+ this.flags = 0;
+ this.name = null;
+ this.popName = null;
+ // CPPONLY: this.ns = 0;
+ this.node = null;
+ this.attributes = null;
+ this.refcount = 0;
+ // CPPONLY: this.htmlCreator = null;
+ }
+
+ // CPPONLY: public @HtmlCreator Object getHtmlCreator() {
+ // CPPONLY: return htmlCreator;
+ // CPPONLY: }
+
+ /**
+ * Setter for copying. This doesn't take another <code>StackNode</code>
+ * because in C++ the caller is responsible for reobtaining the local names
+ * from another interner.
+ *
+ * @param flags
+ * @param ns
+ * @param name
+ * @param node
+ * @param popName
+ * @param attributes
+ */
+ void setValues(int flags, @NsUri String ns, @Local String name, T node,
+ @Local String popName, HtmlAttributes attributes,
+ // CPPONLY: @HtmlCreator Object htmlCreator
+ // [NOCPP[
+ TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ assert isUnused();
+ this.flags = flags;
+ this.name = name;
+ this.popName = popName;
+ this.ns = ns;
+ this.node = node;
+ this.attributes = attributes;
+ this.refcount = 1;
+ /*
+ * Need to track creator for formatting elements when copying.
+ */
+ // CPPONLY: this.htmlCreator = htmlCreator;
+ // [NOCPP[
+ this.locator = locator;
+ // ]NOCPP]
+ }
+
+ /**
+ * Short hand for well-known HTML elements.
+ *
+ * @param elementName
+ * @param node
+ */
+ void setValues(ElementName elementName, T node
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ assert isUnused();
+ this.flags = elementName.getFlags();
+ this.name = elementName.getName();
+ this.popName = elementName.getName();
+ this.ns = "http://www.w3.org/1999/xhtml";
+ this.node = node;
+ this.attributes = null;
+ this.refcount = 1;
+ assert elementName.isInterned() : "Don't use this constructor for custom elements.";
+ /*
+ * Not used for formatting elements, so no need to track creator.
+ */
+ // CPPONLY: this.htmlCreator = null;
+ // [NOCPP[
+ this.locator = locator;
+ // ]NOCPP]
+ }
+
+ /**
+ * Setter for HTML formatting elements.
+ *
+ * @param elementName
+ * @param node
+ * @param attributes
+ */
+ void setValues(ElementName elementName, T node, HtmlAttributes attributes
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ assert isUnused();
+ this.flags = elementName.getFlags();
+ this.name = elementName.getName();
+ this.popName = elementName.getName();
+ this.ns = "http://www.w3.org/1999/xhtml";
+ this.node = node;
+ this.attributes = attributes;
+ this.refcount = 1;
+ assert elementName.isInterned() : "Don't use this constructor for custom elements.";
+ /*
+ * Need to track creator for formatting elements in order to be able
+ * to clone them.
+ */
+ // CPPONLY: this.htmlCreator = elementName.getHtmlCreator();
+ // [NOCPP[
+ this.locator = locator;
+ // ]NOCPP]
+ }
+
+ /**
+ * The common-case HTML setter.
+ *
+ * @param elementName
+ * @param node
+ * @param popName
+ */
+ void setValues(ElementName elementName, T node, @Local String popName
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ assert isUnused();
+ this.flags = elementName.getFlags();
+ this.name = elementName.getName();
+ this.popName = popName;
+ this.ns = "http://www.w3.org/1999/xhtml";
+ this.node = node;
+ this.attributes = null;
+ this.refcount = 1;
+ /*
+ * Not used for formatting elements, so no need to track creator.
+ */
+ // CPPONLY: this.htmlCreator = null;
+ // [NOCPP[
+ this.locator = locator;
+ // ]NOCPP]
+ }
+
+ /**
+ * Setter for SVG elements. Note that the order of the arguments is
+ * what distinguishes this from the HTML setter. This is ugly, but
+ * AFAICT the least disruptive way to make this work with Java's generics
+ * and without unnecessary branches. :-(
+ *
+ * @param elementName
+ * @param popName
+ * @param node
+ */
+ void setValues(ElementName elementName, @Local String popName, T node
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ assert isUnused();
+ this.flags = prepareSvgFlags(elementName.getFlags());
+ this.name = elementName.getName();
+ this.popName = popName;
+ this.ns = "http://www.w3.org/2000/svg";
+ this.node = node;
+ this.attributes = null;
+ this.refcount = 1;
+ /*
+ * Not used for formatting elements, so no need to track creator.
+ */
+ // CPPONLY: this.htmlCreator = null;
+ // [NOCPP[
+ this.locator = locator;
+ // ]NOCPP]
+ }
+
+ /**
+ * Setter for MathML.
+ *
+ * @param elementName
+ * @param node
+ * @param popName
+ * @param markAsIntegrationPoint
+ */
+ void setValues(ElementName elementName, T node, @Local String popName,
+ boolean markAsIntegrationPoint
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ assert isUnused();
+ this.flags = prepareMathFlags(elementName.getFlags(),
+ markAsIntegrationPoint);
+ this.name = elementName.getName();
+ this.popName = popName;
+ this.ns = "http://www.w3.org/1998/Math/MathML";
+ this.node = node;
+ this.attributes = null;
+ this.refcount = 1;
+ /*
+ * Not used for formatting elements, so no need to track creator.
+ */
+ // CPPONLY: this.htmlCreator = null;
+ // [NOCPP[
+ this.locator = locator;
+ // ]NOCPP]
+ }
+
+ private static int prepareSvgFlags(int flags) {
+ flags &= ~(ElementName.FOSTER_PARENTING | ElementName.SCOPING
+ | ElementName.SPECIAL | ElementName.OPTIONAL_END_TAG);
+ if ((flags & ElementName.SCOPING_AS_SVG) != 0) {
+ flags |= (ElementName.SCOPING | ElementName.SPECIAL | ElementName.HTML_INTEGRATION_POINT);
+ }
+ return flags;
+ }
+
+ private static int prepareMathFlags(int flags,
+ boolean markAsIntegrationPoint) {
+ flags &= ~(ElementName.FOSTER_PARENTING | ElementName.SCOPING
+ | ElementName.SPECIAL | ElementName.OPTIONAL_END_TAG);
+ if ((flags & ElementName.SCOPING_AS_MATHML) != 0) {
+ flags |= (ElementName.SCOPING | ElementName.SPECIAL);
+ }
+ if (markAsIntegrationPoint) {
+ flags |= ElementName.HTML_INTEGRATION_POINT;
+ }
+ return flags;
+ }
+
+ @SuppressWarnings("unused") private void destructor() {
+ // The translator adds refcount debug code here.
+ }
+
+ public void dropAttributes() {
+ attributes = null;
+ }
+
+ // [NOCPP[
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override public @Local String toString() {
+ return name;
+ }
+
+ // ]NOCPP]
+
+ public void retain() {
+ refcount++;
+ }
+
+ public void release(TreeBuilder<T> owningTreeBuilder) {
+ refcount--;
+ assert refcount >= 0;
+ if (refcount == 0) {
+ Portability.delete(attributes);
+ if (idxInTreeBuilder >= 0) {
+ owningTreeBuilder.notifyUnusedStackNode(idxInTreeBuilder);
+ } else {
+ assert owningTreeBuilder == null;
+ Portability.delete(this);
+ }
+ }
+ }
+
+ boolean isUnused() {
+ return refcount == 0;
+ }
+}
diff --git a/parser/html/javasrc/StateSnapshot.java b/parser/html/javasrc/StateSnapshot.java
new file mode 100644
index 0000000000..cba711f714
--- /dev/null
+++ b/parser/html/javasrc/StateSnapshot.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2009-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.impl;
+
+import nu.validator.htmlparser.annotation.Auto;
+
+
+public class StateSnapshot<T> implements TreeBuilderState<T> {
+
+ private final @Auto StackNode<T>[] stack;
+
+ private final @Auto StackNode<T>[] listOfActiveFormattingElements;
+
+ private final @Auto int[] templateModeStack;
+
+ private final T formPointer;
+
+ private final T headPointer;
+
+ private final int mode;
+
+ private final int originalMode;
+
+ private final boolean framesetOk;
+
+ private final boolean needToDropLF;
+
+ private final boolean quirks;
+
+ /**
+ * @param stack
+ * @param listOfActiveFormattingElements
+ * @param templateModeStack
+ * @param formPointer
+ * @param headPointer
+ * @param deepTreeSurrogateParent
+ * @param mode
+ * @param originalMode
+ * @param framesetOk
+ * @param needToDropLF
+ * @param quirks
+ */
+ StateSnapshot(StackNode<T>[] stack,
+ StackNode<T>[] listOfActiveFormattingElements, int[] templateModeStack, T formPointer,
+ T headPointer, int mode, int originalMode,
+ boolean framesetOk, boolean needToDropLF, boolean quirks) {
+ this.stack = stack;
+ this.listOfActiveFormattingElements = listOfActiveFormattingElements;
+ this.templateModeStack = templateModeStack;
+ this.formPointer = formPointer;
+ this.headPointer = headPointer;
+ this.mode = mode;
+ this.originalMode = originalMode;
+ this.framesetOk = framesetOk;
+ this.needToDropLF = needToDropLF;
+ this.quirks = quirks;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack()
+ */
+ @Override
+ public StackNode<T>[] getStack() {
+ return stack;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStack()
+ */
+ @Override
+ public int[] getTemplateModeStack() {
+ return templateModeStack;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElements()
+ */
+ @Override
+ public StackNode<T>[] getListOfActiveFormattingElements() {
+ return listOfActiveFormattingElements;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getFormPointer()
+ */
+ @Override
+ public T getFormPointer() {
+ return formPointer;
+ }
+
+ /**
+ * Returns the headPointer.
+ *
+ * @return the headPointer
+ */
+ @Override
+ public T getHeadPointer() {
+ return headPointer;
+ }
+
+ /**
+ * Returns the mode.
+ *
+ * @return the mode
+ */
+ @Override
+ public int getMode() {
+ return mode;
+ }
+
+ /**
+ * Returns the originalMode.
+ *
+ * @return the originalMode
+ */
+ @Override
+ public int getOriginalMode() {
+ return originalMode;
+ }
+
+ /**
+ * Returns the framesetOk.
+ *
+ * @return the framesetOk
+ */
+ @Override
+ public boolean isFramesetOk() {
+ return framesetOk;
+ }
+
+ /**
+ * Returns the needToDropLF.
+ *
+ * @return the needToDropLF
+ */
+ @Override
+ public boolean isNeedToDropLF() {
+ return needToDropLF;
+ }
+
+ /**
+ * Returns the quirks.
+ *
+ * @return the quirks
+ */
+ @Override
+ public boolean isQuirks() {
+ return quirks;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElementsLength()
+ */
+ @Override
+ public int getListOfActiveFormattingElementsLength() {
+ return listOfActiveFormattingElements.length;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getStackLength()
+ */
+ @Override
+ public int getStackLength() {
+ return stack.length;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength()
+ */
+ @Override
+ public int getTemplateModeStackLength() {
+ return templateModeStack.length;
+ }
+
+ @SuppressWarnings("unused") private void destructor() {
+ for (int i = 0; i < stack.length; i++) {
+ stack[i].release(null);
+ }
+ for (int i = 0; i < listOfActiveFormattingElements.length; i++) {
+ if (listOfActiveFormattingElements[i] != null) {
+ listOfActiveFormattingElements[i].release(null);
+ }
+ }
+ }
+}
diff --git a/parser/html/javasrc/Tokenizer.java b/parser/html/javasrc/Tokenizer.java
new file mode 100644
index 0000000000..a8047c7a71
--- /dev/null
+++ b/parser/html/javasrc/Tokenizer.java
@@ -0,0 +1,7636 @@
+/*
+ * Copyright (c) 2005-2007 Henri Sivonen
+ * Copyright (c) 2007-2017 Mozilla Foundation
+ * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla
+ * Foundation, and Opera Software ASA.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The comments following this one that use the same comment syntax as this
+ * comment are quotes from the WHATWG HTML 5 spec as of 2 June 2007
+ * amended as of June 18 2008 and May 31 2010.
+ * That document came with this statement:
+ * "© Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce and
+ * create derivative works of this document."
+ */
+
+package nu.validator.htmlparser.impl;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.ext.Locator2;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import nu.validator.htmlparser.annotation.Auto;
+import nu.validator.htmlparser.annotation.CharacterName;
+import nu.validator.htmlparser.annotation.Const;
+import nu.validator.htmlparser.annotation.Inline;
+import nu.validator.htmlparser.annotation.Local;
+import nu.validator.htmlparser.annotation.NoLength;
+import nu.validator.htmlparser.common.EncodingDeclarationHandler;
+import nu.validator.htmlparser.common.Interner;
+import nu.validator.htmlparser.common.TokenHandler;
+import nu.validator.htmlparser.common.XmlViolationPolicy;
+
+/**
+ * An implementation of
+ * https://html.spec.whatwg.org/multipage/syntax.html#tokenization
+ *
+ * This class implements the <code>Locator</code> interface. This is not an
+ * incidental implementation detail: Users of this class are encouraged to make
+ * use of the <code>Locator</code> nature.
+ *
+ * By default, the tokenizer may report data that XML 1.0 bans. The tokenizer
+ * can be configured to treat these conditions as fatal or to coerce the infoset
+ * to something that XML 1.0 allows.
+ *
+ * @version $Id$
+ * @author hsivonen
+ */
+public class Tokenizer implements Locator, Locator2 {
+
+ private static final int DATA_AND_RCDATA_MASK = ~1;
+
+ public static final int DATA = 0;
+
+ public static final int RCDATA = 1;
+
+ public static final int SCRIPT_DATA = 2;
+
+ public static final int RAWTEXT = 3;
+
+ public static final int SCRIPT_DATA_ESCAPED = 4;
+
+ public static final int ATTRIBUTE_VALUE_DOUBLE_QUOTED = 5;
+
+ public static final int ATTRIBUTE_VALUE_SINGLE_QUOTED = 6;
+
+ public static final int ATTRIBUTE_VALUE_UNQUOTED = 7;
+
+ public static final int PLAINTEXT = 8;
+
+ public static final int TAG_OPEN = 9;
+
+ public static final int CLOSE_TAG_OPEN = 10;
+
+ public static final int TAG_NAME = 11;
+
+ public static final int BEFORE_ATTRIBUTE_NAME = 12;
+
+ public static final int ATTRIBUTE_NAME = 13;
+
+ public static final int AFTER_ATTRIBUTE_NAME = 14;
+
+ public static final int BEFORE_ATTRIBUTE_VALUE = 15;
+
+ public static final int AFTER_ATTRIBUTE_VALUE_QUOTED = 16;
+
+ public static final int BOGUS_COMMENT = 17;
+
+ public static final int MARKUP_DECLARATION_OPEN = 18;
+
+ public static final int DOCTYPE = 19;
+
+ public static final int BEFORE_DOCTYPE_NAME = 20;
+
+ public static final int DOCTYPE_NAME = 21;
+
+ public static final int AFTER_DOCTYPE_NAME = 22;
+
+ public static final int BEFORE_DOCTYPE_PUBLIC_IDENTIFIER = 23;
+
+ public static final int DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED = 24;
+
+ public static final int DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED = 25;
+
+ public static final int AFTER_DOCTYPE_PUBLIC_IDENTIFIER = 26;
+
+ public static final int BEFORE_DOCTYPE_SYSTEM_IDENTIFIER = 27;
+
+ public static final int DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED = 28;
+
+ public static final int DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED = 29;
+
+ public static final int AFTER_DOCTYPE_SYSTEM_IDENTIFIER = 30;
+
+ public static final int BOGUS_DOCTYPE = 31;
+
+ public static final int COMMENT_START = 32;
+
+ public static final int COMMENT_START_DASH = 33;
+
+ public static final int COMMENT = 34;
+
+ public static final int COMMENT_END_DASH = 35;
+
+ public static final int COMMENT_END = 36;
+
+ public static final int COMMENT_END_BANG = 37;
+
+ public static final int NON_DATA_END_TAG_NAME = 38;
+
+ public static final int MARKUP_DECLARATION_HYPHEN = 39;
+
+ public static final int MARKUP_DECLARATION_OCTYPE = 40;
+
+ public static final int DOCTYPE_UBLIC = 41;
+
+ public static final int DOCTYPE_YSTEM = 42;
+
+ public static final int AFTER_DOCTYPE_PUBLIC_KEYWORD = 43;
+
+ public static final int BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS = 44;
+
+ public static final int AFTER_DOCTYPE_SYSTEM_KEYWORD = 45;
+
+ public static final int CONSUME_CHARACTER_REFERENCE = 46;
+
+ public static final int CONSUME_NCR = 47;
+
+ public static final int CHARACTER_REFERENCE_TAIL = 48;
+
+ public static final int HEX_NCR_LOOP = 49;
+
+ public static final int DECIMAL_NRC_LOOP = 50;
+
+ public static final int HANDLE_NCR_VALUE = 51;
+
+ public static final int HANDLE_NCR_VALUE_RECONSUME = 52;
+
+ public static final int CHARACTER_REFERENCE_HILO_LOOKUP = 53;
+
+ public static final int SELF_CLOSING_START_TAG = 54;
+
+ public static final int CDATA_START = 55;
+
+ public static final int CDATA_SECTION = 56;
+
+ public static final int CDATA_RSQB = 57;
+
+ public static final int CDATA_RSQB_RSQB = 58;
+
+ public static final int SCRIPT_DATA_LESS_THAN_SIGN = 59;
+
+ public static final int SCRIPT_DATA_ESCAPE_START = 60;
+
+ public static final int SCRIPT_DATA_ESCAPE_START_DASH = 61;
+
+ public static final int SCRIPT_DATA_ESCAPED_DASH = 62;
+
+ public static final int SCRIPT_DATA_ESCAPED_DASH_DASH = 63;
+
+ public static final int BOGUS_COMMENT_HYPHEN = 64;
+
+ public static final int RAWTEXT_RCDATA_LESS_THAN_SIGN = 65;
+
+ public static final int SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN = 66;
+
+ public static final int SCRIPT_DATA_DOUBLE_ESCAPE_START = 67;
+
+ public static final int SCRIPT_DATA_DOUBLE_ESCAPED = 68;
+
+ public static final int SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN = 69;
+
+ public static final int SCRIPT_DATA_DOUBLE_ESCAPED_DASH = 70;
+
+ public static final int SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH = 71;
+
+ public static final int SCRIPT_DATA_DOUBLE_ESCAPE_END = 72;
+
+ public static final int PROCESSING_INSTRUCTION = 73;
+
+ public static final int PROCESSING_INSTRUCTION_QUESTION_MARK = 74;
+
+ public static final int COMMENT_LESSTHAN = 76;
+
+ public static final int COMMENT_LESSTHAN_BANG = 77;
+
+ public static final int COMMENT_LESSTHAN_BANG_DASH = 78;
+
+ public static final int COMMENT_LESSTHAN_BANG_DASH_DASH = 79;
+
+ /**
+ * Magic value for UTF-16 operations.
+ */
+ private static final int LEAD_OFFSET = (0xD800 - (0x10000 >> 10));
+
+ /**
+ * UTF-16 code unit array containing less than and greater than for emitting
+ * those characters on certain parse errors.
+ */
+ private static final @NoLength char[] LT_GT = { '<', '>' };
+
+ /**
+ * UTF-16 code unit array containing less than and solidus for emitting
+ * those characters on certain parse errors.
+ */
+ private static final @NoLength char[] LT_SOLIDUS = { '<', '/' };
+
+ /**
+ * UTF-16 code unit array containing ]] for emitting those characters on
+ * state transitions.
+ */
+ private static final @NoLength char[] RSQB_RSQB = { ']', ']' };
+
+ /**
+ * Array version of U+FFFD.
+ */
+ private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' };
+
+ // [NOCPP[
+
+ /**
+ * Array version of space.
+ */
+ private static final @NoLength char[] SPACE = { ' ' };
+
+ // ]NOCPP]
+
+ /**
+ * Array version of line feed.
+ */
+ private static final @NoLength char[] LF = { '\n' };
+
+ /**
+ * "CDATA[" as <code>char[]</code>
+ */
+ private static final @NoLength char[] CDATA_LSQB = { 'C', 'D', 'A', 'T',
+ 'A', '[' };
+
+ /**
+ * "octype" as <code>char[]</code>
+ */
+ private static final @NoLength char[] OCTYPE = { 'o', 'c', 't', 'y', 'p',
+ 'e' };
+
+ /**
+ * "ublic" as <code>char[]</code>
+ */
+ private static final @NoLength char[] UBLIC = { 'u', 'b', 'l', 'i', 'c' };
+
+ /**
+ * "ystem" as <code>char[]</code>
+ */
+ private static final @NoLength char[] YSTEM = { 'y', 's', 't', 'e', 'm' };
+
+ private static final char[] TITLE_ARR = { 't', 'i', 't', 'l', 'e' };
+
+ private static final char[] SCRIPT_ARR = { 's', 'c', 'r', 'i', 'p', 't' };
+
+ private static final char[] STYLE_ARR = { 's', 't', 'y', 'l', 'e' };
+
+ private static final char[] PLAINTEXT_ARR = { 'p', 'l', 'a', 'i', 'n', 't',
+ 'e', 'x', 't' };
+
+ private static final char[] XMP_ARR = { 'x', 'm', 'p' };
+
+ private static final char[] TEXTAREA_ARR = { 't', 'e', 'x', 't', 'a', 'r',
+ 'e', 'a' };
+
+ private static final char[] IFRAME_ARR = { 'i', 'f', 'r', 'a', 'm', 'e' };
+
+ private static final char[] NOEMBED_ARR = { 'n', 'o', 'e', 'm', 'b', 'e',
+ 'd' };
+
+ private static final char[] NOSCRIPT_ARR = { 'n', 'o', 's', 'c', 'r', 'i',
+ 'p', 't' };
+
+ private static final char[] NOFRAMES_ARR = { 'n', 'o', 'f', 'r', 'a', 'm',
+ 'e', 's' };
+
+ /**
+ * The token handler.
+ */
+ protected final TokenHandler tokenHandler;
+
+ protected EncodingDeclarationHandler encodingDeclarationHandler;
+
+ // [NOCPP[
+
+ /**
+ * The error handler.
+ */
+ protected ErrorHandler errorHandler;
+
+ // ]NOCPP]
+
+ /**
+ * Whether the previous char read was CR.
+ */
+ protected boolean lastCR;
+
+ protected int stateSave;
+
+ private int returnStateSave;
+
+ protected int index;
+
+ private boolean forceQuirks;
+
+ private char additional;
+
+ private int entCol;
+
+ private int firstCharKey;
+
+ private int lo;
+
+ private int hi;
+
+ private int candidate;
+
+ private int charRefBufMark;
+
+ protected int value;
+
+ private boolean seenDigits;
+
+ private boolean suspendAfterCurrentNonTextToken;
+
+ protected int cstart;
+
+ /**
+ * The SAX public id for the resource being tokenized. (Only passed to back
+ * as part of locator data.)
+ */
+ private String publicId;
+
+ /**
+ * The SAX system id for the resource being tokenized. (Only passed to back
+ * as part of locator data.)
+ */
+ private String systemId;
+
+ /**
+ * Buffer for bufferable things other than those that fit the description
+ * of <code>charRefBuf</code>.
+ */
+ private @Auto char[] strBuf;
+
+ /**
+ * Number of significant <code>char</code>s in <code>strBuf</code>.
+ */
+ private int strBufLen;
+
+ /**
+ * Buffer for characters that might form a character reference but may
+ * end up not forming one.
+ */
+ private final @Auto char[] charRefBuf;
+
+ /**
+ * Number of significant <code>char</code>s in <code>charRefBuf</code>.
+ */
+ private int charRefBufLen;
+
+ /**
+ * Buffer for expanding NCRs falling into the Basic Multilingual Plane.
+ */
+ private final @Auto char[] bmpChar;
+
+ /**
+ * Buffer for expanding astral NCRs.
+ */
+ private final @Auto char[] astralChar;
+
+ /**
+ * The element whose end tag closes the current CDATA or RCDATA element.
+ */
+ protected ElementName endTagExpectation = null;
+
+ private char[] endTagExpectationAsArray; // not @Auto!
+
+ /**
+ * <code>true</code> if tokenizing an end tag
+ */
+ protected boolean endTag;
+
+ /**
+ * <code>true</code> iff the current element/attribute name contains
+ * a hyphen.
+ */
+ private boolean containsHyphen;
+
+ /**
+ * The current tag token name. One of
+ * 1) null,
+ * 2) non-owning reference to nonInternedTagName
+ * 3) non-owning reference to a pre-interned ElementName
+ */
+ private ElementName tagName = null;
+
+ /**
+ * The recycled ElementName instance for the non-pre-interned cases.
+ */
+ private ElementName nonInternedTagName = null;
+
+ /**
+ * The current attribute name.
+ */
+ protected AttributeName attributeName = null;
+
+ // CPPONLY: private AttributeName nonInternedAttributeName = null;
+
+ // [NOCPP[
+
+ /**
+ * Whether comment tokens are emitted.
+ */
+ private boolean wantsComments = false;
+
+ /**
+ * Whether the stream is past the first 1024 bytes.
+ */
+ private boolean metaBoundaryPassed;
+
+ // ]NOCPP]
+
+ /**
+ * The name of the current doctype token.
+ */
+ private @Local String doctypeName;
+
+ /**
+ * The public id of the current doctype token.
+ */
+ private String publicIdentifier;
+
+ /**
+ * The system id of the current doctype token.
+ */
+ private String systemIdentifier;
+
+ /**
+ * The attribute holder.
+ */
+ private HtmlAttributes attributes;
+
+ // [NOCPP[
+
+ /**
+ * The policy for vertical tab and form feed.
+ */
+ private XmlViolationPolicy contentSpacePolicy = XmlViolationPolicy.ALTER_INFOSET;
+
+ /**
+ * The policy for comments.
+ */
+ private XmlViolationPolicy commentPolicy = XmlViolationPolicy.ALTER_INFOSET;
+
+ private XmlViolationPolicy xmlnsPolicy = XmlViolationPolicy.ALTER_INFOSET;
+
+ private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET;
+
+ private int mappingLangToXmlLang;
+
+ // ]NOCPP]
+
+ private final boolean newAttributesEachTime;
+
+ private boolean shouldSuspend;
+
+ protected boolean confident;
+
+ private int line;
+
+ /*
+ * The line number of the current attribute. First set to the line of the
+ * attribute name and if there is a value, set to the line the value
+ * started on.
+ */
+ // CPPONLY: private int attributeLine;
+
+ private Interner interner;
+
+ // CPPONLY: private boolean viewingXmlSource;
+
+ // [NOCPP[
+
+ protected LocatorImpl ampersandLocation;
+
+ public Tokenizer(TokenHandler tokenHandler, boolean newAttributesEachTime) {
+ this.tokenHandler = tokenHandler;
+ this.encodingDeclarationHandler = null;
+ this.lastCR = false;
+ this.stateSave = 0;
+ this.returnStateSave = 0;
+ this.index = 0;
+ this.forceQuirks = false;
+ this.additional = '\u0000';
+ this.entCol = 0;
+ this.firstCharKey = 0;
+ this.lo = 0;
+ this.hi = 0;
+ this.candidate = 0;
+ this.charRefBufMark = 0;
+ this.value = 0;
+ this.seenDigits = false;
+ this.suspendAfterCurrentNonTextToken = false;
+ this.cstart = 0;
+ this.strBufLen = 0;
+ this.newAttributesEachTime = newAttributesEachTime;
+ // &CounterClockwiseContourIntegral; is the longest valid char ref and
+ // the semicolon never gets appended to the buffer.
+ this.charRefBuf = new char[32];
+ this.charRefBufLen = 0;
+ this.bmpChar = new char[1];
+ this.astralChar = new char[2];
+ this.endTagExpectation = null;
+ this.endTagExpectationAsArray = null;
+ this.endTag = false;
+ this.containsHyphen = false;
+ this.tagName = null;
+ this.nonInternedTagName = new ElementName();
+ this.attributeName = null;
+ // CPPONLY: this.nonInternedAttributeName = new AttributeName();
+ this.doctypeName = null;
+ this.publicIdentifier = null;
+ this.systemIdentifier = null;
+ this.attributes = null;
+ this.shouldSuspend = false;
+ this.confident = false;
+ this.line = 0;
+ // CPPONLY: this.attributeLine = 0;
+ this.interner = null;
+ }
+
+ // ]NOCPP]
+
+ /**
+ * The constructor.
+ *
+ * @param tokenHandler
+ * the handler for receiving tokens
+ */
+ public Tokenizer(TokenHandler tokenHandler
+ // CPPONLY: , boolean viewingXmlSource
+ ) {
+ this.tokenHandler = tokenHandler;
+ this.encodingDeclarationHandler = null;
+ // [NOCPP[
+ this.newAttributesEachTime = false;
+ // ]NOCPP]
+ this.lastCR = false;
+ this.stateSave = 0;
+ this.returnStateSave = 0;
+ this.index = 0;
+ this.forceQuirks = false;
+ this.additional = '\u0000';
+ this.entCol = 0;
+ this.firstCharKey = 0;
+ this.lo = 0;
+ this.hi = 0;
+ this.candidate = 0;
+ this.charRefBufMark = 0;
+ this.value = 0;
+ this.seenDigits = false;
+ this.suspendAfterCurrentNonTextToken = false;
+ this.cstart = 0;
+ this.strBufLen = 0;
+ // &CounterClockwiseContourIntegral; is the longest valid char ref and
+ // the semicolon never gets appended to the buffer.
+ this.charRefBuf = new char[32];
+ this.charRefBufLen = 0;
+ this.bmpChar = new char[1];
+ this.astralChar = new char[2];
+ this.endTagExpectation = null;
+ this.endTagExpectationAsArray = null;
+ this.endTag = false;
+ this.containsHyphen = false;
+ this.tagName = null;
+ this.nonInternedTagName = new ElementName();
+ this.attributeName = null;
+ // CPPONLY: this.nonInternedAttributeName = new AttributeName();
+ this.doctypeName = null;
+ this.publicIdentifier = null;
+ this.systemIdentifier = null;
+ // [NOCPP[
+ this.attributes = null;
+ // ]NOCPP]
+ // CPPONLY: this.attributes = tokenHandler.HasBuilder() ? new HtmlAttributes(mappingLangToXmlLang) : null;
+ // CPPONLY: this.newAttributesEachTime = !tokenHandler.HasBuilder();
+ this.shouldSuspend = false;
+ this.confident = false;
+ this.line = 0;
+ // CPPONLY: this.attributeLine = 0;
+ this.interner = null;
+ // CPPONLY: this.viewingXmlSource = viewingXmlSource;
+ }
+
+ public void setInterner(Interner interner) {
+ this.interner = interner;
+ }
+
+ public void initLocation(String newPublicId, String newSystemId) {
+ this.systemId = newSystemId;
+ this.publicId = newPublicId;
+
+ }
+
+ // CPPONLY: boolean isViewingXmlSource() {
+ // CPPONLY: return viewingXmlSource;
+ // CPPONLY: }
+
+ // [NOCPP[
+
+ /**
+ * Returns the mappingLangToXmlLang.
+ *
+ * @return the mappingLangToXmlLang
+ */
+ public boolean isMappingLangToXmlLang() {
+ return mappingLangToXmlLang == AttributeName.HTML_LANG;
+ }
+
+ /**
+ * Sets the mappingLangToXmlLang.
+ *
+ * @param mappingLangToXmlLang
+ * the mappingLangToXmlLang to set
+ */
+ public void setMappingLangToXmlLang(boolean mappingLangToXmlLang) {
+ this.mappingLangToXmlLang = mappingLangToXmlLang ? AttributeName.HTML_LANG
+ : AttributeName.HTML;
+ }
+
+ /**
+ * Sets the error handler.
+ *
+ * @see org.xml.sax.XMLReader#setErrorHandler(org.xml.sax.ErrorHandler)
+ */
+ public void setErrorHandler(ErrorHandler eh) {
+ this.errorHandler = eh;
+ }
+
+ public ErrorHandler getErrorHandler() {
+ return this.errorHandler;
+ }
+
+ /**
+ * Sets the commentPolicy.
+ *
+ * @param commentPolicy
+ * the commentPolicy to set
+ */
+ public void setCommentPolicy(XmlViolationPolicy commentPolicy) {
+ this.commentPolicy = commentPolicy;
+ }
+
+ /**
+ * Sets the contentNonXmlCharPolicy.
+ *
+ * @param contentNonXmlCharPolicy
+ * the contentNonXmlCharPolicy to set
+ */
+ public void setContentNonXmlCharPolicy(
+ XmlViolationPolicy contentNonXmlCharPolicy) {
+ if (contentNonXmlCharPolicy != XmlViolationPolicy.ALLOW) {
+ throw new IllegalArgumentException(
+ "Must use ErrorReportingTokenizer to set contentNonXmlCharPolicy to non-ALLOW.");
+ }
+ }
+
+ /**
+ * Sets the contentSpacePolicy.
+ *
+ * @param contentSpacePolicy
+ * the contentSpacePolicy to set
+ */
+ public void setContentSpacePolicy(XmlViolationPolicy contentSpacePolicy) {
+ this.contentSpacePolicy = contentSpacePolicy;
+ }
+
+ /**
+ * Sets the xmlnsPolicy.
+ *
+ * @param xmlnsPolicy
+ * the xmlnsPolicy to set
+ */
+ public void setXmlnsPolicy(XmlViolationPolicy xmlnsPolicy) {
+ if (xmlnsPolicy == XmlViolationPolicy.FATAL) {
+ throw new IllegalArgumentException("Can't use FATAL here.");
+ }
+ this.xmlnsPolicy = xmlnsPolicy;
+ }
+
+ public void setNamePolicy(XmlViolationPolicy namePolicy) {
+ this.namePolicy = namePolicy;
+ }
+
+ // ]NOCPP]
+
+ // For the token handler to call
+
+ /**
+ * Sets the tokenizer state and the associated element name. This should
+ * only ever used to put the tokenizer into one of the states that have
+ * a special end tag expectation.
+ *
+ * @param specialTokenizerState
+ * the tokenizer state to set
+ */
+ public void setState(int specialTokenizerState) {
+ this.stateSave = specialTokenizerState;
+ this.endTagExpectation = null;
+ this.endTagExpectationAsArray = null;
+ }
+
+ // [NOCPP[
+
+ /**
+ * Sets the tokenizer state and the associated element name. This should
+ * only ever used to put the tokenizer into one of the states that have
+ * a special end tag expectation. For use from the tokenizer test harness.
+ *
+ * @param specialTokenizerState
+ * the tokenizer state to set
+ * @param endTagExpectation
+ * the expected end tag for transitioning back to normal
+ */
+ public void setStateAndEndTagExpectation(int specialTokenizerState,
+ @Local String endTagExpectation) {
+ this.stateSave = specialTokenizerState;
+ if (specialTokenizerState == Tokenizer.DATA) {
+ return;
+ }
+ @Auto char[] asArray = Portability.newCharArrayFromLocal(endTagExpectation);
+ this.endTagExpectation = ElementName.elementNameByBuffer(asArray,
+ asArray.length, interner);
+ assert this.endTagExpectation != null;
+ endTagExpectationToArray();
+ }
+
+ // ]NOCPP]
+
+ /**
+ * Sets the tokenizer state and the associated element name. This should
+ * only ever used to put the tokenizer into one of the states that have
+ * a special end tag expectation.
+ *
+ * @param specialTokenizerState
+ * the tokenizer state to set
+ * @param endTagExpectation
+ * the expected end tag for transitioning back to normal
+ */
+ public void setStateAndEndTagExpectation(int specialTokenizerState,
+ ElementName endTagExpectation) {
+ this.stateSave = specialTokenizerState;
+ this.endTagExpectation = endTagExpectation;
+ endTagExpectationToArray();
+ }
+
+ private void endTagExpectationToArray() {
+ switch (endTagExpectation.getGroup()) {
+ case TreeBuilder.TITLE:
+ endTagExpectationAsArray = TITLE_ARR;
+ return;
+ case TreeBuilder.SCRIPT:
+ endTagExpectationAsArray = SCRIPT_ARR;
+ return;
+ case TreeBuilder.STYLE:
+ endTagExpectationAsArray = STYLE_ARR;
+ return;
+ case TreeBuilder.PLAINTEXT:
+ endTagExpectationAsArray = PLAINTEXT_ARR;
+ return;
+ case TreeBuilder.XMP:
+ endTagExpectationAsArray = XMP_ARR;
+ return;
+ case TreeBuilder.TEXTAREA:
+ endTagExpectationAsArray = TEXTAREA_ARR;
+ return;
+ case TreeBuilder.IFRAME:
+ endTagExpectationAsArray = IFRAME_ARR;
+ return;
+ case TreeBuilder.NOEMBED:
+ endTagExpectationAsArray = NOEMBED_ARR;
+ return;
+ case TreeBuilder.NOSCRIPT:
+ endTagExpectationAsArray = NOSCRIPT_ARR;
+ return;
+ case TreeBuilder.NOFRAMES:
+ endTagExpectationAsArray = NOFRAMES_ARR;
+ return;
+ default:
+ assert false: "Bad end tag expectation.";
+ return;
+ }
+ }
+
+ /**
+ * For C++ use only.
+ */
+ public void setLineNumber(int line) {
+ // CPPONLY: this.attributeLine = line; // XXX is this needed?
+ this.line = line;
+ }
+
+ // start Locator impl
+
+ /**
+ * @see org.xml.sax.Locator#getLineNumber()
+ */
+ @Inline public int getLineNumber() {
+ return line;
+ }
+
+ // [NOCPP[
+
+ /**
+ * @see org.xml.sax.Locator#getColumnNumber()
+ */
+ @Inline public int getColumnNumber() {
+ return -1;
+ }
+
+ /**
+ * @see org.xml.sax.Locator#getPublicId()
+ */
+ public String getPublicId() {
+ return publicId;
+ }
+
+ /**
+ * @see org.xml.sax.Locator#getSystemId()
+ */
+ public String getSystemId() {
+ return systemId;
+ }
+
+ /**
+ * @see org.xml.sax.ext.Locator2#getXMLVersion()
+ */
+ public String getXMLVersion() {
+ return "1.0";
+ }
+
+ /**
+ * @see org.xml.sax.ext.Locator2#getXMLVersion()
+ */
+ public String getEncoding() {
+ try {
+ return encodingDeclarationHandler == null ? null : encodingDeclarationHandler.getCharacterEncoding();
+ } catch (SAXException e) {
+ return null;
+ }
+ }
+
+ // end Locator impl
+
+ // end public API
+
+ public void notifyAboutMetaBoundary() {
+ metaBoundaryPassed = true;
+ }
+
+ // ]NOCPP]
+
+ HtmlAttributes emptyAttributes() {
+ // [NOCPP[
+ if (newAttributesEachTime) {
+ return new HtmlAttributes(mappingLangToXmlLang);
+ } else {
+ // ]NOCPP]
+ return HtmlAttributes.EMPTY_ATTRIBUTES;
+ // [NOCPP[
+ }
+ // ]NOCPP]
+ }
+
+ @Inline private void appendCharRefBuf(char c) {
+ // CPPONLY: assert charRefBufLen < charRefBuf.length:
+ // CPPONLY: "RELEASE: Attempted to overrun charRefBuf!";
+ charRefBuf[charRefBufLen++] = c;
+ }
+
+ private void emitOrAppendCharRefBuf(int returnState) throws SAXException {
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ appendCharRefBufToStrBuf();
+ } else {
+ if (charRefBufLen > 0) {
+ tokenHandler.characters(charRefBuf, 0, charRefBufLen);
+ charRefBufLen = 0;
+ }
+ }
+ }
+
+ @Inline private void clearStrBufAfterUse() {
+ strBufLen = 0;
+ }
+
+ @Inline private void clearStrBufBeforeUse() {
+ assert strBufLen == 0: "strBufLen not reset after previous use!";
+ strBufLen = 0; // no-op in the absence of bugs
+ }
+
+ @Inline private void clearStrBufAfterOneHyphen() {
+ assert strBufLen == 1: "strBufLen length not one!";
+ assert strBuf[0] == '-': "strBuf does not start with a hyphen!";
+ strBufLen = 0;
+ }
+
+ /**
+ * Appends to the buffer.
+ *
+ * @param c
+ * the UTF-16 code unit to append
+ */
+ @Inline private void appendStrBuf(char c) {
+ // CPPONLY: assert strBufLen < strBuf.length: "Previous buffer length insufficient.";
+ // CPPONLY: if (strBufLen == strBuf.length) {
+ // CPPONLY: if (!EnsureBufferSpace(1)) {
+ // CPPONLY: assert false: "RELEASE: Unable to recover from buffer reallocation failure";
+ // CPPONLY: } // TODO: Add telemetry when outer if fires but inner does not
+ // CPPONLY: }
+ strBuf[strBufLen++] = c;
+ }
+
+ /**
+ * The buffer as a String. Currently only used for error reporting.
+ *
+ * <p>
+ * C++ memory note: The return value must be released.
+ *
+ * @return the buffer as a string
+ */
+ protected String strBufToString() {
+ String str = Portability.newStringFromBuffer(strBuf, 0, strBufLen
+ // CPPONLY: , tokenHandler, !newAttributesEachTime && attributeName == AttributeName.CLASS
+ );
+ clearStrBufAfterUse();
+ return str;
+ }
+
+ /**
+ * Returns the buffer as a local name. The return value is released in
+ * emitDoctypeToken().
+ *
+ * @return the buffer as local name
+ */
+ private void strBufToDoctypeName() {
+ doctypeName = Portability.newLocalNameFromBuffer(strBuf, strBufLen, interner);
+ clearStrBufAfterUse();
+ }
+
+ /**
+ * Emits the buffer as character tokens.
+ *
+ * @throws SAXException
+ * if the token handler threw
+ */
+ private void emitStrBuf() throws SAXException {
+ if (strBufLen > 0) {
+ tokenHandler.characters(strBuf, 0, strBufLen);
+ clearStrBufAfterUse();
+ }
+ }
+
+ @Inline private void appendSecondHyphenToBogusComment() throws SAXException {
+ // [NOCPP[
+ switch (commentPolicy) {
+ case ALTER_INFOSET:
+ appendStrBuf(' ');
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ALLOW:
+ warn("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.");
+ // ]NOCPP]
+ appendStrBuf('-');
+ // [NOCPP[
+ break;
+ case FATAL:
+ fatal("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.");
+ break;
+ }
+ // ]NOCPP]
+ }
+
+ // [NOCPP[
+ private void maybeAppendSpaceToBogusComment() throws SAXException {
+ switch (commentPolicy) {
+ case ALTER_INFOSET:
+ appendStrBuf(' ');
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ALLOW:
+ warn("The document is not mappable to XML 1.0 due to a trailing hyphen in a comment.");
+ break;
+ case FATAL:
+ fatal("The document is not mappable to XML 1.0 due to a trailing hyphen in a comment.");
+ break;
+ }
+ }
+
+ // ]NOCPP]
+
+ @Inline private void adjustDoubleHyphenAndAppendToStrBufAndErr(char c, boolean reportedConsecutiveHyphens)
+ throws SAXException {
+ // [NOCPP[
+ switch (commentPolicy) {
+ case ALTER_INFOSET:
+ strBufLen--;
+ // WARNING!!! This expands the worst case of the buffer length
+ // given the length of input!
+ appendStrBuf(' ');
+ appendStrBuf('-');
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ALLOW:
+ if (!reportedConsecutiveHyphens) {
+ warn("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.");
+ }
+ // ]NOCPP]
+ appendStrBuf(c);
+ // [NOCPP[
+ break;
+ case FATAL:
+ fatal("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.");
+ break;
+ }
+ // ]NOCPP]
+ }
+
+ private void appendStrBuf(@NoLength char[] buffer, int offset, int length) throws SAXException {
+ int newLen = Portability.checkedAdd(strBufLen, length);
+ // CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient.";
+ // CPPONLY: if (strBuf.length < newLen) {
+ // CPPONLY: if (!EnsureBufferSpace(length)) {
+ // CPPONLY: assert false: "RELEASE: Unable to recover from buffer reallocation failure";
+ // CPPONLY: } // TODO: Add telemetry when outer if fires but inner does not
+ // CPPONLY: }
+ System.arraycopy(buffer, offset, strBuf, strBufLen, length);
+ strBufLen = newLen;
+ }
+
+ /**
+ * Append the contents of the char reference buffer to the main one.
+ */
+ @Inline private void appendCharRefBufToStrBuf() throws SAXException {
+ appendStrBuf(charRefBuf, 0, charRefBufLen);
+ charRefBufLen = 0;
+ }
+
+ /**
+ * Emits the current comment token.
+ *
+ * NOTE: The method may set <code>shouldSuspend</code>, so the caller
+ * must have this pattern after the state's <code>transition</code> call:
+ *
+ * <pre>
+ * if (shouldSuspend) {
+ * break stateloop;
+ * }
+ * continue stateloop;
+ * </pre>
+ *
+ * @param pos
+ * TODO
+ *
+ * @throws SAXException
+ */
+ private void emitComment(int provisionalHyphens, int pos)
+ throws SAXException {
+ // CPPONLY: RememberGt(pos);
+ // [NOCPP[
+ if (wantsComments) {
+ // ]NOCPP]
+ tokenHandler.comment(strBuf, 0, strBufLen
+ - provisionalHyphens);
+ // [NOCPP[
+ }
+ // ]NOCPP]
+ clearStrBufAfterUse();
+ cstart = pos + 1;
+ suspendIfRequestedAfterCurrentNonTextToken();
+ }
+
+ /**
+ * Flushes coalesced character tokens.
+ *
+ * @param buf
+ * TODO
+ * @param pos
+ * TODO
+ *
+ * @throws SAXException
+ */
+ protected void flushChars(@NoLength char[] buf, int pos)
+ throws SAXException {
+ if (pos > cstart) {
+ tokenHandler.characters(buf, cstart, pos - cstart);
+ }
+ cstart = Integer.MAX_VALUE;
+ }
+
+ /**
+ * Reports an condition that would make the infoset incompatible with XML
+ * 1.0 as fatal.
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ * @throws SAXParseException
+ */
+ public void fatal(String message) throws SAXException {
+ SAXParseException spe = new SAXParseException(message, this);
+ if (errorHandler != null) {
+ errorHandler.fatalError(spe);
+ }
+ throw spe;
+ }
+
+ /**
+ * Reports a Parse Error.
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ public void err(String message) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ SAXParseException spe = new SAXParseException(message, this);
+ errorHandler.error(spe);
+ }
+
+ public void errTreeBuilder(String message) throws SAXException {
+ ErrorHandler eh = null;
+ if (tokenHandler instanceof TreeBuilder<?>) {
+ TreeBuilder<?> treeBuilder = (TreeBuilder<?>) tokenHandler;
+ eh = treeBuilder.getErrorHandler();
+ }
+ if (eh == null) {
+ eh = errorHandler;
+ }
+ if (eh == null) {
+ return;
+ }
+ SAXParseException spe = new SAXParseException(message, this);
+ eh.error(spe);
+ }
+
+ /**
+ * Reports a warning
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ public void warn(String message) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ SAXParseException spe = new SAXParseException(message, this);
+ errorHandler.warning(spe);
+ }
+
+ private void strBufToElementNameString() {
+ if (containsHyphen) {
+ // We've got a custom element or annotation-xml.
+ @Local String annotationName = ElementName.ANNOTATION_XML.getName();
+ if (Portability.localEqualsBuffer(annotationName, strBuf, strBufLen)) {
+ tagName = ElementName.ANNOTATION_XML;
+ } else {
+ nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, strBufLen,
+ interner)
+ // CPPONLY: , true
+ );
+ tagName = nonInternedTagName;
+ }
+ } else {
+ tagName = ElementName.elementNameByBuffer(strBuf, strBufLen, interner);
+ if (tagName == null) {
+ nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, strBufLen,
+ interner)
+ // CPPONLY: , false
+ );
+ tagName = nonInternedTagName;
+ }
+ }
+ containsHyphen = false;
+ clearStrBufAfterUse();
+ }
+
+ /**
+ * Emits a tag token.
+ *
+ * NOTE: The method may set <code>shouldSuspend</code>, so the caller
+ * must have this pattern after the state's <code>transition</code> call:
+ * <pre>
+ * if (shouldSuspend) {
+ * break stateloop;
+ * }
+ * continue stateloop;
+ * </pre>
+ *
+ * @param selfClosing
+ * @param pos
+ * @return
+ * @throws SAXException
+ */
+ private int emitCurrentTagToken(boolean selfClosing, int pos)
+ throws SAXException {
+ // CPPONLY: RememberGt(pos);
+ cstart = pos + 1;
+ maybeErrSlashInEndTag(selfClosing);
+ stateSave = Tokenizer.DATA;
+ HtmlAttributes attrs = (attributes == null ? HtmlAttributes.EMPTY_ATTRIBUTES
+ : attributes);
+ if (endTag) {
+ /*
+ * When an end tag token is emitted, the content model flag must be
+ * switched to the PCDATA state.
+ */
+ maybeErrAttributesOnEndTag(attrs);
+ // CPPONLY: if (!viewingXmlSource) {
+ tokenHandler.endTag(tagName);
+ // CPPONLY: }
+ // CPPONLY: if (newAttributesEachTime) {
+ // CPPONLY: Portability.delete(attributes);
+ // CPPONLY: attributes = null;
+ // CPPONLY: }
+ } else {
+ // CPPONLY: if (viewingXmlSource) {
+ // CPPONLY: assert newAttributesEachTime;
+ // CPPONLY: Portability.delete(attributes);
+ // CPPONLY: attributes = null;
+ // CPPONLY: } else {
+ tokenHandler.startTag(tagName, attrs, selfClosing);
+ // CPPONLY: }
+ }
+ tagName = null;
+ if (newAttributesEachTime) {
+ attributes = null;
+ } else {
+ attributes.clear(mappingLangToXmlLang);
+ }
+ /*
+ * The token handler may have called setStateAndEndTagExpectation
+ * and changed stateSave since the start of this method.
+ */
+ suspendIfRequestedAfterCurrentNonTextToken();
+ return stateSave;
+ }
+
+ private void attributeNameComplete() throws SAXException {
+ attributeName = AttributeName.nameByBuffer(strBuf, strBufLen, interner);
+ if (attributeName == null) {
+ // [NOCPP[
+ attributeName = AttributeName.createAttributeName(
+ Portability.newLocalNameFromBuffer(strBuf, strBufLen,
+ interner),
+ namePolicy != XmlViolationPolicy.ALLOW);
+ // ]NOCPP]
+ // CPPONLY: nonInternedAttributeName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, strBufLen, interner));
+ // CPPONLY: attributeName = nonInternedAttributeName;
+ }
+ clearStrBufAfterUse();
+
+ if (attributes == null) {
+ attributes = new HtmlAttributes(mappingLangToXmlLang);
+ }
+
+ /*
+ * When the user agent leaves the attribute name state (and before
+ * emitting the tag token, if appropriate), the complete attribute's
+ * name must be compared to the other attributes on the same token; if
+ * there is already an attribute on the token with the exact same name,
+ * then this is a parse error and the new attribute must be dropped,
+ * along with the value that gets associated with it (if any).
+ */
+ if (attributes.contains(attributeName)) {
+ errDuplicateAttribute();
+ attributeName = null;
+ }
+ }
+
+ private void addAttributeWithoutValue() throws SAXException {
+ noteAttributeWithoutValue();
+
+ // [NOCPP[
+ if (metaBoundaryPassed && AttributeName.CHARSET == attributeName
+ && ElementName.META == tagName) {
+ err("A \u201Ccharset\u201D attribute on a \u201Cmeta\u201D element found after the first 1024 bytes.");
+ }
+ // ]NOCPP]
+ if (attributeName != null) {
+ // [NOCPP[
+ if (AttributeName.SRC == attributeName
+ || AttributeName.HREF == attributeName) {
+ warn("Attribute \u201C"
+ + attributeName.getLocal(AttributeName.HTML)
+ + "\u201D without an explicit value seen. The attribute may be dropped by IE7.");
+ }
+ // ]NOCPP]
+ attributes.addAttribute(attributeName,
+ Portability.newEmptyString()
+ // [NOCPP[
+ , xmlnsPolicy
+ // ]NOCPP]
+ // CPPONLY: , attributeLine
+ );
+ attributeName = null;
+ } else {
+ clearStrBufAfterUse();
+ }
+ }
+
+ private void addAttributeWithValue() throws SAXException {
+ // [NOCPP[
+ if (metaBoundaryPassed && ElementName.META == tagName
+ && AttributeName.CHARSET == attributeName) {
+ err("A \u201Ccharset\u201D attribute on a \u201Cmeta\u201D element found after the first 1024 bytes.");
+ }
+ // ]NOCPP]
+ if (attributeName != null) {
+ String val = strBufToString(); // Ownership transferred to
+ // HtmlAttributes
+ // CPPONLY: if (mViewSource) {
+ // CPPONLY: mViewSource.MaybeLinkifyAttributeValue(attributeName, val);
+ // CPPONLY: }
+ attributes.addAttribute(attributeName, val
+ // [NOCPP[
+ , xmlnsPolicy
+ // ]NOCPP]
+ // CPPONLY: , attributeLine
+ );
+ attributeName = null;
+ } else {
+ // We have a duplicate attribute. Explicitly discard its value.
+ clearStrBufAfterUse();
+ }
+ }
+
+ // [NOCPP[
+
+ protected void startErrorReporting() throws SAXException {
+
+ }
+
+ // ]NOCPP]
+
+ public void start() throws SAXException {
+ initializeWithoutStarting();
+ tokenHandler.startTokenization(this);
+ // CPPONLY: line = 0;
+ // CPPONLY: col = 1;
+ // CPPONLY: nextCharOnNewLine = true;
+ // [NOCPP[
+ startErrorReporting();
+ // ]NOCPP]
+ }
+
+ public boolean tokenizeBuffer(UTF16Buffer buffer) throws SAXException {
+ int state = stateSave;
+ int returnState = returnStateSave;
+ char c = '\u0000';
+ shouldSuspend = false;
+ lastCR = false;
+
+ int start = buffer.getStart();
+ int end = buffer.getEnd();
+
+ // In C++, the caller of tokenizeBuffer needs to do this explicitly.
+ // [NOCPP[
+ ensureBufferSpace(end - start);
+ // ]NOCPP]
+
+ /**
+ * The index of the last <code>char</code> read from <code>buf</code>.
+ */
+ int pos = start - 1;
+
+ /**
+ * The index of the first <code>char</code> in <code>buf</code> that is
+ * part of a coalesced run of character tokens or
+ * <code>Integer.MAX_VALUE</code> if there is not a current run being
+ * coalesced.
+ */
+ switch (state) {
+ case DATA:
+ case RCDATA:
+ case SCRIPT_DATA:
+ case PLAINTEXT:
+ case RAWTEXT:
+ case CDATA_SECTION:
+ case SCRIPT_DATA_ESCAPED:
+ case SCRIPT_DATA_ESCAPE_START:
+ case SCRIPT_DATA_ESCAPE_START_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_START:
+ case SCRIPT_DATA_DOUBLE_ESCAPED:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_END:
+ cstart = start;
+ break;
+ default:
+ cstart = Integer.MAX_VALUE;
+ break;
+ }
+
+ /**
+ * The number of <code>char</code>s in <code>buf</code> that have
+ * meaning. (The rest of the array is garbage and should not be
+ * examined.)
+ */
+ // CPPONLY: if (mViewSource) {
+ // CPPONLY: mViewSource.SetBuffer(buffer);
+ // CPPONLY: pos = stateLoop(state, c, pos, buffer.getBuffer(), false, returnState, buffer.getEnd());
+ // CPPONLY: mViewSource.DropBuffer((pos == buffer.getEnd()) ? pos : pos + 1);
+ // CPPONLY: } else {
+ // CPPONLY: pos = stateLoop(state, c, pos, buffer.getBuffer(), false, returnState, buffer.getEnd());
+ // CPPONLY: }
+ // [NOCPP[
+ pos = stateLoop(state, c, pos, buffer.getBuffer(), false, returnState,
+ end);
+ // ]NOCPP]
+ if (pos == end) {
+ // exiting due to end of buffer
+ buffer.setStart(pos);
+ } else {
+ buffer.setStart(pos + 1);
+ }
+ return lastCR;
+ }
+
+ // [NOCPP[
+ private void ensureBufferSpace(int inputLength) throws SAXException {
+ // Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB.
+ // Adding to the general worst case instead of only the
+ // TreeBuilder-exposed worst case to avoid re-introducing a bug when
+ // unifying the tokenizer and tree builder buffers in the future.
+ int worstCase = strBufLen + inputLength + charRefBufLen + 2;
+ tokenHandler.ensureBufferSpace(worstCase);
+ if (commentPolicy == XmlViolationPolicy.ALTER_INFOSET) {
+ // When altering infoset, if the comment contents are consecutive
+ // hyphens, each hyphen generates a space, too. These buffer
+ // contents never get emitted as characters() to the tokenHandler,
+ // which is why this calculation happens after the call to
+ // ensureBufferSpace on tokenHandler.
+ worstCase *= 2;
+ }
+ if (strBuf == null) {
+ // Add an arbitrary small value to avoid immediate reallocation
+ // once there are a few characters in the buffer.
+ strBuf = new char[worstCase + 128];
+ } else if (worstCase > strBuf.length) {
+ // HotSpot reportedly allocates memory with 8-byte accuracy, so
+ // there's no point in trying to do math here to avoid slop.
+ // Maybe we should add some small constant to worstCase here
+ // but not doing that without profiling. In C++ with jemalloc,
+ // the corresponding method should do math to round up here
+ // to avoid slop.
+ char[] newBuf = new char[Math.max(worstCase, (strBuf.length*5)/4)];
+ System.arraycopy(strBuf, 0, newBuf, 0, strBufLen);
+ strBuf = newBuf;
+ }
+ }
+ // ]NOCPP]
+
+ @SuppressWarnings("unused") private int stateLoop(int state, char c,
+ int pos, @NoLength char[] buf, boolean reconsume, int returnState,
+ int endPos) throws SAXException {
+ boolean reportedConsecutiveHyphens = false;
+ /*
+ * Idioms used in this code:
+ *
+ *
+ * Consuming the next input character
+ *
+ * To consume the next input character, the code does this: if (++pos ==
+ * endPos) { break stateloop; } c = checkChar(buf, pos);
+ *
+ *
+ * Staying in a state
+ *
+ * When there's a state that the tokenizer may stay in over multiple
+ * input characters, the state has a wrapper |for(;;)| loop and staying
+ * in the state continues the loop.
+ *
+ *
+ * Switching to another state
+ *
+ * To switch to another state, the code sets the state variable to the
+ * magic number of the new state. Then it either continues stateloop or
+ * breaks out of the state's own wrapper loop if the target state is
+ * right after the current state in source order. (This is a partial
+ * workaround for Java's lack of goto.)
+ *
+ *
+ * Reconsume support
+ *
+ * The spec sometimes says that an input character is reconsumed in
+ * another state. If a state can ever be entered so that an input
+ * character can be reconsumed in it, the state's code starts with an
+ * |if (reconsume)| that sets reconsume to false and skips over the
+ * normal code for consuming a new character.
+ *
+ * To reconsume the current character in another state, the code sets
+ * |reconsume| to true and then switches to the other state.
+ *
+ *
+ * Emitting character tokens
+ *
+ * This method emits character tokens lazily. Whenever a new range of
+ * character tokens starts, the field cstart must be set to the start
+ * index of the range. The flushChars() method must be called at the end
+ * of a range to flush it.
+ *
+ *
+ * U+0000 handling
+ *
+ * The various states have to handle the replacement of U+0000 with
+ * U+FFFD. However, if U+0000 would be reconsumed in another state, the
+ * replacement doesn't need to happen, because it's handled by the
+ * reconsuming state.
+ *
+ *
+ * LF handling
+ *
+ * Every state needs to increment the line number upon LF unless the LF
+ * gets reconsumed by another state which increments the line number.
+ *
+ *
+ * CR handling
+ *
+ * Every state needs to handle CR unless the CR gets reconsumed and is
+ * handled by the reconsuming state. The CR needs to be handled as if it
+ * were and LF, the lastCR field must be set to true and then this
+ * method must return. The IO driver will then swallow the next
+ * character if it is an LF to coalesce CRLF.
+ */
+ stateloop: for (;;) {
+ switch (state) {
+ case DATA:
+ dataloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '&':
+ /*
+ * U+0026 AMPERSAND (&) Switch to the character
+ * reference in data state.
+ */
+ flushChars(buf, pos);
+ assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\u0000');
+ returnState = state;
+ state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
+ continue stateloop;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the tag
+ * open state.
+ */
+ flushChars(buf, pos);
+
+ state = transition(state, Tokenizer.TAG_OPEN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break dataloop;
+ case '\u0000':
+ maybeEmitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the input character as a
+ * character token.
+ *
+ * Stay in the data state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case TAG_OPEN:
+ tagopenloop: for (;;) {
+ /*
+ * The behavior of this state depends on the content
+ * model flag.
+ */
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * If the content model flag is set to the PCDATA state
+ * Consume the next input character:
+ */
+ if (c >= 'A' && c <= 'Z') {
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to U+005A
+ * LATIN CAPITAL LETTER Z Create a new start tag
+ * token,
+ */
+ endTag = false;
+ /*
+ * set its tag name to the lowercase version of the
+ * input character (add 0x0020 to the character's
+ * code point),
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf((char) (c + 0x20));
+ containsHyphen = false;
+ /* then switch to the tag name state. */
+ state = transition(state, Tokenizer.TAG_NAME, reconsume, pos);
+ /*
+ * (Don't emit the token yet; further details will
+ * be filled in before it is emitted.)
+ */
+ // `break` optimizes; `continue stateloop;` would be valid
+ break tagopenloop;
+ } else if (c >= 'a' && c <= 'z') {
+ /*
+ * U+0061 LATIN SMALL LETTER A through to U+007A
+ * LATIN SMALL LETTER Z Create a new start tag
+ * token,
+ */
+ endTag = false;
+ /*
+ * set its tag name to the input character,
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ containsHyphen = false;
+ /* then switch to the tag name state. */
+ state = transition(state, Tokenizer.TAG_NAME, reconsume, pos);
+ /*
+ * (Don't emit the token yet; further details will
+ * be filled in before it is emitted.)
+ */
+ // `break` optimizes; `continue stateloop;` would be valid
+ break tagopenloop;
+ }
+ switch (c) {
+ case '!':
+ /*
+ * U+0021 EXCLAMATION MARK (!) Switch to the
+ * markup declaration open state.
+ */
+ state = transition(state, Tokenizer.MARKUP_DECLARATION_OPEN, reconsume, pos);
+ continue stateloop;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Switch to the close tag
+ * open state.
+ */
+ state = transition(state, Tokenizer.CLOSE_TAG_OPEN, reconsume, pos);
+ continue stateloop;
+ case '?':
+ // CPPONLY: if (viewingXmlSource) {
+ // CPPONLY: state = transition(state,
+ // CPPONLY: Tokenizer.PROCESSING_INSTRUCTION,
+ // CPPONLY: reconsume,
+ // CPPONLY: pos);
+ // CPPONLY: continue stateloop;
+ // CPPONLY: }
+ /*
+ * U+003F QUESTION MARK (?) Parse error.
+ */
+ errProcessingInstruction();
+ /*
+ * Switch to the bogus comment state.
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Parse error.
+ */
+ errLtGt();
+ /*
+ * Emit a U+003C LESS-THAN SIGN character token
+ * and a U+003E GREATER-THAN SIGN character
+ * token.
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 2);
+ /* Switch to the data state. */
+ cstart = pos + 1;
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ continue stateloop;
+ default:
+ /*
+ * Anything else Parse error.
+ */
+ errBadCharAfterLt(c);
+ /*
+ * Emit a U+003C LESS-THAN SIGN character token
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ /*
+ * and reconsume the current input character in
+ * the data state.
+ */
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case TAG_NAME:
+ tagnameloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ strBufToElementNameString();
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the before attribute name state.
+ */
+ strBufToElementNameString();
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break tagnameloop;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Switch to the self-closing
+ * start tag state.
+ */
+ strBufToElementNameString();
+ state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * tag token.
+ */
+ strBufToElementNameString();
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ if (c >= 'A' && c <= 'Z') {
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Append the
+ * lowercase version of the current input
+ * character (add 0x0020 to the character's
+ * code point) to the current tag token's
+ * tag name.
+ */
+ c += 0x20;
+ } else if (c == '-') {
+ containsHyphen = true;
+ }
+ /*
+ * Anything else Append the current input
+ * character to the current tag token's tag
+ * name.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the tag name state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BEFORE_ATTRIBUTE_NAME:
+ beforeattributenameloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the before attribute name state.
+ */
+ continue;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Switch to the self-closing
+ * start tag state.
+ */
+ state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * tag token.
+ */
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case '\"':
+ case '\'':
+ case '<':
+ case '=':
+ /*
+ * U+0022 QUOTATION MARK (") U+0027 APOSTROPHE
+ * (') U+003C LESS-THAN SIGN (<) U+003D EQUALS
+ * SIGN (=) Parse error.
+ */
+ errBadCharBeforeAttributeNameOrNull(c);
+ /*
+ * Treat it as per the "anything else" entry
+ * below.
+ */
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Start a new attribute in the
+ * current tag token.
+ */
+ if (c >= 'A' && c <= 'Z') {
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Set that
+ * attribute's name to the lowercase version
+ * of the current input character (add
+ * 0x0020 to the character's code point)
+ */
+ c += 0x20;
+ }
+ // CPPONLY: attributeLine = line;
+ /*
+ * Set that attribute's name to the current
+ * input character,
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ /*
+ * and its value to the empty string.
+ */
+ // Will do later.
+ /*
+ * Switch to the attribute name state.
+ */
+ state = transition(state, Tokenizer.ATTRIBUTE_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break beforeattributenameloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ATTRIBUTE_NAME:
+ attributenameloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ attributeNameComplete();
+ state = transition(state, Tokenizer.AFTER_ATTRIBUTE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the after attribute name state.
+ */
+ attributeNameComplete();
+ state = transition(state, Tokenizer.AFTER_ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Switch to the self-closing
+ * start tag state.
+ */
+ attributeNameComplete();
+ addAttributeWithoutValue();
+ state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
+ continue stateloop;
+ case '=':
+ /*
+ * U+003D EQUALS SIGN (=) Switch to the before
+ * attribute value state.
+ */
+ attributeNameComplete();
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_VALUE, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break attributenameloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * tag token.
+ */
+ attributeNameComplete();
+ addAttributeWithoutValue();
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case '\"':
+ case '\'':
+ case '<':
+ /*
+ * U+0022 QUOTATION MARK (") U+0027 APOSTROPHE
+ * (') U+003C LESS-THAN SIGN (<) Parse error.
+ */
+ errQuoteOrLtInAttributeNameOrNull(c);
+ /*
+ * Treat it as per the "anything else" entry
+ * below.
+ */
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ if (c >= 'A' && c <= 'Z') {
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Append the
+ * lowercase version of the current input
+ * character (add 0x0020 to the character's
+ * code point) to the current attribute's
+ * name.
+ */
+ c += 0x20;
+ }
+ /*
+ * Anything else Append the current input
+ * character to the current attribute's name.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the attribute name state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BEFORE_ATTRIBUTE_VALUE:
+ beforeattributevalueloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the before attribute value state.
+ */
+ continue;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Switch to the
+ * attribute value (double-quoted) state.
+ */
+ // CPPONLY: attributeLine = line;
+ clearStrBufBeforeUse();
+ state = transition(state, Tokenizer.ATTRIBUTE_VALUE_DOUBLE_QUOTED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break beforeattributevalueloop;
+ case '&':
+ /*
+ * U+0026 AMPERSAND (&) Switch to the attribute
+ * value (unquoted) state and reconsume this
+ * input character.
+ */
+ // CPPONLY: attributeLine = line;
+ clearStrBufBeforeUse();
+ reconsume = true;
+ state = transition(state, Tokenizer.ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos);
+ noteUnquotedAttributeValue();
+ continue stateloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Switch to the attribute
+ * value (single-quoted) state.
+ */
+ // CPPONLY: attributeLine = line;
+ clearStrBufBeforeUse();
+ state = transition(state, Tokenizer.ATTRIBUTE_VALUE_SINGLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Parse error.
+ */
+ errAttributeValueMissing();
+ /*
+ * Emit the current tag token.
+ */
+ addAttributeWithoutValue();
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case '<':
+ case '=':
+ case '`':
+ /*
+ * U+003C LESS-THAN SIGN (<) U+003D EQUALS SIGN
+ * (=) U+0060 GRAVE ACCENT (`)
+ */
+ errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c);
+ /*
+ * Treat it as per the "anything else" entry
+ * below.
+ */
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current attribute's value.
+ */
+ // CPPONLY: attributeLine = line;
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ /*
+ * Switch to the attribute value (unquoted)
+ * state.
+ */
+
+ state = transition(state, Tokenizer.ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos);
+ noteUnquotedAttributeValue();
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ attributevaluedoublequotedloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Switch to the after
+ * attribute value (quoted) state.
+ */
+ addAttributeWithValue();
+
+ state = transition(state, Tokenizer.AFTER_ATTRIBUTE_VALUE_QUOTED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break attributevaluedoublequotedloop;
+ case '&':
+ /*
+ * U+0026 AMPERSAND (&) Switch to the character
+ * reference in attribute value state, with the
+ * additional allowed character being U+0022
+ * QUOTATION MARK (").
+ */
+ assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\"');
+ returnState = state;
+ state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current attribute's value.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the attribute value (double-quoted)
+ * state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_ATTRIBUTE_VALUE_QUOTED:
+ afterattributevaluequotedloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the before attribute name state.
+ */
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Switch to the self-closing
+ * start tag state.
+ */
+ state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break afterattributevaluequotedloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * tag token.
+ */
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ default:
+ /*
+ * Anything else Parse error.
+ */
+ errNoSpaceBetweenAttributes();
+ /*
+ * Reconsume the character in the before
+ * attribute name state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SELF_CLOSING_START_TAG:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Set the self-closing
+ * flag of the current tag token. Emit the current
+ * tag token.
+ */
+ state = transition(state, emitCurrentTagToken(true, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ default:
+ /* Anything else Parse error. */
+ errSlashNotFollowedByGt();
+ /*
+ * Reconsume the character in the before attribute
+ * name state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ }
+ // no fallthrough, reordering opportunity
+ case ATTRIBUTE_VALUE_UNQUOTED:
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ addAttributeWithValue();
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the before attribute name state.
+ */
+ addAttributeWithValue();
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ case '&':
+ /*
+ * U+0026 AMPERSAND (&) Switch to the character
+ * reference in attribute value state, with the
+ * additional allowed character being U+003E
+ * GREATER-THAN SIGN (>)
+ */
+ assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('>');
+ returnState = state;
+ state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * tag token.
+ */
+ addAttributeWithValue();
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case '<':
+ case '\"':
+ case '\'':
+ case '=':
+ case '`':
+ /*
+ * U+0022 QUOTATION MARK (") U+0027 APOSTROPHE
+ * (') U+003C LESS-THAN SIGN (<) U+003D EQUALS
+ * SIGN (=) U+0060 GRAVE ACCENT (`) Parse error.
+ */
+ errUnquotedAttributeValOrNull(c);
+ /*
+ * Treat it as per the "anything else" entry
+ * below.
+ */
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current attribute's value.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the attribute value (unquoted) state.
+ */
+ continue;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case AFTER_ATTRIBUTE_NAME:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the after attribute name state.
+ */
+ continue;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Switch to the self-closing
+ * start tag state.
+ */
+ addAttributeWithoutValue();
+ state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
+ continue stateloop;
+ case '=':
+ /*
+ * U+003D EQUALS SIGN (=) Switch to the before
+ * attribute value state.
+ */
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_VALUE, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * tag token.
+ */
+ addAttributeWithoutValue();
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ /*
+ * Switch to the data state.
+ */
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case '\"':
+ case '\'':
+ case '<':
+ errQuoteOrLtInAttributeNameOrNull(c);
+ /*
+ * Treat it as per the "anything else" entry
+ * below.
+ */
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ addAttributeWithoutValue();
+ /*
+ * Anything else Start a new attribute in the
+ * current tag token.
+ */
+ if (c >= 'A' && c <= 'Z') {
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Set that
+ * attribute's name to the lowercase version
+ * of the current input character (add
+ * 0x0020 to the character's code point)
+ */
+ c += 0x20;
+ }
+ /*
+ * Set that attribute's name to the current
+ * input character,
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ /*
+ * and its value to the empty string.
+ */
+ // Will do later.
+ /*
+ * Switch to the attribute name state.
+ */
+ state = transition(state, Tokenizer.ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case MARKUP_DECLARATION_OPEN:
+ markupdeclarationopenloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * If the next two characters are both U+002D
+ * HYPHEN-MINUS characters (-), consume those two
+ * characters, create a comment token whose data is the
+ * empty string, and switch to the comment start state.
+ *
+ * Otherwise, if the next seven characters are an ASCII
+ * case-insensitive match for the word "DOCTYPE", then
+ * consume those characters and switch to the DOCTYPE
+ * state.
+ *
+ * Otherwise, if the insertion mode is
+ * "in foreign content" and the current node is not an
+ * element in the HTML namespace and the next seven
+ * characters are an case-sensitive match for the string
+ * "[CDATA[" (the five uppercase letters "CDATA" with a
+ * U+005B LEFT SQUARE BRACKET character before and
+ * after), then consume those characters and switch to
+ * the CDATA section state.
+ *
+ * Otherwise, is is a parse error. Switch to the bogus
+ * comment state. The next character that is consumed,
+ * if any, is the first character that will be in the
+ * comment.
+ */
+ switch (c) {
+ case '-':
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.MARKUP_DECLARATION_HYPHEN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break markupdeclarationopenloop;
+ case 'd':
+ case 'D':
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ index = 0;
+ state = transition(state, Tokenizer.MARKUP_DECLARATION_OCTYPE, reconsume, pos);
+ continue stateloop;
+ case '[':
+ if (tokenHandler.cdataSectionAllowed()) {
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ index = 0;
+ state = transition(state, Tokenizer.CDATA_START, reconsume, pos);
+ continue stateloop;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ errBogusComment();
+ clearStrBufBeforeUse();
+ reconsume = true;
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case MARKUP_DECLARATION_HYPHEN:
+ markupdeclarationhyphenloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-':
+ clearStrBufAfterOneHyphen();
+ state = transition(state, Tokenizer.COMMENT_START, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break markupdeclarationhyphenloop;
+ default:
+ errBogusComment();
+ reconsume = true;
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_START:
+ reportedConsecutiveHyphens = false;
+ commentstartloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Comment start state
+ *
+ *
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Switch to the comment
+ * start dash state.
+ */
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_START_DASH, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Parse error.
+ */
+ errPrematureEndOfComment();
+ /* Emit the comment token. */
+ emitComment(0, pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break commentstartloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the input character to
+ * the comment token's data.
+ */
+ appendStrBuf(c);
+ /*
+ * Switch to the comment state.
+ */
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break commentstartloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT:
+ commentloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Comment state Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Switch to the comment
+ * end dash state
+ */
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_END_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break commentloop;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the input character to
+ * the comment token's data.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the comment state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_END_DASH:
+ commentenddashloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Comment end dash state Consume the next input
+ * character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Switch to the comment
+ * end state
+ */
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_END, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break commentenddashloop;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append a U+002D HYPHEN-MINUS
+ * (-) character and the input character to the
+ * comment token's data.
+ */
+ appendStrBuf(c);
+ /*
+ * Switch to the comment state.
+ */
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_END:
+ commentendloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Comment end dash state Consume the next input
+ * character:
+ */
+ switch (c) {
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the comment
+ * token.
+ */
+ emitComment(2, pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '-':
+ /* U+002D HYPHEN-MINUS (-) Parse error. */
+ /*
+ * Append a U+002D HYPHEN-MINUS (-) character to
+ * the comment token's data.
+ */
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ /*
+ * Stay in the comment end state.
+ */
+ continue;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ adjustDoubleHyphenAndAppendToStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ adjustDoubleHyphenAndAppendToStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ case '!':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_END_BANG, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break commentendloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Append two U+002D HYPHEN-MINUS (-) characters
+ * and the input character to the comment
+ * token's data.
+ */
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ /*
+ * Switch to the comment state.
+ */
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_END_BANG:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Comment end bang state
+ *
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the comment
+ * token.
+ */
+ emitComment(3, pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '-':
+ /*
+ * Append two U+002D HYPHEN-MINUS (-) characters
+ * and a U+0021 EXCLAMATION MARK (!) character
+ * to the comment token's data.
+ */
+ appendStrBuf(c);
+ /*
+ * Switch to the comment end dash state.
+ */
+ state = transition(state, Tokenizer.COMMENT_END_DASH, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append two U+002D HYPHEN-MINUS
+ * (-) characters, a U+0021 EXCLAMATION MARK (!)
+ * character, and the input character to the
+ * comment token's data. Switch to the comment
+ * state.
+ */
+ appendStrBuf(c);
+ /*
+ * Switch to the comment state.
+ */
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case COMMENT_LESSTHAN:
+ commentlessthanloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '!':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN_BANG, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break commentlessthanloop;
+ case '<':
+ appendStrBuf(c);
+ continue;
+ case '-':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_END_DASH, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_LESSTHAN_BANG:
+ commentlessthanbangloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN_BANG_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break commentlessthanbangloop;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_LESSTHAN_BANG_DASH:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-':
+ appendStrBuf(c);
+ state = transition(state,
+ Tokenizer.COMMENT_LESSTHAN_BANG_DASH_DASH,
+ reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state,
+ Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT,
+ reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT,
+ reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT,
+ reconsume, pos);
+ continue stateloop;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case COMMENT_LESSTHAN_BANG_DASH_DASH:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>':
+ appendStrBuf(c);
+ emitComment(3, pos);
+ state = transition(state, Tokenizer.DATA, reconsume,
+ pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '-':
+ errNestedComment();
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c,
+ reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = transition(state, Tokenizer.COMMENT_END,
+ reconsume, pos);
+ continue stateloop;
+ case '\r':
+ c = '\n';
+ silentCarriageReturn();
+ errNestedComment();
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c,
+ reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = transition(state, Tokenizer.COMMENT,
+ reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ errNestedComment();
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c,
+ reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = transition(state, Tokenizer.COMMENT,
+ reconsume, pos);
+ continue stateloop;
+ case '!':
+ errNestedComment();
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c,
+ reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = transition(state,
+ Tokenizer.COMMENT_END_BANG, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ errNestedComment();
+ adjustDoubleHyphenAndAppendToStrBufAndErr(c,
+ reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = transition(state, Tokenizer.COMMENT,
+ reconsume, pos);
+ continue stateloop;
+ }
+ // no fallthrough, reordering opportunity
+ case COMMENT_START_DASH:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Comment start dash state
+ *
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Switch to the comment end
+ * state
+ */
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_END, reconsume, pos);
+ continue stateloop;
+ case '>':
+ errPrematureEndOfComment();
+ /* Emit the comment token. */
+ emitComment(1, pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '<':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.COMMENT_LESSTHAN, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Append a U+002D HYPHEN-MINUS character (-) and
+ * the current input character to the comment
+ * token's data.
+ */
+ appendStrBuf(c);
+ /*
+ * Switch to the comment state.
+ */
+ state = transition(state, Tokenizer.COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ // no fallthrough, reordering opportunity
+ case CDATA_START:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ if (index < 6) { // CDATA_LSQB.length
+ if (c == Tokenizer.CDATA_LSQB[index]) {
+ appendStrBuf(c);
+ } else {
+ errBogusComment();
+ reconsume = true;
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ index++;
+ continue;
+ } else {
+ clearStrBufAfterUse();
+ cstart = pos; // start coalescing
+ reconsume = true;
+ state = transition(state, Tokenizer.CDATA_SECTION, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case CDATA_SECTION:
+ cdatasectionloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case ']':
+ flushChars(buf, pos);
+ state = transition(state, Tokenizer.CDATA_RSQB, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break cdatasectionloop;
+ case '\u0000':
+ maybeEmitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case CDATA_RSQB:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case ']':
+ state = transition(state, Tokenizer.CDATA_RSQB_RSQB,
+ reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break;
+ default:
+ tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, Tokenizer.CDATA_SECTION,
+ reconsume, pos);
+ continue stateloop;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case CDATA_RSQB_RSQB:
+ cdatarsqbrsqb: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case ']':
+ // Saw a third ]. Emit one ] (logically the
+ // first one) and stay in this state to
+ // remember that the last two characters seen
+ // have been ]].
+ tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 1);
+ continue;
+ case '>':
+ cstart = pos + 1;
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ // Since a CDATA section starts with a less-than sign, it
+ // participates in the suspension-after-current-token
+ // behavior. (The suspension can be requested when the
+ // less-than sign has been seen but we don't yet know the
+ // resulting token type.) Therefore, we need to deal with
+ // a potential request here.
+ suspendIfRequestedAfterCurrentNonTextToken();
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 2);
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, Tokenizer.CDATA_SECTION, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ attributevaluesinglequotedloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Switch to the after
+ * attribute value (quoted) state.
+ */
+ addAttributeWithValue();
+
+ state = transition(state, Tokenizer.AFTER_ATTRIBUTE_VALUE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '&':
+ /*
+ * U+0026 AMPERSAND (&) Switch to the character
+ * reference in attribute value state, with the
+ * + additional allowed character being U+0027
+ * APOSTROPHE (').
+ */
+ assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\'');
+ returnState = state;
+ state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break attributevaluesinglequotedloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current attribute's value.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the attribute value (double-quoted)
+ * state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case CONSUME_CHARACTER_REFERENCE:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Unlike the definition is the spec, this state does not
+ * return a value and never requires the caller to
+ * backtrack. This state takes care of emitting characters
+ * or appending to the current attribute value. It also
+ * takes care of that in the case when consuming the
+ * character reference fails.
+ */
+ /*
+ * This section defines how to consume a character
+ * reference. This definition is used when parsing character
+ * references in text and in attributes.
+ *
+ * The behavior depends on the identity of the next
+ * character (the one immediately after the U+0026 AMPERSAND
+ * character):
+ */
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r': // we'll reconsume!
+ case '\u000C':
+ case '<':
+ case '&':
+ case '\u0000':
+ case ';':
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ case '#':
+ /*
+ * U+0023 NUMBER SIGN (#) Consume the U+0023 NUMBER
+ * SIGN.
+ */
+ appendCharRefBuf('#');
+ state = transition(state, Tokenizer.CONSUME_NCR, reconsume, pos);
+ continue stateloop;
+ default:
+ if (c == additional) {
+ emitOrAppendCharRefBuf(returnState);
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ if (c >= 'a' && c <= 'z') {
+ firstCharKey = c - 'a' + 26;
+ } else if (c >= 'A' && c <= 'Z') {
+ firstCharKey = c - 'A';
+ } else {
+ // No match
+ if (c == ';') {
+ errNoNamedCharacterMatch();
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ // Didn't fail yet
+ appendCharRefBuf(c);
+ state = transition(state, Tokenizer.CHARACTER_REFERENCE_HILO_LOOKUP, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case CHARACTER_REFERENCE_HILO_LOOKUP:
+ {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * The data structure is as follows:
+ *
+ * HILO_ACCEL is a two-dimensional int array whose major
+ * index corresponds to the second character of the
+ * character reference (code point as index) and the
+ * minor index corresponds to the first character of the
+ * character reference (packed so that A-Z runs from 0
+ * to 25 and a-z runs from 26 to 51). This layout makes
+ * it easier to use the sparseness of the data structure
+ * to omit parts of it: The second dimension of the
+ * table is null when no character reference starts with
+ * the character corresponding to that row.
+ *
+ * The int value HILO_ACCEL (by these indeces) is zero
+ * if there exists no character reference starting with
+ * that two-letter prefix. Otherwise, the value is an
+ * int that packs two shorts so that the higher short is
+ * the index of the highest character reference name
+ * with that prefix in NAMES and the lower short
+ * corresponds to the index of the lowest character
+ * reference name with that prefix. (It happens that the
+ * first two character reference names share their
+ * prefix so the packed int cannot be 0 by packing the
+ * two shorts.)
+ *
+ * NAMES is an array of byte arrays where each byte
+ * array encodes the name of a character references as
+ * ASCII. The names omit the first two letters of the
+ * name. (Since storing the first two letters would be
+ * redundant with the data contained in HILO_ACCEL.) The
+ * entries are lexically sorted.
+ *
+ * For a given index in NAMES, the same index in VALUES
+ * contains the corresponding expansion as an array of
+ * two UTF-16 code units (either the character and
+ * U+0000 or a suggogate pair).
+ */
+ int hilo = 0;
+ if (c <= 'z') {
+ @Const @NoLength int[] row = NamedCharactersAccel.HILO_ACCEL[c];
+ if (row != null) {
+ hilo = row[firstCharKey];
+ }
+ }
+ if (hilo == 0) {
+ if (c == ';') {
+ errNoNamedCharacterMatch();
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ // Didn't fail yet
+ appendCharRefBuf(c);
+ lo = hilo & 0xFFFF;
+ hi = hilo >> 16;
+ entCol = -1;
+ candidate = -1;
+ charRefBufMark = 0;
+ state = transition(state, Tokenizer.CHARACTER_REFERENCE_TAIL, reconsume, pos);
+ // fallthrough optimizes; `continue stateloop;` would also be valid
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case CHARACTER_REFERENCE_TAIL:
+ outer: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ entCol++;
+ /*
+ * Consume the maximum number of characters possible,
+ * with the consumed characters matching one of the
+ * identifiers in the first column of the named
+ * character references table (in a case-sensitive
+ * manner).
+ */
+ loloop: for (;;) {
+ if (hi < lo) {
+ break outer;
+ }
+ if (entCol == NamedCharacters.NAMES[lo].length()) {
+ candidate = lo;
+ charRefBufMark = charRefBufLen;
+ lo++;
+ } else if (entCol > NamedCharacters.NAMES[lo].length()) {
+ break outer;
+ } else if (c > NamedCharacters.NAMES[lo].charAt(entCol)) {
+ lo++;
+ } else {
+ break loloop;
+ }
+ }
+
+ hiloop: for (;;) {
+ if (hi < lo) {
+ break outer;
+ }
+ if (entCol == NamedCharacters.NAMES[hi].length()) {
+ break hiloop;
+ }
+ if (entCol > NamedCharacters.NAMES[hi].length()) {
+ break outer;
+ } else if (c < NamedCharacters.NAMES[hi].charAt(entCol)) {
+ hi--;
+ } else {
+ break hiloop;
+ }
+ }
+
+ if (c == ';') {
+ // If we see a semicolon, there cannot be a
+ // longer match. Break the loop. However, before
+ // breaking, take the longest match so far as the
+ // candidate, if we are just about to complete a
+ // match.
+ if (entCol + 1 == NamedCharacters.NAMES[lo].length()) {
+ candidate = lo;
+ charRefBufMark = charRefBufLen;
+ }
+ break outer;
+ }
+
+ if (hi < lo) {
+ break outer;
+ }
+ appendCharRefBuf(c);
+ continue;
+ }
+
+ if (candidate == -1) {
+ // reconsume deals with CR, LF or nul
+ if (c == ';') {
+ errNoNamedCharacterMatch();
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ } else {
+ // c can't be CR, LF or nul if we got here
+ @Const @CharacterName String candidateName = NamedCharacters.NAMES[candidate];
+ if (candidateName.length() == 0
+ || candidateName.charAt(candidateName.length() - 1) != ';') {
+ /*
+ * If the last character matched is not a U+003B
+ * SEMICOLON (;), there is a parse error.
+ */
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ /*
+ * If the entity is being consumed as part of an
+ * attribute, and the last character matched is
+ * not a U+003B SEMICOLON (;),
+ */
+ char ch;
+ if (charRefBufMark == charRefBufLen) {
+ ch = c;
+ } else {
+ ch = charRefBuf[charRefBufMark];
+ }
+ if (ch == '=' || (ch >= '0' && ch <= '9')
+ || (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')) {
+ /*
+ * and the next character is either a U+003D
+ * EQUALS SIGN character (=) or in the range
+ * U+0030 DIGIT ZERO to U+0039 DIGIT NINE,
+ * U+0041 LATIN CAPITAL LETTER A to U+005A
+ * LATIN CAPITAL LETTER Z, or U+0061 LATIN
+ * SMALL LETTER A to U+007A LATIN SMALL
+ * LETTER Z, then, for historical reasons,
+ * all the characters that were matched
+ * after the U+0026 AMPERSAND (&) must be
+ * unconsumed, and nothing is returned.
+ */
+ if (c == ';') {
+ errNoNamedCharacterMatch();
+ }
+ appendCharRefBufToStrBuf();
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ errUnescapedAmpersandInterpretedAsCharacterReference();
+ } else {
+ errNotSemicolonTerminated();
+ }
+ }
+
+ /*
+ * Otherwise, return a character token for the character
+ * corresponding to the entity name (as given by the
+ * second column of the named character references
+ * table).
+ */
+ // CPPONLY: completedNamedCharacterReference();
+ @Const @NoLength char[] val = NamedCharacters.VALUES[candidate];
+ if (
+ // [NOCPP[
+ val.length == 1
+ // ]NOCPP]
+ // CPPONLY: val[1] == 0
+ ) {
+ emitOrAppendOne(val, returnState);
+ } else {
+ emitOrAppendTwo(val, returnState);
+ }
+ // this is so complicated!
+ if (charRefBufMark < charRefBufLen) {
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ appendStrBuf(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ } else {
+ tokenHandler.characters(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ }
+ }
+ // charRefBufLen will be zeroed below!
+
+ // Check if we broke out early with c being the last
+ // character that matched as opposed to being the
+ // first one that didn't match. In the case of an
+ // early break, the next run on text should start
+ // *after* the current character and the current
+ // character shouldn't be reconsumed.
+ boolean earlyBreak = (c == ';' && charRefBufMark == charRefBufLen);
+ charRefBufLen = 0;
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = earlyBreak ? pos + 1 : pos;
+ }
+ reconsume = !earlyBreak;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ /*
+ * If the markup contains I'm &notit; I tell you, the
+ * entity is parsed as "not", as in, I'm ¬it; I tell
+ * you. But if the markup was I'm &notin; I tell you,
+ * the entity would be parsed as "notin;", resulting in
+ * I'm ∉ I tell you.
+ */
+ }
+ // no fallthrough, reordering opportunity
+ case CONSUME_NCR:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ value = 0;
+ seenDigits = false;
+ /*
+ * The behavior further depends on the character after the
+ * U+0023 NUMBER SIGN:
+ */
+ switch (c) {
+ case 'x':
+ case 'X':
+
+ /*
+ * U+0078 LATIN SMALL LETTER X U+0058 LATIN CAPITAL
+ * LETTER X Consume the X.
+ *
+ * Follow the steps below, but using the range of
+ * characters U+0030 DIGIT ZERO through to U+0039
+ * DIGIT NINE, U+0061 LATIN SMALL LETTER A through
+ * to U+0066 LATIN SMALL LETTER F, and U+0041 LATIN
+ * CAPITAL LETTER A, through to U+0046 LATIN CAPITAL
+ * LETTER F (in other words, 0-9, A-F, a-f).
+ *
+ * When it comes to interpreting the number,
+ * interpret it as a hexadecimal number.
+ */
+ appendCharRefBuf(c);
+ state = transition(state, Tokenizer.HEX_NCR_LOOP, reconsume, pos);
+ continue stateloop;
+ default:
+ /*
+ * Anything else Follow the steps below, but using
+ * the range of characters U+0030 DIGIT ZERO through
+ * to U+0039 DIGIT NINE (i.e. just 0-9).
+ *
+ * When it comes to interpreting the number,
+ * interpret it as a decimal number.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.DECIMAL_NRC_LOOP, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DECIMAL_NRC_LOOP:
+ decimalloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume as many characters as match the range of
+ * characters given above.
+ */
+ assert value >= 0: "value must not become negative.";
+ if (c >= '0' && c <= '9') {
+ seenDigits = true;
+ // Avoid overflow
+ if (value <= 0x10FFFF) {
+ value *= 10;
+ value += c - '0';
+ }
+ continue;
+ } else if (c == ';') {
+ if (seenDigits) {
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos + 1;
+ }
+ state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break decimalloop;
+ } else {
+ errNoDigitsInNCR();
+ appendCharRefBuf(';');
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos + 1;
+ }
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ } else {
+ /*
+ * If no characters match the range, then don't
+ * consume any characters (and unconsume the U+0023
+ * NUMBER SIGN character and, if appropriate, the X
+ * character). This is a parse error; nothing is
+ * returned.
+ *
+ * Otherwise, if the next character is a U+003B
+ * SEMICOLON, consume that too. If it isn't, there
+ * is a parse error.
+ */
+ if (!seenDigits) {
+ errNoDigitsInNCR();
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ } else {
+ errCharRefLacksSemicolon();
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break decimalloop;
+ }
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case HANDLE_NCR_VALUE:
+ // WARNING previous state sets reconsume
+ // We are not going to emit the contents of charRefBuf.
+ charRefBufLen = 0;
+ // XXX inline this case if the method size can take it
+ handleNcrValue(returnState);
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ // no fallthrough, reordering opportunity
+ case HEX_NCR_LOOP:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume as many characters as match the range of
+ * characters given above.
+ */
+ assert value >= 0: "value must not become negative.";
+ if (c >= '0' && c <= '9') {
+ seenDigits = true;
+ // Avoid overflow
+ if (value <= 0x10FFFF) {
+ value *= 16;
+ value += c - '0';
+ }
+ continue;
+ } else if (c >= 'A' && c <= 'F') {
+ seenDigits = true;
+ // Avoid overflow
+ if (value <= 0x10FFFF) {
+ value *= 16;
+ value += c - 'A' + 10;
+ }
+ continue;
+ } else if (c >= 'a' && c <= 'f') {
+ seenDigits = true;
+ // Avoid overflow
+ if (value <= 0x10FFFF) {
+ value *= 16;
+ value += c - 'a' + 10;
+ }
+ continue;
+ } else if (c == ';') {
+ if (seenDigits) {
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos + 1;
+ }
+ state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos);
+ continue stateloop;
+ } else {
+ errNoDigitsInNCR();
+ appendCharRefBuf(';');
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos + 1;
+ }
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ } else {
+ /*
+ * If no characters match the range, then don't
+ * consume any characters (and unconsume the U+0023
+ * NUMBER SIGN character and, if appropriate, the X
+ * character). This is a parse error; nothing is
+ * returned.
+ *
+ * Otherwise, if the next character is a U+003B
+ * SEMICOLON, consume that too. If it isn't, there
+ * is a parse error.
+ */
+ if (!seenDigits) {
+ errNoDigitsInNCR();
+ emitOrAppendCharRefBuf(returnState);
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ } else {
+ errCharRefLacksSemicolon();
+ if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = transition(state, Tokenizer.HANDLE_NCR_VALUE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case PLAINTEXT:
+ plaintextloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\u0000':
+ emitPlaintextReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Stay in the
+ * RAWTEXT state.
+ */
+ continue;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case CLOSE_TAG_OPEN:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Otherwise, if the content model flag is set to the PCDATA
+ * state, or if the next few characters do match that tag
+ * name, consume the next input character:
+ */
+ switch (c) {
+ case '>':
+ /* U+003E GREATER-THAN SIGN (>) Parse error. */
+ errLtSlashGt();
+ /*
+ * Switch to the data state.
+ */
+ cstart = pos + 1;
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ silentCarriageReturn();
+ /* Anything else Parse error. */
+ errGarbageAfterLtSlash();
+ /*
+ * Switch to the bogus comment state.
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf('\n');
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ /* Anything else Parse error. */
+ errGarbageAfterLtSlash();
+ /*
+ * Switch to the bogus comment state.
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ }
+ if (c >= 'a' && c <= 'z') {
+ /*
+ * U+0061 LATIN SMALL LETTER A through to U+007A
+ * LATIN SMALL LETTER Z Create a new end tag
+ * token,
+ */
+ endTag = true;
+ /*
+ * set its tag name to the input character,
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ containsHyphen = false;
+ /*
+ * then switch to the tag name state. (Don't
+ * emit the token yet; further details will be
+ * filled in before it is emitted.)
+ */
+ state = transition(state, Tokenizer.TAG_NAME, reconsume, pos);
+ continue stateloop;
+ } else {
+ /* Anything else Parse error. */
+ errGarbageAfterLtSlash();
+ /*
+ * Switch to the bogus comment state.
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case RCDATA:
+ rcdataloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '&':
+ /*
+ * U+0026 AMPERSAND (&) Switch to the character
+ * reference in RCDATA state.
+ */
+ flushChars(buf, pos);
+ assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\u0000');
+ returnState = state;
+ state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
+ continue stateloop;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the
+ * RCDATA less-than sign state.
+ */
+ flushChars(buf, pos);
+
+ returnState = state;
+ state = transition(state, Tokenizer.RAWTEXT_RCDATA_LESS_THAN_SIGN, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Emit the current input character as a
+ * character token. Stay in the RCDATA state.
+ */
+ continue;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case RAWTEXT:
+ rawtextloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the
+ * RAWTEXT less-than sign state.
+ */
+ flushChars(buf, pos);
+
+ returnState = state;
+ state = transition(state, Tokenizer.RAWTEXT_RCDATA_LESS_THAN_SIGN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break rawtextloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Emit the current input character as a
+ * character token. Stay in the RAWTEXT state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case RAWTEXT_RCDATA_LESS_THAN_SIGN:
+ rawtextrcdatalessthansignloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Set the temporary buffer
+ * to the empty string. Switch to the script
+ * data end tag open state.
+ */
+ index = 0;
+ clearStrBufBeforeUse();
+ state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break rawtextrcdatalessthansignloop;
+ default:
+ /*
+ * Otherwise, emit a U+003C LESS-THAN SIGN
+ * character token
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ /*
+ * and reconsume the current input character in
+ * the data state.
+ */
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case NON_DATA_END_TAG_NAME:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * ASSERT! when entering this state, set index to 0 and
+ * call clearStrBufBeforeUse(); Let's implement the above
+ * without lookahead. strBuf is the 'temporary buffer'.
+ */
+ if (endTagExpectationAsArray == null) {
+ tokenHandler.characters(Tokenizer.LT_SOLIDUS,
+ 0, 2);
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ } else if (index < endTagExpectationAsArray.length) {
+ char e = endTagExpectationAsArray[index];
+ char folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != e) {
+ // [NOCPP[
+ errHtml4LtSlashInRcdata(folded);
+ // ]NOCPP]
+ tokenHandler.characters(Tokenizer.LT_SOLIDUS,
+ 0, 2);
+ emitStrBuf();
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ appendStrBuf(c);
+ index++;
+ continue;
+ } else {
+ endTag = true;
+ // XXX replace contentModelElement with different
+ // type
+ tagName = endTagExpectation;
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ clearStrBufAfterUse(); // strBuf not used
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE
+ * FEED (LF) U+000C FORM FEED (FF) U+0020
+ * SPACE If the current end tag token is an
+ * appropriate end tag token, then switch to
+ * the before attribute name state.
+ */
+ clearStrBufAfterUse(); // strBuf not used
+ state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
+ continue stateloop;
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) If the current end tag
+ * token is an appropriate end tag token,
+ * then switch to the self-closing start tag
+ * state.
+ */
+ clearStrBufAfterUse(); // strBuf not used
+ state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) If the
+ * current end tag token is an appropriate
+ * end tag token, then emit the current tag
+ * token and switch to the data state.
+ */
+ clearStrBufAfterUse(); // strBuf not used
+ state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ /*
+ * Emit a U+003C LESS-THAN SIGN character
+ * token, a U+002F SOLIDUS character token,
+ * a character token for each of the
+ * characters in the temporary buffer (in
+ * the order they were added to the buffer),
+ * and reconsume the current input character
+ * in the RAWTEXT state.
+ */
+ // [NOCPP[
+ errWarnLtSlashInRcdata();
+ // ]NOCPP]
+ tokenHandler.characters(
+ Tokenizer.LT_SOLIDUS, 0, 2);
+ emitStrBuf();
+ cstart = pos; // don't drop the
+ // character
+ reconsume = true;
+ state = transition(state, returnState, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ }
+ // no fallthrough, reordering opportunity
+ // BEGIN HOTSPOT WORKAROUND
+ case BOGUS_COMMENT:
+ boguscommentloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume every character up to and including the first
+ * U+003E GREATER-THAN SIGN character (>) or the end of
+ * the file (EOF), whichever comes first. Emit a comment
+ * token whose data is the concatenation of all the
+ * characters starting from and including the character
+ * that caused the state machine to switch into the
+ * bogus comment state, up to and including the
+ * character immediately before the last consumed
+ * character (i.e. up to the character just before the
+ * U+003E or EOF character). (If the comment was started
+ * by the end of the file (EOF), the token is empty.)
+ *
+ * Switch to the data state.
+ *
+ * If the end of the file was reached, reconsume the EOF
+ * character.
+ */
+ switch (c) {
+ case '>':
+ emitComment(0, pos);
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '-':
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.BOGUS_COMMENT_HYPHEN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break boguscommentloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BOGUS_COMMENT_HYPHEN:
+ boguscommenthyphenloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>':
+ // [NOCPP[
+ maybeAppendSpaceToBogusComment();
+ // ]NOCPP]
+ emitComment(0, pos);
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '-':
+ appendSecondHyphenToBogusComment();
+ continue boguscommenthyphenloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ appendStrBuf(c);
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case SCRIPT_DATA:
+ scriptdataloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the
+ * script data less-than sign state.
+ */
+ flushChars(buf, pos);
+ returnState = state;
+ state = transition(state, Tokenizer.SCRIPT_DATA_LESS_THAN_SIGN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Stay in the
+ * script data state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_LESS_THAN_SIGN:
+ scriptdatalessthansignloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Set the temporary buffer
+ * to the empty string. Switch to the script
+ * data end tag open state.
+ */
+ index = 0;
+ clearStrBufBeforeUse();
+ state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos);
+ continue stateloop;
+ case '!':
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ cstart = pos;
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPE_START, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdatalessthansignloop;
+ default:
+ /*
+ * Otherwise, emit a U+003C LESS-THAN SIGN
+ * character token
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ /*
+ * and reconsume the current input character in
+ * the data state.
+ */
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_ESCAPE_START:
+ scriptdataescapestartloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Switch to the
+ * script data escape start dash state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPE_START_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataescapestartloop;
+ default:
+ /*
+ * Anything else Reconsume the current input
+ * character in the script data state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_ESCAPE_START_DASH:
+ scriptdataescapestartdashloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Switch to the
+ * script data escaped dash dash state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_DASH_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataescapestartdashloop;
+ default:
+ /*
+ * Anything else Reconsume the current input
+ * character in the script data state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_ESCAPED_DASH_DASH:
+ scriptdataescapeddashdashloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Stay in the
+ * script data escaped dash dash state.
+ */
+ continue;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the
+ * script data escaped less-than sign state.
+ */
+ flushChars(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit a U+003E
+ * GREATER-THAN SIGN character token. Switch to
+ * the script data state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ break scriptdataescapeddashdashloop;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Switch to the
+ * script data escaped state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataescapeddashdashloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_ESCAPED:
+ scriptdataescapedloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Switch to the
+ * script data escaped dash state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataescapedloop;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the
+ * script data escaped less-than sign state.
+ */
+ flushChars(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Stay in the
+ * script data escaped state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_ESCAPED_DASH:
+ scriptdataescapeddashloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Switch to the
+ * script data escaped dash dash state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_DASH_DASH, reconsume, pos);
+ continue stateloop;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Switch to the
+ * script data escaped less-than sign state.
+ */
+ flushChars(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataescapeddashloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Switch to the
+ * script data escaped state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
+ scriptdataescapedlessthanloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Set the temporary buffer
+ * to the empty string. Switch to the script
+ * data escaped end tag open state.
+ */
+ index = 0;
+ clearStrBufBeforeUse();
+ returnState = Tokenizer.SCRIPT_DATA_ESCAPED;
+ state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos);
+ continue stateloop;
+ case 'S':
+ case 's':
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Emit a U+003C
+ * LESS-THAN SIGN character token and the
+ * current input character as a character token.
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ cstart = pos;
+ index = 1;
+ /*
+ * Set the temporary buffer to the empty string.
+ * Append the lowercase version of the current
+ * input character (add 0x0020 to the
+ * character's code point) to the temporary
+ * buffer. Switch to the script data double
+ * escape start state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPE_START, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdataescapedlessthanloop;
+ default:
+ /*
+ * Anything else Emit a U+003C LESS-THAN SIGN
+ * character token and reconsume the current
+ * input character in the script data escaped
+ * state.
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_DOUBLE_ESCAPE_START:
+ scriptdatadoubleescapestartloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ assert index > 0;
+ if (index < 6) { // SCRIPT_ARR.length
+ char folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != Tokenizer.SCRIPT_ARR[index]) {
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ index++;
+ continue;
+ }
+ switch (c) {
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ case '/':
+ case '>':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * U+002F SOLIDUS (/) U+003E GREATER-THAN SIGN
+ * (>) Emit the current input character as a
+ * character token. If the temporary buffer is
+ * the string "script", then switch to the
+ * script data double escaped state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdatadoubleescapestartloop;
+ default:
+ /*
+ * Anything else Reconsume the current input
+ * character in the script data escaped state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_DOUBLE_ESCAPED:
+ scriptdatadoubleescapedloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Switch to the
+ * script data double escaped dash state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdatadoubleescapedloop;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Emit a U+003C
+ * LESS-THAN SIGN character token. Switch to the
+ * script data double escaped less-than sign
+ * state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ continue;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Stay in the
+ * script data double escaped state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH:
+ scriptdatadoubleescapeddashloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Switch to the
+ * script data double escaped dash dash state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdatadoubleescapeddashloop;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Emit a U+003C
+ * LESS-THAN SIGN character token. Switch to the
+ * script data double escaped less-than sign
+ * state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Switch to the
+ * script data double escaped state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH:
+ scriptdatadoubleescapeddashdashloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '-':
+ /*
+ * U+002D HYPHEN-MINUS (-) Emit a U+002D
+ * HYPHEN-MINUS character token. Stay in the
+ * script data double escaped dash dash state.
+ */
+ continue;
+ case '<':
+ /*
+ * U+003C LESS-THAN SIGN (<) Emit a U+003C
+ * LESS-THAN SIGN character token. Switch to the
+ * script data double escaped less-than sign
+ * state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdatadoubleescapeddashdashloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit a U+003E
+ * GREATER-THAN SIGN character token. Switch to
+ * the script data state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA, reconsume, pos);
+ continue stateloop;
+ case '\u0000':
+ emitReplacementCharacter(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Emit the current input
+ * character as a character token. Switch to the
+ * script data double escaped state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN:
+ scriptdatadoubleescapedlessthanloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '/':
+ /*
+ * U+002F SOLIDUS (/) Emit a U+002F SOLIDUS
+ * character token. Set the temporary buffer to
+ * the empty string. Switch to the script data
+ * double escape end state.
+ */
+ index = 0;
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPE_END, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break scriptdatadoubleescapedlessthanloop;
+ default:
+ /*
+ * Anything else Reconsume the current input
+ * character in the script data double escaped
+ * state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case SCRIPT_DATA_DOUBLE_ESCAPE_END:
+ scriptdatadoubleescapeendloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ if (index < 6) { // SCRIPT_ARR.length
+ char folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != Tokenizer.SCRIPT_ARR[index]) {
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ index++;
+ continue;
+ }
+ switch (c) {
+ case '\r':
+ emitCarriageReturn(buf, pos);
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ case '/':
+ case '>':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * U+002F SOLIDUS (/) U+003E GREATER-THAN SIGN
+ * (>) Emit the current input character as a
+ * character token. If the temporary buffer is
+ * the string "script", then switch to the
+ * script data escaped state.
+ */
+ state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPED, reconsume, pos);
+ continue stateloop;
+ default:
+ /*
+ * Reconsume the current input character in the
+ * script data double escaped state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case MARKUP_DECLARATION_OCTYPE:
+ markupdeclarationdoctypeloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ if (index < 6) { // OCTYPE.length
+ char folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded == Tokenizer.OCTYPE[index]) {
+ appendStrBuf(c);
+ } else {
+ errBogusComment();
+ reconsume = true;
+ state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
+ continue stateloop;
+ }
+ index++;
+ continue;
+ } else {
+ reconsume = true;
+ state = transition(state, Tokenizer.DOCTYPE, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break markupdeclarationdoctypeloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DOCTYPE:
+ doctypeloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ initDoctypeFields();
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the before DOCTYPE name state.
+ */
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypeloop;
+ default:
+ /*
+ * Anything else Parse error.
+ */
+ errMissingSpaceBeforeDoctypeName();
+ /*
+ * Reconsume the current character in the before
+ * DOCTYPE name state.
+ */
+ reconsume = true;
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypeloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BEFORE_DOCTYPE_NAME:
+ beforedoctypenameloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the before DOCTYPE name state.
+ */
+ continue;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Parse error.
+ */
+ errNamelessDoctype();
+ /*
+ * Create a new DOCTYPE token. Set its
+ * force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit the token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ if (c >= 'A' && c <= 'Z') {
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Create a
+ * new DOCTYPE token. Set the token's name
+ * to the lowercase version of the input
+ * character (add 0x0020 to the character's
+ * code point).
+ */
+ c += 0x20;
+ }
+ /* Anything else Create a new DOCTYPE token. */
+ /*
+ * Set the token's name name to the current
+ * input character.
+ */
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ /*
+ * Switch to the DOCTYPE name state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break beforedoctypenameloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DOCTYPE_NAME:
+ doctypenameloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ strBufToDoctypeName();
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_NAME, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the after DOCTYPE name state.
+ */
+ strBufToDoctypeName();
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_NAME, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypenameloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * DOCTYPE token.
+ */
+ strBufToDoctypeName();
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * U+0041 LATIN CAPITAL LETTER A through to
+ * U+005A LATIN CAPITAL LETTER Z Append the
+ * lowercase version of the input character (add
+ * 0x0020 to the character's code point) to the
+ * current DOCTYPE token's name.
+ */
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x0020;
+ }
+ /*
+ * Anything else Append the current input
+ * character to the current DOCTYPE token's
+ * name.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the DOCTYPE name state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_DOCTYPE_NAME:
+ afterdoctypenameloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the after DOCTYPE name state.
+ */
+ continue;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case 'p':
+ case 'P':
+ index = 0;
+ state = transition(state, Tokenizer.DOCTYPE_UBLIC, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break afterdoctypenameloop;
+ case 's':
+ case 'S':
+ index = 0;
+ state = transition(state, Tokenizer.DOCTYPE_YSTEM, reconsume, pos);
+ continue stateloop;
+ default:
+ /*
+ * Otherwise, this is the parse error.
+ */
+ bogusDoctype();
+
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DOCTYPE_UBLIC:
+ doctypeublicloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * If the six characters starting from the current input
+ * character are an ASCII case-insensitive match for the
+ * word "PUBLIC", then consume those characters and
+ * switch to the before DOCTYPE public identifier state.
+ */
+ if (index < 5) { // UBLIC.length
+ char folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != Tokenizer.UBLIC[index]) {
+ bogusDoctype();
+ // forceQuirks = true;
+ reconsume = true;
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ index++;
+ continue;
+ } else {
+ reconsume = true;
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_PUBLIC_KEYWORD, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypeublicloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ afterdoctypepublickeywordloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the before DOCTYPE public
+ * identifier state.
+ */
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break afterdoctypepublickeywordloop;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Parse Error.
+ */
+ errNoSpaceBetweenDoctypePublicKeywordAndQuote();
+ /*
+ * Set the DOCTYPE token's public identifier to
+ * the empty string (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE public identifier
+ * (double-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Parse Error.
+ */
+ errNoSpaceBetweenDoctypePublicKeywordAndQuote();
+ /*
+ * Set the DOCTYPE token's public identifier to
+ * the empty string (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE public identifier
+ * (single-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /* U+003E GREATER-THAN SIGN (>) Parse error. */
+ errExpectedPublicId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ bogusDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
+ beforedoctypepublicidentifierloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the before DOCTYPE public identifier
+ * state.
+ */
+ continue;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Set the DOCTYPE
+ * token's public identifier to the empty string
+ * (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE public identifier
+ * (double-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break beforedoctypepublicidentifierloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Set the DOCTYPE token's
+ * public identifier to the empty string (not
+ * missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE public identifier
+ * (single-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /* U+003E GREATER-THAN SIGN (>) Parse error. */
+ errExpectedPublicId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ bogusDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ doctypepublicidentifierdoublequotedloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Switch to the after
+ * DOCTYPE public identifier state.
+ */
+ publicIdentifier = strBufToString();
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypepublicidentifierdoublequotedloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Parse error.
+ */
+ errGtInPublicId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ publicIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current DOCTYPE token's
+ * public identifier.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the DOCTYPE public identifier
+ * (double-quoted) state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ afterdoctypepublicidentifierloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ state = transition(state, Tokenizer.BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the between DOCTYPE public and
+ * system identifiers state.
+ */
+ state = transition(state, Tokenizer.BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break afterdoctypepublicidentifierloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Parse error.
+ */
+ errNoSpaceBetweenPublicAndSystemIds();
+ /*
+ * Set the DOCTYPE token's system identifier to
+ * the empty string (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE system identifier
+ * (double-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Parse error.
+ */
+ errNoSpaceBetweenPublicAndSystemIds();
+ /*
+ * Set the DOCTYPE token's system identifier to
+ * the empty string (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE system identifier
+ * (single-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ default:
+ bogusDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
+ betweendoctypepublicandsystemidentifiersloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the between DOCTYPE public and system
+ * identifiers state.
+ */
+ continue;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Set the DOCTYPE
+ * token's system identifier to the empty string
+ * (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE system identifier
+ * (double-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break betweendoctypepublicandsystemidentifiersloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Set the DOCTYPE token's
+ * system identifier to the empty string (not
+ * missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE system identifier
+ * (single-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ default:
+ bogusDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ doctypesystemidentifierdoublequotedloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Switch to the after
+ * DOCTYPE system identifier state.
+ */
+ systemIdentifier = strBufToString();
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypesystemidentifierdoublequotedloop;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Parse error.
+ */
+ errGtInSystemId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ systemIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current DOCTYPE token's
+ * system identifier.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the DOCTYPE system identifier
+ * (double-quoted) state.
+ */
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
+ afterdoctypesystemidentifierloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the after DOCTYPE system identifier state.
+ */
+ continue;
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit the current
+ * DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ /*
+ * Switch to the bogus DOCTYPE state. (This does
+ * not set the DOCTYPE token's force-quirks flag
+ * to on.)
+ */
+ bogusDoctypeWithoutQuirks();
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break afterdoctypesystemidentifierloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BOGUS_DOCTYPE:
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '>':
+ /*
+ * U+003E GREATER-THAN SIGN (>) Emit that
+ * DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Stay in the bogus DOCTYPE
+ * state.
+ */
+ continue;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case DOCTYPE_YSTEM:
+ doctypeystemloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Otherwise, if the six characters starting from the
+ * current input character are an ASCII case-insensitive
+ * match for the word "SYSTEM", then consume those
+ * characters and switch to the before DOCTYPE system
+ * identifier state.
+ */
+ if (index < 5) { // YSTEM.length
+ char folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != Tokenizer.YSTEM[index]) {
+ bogusDoctype();
+ reconsume = true;
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ index++;
+ continue stateloop;
+ } else {
+ reconsume = true;
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_SYSTEM_KEYWORD, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break doctypeystemloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ afterdoctypesystemkeywordloop: for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ }
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos);
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE
+ * Switch to the before DOCTYPE public
+ * identifier state.
+ */
+ state = transition(state, Tokenizer.BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break afterdoctypesystemkeywordloop;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Parse Error.
+ */
+ errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
+ /*
+ * Set the DOCTYPE token's system identifier to
+ * the empty string (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE public identifier
+ * (double-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Parse Error.
+ */
+ errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
+ /*
+ * Set the DOCTYPE token's public identifier to
+ * the empty string (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE public identifier
+ * (single-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '>':
+ /* U+003E GREATER-THAN SIGN (>) Parse error. */
+ errExpectedPublicId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ bogusDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ beforedoctypesystemidentifierloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\r':
+ silentCarriageReturn();
+ break stateloop;
+ case '\n':
+ silentLineFeed();
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case ' ':
+ case '\t':
+ case '\u000C':
+ /*
+ * U+0009 CHARACTER TABULATION U+000A LINE FEED
+ * (LF) U+000C FORM FEED (FF) U+0020 SPACE Stay
+ * in the before DOCTYPE system identifier
+ * state.
+ */
+ continue;
+ case '"':
+ /*
+ * U+0022 QUOTATION MARK (") Set the DOCTYPE
+ * token's system identifier to the empty string
+ * (not missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE system identifier
+ * (double-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
+ continue stateloop;
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Set the DOCTYPE token's
+ * system identifier to the empty string (not
+ * missing),
+ */
+ clearStrBufBeforeUse();
+ /*
+ * then switch to the DOCTYPE system identifier
+ * (single-quoted) state.
+ */
+ state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break beforedoctypesystemidentifierloop;
+ case '>':
+ /* U+003E GREATER-THAN SIGN (>) Parse error. */
+ errExpectedSystemId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ bogusDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ // done by bogusDoctype();
+ /*
+ * Switch to the bogus DOCTYPE state.
+ */
+ state = transition(state, Tokenizer.BOGUS_DOCTYPE, reconsume, pos);
+ continue stateloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Switch to the after
+ * DOCTYPE system identifier state.
+ */
+ systemIdentifier = strBufToString();
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos);
+ continue stateloop;
+ case '>':
+ errGtInSystemId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ systemIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current DOCTYPE token's
+ * system identifier.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the DOCTYPE system identifier
+ * (double-quoted) state.
+ */
+ continue;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
+ for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ /*
+ * Consume the next input character:
+ */
+ switch (c) {
+ case '\'':
+ /*
+ * U+0027 APOSTROPHE (') Switch to the after
+ * DOCTYPE public identifier state.
+ */
+ publicIdentifier = strBufToString();
+ state = transition(state, Tokenizer.AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos);
+ continue stateloop;
+ case '>':
+ errGtInPublicId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ publicIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ /*
+ * Switch to the data state.
+ */
+ state = transition(state, Tokenizer.DATA, reconsume, pos);
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ case '\r':
+ appendStrBufCarriageReturn();
+ break stateloop;
+ case '\n':
+ appendStrBufLineFeed();
+ continue;
+ case '\u0000':
+ c = '\uFFFD';
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ /*
+ * Anything else Append the current input
+ * character to the current DOCTYPE token's
+ * public identifier.
+ */
+ appendStrBuf(c);
+ /*
+ * Stay in the DOCTYPE public identifier
+ * (single-quoted) state.
+ */
+ continue;
+ }
+ }
+ // no fallthrough, reordering opportunity
+ case PROCESSING_INSTRUCTION:
+ processinginstructionloop: for (;;) {
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '?':
+ state = transition(
+ state,
+ Tokenizer.PROCESSING_INSTRUCTION_QUESTION_MARK,
+ reconsume, pos);
+ // `break` optimizes; `continue stateloop;` would be valid
+ break processinginstructionloop;
+ default:
+ continue;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case PROCESSING_INSTRUCTION_QUESTION_MARK:
+ if (++pos == endPos) {
+ break stateloop;
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>':
+ state = transition(state, Tokenizer.DATA,
+ reconsume, pos);
+ // Processing instruction syntax goes through these
+ // states only in Gecko's XML View Source--not in HTML
+ // parsing in Java or in Gecko.
+ // Since XML View Source doesn't use the
+ // suspension-after-current-token facility, its extension
+ // to processing-instruction states is strictly unnecessary
+ // at the moment. However, if these states ever were to be
+ // used together with the suspension-after-current-token
+ // facility, these states would need to participate, since
+ // suspension could be requested when only less-than has been
+ // seen and we don't yet know if we end up here. Handling
+ // the currently-unnecessary case in order to avoid leaving
+ // a trap for future modification.
+ suspendIfRequestedAfterCurrentNonTextToken();
+ if (shouldSuspend) {
+ break stateloop;
+ }
+ continue stateloop;
+ default:
+ state = transition(state,
+ Tokenizer.PROCESSING_INSTRUCTION,
+ reconsume, pos);
+ continue stateloop;
+ }
+ // END HOTSPOT WORKAROUND
+ }
+ }
+ flushChars(buf, pos);
+ /*
+ * if (prevCR && pos != endPos) { // why is this needed? pos--; col--; }
+ */
+ // Save locals
+ stateSave = state;
+ returnStateSave = returnState;
+ return pos;
+ }
+
+ // HOTSPOT WORKAROUND INSERTION POINT
+
+ // [NOCPP[
+
+ protected int transition(int from, int to, boolean reconsume, int pos) throws SAXException {
+ return to;
+ }
+
+ // ]NOCPP]
+
+ private void initDoctypeFields() {
+ // Discard the characters "DOCTYPE" accumulated as a potential bogus
+ // comment into strBuf.
+ clearStrBufAfterUse();
+ doctypeName = null;
+ if (systemIdentifier != null) {
+ Portability.releaseString(systemIdentifier);
+ systemIdentifier = null;
+ }
+ if (publicIdentifier != null) {
+ Portability.releaseString(publicIdentifier);
+ publicIdentifier = null;
+ }
+ forceQuirks = false;
+ }
+
+ @Inline private void adjustDoubleHyphenAndAppendToStrBufCarriageReturn()
+ throws SAXException {
+ silentCarriageReturn();
+ adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false);
+ }
+
+ @Inline private void adjustDoubleHyphenAndAppendToStrBufLineFeed()
+ throws SAXException {
+ silentLineFeed();
+ adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false);
+ }
+
+ @Inline private void appendStrBufLineFeed() {
+ silentLineFeed();
+ appendStrBuf('\n');
+ }
+
+ @Inline private void appendStrBufCarriageReturn() {
+ silentCarriageReturn();
+ appendStrBuf('\n');
+ }
+
+ // [NOCPP[
+
+ @Inline protected void silentCarriageReturn() {
+ ++line;
+ lastCR = true;
+ }
+
+ @Inline protected void silentLineFeed() {
+ ++line;
+ }
+
+ // ]NOCPP]
+
+ private void emitCarriageReturn(@NoLength char[] buf, int pos)
+ throws SAXException {
+ silentCarriageReturn();
+ flushChars(buf, pos);
+ tokenHandler.characters(Tokenizer.LF, 0, 1);
+ cstart = Integer.MAX_VALUE;
+ }
+
+ private void emitReplacementCharacter(@NoLength char[] buf, int pos)
+ throws SAXException {
+ flushChars(buf, pos);
+ tokenHandler.zeroOriginatingReplacementCharacter();
+ cstart = pos + 1;
+ }
+
+ private void maybeEmitReplacementCharacter(@NoLength char[] buf, int pos)
+ throws SAXException {
+ flushChars(buf, pos);
+ tokenHandler.zeroOrReplacementCharacter();
+ cstart = pos + 1;
+ }
+
+ private void emitPlaintextReplacementCharacter(@NoLength char[] buf, int pos)
+ throws SAXException {
+ flushChars(buf, pos);
+ tokenHandler.characters(REPLACEMENT_CHARACTER, 0, 1);
+ cstart = pos + 1;
+ }
+
+ private void setAdditionalAndRememberAmpersandLocation(char add) {
+ additional = add;
+ // [NOCPP[
+ ampersandLocation = new LocatorImpl(this);
+ // ]NOCPP]
+ }
+
+ private void bogusDoctype() throws SAXException {
+ errBogusDoctype();
+ forceQuirks = true;
+ }
+
+ private void bogusDoctypeWithoutQuirks() throws SAXException {
+ errBogusDoctype();
+ forceQuirks = false;
+ }
+
+ private void handleNcrValue(int returnState) throws SAXException {
+ /*
+ * If one or more characters match the range, then take them all and
+ * interpret the string of characters as a number (either hexadecimal or
+ * decimal as appropriate).
+ */
+ if (value <= 0xFFFF) {
+ if (value >= 0x80 && value <= 0x9f) {
+ /*
+ * If that number is one of the numbers in the first column of
+ * the following table, then this is a parse error.
+ */
+ errNcrInC1Range();
+ /*
+ * Find the row with that number in the first column, and return
+ * a character token for the Unicode character given in the
+ * second column of that row.
+ */
+ @NoLength char[] val = NamedCharacters.WINDOWS_1252[value - 0x80];
+ emitOrAppendOne(val, returnState);
+ // [NOCPP[
+ } else if (value == 0xC
+ && contentSpacePolicy != XmlViolationPolicy.ALLOW) {
+ if (contentSpacePolicy == XmlViolationPolicy.ALTER_INFOSET) {
+ emitOrAppendOne(Tokenizer.SPACE, returnState);
+ } else if (contentSpacePolicy == XmlViolationPolicy.FATAL) {
+ fatal("A character reference expanded to a form feed which is not legal XML 1.0 white space.");
+ }
+ // ]NOCPP]
+ } else if (value == 0x0) {
+ errNcrZero();
+ emitOrAppendOne(Tokenizer.REPLACEMENT_CHARACTER, returnState);
+ } else if ((value & 0xF800) == 0xD800) {
+ errNcrSurrogate();
+ emitOrAppendOne(Tokenizer.REPLACEMENT_CHARACTER, returnState);
+ } else {
+ /*
+ * Otherwise, return a character token for the Unicode character
+ * whose code point is that number.
+ */
+ char ch = (char) value;
+ // [NOCPP[
+ if (value == 0x0D) {
+ errNcrCr();
+ } else if ((value <= 0x0008) || (value == 0x000B)
+ || (value >= 0x000E && value <= 0x001F)) {
+ ch = errNcrControlChar(ch);
+ } else if (value >= 0xFDD0 && value <= 0xFDEF) {
+ errNcrUnassigned();
+ } else if ((value & 0xFFFE) == 0xFFFE) {
+ ch = errNcrNonCharacter(ch);
+ } else if (value >= 0x007F && value <= 0x009F) {
+ errNcrControlChar();
+ } else {
+ maybeWarnPrivateUse(ch);
+ }
+ // ]NOCPP]
+ bmpChar[0] = ch;
+ emitOrAppendOne(bmpChar, returnState);
+ }
+ } else if (value <= 0x10FFFF) {
+ // [NOCPP[
+ maybeWarnPrivateUseAstral();
+ if ((value & 0xFFFE) == 0xFFFE) {
+ errAstralNonCharacter(value);
+ }
+ // ]NOCPP]
+ astralChar[0] = (char) (Tokenizer.LEAD_OFFSET + (value >> 10));
+ astralChar[1] = (char) (0xDC00 + (value & 0x3FF));
+ emitOrAppendTwo(astralChar, returnState);
+ } else {
+ errNcrOutOfRange();
+ emitOrAppendOne(Tokenizer.REPLACEMENT_CHARACTER, returnState);
+ }
+ }
+
+ public void eof() throws SAXException {
+ int state = stateSave;
+ int returnState = returnStateSave;
+
+ eofloop: for (;;) {
+ switch (state) {
+ case SCRIPT_DATA_LESS_THAN_SIGN:
+ case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
+ /*
+ * Otherwise, emit a U+003C LESS-THAN SIGN character token
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ /*
+ * and reconsume the current input character in the data
+ * state.
+ */
+ break eofloop;
+ case TAG_OPEN:
+ /*
+ * The behavior of this state depends on the content model
+ * flag.
+ */
+ /*
+ * Anything else Parse error.
+ */
+ errEofAfterLt();
+ /*
+ * Emit a U+003C LESS-THAN SIGN character token
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ /*
+ * and reconsume the current input character in the data
+ * state.
+ */
+ break eofloop;
+ case RAWTEXT_RCDATA_LESS_THAN_SIGN:
+ /*
+ * Emit a U+003C LESS-THAN SIGN character token
+ */
+ tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
+ /*
+ * and reconsume the current input character in the RCDATA
+ * state.
+ */
+ break eofloop;
+ case NON_DATA_END_TAG_NAME:
+ /*
+ * Emit a U+003C LESS-THAN SIGN character token, a U+002F
+ * SOLIDUS character token,
+ */
+ tokenHandler.characters(Tokenizer.LT_SOLIDUS, 0, 2);
+ /*
+ * a character token for each of the characters in the
+ * temporary buffer (in the order they were added to the
+ * buffer),
+ */
+ emitStrBuf();
+ /*
+ * and reconsume the current input character in the RCDATA
+ * state.
+ */
+ break eofloop;
+ case CLOSE_TAG_OPEN:
+ /* EOF Parse error. */
+ errEofAfterLt();
+ /*
+ * Emit a U+003C LESS-THAN SIGN character token and a U+002F
+ * SOLIDUS character token.
+ */
+ tokenHandler.characters(Tokenizer.LT_SOLIDUS, 0, 2);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case TAG_NAME:
+ /*
+ * EOF Parse error.
+ */
+ errEofInTagName();
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case BEFORE_ATTRIBUTE_NAME:
+ case AFTER_ATTRIBUTE_VALUE_QUOTED:
+ case SELF_CLOSING_START_TAG:
+ /* EOF Parse error. */
+ errEofWithoutGt();
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case ATTRIBUTE_NAME:
+ /*
+ * EOF Parse error.
+ */
+ errEofInAttributeName();
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case AFTER_ATTRIBUTE_NAME:
+ case BEFORE_ATTRIBUTE_VALUE:
+ /* EOF Parse error. */
+ errEofWithoutGt();
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ case ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ case ATTRIBUTE_VALUE_UNQUOTED:
+ /* EOF Parse error. */
+ errEofInAttributeValue();
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case BOGUS_COMMENT:
+ emitComment(0, 0);
+ break eofloop;
+ case BOGUS_COMMENT_HYPHEN:
+ // [NOCPP[
+ maybeAppendSpaceToBogusComment();
+ // ]NOCPP]
+ emitComment(0, 0);
+ break eofloop;
+ case MARKUP_DECLARATION_OPEN:
+ errBogusComment();
+ emitComment(0, 0);
+ break eofloop;
+ case MARKUP_DECLARATION_HYPHEN:
+ errBogusComment();
+ emitComment(0, 0);
+ break eofloop;
+ case MARKUP_DECLARATION_OCTYPE:
+ if (index < 6) {
+ errBogusComment();
+ emitComment(0, 0);
+ } else {
+ /* EOF Parse error. */
+ errEofInDoctype();
+ /*
+ * Create a new DOCTYPE token. Set its force-quirks flag
+ * to on.
+ */
+ doctypeName = null;
+ if (systemIdentifier != null) {
+ Portability.releaseString(systemIdentifier);
+ systemIdentifier = null;
+ }
+ if (publicIdentifier != null) {
+ Portability.releaseString(publicIdentifier);
+ publicIdentifier = null;
+ }
+ forceQuirks = true;
+ /*
+ * Emit the token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ }
+ break eofloop;
+ case COMMENT_START:
+ case COMMENT:
+ case COMMENT_LESSTHAN:
+ case COMMENT_LESSTHAN_BANG:
+ /*
+ * EOF Parse error.
+ */
+ errEofInComment();
+ /* Emit the comment token. */
+ emitComment(0, 0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case COMMENT_END:
+ case COMMENT_LESSTHAN_BANG_DASH_DASH:
+ errEofInComment();
+ /* Emit the comment token. */
+ emitComment(2, 0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case COMMENT_END_DASH:
+ case COMMENT_START_DASH:
+ case COMMENT_LESSTHAN_BANG_DASH:
+ errEofInComment();
+ /* Emit the comment token. */
+ emitComment(1, 0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case COMMENT_END_BANG:
+ errEofInComment();
+ /* Emit the comment token. */
+ emitComment(3, 0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case DOCTYPE:
+ case BEFORE_DOCTYPE_NAME:
+ errEofInDoctype();
+ /*
+ * Create a new DOCTYPE token. Set its force-quirks flag to
+ * on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit the token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case DOCTYPE_NAME:
+ errEofInDoctype();
+ strBufToDoctypeName();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case DOCTYPE_UBLIC:
+ case DOCTYPE_YSTEM:
+ case AFTER_DOCTYPE_NAME:
+ case AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ case AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
+ errEofInDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
+ /* EOF Parse error. */
+ errEofInPublicId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ publicIdentifier = strBufToString();
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
+ errEofInDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
+ /* EOF Parse error. */
+ errEofInSystemId();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ systemIdentifier = strBufToString();
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
+ errEofInDoctype();
+ /*
+ * Set the DOCTYPE token's force-quirks flag to on.
+ */
+ forceQuirks = true;
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case BOGUS_DOCTYPE:
+ /*
+ * Emit that DOCTYPE token.
+ */
+ emitDoctypeToken(0);
+ /*
+ * Reconsume the EOF character in the data state.
+ */
+ break eofloop;
+ case CONSUME_CHARACTER_REFERENCE:
+ /*
+ * Unlike the definition is the spec, this state does not
+ * return a value and never requires the caller to
+ * backtrack. This state takes care of emitting characters
+ * or appending to the current attribute value. It also
+ * takes care of that in the case when consuming the entity
+ * fails.
+ */
+ /*
+ * This section defines how to consume an entity. This
+ * definition is used when parsing entities in text and in
+ * attributes.
+ *
+ * The behavior depends on the identity of the next
+ * character (the one immediately after the U+0026 AMPERSAND
+ * character):
+ */
+
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue;
+ case CHARACTER_REFERENCE_HILO_LOOKUP:
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue;
+ case CHARACTER_REFERENCE_TAIL:
+ outer: for (;;) {
+ char c = '\u0000';
+ entCol++;
+ /*
+ * Consume the maximum number of characters possible,
+ * with the consumed characters matching one of the
+ * identifiers in the first column of the named
+ * character references table (in a case-sensitive
+ * manner).
+ */
+ hiloop: for (;;) {
+ if (hi == -1) {
+ break hiloop;
+ }
+ if (entCol == NamedCharacters.NAMES[hi].length()) {
+ break hiloop;
+ }
+ if (entCol > NamedCharacters.NAMES[hi].length()) {
+ break outer;
+ } else if (c < NamedCharacters.NAMES[hi].charAt(entCol)) {
+ hi--;
+ } else {
+ break hiloop;
+ }
+ }
+
+ loloop: for (;;) {
+ if (hi < lo) {
+ break outer;
+ }
+ if (entCol == NamedCharacters.NAMES[lo].length()) {
+ candidate = lo;
+ charRefBufMark = charRefBufLen;
+ lo++;
+ } else if (entCol > NamedCharacters.NAMES[lo].length()) {
+ break outer;
+ } else if (c > NamedCharacters.NAMES[lo].charAt(entCol)) {
+ lo++;
+ } else {
+ break loloop;
+ }
+ }
+ if (hi < lo) {
+ break outer;
+ }
+ continue;
+ }
+
+ if (candidate == -1) {
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue eofloop;
+ } else {
+ @Const @CharacterName String candidateName = NamedCharacters.NAMES[candidate];
+ if (candidateName.length() == 0
+ || candidateName.charAt(candidateName.length() - 1) != ';') {
+ /*
+ * If the last character matched is not a U+003B
+ * SEMICOLON (;), there is a parse error.
+ */
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ /*
+ * If the entity is being consumed as part of an
+ * attribute, and the last character matched is
+ * not a U+003B SEMICOLON (;),
+ */
+ char ch;
+ if (charRefBufMark == charRefBufLen) {
+ ch = '\u0000';
+ } else {
+ ch = charRefBuf[charRefBufMark];
+ }
+ if ((ch >= '0' && ch <= '9')
+ || (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')) {
+ /*
+ * and the next character is in the range
+ * U+0030 DIGIT ZERO to U+0039 DIGIT NINE,
+ * U+0041 LATIN CAPITAL LETTER A to U+005A
+ * LATIN CAPITAL LETTER Z, or U+0061 LATIN
+ * SMALL LETTER A to U+007A LATIN SMALL
+ * LETTER Z, then, for historical reasons,
+ * all the characters that were matched
+ * after the U+0026 AMPERSAND (&) must be
+ * unconsumed, and nothing is returned.
+ */
+ appendCharRefBufToStrBuf();
+ state = returnState;
+ continue eofloop;
+ }
+ }
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ errUnescapedAmpersandInterpretedAsCharacterReference();
+ } else {
+ errNotSemicolonTerminated();
+ }
+ }
+
+ /*
+ * Otherwise, return a character token for the character
+ * corresponding to the entity name (as given by the
+ * second column of the named character references
+ * table).
+ */
+ @Const @NoLength char[] val = NamedCharacters.VALUES[candidate];
+ if (
+ // [NOCPP[
+ val.length == 1
+ // ]NOCPP]
+ // CPPONLY: val[1] == 0
+ ) {
+ emitOrAppendOne(val, returnState);
+ } else {
+ emitOrAppendTwo(val, returnState);
+ }
+ // this is so complicated!
+ if (charRefBufMark < charRefBufLen) {
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ appendStrBuf(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ } else {
+ tokenHandler.characters(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ }
+ }
+ charRefBufLen = 0;
+ state = returnState;
+ continue eofloop;
+ /*
+ * If the markup contains I'm &notit; I tell you, the
+ * entity is parsed as "not", as in, I'm ¬it; I tell
+ * you. But if the markup was I'm &notin; I tell you,
+ * the entity would be parsed as "notin;", resulting in
+ * I'm ∉ I tell you.
+ */
+ }
+ case CONSUME_NCR:
+ case DECIMAL_NRC_LOOP:
+ case HEX_NCR_LOOP:
+ /*
+ * If no characters match the range, then don't consume any
+ * characters (and unconsume the U+0023 NUMBER SIGN
+ * character and, if appropriate, the X character). This is
+ * a parse error; nothing is returned.
+ *
+ * Otherwise, if the next character is a U+003B SEMICOLON,
+ * consume that too. If it isn't, there is a parse error.
+ */
+ if (!seenDigits) {
+ errNoDigitsInNCR();
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue;
+ } else {
+ errCharRefLacksSemicolon();
+ }
+ // WARNING previous state sets reconsume
+ handleNcrValue(returnState);
+ state = returnState;
+ continue;
+ case CDATA_RSQB:
+ tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 1);
+ break eofloop;
+ case CDATA_RSQB_RSQB:
+ tokenHandler.characters(Tokenizer.RSQB_RSQB, 0, 2);
+ break eofloop;
+ case DATA:
+ default:
+ break eofloop;
+ }
+ }
+ // case DATA:
+ /*
+ * EOF Emit an end-of-file token.
+ */
+ tokenHandler.eof();
+ return;
+ }
+
+ /**
+ * Emits a doctype token.
+ *
+ * NOTE: The method may set <code>shouldSuspend</code>, so the caller
+ * must have this pattern after the state's <code>transition</code> call:
+ * <pre>
+ * if (shouldSuspend) {
+ * break stateloop;
+ * }
+ * continue stateloop;
+ * </pre>
+ *
+ * @param pos
+ * @throws SAXException
+ */
+ private void emitDoctypeToken(int pos) throws SAXException {
+ // CPPONLY: RememberGt(pos);
+ cstart = pos + 1;
+ tokenHandler.doctype(doctypeName, publicIdentifier, systemIdentifier,
+ forceQuirks);
+ // It is OK and sufficient to release these here, since
+ // there's no way out of the doctype states than through paths
+ // that call this method.
+ doctypeName = null;
+ Portability.releaseString(publicIdentifier);
+ publicIdentifier = null;
+ Portability.releaseString(systemIdentifier);
+ systemIdentifier = null;
+ suspendIfRequestedAfterCurrentNonTextToken();
+ }
+
+ /**
+ * If a previous call to <code>suspendAfterCurrentTokenIfNotInText()</code>
+ * happened in a non-text context, this method turns that deferred suspension
+ * request into an immediately-pending suspension request.
+ */
+ private void suspendIfRequestedAfterCurrentNonTextToken() {
+ if (suspendAfterCurrentNonTextToken) {
+ suspendAfterCurrentNonTextToken = false;
+ shouldSuspend = true;
+ }
+ }
+
+ // Making this private until the full Java implementation is done.
+ /**
+ * Request suspension after the current token if the tokenizer is currently
+ * in a non-text state (i.e. it's known that the next token will be a
+ * non-text token).
+ *
+ * Must not be called when <code>tokenizeBuffer()</code> is on the call
+ * stack.
+ */
+ @SuppressWarnings("unused") private void suspendAfterCurrentTokenIfNotInText() {
+ switch (stateSave) {
+ case DATA:
+ case RCDATA:
+ case SCRIPT_DATA:
+ case RAWTEXT:
+ case SCRIPT_DATA_ESCAPED:
+ case PLAINTEXT:
+ case NON_DATA_END_TAG_NAME: // We haven't yet committed to the next
+ // token being a non-text token, though
+ // it could be.
+ case SCRIPT_DATA_LESS_THAN_SIGN:
+ case SCRIPT_DATA_ESCAPE_START:
+ case SCRIPT_DATA_ESCAPE_START_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH_DASH:
+ case RAWTEXT_RCDATA_LESS_THAN_SIGN:
+ case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_START:
+ case SCRIPT_DATA_DOUBLE_ESCAPED:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_END:
+ return;
+ case TAG_NAME:
+ case BEFORE_ATTRIBUTE_NAME:
+ case ATTRIBUTE_NAME:
+ case AFTER_ATTRIBUTE_NAME:
+ case BEFORE_ATTRIBUTE_VALUE:
+ case AFTER_ATTRIBUTE_VALUE_QUOTED:
+ case BOGUS_COMMENT:
+ case MARKUP_DECLARATION_OPEN:
+ case DOCTYPE:
+ case BEFORE_DOCTYPE_NAME:
+ case DOCTYPE_NAME:
+ case AFTER_DOCTYPE_NAME:
+ case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
+ case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
+ case AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
+ case AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
+ case BOGUS_DOCTYPE:
+ case COMMENT_START:
+ case COMMENT_START_DASH:
+ case COMMENT:
+ case COMMENT_END_DASH:
+ case COMMENT_END:
+ case COMMENT_END_BANG:
+ case TAG_OPEN:
+ case CLOSE_TAG_OPEN:
+ case MARKUP_DECLARATION_HYPHEN:
+ case MARKUP_DECLARATION_OCTYPE:
+ case DOCTYPE_UBLIC:
+ case DOCTYPE_YSTEM:
+ case AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
+ case AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ case SELF_CLOSING_START_TAG:
+ case ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ case ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ case ATTRIBUTE_VALUE_UNQUOTED:
+ case BOGUS_COMMENT_HYPHEN:
+ case COMMENT_LESSTHAN:
+ case COMMENT_LESSTHAN_BANG:
+ case COMMENT_LESSTHAN_BANG_DASH:
+ case COMMENT_LESSTHAN_BANG_DASH_DASH:
+ case CDATA_START:
+ case CDATA_SECTION:
+ case CDATA_RSQB:
+ case CDATA_RSQB_RSQB:
+ case PROCESSING_INSTRUCTION:
+ case PROCESSING_INSTRUCTION_QUESTION_MARK:
+ break;
+ case CONSUME_CHARACTER_REFERENCE:
+ case CONSUME_NCR:
+ case CHARACTER_REFERENCE_TAIL:
+ case HEX_NCR_LOOP:
+ case DECIMAL_NRC_LOOP:
+ case HANDLE_NCR_VALUE:
+ case HANDLE_NCR_VALUE_RECONSUME:
+ case CHARACTER_REFERENCE_HILO_LOOKUP:
+ if (returnStateSave == DATA || returnStateSave == RCDATA) {
+ return;
+ }
+ break;
+ default:
+ assert false : "Incomplete switch";
+ return;
+ }
+ suspendAfterCurrentNonTextToken = true;
+ }
+
+ // Making this private until the full Java implementation is done.
+ /**
+ * Queries if we are about to suspend after the current non-text token due to a request
+ * from <code>suspendAfterCurrentTokenIfNotInText()</code>.
+ * @return <code>true</code> iff <code>suspendAfterCurrentTokenIfNotInText()</code> was
+ * called in a non-text position and the then-current token has not been emitted yet.
+ */
+ @SuppressWarnings("unused") private boolean suspensionAfterCurrentNonTextTokenPending() {
+ return suspendAfterCurrentNonTextToken;
+ }
+
+ // [NOCPP[
+
+ @Inline protected char checkChar(@NoLength char[] buf, int pos)
+ throws SAXException {
+ return buf[pos];
+ }
+
+ // ]NOCPP]
+
+ public boolean internalEncodingDeclaration(String internalCharset)
+ throws SAXException {
+ if (encodingDeclarationHandler != null) {
+ return encodingDeclarationHandler.internalEncodingDeclaration(internalCharset);
+ }
+ return false;
+ }
+
+ /**
+ * @param val
+ * @throws SAXException
+ */
+ private void emitOrAppendTwo(@Const @NoLength char[] val, int returnState)
+ throws SAXException {
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ appendStrBuf(val[0]);
+ appendStrBuf(val[1]);
+ } else {
+ tokenHandler.characters(val, 0, 2);
+ }
+ }
+
+ private void emitOrAppendOne(@Const @NoLength char[] val, int returnState)
+ throws SAXException {
+ if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
+ appendStrBuf(val[0]);
+ } else {
+ tokenHandler.characters(val, 0, 1);
+ }
+ }
+
+ public void end() throws SAXException {
+ strBuf = null;
+ doctypeName = null;
+ if (systemIdentifier != null) {
+ Portability.releaseString(systemIdentifier);
+ systemIdentifier = null;
+ }
+ if (publicIdentifier != null) {
+ Portability.releaseString(publicIdentifier);
+ publicIdentifier = null;
+ }
+ tagName = null;
+ nonInternedTagName.setNameForNonInterned(null
+ // CPPONLY: , false
+ );
+ attributeName = null;
+ // CPPONLY: nonInternedAttributeName.setNameForNonInterned(null);
+ tokenHandler.endTokenization();
+ if (attributes != null) {
+ // [NOCPP[
+ attributes = null;
+ // ]NOCPP]
+ // CPPONLY: attributes.clear(mappingLangToXmlLang);
+ }
+ }
+
+ public void requestSuspension() {
+ shouldSuspend = true;
+ }
+
+ // [NOCPP[
+
+ public void becomeConfident() {
+ confident = true;
+ }
+
+ /**
+ * Returns the nextCharOnNewLine.
+ *
+ * @return the nextCharOnNewLine
+ */
+ public boolean isNextCharOnNewLine() {
+ return false;
+ }
+
+ public boolean isPrevCR() {
+ return lastCR;
+ }
+
+ /**
+ * Returns the line.
+ *
+ * @return the line
+ */
+ public int getLine() {
+ return -1;
+ }
+
+ /**
+ * Returns the col.
+ *
+ * @return the col
+ */
+ public int getCol() {
+ return -1;
+ }
+
+ // ]NOCPP]
+
+ public boolean isInDataState() {
+ return (stateSave == DATA);
+ }
+
+ public void resetToDataState() {
+ clearStrBufAfterUse();
+ charRefBufLen = 0;
+ stateSave = Tokenizer.DATA;
+ // line = 1; XXX line numbers
+ lastCR = false;
+ index = 0;
+ forceQuirks = false;
+ additional = '\u0000';
+ entCol = -1;
+ firstCharKey = -1;
+ lo = 0;
+ hi = 0; // will always be overwritten before use anyway
+ candidate = -1;
+ charRefBufMark = 0;
+ value = 0;
+ seenDigits = false;
+ suspendAfterCurrentNonTextToken = false;
+ endTag = false;
+ shouldSuspend = false;
+ initDoctypeFields();
+ containsHyphen = false;
+ tagName = null;
+ attributeName = null;
+ if (newAttributesEachTime) {
+ if (attributes != null) {
+ Portability.delete(attributes);
+ attributes = null;
+ }
+ }
+ }
+
+ public void loadState(Tokenizer other) throws SAXException {
+ strBufLen = other.strBufLen;
+ if (strBufLen > strBuf.length) {
+ strBuf = new char[strBufLen];
+ }
+ System.arraycopy(other.strBuf, 0, strBuf, 0, strBufLen);
+
+ charRefBufLen = other.charRefBufLen;
+ System.arraycopy(other.charRefBuf, 0, charRefBuf, 0, charRefBufLen);
+
+ stateSave = other.stateSave;
+ returnStateSave = other.returnStateSave;
+ endTagExpectation = other.endTagExpectation;
+ endTagExpectationAsArray = other.endTagExpectationAsArray;
+ // line = 1; XXX line numbers
+ lastCR = other.lastCR;
+ index = other.index;
+ forceQuirks = other.forceQuirks;
+ additional = other.additional;
+ entCol = other.entCol;
+ firstCharKey = other.firstCharKey;
+ lo = other.lo;
+ hi = other.hi;
+ candidate = other.candidate;
+ charRefBufMark = other.charRefBufMark;
+ value = other.value;
+ seenDigits = other.seenDigits;
+ endTag = other.endTag;
+ shouldSuspend = false;
+ suspendAfterCurrentNonTextToken = false;
+ doctypeName = other.doctypeName;
+
+ Portability.releaseString(systemIdentifier);
+ if (other.systemIdentifier == null) {
+ systemIdentifier = null;
+ } else {
+ systemIdentifier = Portability.newStringFromString(other.systemIdentifier);
+ }
+
+ Portability.releaseString(publicIdentifier);
+ if (other.publicIdentifier == null) {
+ publicIdentifier = null;
+ } else {
+ publicIdentifier = Portability.newStringFromString(other.publicIdentifier);
+ }
+
+ containsHyphen = other.containsHyphen;
+ if (other.tagName == null) {
+ tagName = null;
+ } else if (other.tagName.isInterned()) {
+ tagName = other.tagName;
+ } else {
+ // In the C++ case, the atoms in the other tokenizer are from a
+ // different tokenizer-scoped atom table. Therefore, we have to
+ // obtain the correspoding atom from our own atom table.
+ nonInternedTagName.setNameForNonInterned(other.tagName.getName()
+ // CPPONLY: , other.tagName.isCustom()
+ );
+ tagName = nonInternedTagName;
+ }
+
+ // [NOCPP[
+ attributeName = other.attributeName;
+ // ]NOCPP]
+ // CPPONLY: if (other.attributeName == null) {
+ // CPPONLY: attributeName = null;
+ // CPPONLY: } else if (other.attributeName.isInterned()) {
+ // CPPONLY: attributeName = other.attributeName;
+ // CPPONLY: } else {
+ // CPPONLY: // In the C++ case, the atoms in the other tokenizer are from a
+ // CPPONLY: // different tokenizer-scoped atom table. Therefore, we have to
+ // CPPONLY: // obtain the correspoding atom from our own atom table.
+ // CPPONLY: nonInternedAttributeName.setNameForNonInterned(other.attributeName.getLocal(AttributeName.HTML));
+ // CPPONLY: attributeName = nonInternedAttributeName;
+ // CPPONLY: }
+
+ Portability.delete(attributes);
+ if (other.attributes == null) {
+ attributes = null;
+ } else {
+ attributes = other.attributes.cloneAttributes();
+ }
+ }
+
+ public void initializeWithoutStarting() throws SAXException {
+ confident = false;
+ strBuf = null;
+ line = 1;
+ // CPPONLY: attributeLine = 1;
+ // [NOCPP[
+ metaBoundaryPassed = false;
+ wantsComments = tokenHandler.wantsComments();
+ if (!newAttributesEachTime) {
+ attributes = new HtmlAttributes(mappingLangToXmlLang);
+ }
+ // ]NOCPP]
+ resetToDataState();
+ }
+
+ protected void errGarbageAfterLtSlash() throws SAXException {
+ }
+
+ protected void errLtSlashGt() throws SAXException {
+ }
+
+ protected void errWarnLtSlashInRcdata() throws SAXException {
+ }
+
+ protected void errHtml4LtSlashInRcdata(char folded) throws SAXException {
+ }
+
+ protected void errCharRefLacksSemicolon() throws SAXException {
+ }
+
+ protected void errNoDigitsInNCR() throws SAXException {
+ }
+
+ protected void errGtInSystemId() throws SAXException {
+ }
+
+ protected void errGtInPublicId() throws SAXException {
+ }
+
+ protected void errNamelessDoctype() throws SAXException {
+ }
+
+ protected void errNestedComment() throws SAXException {
+ }
+
+ protected void errPrematureEndOfComment() throws SAXException {
+ }
+
+ protected void errBogusComment() throws SAXException {
+ }
+
+ protected void errUnquotedAttributeValOrNull(char c) throws SAXException {
+ }
+
+ protected void errSlashNotFollowedByGt() throws SAXException {
+ }
+
+ protected void errNoSpaceBetweenAttributes() throws SAXException {
+ }
+
+ protected void errLtOrEqualsOrGraveInUnquotedAttributeOrNull(char c)
+ throws SAXException {
+ }
+
+ protected void errAttributeValueMissing() throws SAXException {
+ }
+
+ protected void errBadCharBeforeAttributeNameOrNull(char c)
+ throws SAXException {
+ }
+
+ protected void errEqualsSignBeforeAttributeName() throws SAXException {
+ }
+
+ protected void errBadCharAfterLt(char c) throws SAXException {
+ }
+
+ protected void errLtGt() throws SAXException {
+ }
+
+ protected void errProcessingInstruction() throws SAXException {
+ }
+
+ protected void errUnescapedAmpersandInterpretedAsCharacterReference()
+ throws SAXException {
+ }
+
+ protected void errNotSemicolonTerminated() throws SAXException {
+ }
+
+ protected void errNoNamedCharacterMatch() throws SAXException {
+ }
+
+ protected void errQuoteBeforeAttributeName(char c) throws SAXException {
+ }
+
+ protected void errQuoteOrLtInAttributeNameOrNull(char c)
+ throws SAXException {
+ }
+
+ protected void errExpectedPublicId() throws SAXException {
+ }
+
+ protected void errBogusDoctype() throws SAXException {
+ }
+
+ protected void maybeWarnPrivateUseAstral() throws SAXException {
+ }
+
+ protected void maybeWarnPrivateUse(char ch) throws SAXException {
+ }
+
+ protected void maybeErrAttributesOnEndTag(HtmlAttributes attrs)
+ throws SAXException {
+ }
+
+ protected void maybeErrSlashInEndTag(boolean selfClosing)
+ throws SAXException {
+ }
+
+ protected char errNcrNonCharacter(char ch) throws SAXException {
+ return ch;
+ }
+
+ protected void errAstralNonCharacter(int ch) throws SAXException {
+ }
+
+ protected void errNcrSurrogate() throws SAXException {
+ }
+
+ protected char errNcrControlChar(char ch) throws SAXException {
+ return ch;
+ }
+
+ protected void errNcrCr() throws SAXException {
+ }
+
+ protected void errNcrInC1Range() throws SAXException {
+ }
+
+ protected void errEofInPublicId() throws SAXException {
+ }
+
+ protected void errEofInComment() throws SAXException {
+ }
+
+ protected void errEofInDoctype() throws SAXException {
+ }
+
+ protected void errEofInAttributeValue() throws SAXException {
+ }
+
+ protected void errEofInAttributeName() throws SAXException {
+ }
+
+ protected void errEofWithoutGt() throws SAXException {
+ }
+
+ protected void errEofInTagName() throws SAXException {
+ }
+
+ protected void errEofInEndTag() throws SAXException {
+ }
+
+ protected void errEofAfterLt() throws SAXException {
+ }
+
+ protected void errNcrOutOfRange() throws SAXException {
+ }
+
+ protected void errNcrUnassigned() throws SAXException {
+ }
+
+ protected void errDuplicateAttribute() throws SAXException {
+ }
+
+ protected void errEofInSystemId() throws SAXException {
+ }
+
+ protected void errExpectedSystemId() throws SAXException {
+ }
+
+ protected void errMissingSpaceBeforeDoctypeName() throws SAXException {
+ }
+
+ protected void errNcrControlChar() throws SAXException {
+ }
+
+ protected void errNcrZero() throws SAXException {
+ }
+
+ protected void errNoSpaceBetweenDoctypeSystemKeywordAndQuote()
+ throws SAXException {
+ }
+
+ protected void errNoSpaceBetweenPublicAndSystemIds() throws SAXException {
+ }
+
+ protected void errNoSpaceBetweenDoctypePublicKeywordAndQuote()
+ throws SAXException {
+ }
+
+ protected void noteAttributeWithoutValue() throws SAXException {
+ }
+
+ protected void noteUnquotedAttributeValue() throws SAXException {
+ }
+
+ /**
+ * Sets the encodingDeclarationHandler.
+ *
+ * @param encodingDeclarationHandler
+ * the encodingDeclarationHandler to set
+ */
+ public void setEncodingDeclarationHandler(
+ EncodingDeclarationHandler encodingDeclarationHandler) {
+ this.encodingDeclarationHandler = encodingDeclarationHandler;
+ }
+
+ void destructor() {
+ Portability.delete(nonInternedTagName);
+ nonInternedTagName = null;
+ // CPPONLY: Portability.delete(nonInternedAttributeName);
+ // CPPONLY: nonInternedAttributeName = null;
+ // The translator will write refcount tracing stuff here
+ Portability.delete(attributes);
+ attributes = null;
+ }
+
+ // [NOCPP[
+
+ /**
+ * Sets an offset to be added to the position reported to
+ * <code>TransitionHandler</code>.
+ *
+ * @param offset the offset
+ */
+ public void setTransitionBaseOffset(int offset) {
+
+ }
+
+ // ]NOCPP]
+
+}
diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java
new file mode 100644
index 0000000000..1f437bf744
--- /dev/null
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -0,0 +1,6550 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2007-2017 Mozilla Foundation
+ * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
+ * Foundation, and Opera Software ASA.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The comments following this one that use the same comment syntax as this
+ * comment are quotes from the WHATWG HTML 5 spec as of 27 June 2007
+ * amended as of June 28 2007.
+ * That document came with this statement:
+ * "© Copyright 2004-2007 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce and
+ * create derivative works of this document."
+ */
+
+package nu.validator.htmlparser.impl;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import nu.validator.htmlparser.annotation.Auto;
+import nu.validator.htmlparser.annotation.Const;
+import nu.validator.htmlparser.annotation.IdType;
+import nu.validator.htmlparser.annotation.Inline;
+import nu.validator.htmlparser.annotation.Literal;
+import nu.validator.htmlparser.annotation.Local;
+import nu.validator.htmlparser.annotation.NoLength;
+import nu.validator.htmlparser.annotation.NsUri;
+import nu.validator.htmlparser.common.DocumentMode;
+import nu.validator.htmlparser.common.DocumentModeHandler;
+import nu.validator.htmlparser.common.Interner;
+import nu.validator.htmlparser.common.TokenHandler;
+import nu.validator.htmlparser.common.XmlViolationPolicy;
+
+public abstract class TreeBuilder<T> implements TokenHandler,
+ TreeBuilderState<T> {
+
+ /**
+ * Array version of U+FFFD.
+ */
+ private static final @NoLength char[] REPLACEMENT_CHARACTER = { '\uFFFD' };
+
+ // Start dispatch groups
+
+ final static int OTHER = 0;
+
+ final static int A = 1;
+
+ final static int BASE = 2;
+
+ final static int BODY = 3;
+
+ final static int BR = 4;
+
+ final static int BUTTON = 5;
+
+ final static int CAPTION = 6;
+
+ final static int COL = 7;
+
+ final static int COLGROUP = 8;
+
+ final static int FORM = 9;
+
+ final static int FRAME = 10;
+
+ final static int FRAMESET = 11;
+
+ final static int IMAGE = 12;
+
+ final static int INPUT = 13;
+
+ final static int RT_OR_RP = 14;
+
+ final static int LI = 15;
+
+ final static int LINK_OR_BASEFONT_OR_BGSOUND = 16;
+
+ final static int MATH = 17;
+
+ final static int META = 18;
+
+ final static int SVG = 19;
+
+ final static int HEAD = 20;
+
+ final static int HR = 22;
+
+ final static int HTML = 23;
+
+ final static int NOBR = 24;
+
+ final static int NOFRAMES = 25;
+
+ final static int NOSCRIPT = 26;
+
+ final static int OPTGROUP = 27;
+
+ final static int OPTION = 28;
+
+ final static int P = 29;
+
+ final static int PLAINTEXT = 30;
+
+ final static int SCRIPT = 31;
+
+ final static int SELECT = 32;
+
+ final static int STYLE = 33;
+
+ final static int TABLE = 34;
+
+ final static int TEXTAREA = 35;
+
+ final static int TITLE = 36;
+
+ final static int TR = 37;
+
+ final static int XMP = 38;
+
+ final static int TBODY_OR_THEAD_OR_TFOOT = 39;
+
+ final static int TD_OR_TH = 40;
+
+ final static int DD_OR_DT = 41;
+
+ final static int H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 = 42;
+
+ final static int MARQUEE_OR_APPLET = 43;
+
+ final static int PRE_OR_LISTING = 44;
+
+ final static int B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U = 45;
+
+ final static int UL_OR_OL_OR_DL = 46;
+
+ final static int IFRAME = 47;
+
+ final static int EMBED = 48;
+
+ final static int AREA_OR_WBR = 49;
+
+ final static int DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50;
+
+ final static int ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY = 51;
+
+ final static int RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR = 52;
+
+ final static int RB_OR_RTC = 53;
+
+ final static int PARAM_OR_SOURCE_OR_TRACK = 55;
+
+ final static int MGLYPH_OR_MALIGNMARK = 56;
+
+ final static int MI_MO_MN_MS_MTEXT = 57;
+
+ final static int ANNOTATION_XML = 58;
+
+ final static int FOREIGNOBJECT_OR_DESC = 59;
+
+ final static int NOEMBED = 60;
+
+ final static int FIELDSET = 61;
+
+ final static int OUTPUT = 62;
+
+ final static int OBJECT = 63;
+
+ final static int FONT = 64;
+
+ final static int KEYGEN = 65;
+
+ final static int TEMPLATE = 66;
+
+ final static int IMG = 67;
+
+ // start insertion modes
+
+ private static final int IN_ROW = 0;
+
+ private static final int IN_TABLE_BODY = 1;
+
+ private static final int IN_TABLE = 2;
+
+ private static final int IN_CAPTION = 3;
+
+ private static final int IN_CELL = 4;
+
+ private static final int FRAMESET_OK = 5;
+
+ private static final int IN_BODY = 6;
+
+ private static final int IN_HEAD = 7;
+
+ private static final int IN_HEAD_NOSCRIPT = 8;
+
+ // no fall-through
+
+ private static final int IN_COLUMN_GROUP = 9;
+
+ // no fall-through
+
+ private static final int IN_SELECT_IN_TABLE = 10;
+
+ private static final int IN_SELECT = 11;
+
+ // no fall-through
+
+ private static final int AFTER_BODY = 12;
+
+ // no fall-through
+
+ private static final int IN_FRAMESET = 13;
+
+ private static final int AFTER_FRAMESET = 14;
+
+ // no fall-through
+
+ private static final int INITIAL = 15;
+
+ // could add fall-through
+
+ private static final int BEFORE_HTML = 16;
+
+ // could add fall-through
+
+ private static final int BEFORE_HEAD = 17;
+
+ // no fall-through
+
+ private static final int AFTER_HEAD = 18;
+
+ // no fall-through
+
+ private static final int AFTER_AFTER_BODY = 19;
+
+ // no fall-through
+
+ private static final int AFTER_AFTER_FRAMESET = 20;
+
+ // no fall-through
+
+ private static final int TEXT = 21;
+
+ private static final int IN_TEMPLATE = 22;
+
+ // start charset states
+
+ private static final int CHARSET_INITIAL = 0;
+
+ private static final int CHARSET_C = 1;
+
+ private static final int CHARSET_H = 2;
+
+ private static final int CHARSET_A = 3;
+
+ private static final int CHARSET_R = 4;
+
+ private static final int CHARSET_S = 5;
+
+ private static final int CHARSET_E = 6;
+
+ private static final int CHARSET_T = 7;
+
+ private static final int CHARSET_EQUALS = 8;
+
+ private static final int CHARSET_SINGLE_QUOTED = 9;
+
+ private static final int CHARSET_DOUBLE_QUOTED = 10;
+
+ private static final int CHARSET_UNQUOTED = 11;
+
+ // end pseudo enums
+
+ @Literal private final static String[] QUIRKY_PUBLIC_IDS = {
+ "+//silmaril//dtd html pro v0r11 19970101//",
+ "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
+ "-//as//dtd html 3.0 aswedit + extensions//",
+ "-//ietf//dtd html 2.0 level 1//",
+ "-//ietf//dtd html 2.0 level 2//",
+ "-//ietf//dtd html 2.0 strict level 1//",
+ "-//ietf//dtd html 2.0 strict level 2//",
+ "-//ietf//dtd html 2.0 strict//",
+ "-//ietf//dtd html 2.0//",
+ "-//ietf//dtd html 2.1e//",
+ "-//ietf//dtd html 3.0//",
+ "-//ietf//dtd html 3.2 final//",
+ "-//ietf//dtd html 3.2//",
+ "-//ietf//dtd html 3//",
+ "-//ietf//dtd html level 0//",
+ "-//ietf//dtd html level 1//",
+ "-//ietf//dtd html level 2//",
+ "-//ietf//dtd html level 3//",
+ "-//ietf//dtd html strict level 0//",
+ "-//ietf//dtd html strict level 1//",
+ "-//ietf//dtd html strict level 2//",
+ "-//ietf//dtd html strict level 3//",
+ "-//ietf//dtd html strict//",
+ "-//ietf//dtd html//",
+ "-//metrius//dtd metrius presentational//",
+ "-//microsoft//dtd internet explorer 2.0 html strict//",
+ "-//microsoft//dtd internet explorer 2.0 html//",
+ "-//microsoft//dtd internet explorer 2.0 tables//",
+ "-//microsoft//dtd internet explorer 3.0 html strict//",
+ "-//microsoft//dtd internet explorer 3.0 html//",
+ "-//microsoft//dtd internet explorer 3.0 tables//",
+ "-//netscape comm. corp.//dtd html//",
+ "-//netscape comm. corp.//dtd strict html//",
+ "-//o'reilly and associates//dtd html 2.0//",
+ "-//o'reilly and associates//dtd html extended 1.0//",
+ "-//o'reilly and associates//dtd html extended relaxed 1.0//",
+ "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
+ "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
+ "-//spyglass//dtd html 2.0 extended//",
+ "-//sq//dtd html 2.0 hotmetal + extensions//",
+ "-//sun microsystems corp.//dtd hotjava html//",
+ "-//sun microsystems corp.//dtd hotjava strict html//",
+ "-//w3c//dtd html 3 1995-03-24//", "-//w3c//dtd html 3.2 draft//",
+ "-//w3c//dtd html 3.2 final//", "-//w3c//dtd html 3.2//",
+ "-//w3c//dtd html 3.2s draft//", "-//w3c//dtd html 4.0 frameset//",
+ "-//w3c//dtd html 4.0 transitional//",
+ "-//w3c//dtd html experimental 19960712//",
+ "-//w3c//dtd html experimental 970421//", "-//w3c//dtd w3 html//",
+ "-//w3o//dtd w3 html 3.0//", "-//webtechs//dtd mozilla html 2.0//",
+ "-//webtechs//dtd mozilla html//" };
+
+ private static final int NOT_FOUND_ON_STACK = Integer.MAX_VALUE;
+
+ // [NOCPP[
+
+ private static final @Local String HTML_LOCAL = "html";
+
+ // ]NOCPP]
+
+ private int mode = INITIAL;
+
+ private int originalMode = INITIAL;
+
+ /**
+ * Used only when moving back to IN_BODY.
+ */
+ private boolean framesetOk = true;
+
+ protected Tokenizer tokenizer;
+
+ // [NOCPP[
+
+ protected ErrorHandler errorHandler;
+
+ private DocumentModeHandler documentModeHandler;
+
+ // ]NOCPP]
+
+ private boolean scriptingEnabled = false;
+
+ private boolean needToDropLF;
+
+ // [NOCPP[
+
+ private boolean wantingComments;
+
+ // ]NOCPP]
+
+ private boolean fragment;
+
+ private @Local String contextName;
+
+ private @NsUri String contextNamespace;
+
+ private T contextNode;
+
+ /**
+ * Stack of template insertion modes
+ */
+ private @Auto int[] templateModeStack;
+
+ /**
+ * Current template mode stack pointer.
+ */
+ private int templateModePtr = -1;
+
+ private @Auto StackNode<T>[] stackNodes;
+
+ /**
+ * Index of the earliest possible unused or empty element in stackNodes.
+ */
+ private int stackNodesIdx = -1;
+
+ private int numStackNodes = 0;
+
+ private @Auto StackNode<T>[] stack;
+
+ private int currentPtr = -1;
+
+ private @Auto StackNode<T>[] listOfActiveFormattingElements;
+
+ private int listPtr = -1;
+
+ private T formPointer;
+
+ private T headPointer;
+
+ protected @Auto char[] charBuffer;
+
+ protected int charBufferLen = 0;
+
+ private boolean quirks = false;
+
+ private boolean forceNoQuirks = false;
+
+ // [NOCPP[
+
+ private boolean reportingDoctype = true;
+
+ private XmlViolationPolicy namePolicy = XmlViolationPolicy.ALTER_INFOSET;
+
+ private final Map<String, LocatorImpl> idLocations = new HashMap<String, LocatorImpl>();
+
+ // ]NOCPP]
+
+ protected TreeBuilder() {
+ fragment = false;
+ }
+
+ /**
+ * Reports an condition that would make the infoset incompatible with XML
+ * 1.0 as fatal.
+ *
+ * @throws SAXException
+ * @throws SAXParseException
+ */
+ protected void fatal() throws SAXException {
+ }
+
+ // CPPONLY: @Inline private @Creator Object htmlCreator(@HtmlCreator Object htmlCreator) {
+ // CPPONLY: @Creator Object creator;
+ // CPPONLY: creator.html = htmlCreator;
+ // CPPONLY: return creator;
+ // CPPONLY: }
+ // CPPONLY:
+ // CPPONLY: @Inline private @Creator Object svgCreator(@SvgCreator Object svgCreator) {
+ // CPPONLY: @Creator Object creator;
+ // CPPONLY: creator.svg = svgCreator;
+ // CPPONLY: return creator;
+ // CPPONLY: }
+
+ // [NOCPP[
+
+ protected final void fatal(Exception e) throws SAXException {
+ SAXParseException spe = new SAXParseException(e.getMessage(),
+ tokenizer, e);
+ if (errorHandler != null) {
+ errorHandler.fatalError(spe);
+ }
+ throw spe;
+ }
+
+ final void fatal(String s) throws SAXException {
+ SAXParseException spe = new SAXParseException(s, tokenizer);
+ if (errorHandler != null) {
+ errorHandler.fatalError(spe);
+ }
+ throw spe;
+ }
+
+ /**
+ * Reports a Parse Error.
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ final void err(String message) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck(message);
+ }
+
+ /**
+ * Reports a Parse Error without checking if an error handler is present.
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ final void errNoCheck(String message) throws SAXException {
+ SAXParseException spe = new SAXParseException(message, tokenizer);
+ errorHandler.error(spe);
+ }
+
+ private void errListUnclosedStartTags(int eltPos) throws SAXException {
+ if (currentPtr != -1) {
+ for (int i = currentPtr; i > eltPos; i--) {
+ reportUnclosedElementNameAndLocation(i);
+ }
+ }
+ }
+
+ /**
+ * Reports the name and location of an unclosed element.
+ *
+ * @throws SAXException
+ */
+ private final void reportUnclosedElementNameAndLocation(int pos) throws SAXException {
+ StackNode<T> node = stack[pos];
+ if (node.isOptionalEndTag()) {
+ return;
+ }
+ TaintableLocatorImpl locator = node.getLocator();
+ if (locator.isTainted()) {
+ return;
+ }
+ locator.markTainted();
+ SAXParseException spe = new SAXParseException(
+ "Unclosed element \u201C" + node.popName + "\u201D.", locator);
+ errorHandler.error(spe);
+ }
+
+ /**
+ * Reports a warning
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ final void warn(String message) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ SAXParseException spe = new SAXParseException(message, tokenizer);
+ errorHandler.warning(spe);
+ }
+
+ /**
+ * Reports a warning with an explicit locator
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ final void warn(String message, Locator locator) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ SAXParseException spe = new SAXParseException(message, locator);
+ errorHandler.warning(spe);
+ }
+
+ // ]NOCPP]
+
+ @SuppressWarnings("unchecked") public final void startTokenization(Tokenizer self) throws SAXException {
+ tokenizer = self;
+ stackNodes = new StackNode[64];
+ stack = new StackNode[64];
+ templateModeStack = new int[64];
+ listOfActiveFormattingElements = new StackNode[64];
+ needToDropLF = false;
+ originalMode = INITIAL;
+ templateModePtr = -1;
+ stackNodesIdx = 0;
+ numStackNodes = 0;
+ currentPtr = -1;
+ listPtr = -1;
+ formPointer = null;
+ headPointer = null;
+ // [NOCPP[
+ idLocations.clear();
+ wantingComments = wantsComments();
+ // ]NOCPP]
+ start(fragment);
+ charBufferLen = 0;
+ charBuffer = null;
+ framesetOk = true;
+ if (fragment) {
+ T elt;
+ if (contextNode != null) {
+ elt = contextNode;
+ } else {
+ elt = createHtmlElementSetAsRoot(tokenizer.emptyAttributes());
+ }
+ // When the context node is not in the HTML namespace, contrary
+ // to the spec, the first node on the stack is not set to "html"
+ // in the HTML namespace. Instead, it is set to a node that has
+ // the characteristics of the appropriate "adjusted current node".
+ // This way, there is no need to perform "adjusted current node"
+ // checks during tree construction. Instead, it's sufficient to
+ // just look at the current node. However, this also means that it
+ // is not safe to treat "html" in the HTML namespace as a sentinel
+ // that ends stack popping. Instead, stack popping loops that are
+ // meant not to pop the first element on the stack need to check
+ // for currentPos becoming zero.
+ if (contextNamespace == "http://www.w3.org/2000/svg") {
+ ElementName elementName = ElementName.SVG;
+ if ("title" == contextName || "desc" == contextName
+ || "foreignObject" == contextName) {
+ // These elements are all alike and we don't care about
+ // the exact name.
+ elementName = ElementName.FOREIGNOBJECT;
+ }
+ // This is the SVG variant of the StackNode constructor.
+ StackNode<T> node = createStackNode(elementName,
+ elementName.getCamelCaseName(), elt
+ // [NOCPP[
+ , errorHandler == null ? null
+ : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ currentPtr++;
+ stack[currentPtr] = node;
+ tokenizer.setState(Tokenizer.DATA);
+ // The frameset-ok flag is set even though <frameset> never
+ // ends up being allowed as HTML frameset in the fragment case.
+ mode = FRAMESET_OK;
+ } else if (contextNamespace == "http://www.w3.org/1998/Math/MathML") {
+ ElementName elementName = ElementName.MATH;
+ if ("mi" == contextName || "mo" == contextName
+ || "mn" == contextName || "ms" == contextName
+ || "mtext" == contextName) {
+ // These elements are all alike and we don't care about
+ // the exact name.
+ elementName = ElementName.MTEXT;
+ } else if ("annotation-xml" == contextName) {
+ elementName = ElementName.ANNOTATION_XML;
+ // Blink does not check the encoding attribute of the
+ // annotation-xml element innerHTML is being set on.
+ // Let's do the same at least until
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26783
+ // is resolved.
+ }
+ // This is the MathML variant of the StackNode constructor.
+ StackNode<T> node = createStackNode(elementName, elt,
+ elementName.getName(), false
+ // [NOCPP[
+ , errorHandler == null ? null
+ : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ currentPtr++;
+ stack[currentPtr] = node;
+ tokenizer.setState(Tokenizer.DATA);
+ // The frameset-ok flag is set even though <frameset> never
+ // ends up being allowed as HTML frameset in the fragment case.
+ mode = FRAMESET_OK;
+ } else { // html
+ StackNode<T> node = createStackNode(ElementName.HTML, elt
+ // [NOCPP[
+ , errorHandler == null ? null
+ : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ currentPtr++;
+ stack[currentPtr] = node;
+ if ("template" == contextName) {
+ pushTemplateMode(IN_TEMPLATE);
+ }
+ resetTheInsertionMode();
+ formPointer = getFormPointerForContext(contextNode);
+ if ("title" == contextName || "textarea" == contextName) {
+ tokenizer.setState(Tokenizer.RCDATA);
+ } else if ("style" == contextName || "xmp" == contextName
+ || "iframe" == contextName || "noembed" == contextName
+ || "noframes" == contextName
+ || (scriptingEnabled && "noscript" == contextName)) {
+ tokenizer.setState(Tokenizer.RAWTEXT);
+ } else if ("plaintext" == contextName) {
+ tokenizer.setState(Tokenizer.PLAINTEXT);
+ } else if ("script" == contextName) {
+ tokenizer.setState(Tokenizer.SCRIPT_DATA);
+ } else {
+ tokenizer.setState(Tokenizer.DATA);
+ }
+ }
+ } else {
+ mode = INITIAL;
+ // If we are viewing XML source, put a foreign element permanently
+ // on the stack so that cdataSectionAllowed() returns true.
+ // CPPONLY: if (tokenizer.isViewingXmlSource()) {
+ // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg",
+ // CPPONLY: "svg",
+ // CPPONLY: tokenizer.emptyAttributes(), null,
+ // CPPONLY: svgCreator(NS_NewSVGSVGElement));
+ // CPPONLY: StackNode<T> node = createStackNode(ElementName.SVG,
+ // CPPONLY: "svg",
+ // CPPONLY: elt);
+ // CPPONLY: currentPtr++;
+ // CPPONLY: stack[currentPtr] = node;
+ // CPPONLY: }
+ }
+ }
+
+ public final void doctype(@Local String name, String publicIdentifier,
+ String systemIdentifier, boolean forceQuirks) throws SAXException {
+ needToDropLF = false;
+ if (!isInForeign() && mode == INITIAL) {
+ // [NOCPP[
+ if (reportingDoctype) {
+ // ]NOCPP]
+ String emptyString = Portability.newEmptyString();
+ appendDoctypeToDocument(name == null ? "" : name,
+ publicIdentifier == null ? emptyString
+ : publicIdentifier,
+ systemIdentifier == null ? emptyString
+ : systemIdentifier);
+ Portability.releaseString(emptyString);
+ // [NOCPP[
+ }
+ // ]NOCPP]
+ if (isQuirky(name, publicIdentifier, systemIdentifier,
+ forceQuirks)) {
+ errQuirkyDoctype();
+ documentModeInternal(DocumentMode.QUIRKS_MODE,
+ publicIdentifier, systemIdentifier);
+ } else if (isAlmostStandards(publicIdentifier,
+ systemIdentifier)) {
+ errAlmostStandardsDoctype();
+ documentModeInternal(
+ DocumentMode.ALMOST_STANDARDS_MODE,
+ publicIdentifier, systemIdentifier);
+ } else {
+ // [NOCPP[
+ if ((Portability.literalEqualsString(
+ "-//W3C//DTD HTML 4.0//EN", publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString(
+ "http://www.w3.org/TR/REC-html40/strict.dtd",
+ systemIdentifier)))
+ || (Portability.literalEqualsString(
+ "-//W3C//DTD HTML 4.01//EN",
+ publicIdentifier) && (systemIdentifier == null || Portability.literalEqualsString(
+ "http://www.w3.org/TR/html4/strict.dtd",
+ systemIdentifier)))
+ || (Portability.literalEqualsString(
+ "-//W3C//DTD XHTML 1.0 Strict//EN",
+ publicIdentifier) && Portability.literalEqualsString(
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
+ systemIdentifier))
+ || (Portability.literalEqualsString(
+ "-//W3C//DTD XHTML 1.1//EN",
+ publicIdentifier) && Portability.literalEqualsString(
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd",
+ systemIdentifier))
+
+ ) {
+ err("Obsolete doctype. Expected \u201C<!DOCTYPE html>\u201D.");
+ } else if (!((systemIdentifier == null || Portability.literalEqualsString(
+ "about:legacy-compat", systemIdentifier)) && publicIdentifier == null)) {
+ err("Legacy doctype. Expected \u201C<!DOCTYPE html>\u201D.");
+ }
+ // ]NOCPP]
+ documentModeInternal(DocumentMode.STANDARDS_MODE,
+ publicIdentifier, systemIdentifier);
+ }
+
+ /*
+ *
+ * Then, switch to the root element mode of the tree construction
+ * stage.
+ */
+ mode = BEFORE_HTML;
+ return;
+ }
+ /*
+ * A DOCTYPE token Parse error.
+ */
+ errStrayDoctype();
+ /*
+ * Ignore the token.
+ */
+ return;
+ }
+
+ public final void comment(@NoLength char[] buf, int start, int length)
+ throws SAXException {
+ needToDropLF = false;
+ // [NOCPP[
+ if (!wantingComments) {
+ return;
+ }
+ // ]NOCPP]
+ if (!isInForeign()) {
+ switch (mode) {
+ case INITIAL:
+ case BEFORE_HTML:
+ case AFTER_AFTER_BODY:
+ case AFTER_AFTER_FRAMESET:
+ /*
+ * A comment token Append a Comment node to the Document
+ * object with the data attribute set to the data given in
+ * the comment token.
+ */
+ appendCommentToDocument(buf, start, length);
+ return;
+ case AFTER_BODY:
+ /*
+ * A comment token Append a Comment node to the first
+ * element in the stack of open elements (the html element),
+ * with the data attribute set to the data given in the
+ * comment token.
+ */
+ flushCharacters();
+ appendComment(stack[0].node, buf, start, length);
+ return;
+ default:
+ break;
+ }
+ }
+ /*
+ * A comment token Append a Comment node to the current node with the
+ * data attribute set to the data given in the comment token.
+ */
+ flushCharacters();
+ appendComment(stack[currentPtr].node, buf, start, length);
+ return;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.common.TokenHandler#characters(char[], int,
+ * int)
+ */
+ public final void characters(@Const @NoLength char[] buf, int start, int length)
+ throws SAXException {
+ // Note: Can't attach error messages to EOF in C++ yet
+
+ // CPPONLY: if (tokenizer.isViewingXmlSource()) {
+ // CPPONLY: return;
+ // CPPONLY: }
+ if (needToDropLF) {
+ needToDropLF = false;
+ if (buf[start] == '\n') {
+ start++;
+ length--;
+ if (length == 0) {
+ return;
+ }
+ }
+ }
+
+ // optimize the most common case
+ switch (mode) {
+ case IN_BODY:
+ case IN_CELL:
+ case IN_CAPTION:
+ if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
+ reconstructTheActiveFormattingElements();
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case TEXT:
+ accumulateCharacters(buf, start, length);
+ return;
+ case IN_TABLE:
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ accumulateCharactersForced(buf, start, length);
+ return;
+ default:
+ int end = start + length;
+ charactersloop: for (int i = start; i < end; i++) {
+ switch (buf[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\u000C':
+ /*
+ * A character token that is one of one of U+0009
+ * CHARACTER TABULATION, U+000A LINE FEED (LF),
+ * U+000C FORM FEED (FF), or U+0020 SPACE
+ */
+ switch (mode) {
+ case INITIAL:
+ case BEFORE_HTML:
+ case BEFORE_HEAD:
+ /*
+ * Ignore the token.
+ */
+ start = i + 1;
+ continue;
+ case IN_HEAD:
+ case IN_HEAD_NOSCRIPT:
+ case AFTER_HEAD:
+ case IN_COLUMN_GROUP:
+ case IN_FRAMESET:
+ case AFTER_FRAMESET:
+ /*
+ * Append the character to the current node.
+ */
+ continue;
+ case FRAMESET_OK:
+ case IN_TEMPLATE:
+ case IN_BODY:
+ case IN_CELL:
+ case IN_CAPTION:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+
+ /*
+ * Reconstruct the active formatting
+ * elements, if any.
+ */
+ if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
+ flushCharacters();
+ reconstructTheActiveFormattingElements();
+ }
+ /*
+ * Append the token's character to the
+ * current node.
+ */
+ break charactersloop;
+ case IN_SELECT:
+ case IN_SELECT_IN_TABLE:
+ break charactersloop;
+ case IN_TABLE:
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ accumulateCharactersForced(buf, i, 1);
+ start = i + 1;
+ continue;
+ case AFTER_BODY:
+ case AFTER_AFTER_BODY:
+ case AFTER_AFTER_FRAMESET:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * Reconstruct the active formatting
+ * elements, if any.
+ */
+ flushCharacters();
+ reconstructTheActiveFormattingElements();
+ /*
+ * Append the token's character to the
+ * current node.
+ */
+ continue;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH_ASSERT();
+ default:
+ /*
+ * A character token that is not one of one of
+ * U+0009 CHARACTER TABULATION, U+000A LINE FEED
+ * (LF), U+000C FORM FEED (FF), or U+0020 SPACE
+ */
+ switch (mode) {
+ case INITIAL:
+ /*
+ * Parse error.
+ */
+ // [NOCPP[
+ // XXX figure out a way to report this in the Gecko View Source case
+ err("Non-space characters found without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
+ // ]NOCPP]
+ /*
+ *
+ * Set the document to quirks mode.
+ */
+ documentModeInternal(
+ DocumentMode.QUIRKS_MODE, null,
+ null);
+ /*
+ * Then, switch to the root element mode of
+ * the tree construction stage
+ */
+ mode = BEFORE_HTML;
+ /*
+ * and reprocess the current token.
+ */
+ i--;
+ continue;
+ case BEFORE_HTML:
+ /*
+ * Create an HTMLElement node with the tag
+ * name html, in the HTML namespace. Append
+ * it to the Document object.
+ */
+ // No need to flush characters here,
+ // because there's nothing to flush.
+ appendHtmlElementToDocumentAndPush();
+ /* Switch to the main mode */
+ mode = BEFORE_HEAD;
+ /*
+ * reprocess the current token.
+ */
+ i--;
+ continue;
+ case BEFORE_HEAD:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * /Act as if a start tag token with the tag
+ * name "head" and no attributes had been
+ * seen,
+ */
+ flushCharacters();
+ appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ /*
+ * then reprocess the current token.
+ *
+ * This will result in an empty head element
+ * being generated, with the current token
+ * being reprocessed in the "after head"
+ * insertion mode.
+ */
+ i--;
+ continue;
+ case IN_HEAD:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * Act as if an end tag token with the tag
+ * name "head" had been seen,
+ */
+ flushCharacters();
+ pop();
+ mode = AFTER_HEAD;
+ /*
+ * and reprocess the current token.
+ */
+ i--;
+ continue;
+ case IN_HEAD_NOSCRIPT:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * Parse error. Act as if an end tag with
+ * the tag name "noscript" had been seen
+ */
+ errNonSpaceInNoscriptInHead();
+ flushCharacters();
+ pop();
+ mode = IN_HEAD;
+ /*
+ * and reprocess the current token.
+ */
+ i--;
+ continue;
+ case AFTER_HEAD:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * Act as if a start tag token with the tag
+ * name "body" and no attributes had been
+ * seen,
+ */
+ flushCharacters();
+ appendToCurrentNodeAndPushBodyElement();
+ mode = FRAMESET_OK;
+ /*
+ * and then reprocess the current token.
+ */
+ i--;
+ continue;
+ case FRAMESET_OK:
+ framesetOk = false;
+ mode = IN_BODY;
+ i--;
+ continue;
+ case IN_TEMPLATE:
+ case IN_BODY:
+ case IN_CELL:
+ case IN_CAPTION:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * Reconstruct the active formatting
+ * elements, if any.
+ */
+ if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
+ flushCharacters();
+ reconstructTheActiveFormattingElements();
+ }
+ /*
+ * Append the token's character to the
+ * current node.
+ */
+ break charactersloop;
+ case IN_TABLE:
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ accumulateCharactersForced(buf, i, 1);
+ start = i + 1;
+ continue;
+ case IN_COLUMN_GROUP:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ start = i;
+ }
+ /*
+ * Act as if an end tag with the tag name
+ * "colgroup" had been seen, and then, if
+ * that token wasn't ignored, reprocess the
+ * current token.
+ */
+ if (currentPtr == 0 || stack[currentPtr].getGroup() ==
+ TreeBuilder.TEMPLATE) {
+ errNonSpaceInColgroupInFragment();
+ start = i + 1;
+ continue;
+ }
+ flushCharacters();
+ pop();
+ mode = IN_TABLE;
+ i--;
+ continue;
+ case IN_SELECT:
+ case IN_SELECT_IN_TABLE:
+ break charactersloop;
+ case AFTER_BODY:
+ errNonSpaceAfterBody();
+ fatal();
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ i--;
+ continue;
+ case IN_FRAMESET:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ // start index is adjusted below.
+ }
+ /*
+ * Parse error.
+ */
+ errNonSpaceInFrameset();
+ /*
+ * Ignore the token.
+ */
+ start = i + 1;
+ continue;
+ case AFTER_FRAMESET:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ // start index is adjusted below.
+ }
+ /*
+ * Parse error.
+ */
+ errNonSpaceAfterFrameset();
+ /*
+ * Ignore the token.
+ */
+ start = i + 1;
+ continue;
+ case AFTER_AFTER_BODY:
+ /*
+ * Parse error.
+ */
+ errNonSpaceInTrailer();
+ /*
+ * Switch back to the main mode and
+ * reprocess the token.
+ */
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ i--;
+ continue;
+ case AFTER_AFTER_FRAMESET:
+ if (start < i) {
+ accumulateCharacters(buf, start, i
+ - start);
+ // start index is adjusted below.
+ }
+ /*
+ * Parse error.
+ */
+ errNonSpaceInTrailer();
+ /*
+ * Ignore the token.
+ */
+ start = i + 1;
+ continue;
+ }
+ }
+ }
+ if (start < end) {
+ accumulateCharacters(buf, start, end - start);
+ }
+ }
+ }
+
+ /**
+ * @see nu.validator.htmlparser.common.TokenHandler#zeroOriginatingReplacementCharacter()
+ */
+ public void zeroOriginatingReplacementCharacter() throws SAXException {
+ if (mode == TEXT) {
+ accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
+ return;
+ }
+ if (currentPtr >= 0) {
+ if (isSpecialParentInForeign(stack[currentPtr])) {
+ return;
+ }
+ accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
+ }
+ }
+
+ /**
+ * @see nu.validator.htmlparser.common.TokenHandler#zeroOrReplacementCharacter()
+ */
+ public void zeroOrReplacementCharacter() throws SAXException {
+ zeroOriginatingReplacementCharacter();
+ }
+
+ public final void eof() throws SAXException {
+ flushCharacters();
+ // Note: Can't attach error messages to EOF in C++ yet
+ eofloop: for (;;) {
+ switch (mode) {
+ case INITIAL:
+ /*
+ * Parse error.
+ */
+ // [NOCPP[
+ err("End of file seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
+ // ]NOCPP]
+ /*
+ *
+ * Set the document to quirks mode.
+ */
+ documentModeInternal(DocumentMode.QUIRKS_MODE, null, null);
+ /*
+ * Then, switch to the root element mode of the tree
+ * construction stage
+ */
+ mode = BEFORE_HTML;
+ /*
+ * and reprocess the current token.
+ */
+ continue;
+ case BEFORE_HTML:
+ /*
+ * Create an HTMLElement node with the tag name html, in the
+ * HTML namespace. Append it to the Document object.
+ */
+ appendHtmlElementToDocumentAndPush();
+ // XXX application cache manifest
+ /* Switch to the main mode */
+ mode = BEFORE_HEAD;
+ /*
+ * reprocess the current token.
+ */
+ continue;
+ case BEFORE_HEAD:
+ appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ continue;
+ case IN_HEAD:
+ // [NOCPP[
+ if (errorHandler != null && currentPtr > 1) {
+ errEofWithUnclosedElements();
+ }
+ // ]NOCPP]
+ while (currentPtr > 0) {
+ popOnEof();
+ }
+ mode = AFTER_HEAD;
+ continue;
+ case IN_HEAD_NOSCRIPT:
+ // [NOCPP[
+ errEofWithUnclosedElements();
+ // ]NOCPP]
+ while (currentPtr > 1) {
+ popOnEof();
+ }
+ mode = IN_HEAD;
+ continue;
+ case AFTER_HEAD:
+ appendToCurrentNodeAndPushBodyElement();
+ mode = IN_BODY;
+ continue;
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ case IN_TABLE:
+ case IN_SELECT_IN_TABLE:
+ case IN_SELECT:
+ case IN_COLUMN_GROUP:
+ case FRAMESET_OK:
+ case IN_CAPTION:
+ case IN_CELL:
+ case IN_BODY:
+ // [NOCPP[
+ // i > 0 to stop in time in the foreign fragment case.
+ openelementloop: for (int i = currentPtr; i > 0; i--) {
+ int group = stack[i].getGroup();
+ switch (group) {
+ case DD_OR_DT:
+ case LI:
+ case P:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case BODY:
+ case HTML:
+ break;
+ default:
+ errEofWithUnclosedElements();
+ break openelementloop;
+ }
+ }
+ // ]NOCPP]
+
+ if (isTemplateModeStackEmpty()) {
+ break eofloop;
+ }
+
+ // fall through to IN_TEMPLATE
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_TEMPLATE:
+ int eltPos = findLast("template");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment;
+ break eofloop;
+ }
+ if (errorHandler != null) {
+ errListUnclosedStartTags(0);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ popTemplateMode();
+ resetTheInsertionMode();
+
+ // Reprocess token.
+ continue;
+ case TEXT:
+ // [NOCPP[
+ if (errorHandler != null) {
+ errNoCheck("End of file seen when expecting text or an end tag.");
+ errListUnclosedStartTags(0);
+ }
+ // ]NOCPP]
+ // XXX mark script as already executed
+ if (originalMode == AFTER_HEAD) {
+ popOnEof();
+ }
+ popOnEof();
+ mode = originalMode;
+ continue;
+ case IN_FRAMESET:
+ // [NOCPP[
+ if (errorHandler != null && currentPtr > 0) {
+ errEofWithUnclosedElements();
+ }
+ // ]NOCPP]
+ break eofloop;
+ case AFTER_BODY:
+ case AFTER_FRAMESET:
+ case AFTER_AFTER_BODY:
+ case AFTER_AFTER_FRAMESET:
+ default:
+ // [NOCPP[
+ if (currentPtr == 0) { // This silliness is here to poison
+ // buggy compiler optimizations in
+ // GWT
+ System.currentTimeMillis();
+ }
+ // ]NOCPP]
+ break eofloop;
+ }
+ }
+ while (currentPtr > 0) {
+ popOnEof();
+ }
+ if (!fragment) {
+ popOnEof();
+ }
+ /* Stop parsing. */
+ }
+
+ /**
+ * @see nu.validator.htmlparser.common.TokenHandler#endTokenization()
+ */
+ public final void endTokenization() throws SAXException {
+ formPointer = null;
+ headPointer = null;
+ contextName = null;
+ contextNode = null;
+ templateModeStack = null;
+ if (stack != null) {
+ while (currentPtr > -1) {
+ stack[currentPtr].release(this);
+ currentPtr--;
+ }
+ stack = null;
+ }
+ if (listOfActiveFormattingElements != null) {
+ while (listPtr > -1) {
+ if (listOfActiveFormattingElements[listPtr] != null) {
+ listOfActiveFormattingElements[listPtr].release(this);
+ }
+ listPtr--;
+ }
+ listOfActiveFormattingElements = null;
+ }
+ if (stackNodes != null) {
+ for (int i = 0; i < numStackNodes; i++) {
+ assert stackNodes[i].isUnused();
+ Portability.delete(stackNodes[i]);
+ }
+ numStackNodes = 0;
+ stackNodesIdx = 0;
+ stackNodes = null;
+ }
+ // [NOCPP[
+ idLocations.clear();
+ // ]NOCPP]
+ charBuffer = null;
+ end();
+ }
+
+ public final void startTag(ElementName elementName,
+ HtmlAttributes attributes, boolean selfClosing) throws SAXException {
+ flushCharacters();
+
+ // [NOCPP[
+ if (errorHandler != null) {
+ // ID uniqueness
+ @IdType String id = attributes.getId();
+ if (id != null) {
+ LocatorImpl oldLoc = idLocations.get(id);
+ if (oldLoc != null) {
+ err("Duplicate ID \u201C" + id + "\u201D.");
+ errorHandler.warning(new SAXParseException(
+ "The first occurrence of ID \u201C" + id
+ + "\u201D was here.", oldLoc));
+ } else {
+ idLocations.put(id, new LocatorImpl(tokenizer));
+ }
+ }
+ }
+ // ]NOCPP]
+
+ int eltPos;
+ needToDropLF = false;
+ starttagloop: for (;;) {
+ int group = elementName.getGroup();
+ @Local String name = elementName.getName();
+ if (isInForeign()) {
+ StackNode<T> currentNode = stack[currentPtr];
+ @NsUri String currNs = currentNode.ns;
+ if (!(currentNode.isHtmlIntegrationPoint() || (currNs == "http://www.w3.org/1998/Math/MathML" && ((currentNode.getGroup() == MI_MO_MN_MS_MTEXT && group != MGLYPH_OR_MALIGNMARK) || (currentNode.getGroup() == ANNOTATION_XML && group == SVG))))) {
+ switch (group) {
+ case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+ case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+ case BODY:
+ case BR:
+ case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
+ case DD_OR_DT:
+ case UL_OR_OL_OR_DL:
+ case EMBED:
+ case IMG:
+ case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
+ case HEAD:
+ case HR:
+ case LI:
+ case META:
+ case NOBR:
+ case P:
+ case PRE_OR_LISTING:
+ case TABLE:
+ case FONT:
+ // re-check FONT to deal with the special case
+ if (!(group == FONT && !(attributes.contains(AttributeName.COLOR)
+ || attributes.contains(AttributeName.FACE) || attributes.contains(AttributeName.SIZE)))) {
+ errHtmlStartTagInForeignContext(name);
+ if (!fragment) {
+ while (!isSpecialParentInForeign(stack[currentPtr])) {
+ popForeign(-1, -1);
+ }
+ continue starttagloop;
+ } // else fall thru
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ if ("http://www.w3.org/2000/svg" == currNs) {
+ attributes.adjustForSvg();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterSVG(
+ elementName, attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterSVG(
+ elementName, attributes);
+ }
+ attributes = null; // CPP
+ break starttagloop;
+ } else {
+ attributes.adjustForMath();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterMathML(
+ elementName, attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterMathML(
+ elementName, attributes);
+ }
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ } // switch
+ } // foreignObject / annotation-xml
+ }
+ switch (mode) {
+ case IN_TEMPLATE:
+ switch (group) {
+ case COL:
+ popTemplateMode();
+ pushTemplateMode(IN_COLUMN_GROUP);
+ mode = IN_COLUMN_GROUP;
+ // Reprocess token.
+ continue;
+ case CAPTION:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ popTemplateMode();
+ pushTemplateMode(IN_TABLE);
+ mode = IN_TABLE;
+ // Reprocess token.
+ continue;
+ case TR:
+ popTemplateMode();
+ pushTemplateMode(IN_TABLE_BODY);
+ mode = IN_TABLE_BODY;
+ // Reprocess token.
+ continue;
+ case TD_OR_TH:
+ popTemplateMode();
+ pushTemplateMode(IN_ROW);
+ mode = IN_ROW;
+ // Reprocess token.
+ continue;
+ case META:
+ checkMetaCharset(attributes);
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case TITLE:
+ startTagTitleInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND:
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case SCRIPT:
+ startTagScriptInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case NOFRAMES:
+ case STYLE:
+ startTagGenericRawText(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case TEMPLATE:
+ startTagTemplateInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ popTemplateMode();
+ pushTemplateMode(IN_BODY);
+ mode = IN_BODY;
+ // Reprocess token.
+ continue;
+ }
+ case IN_ROW:
+ switch (group) {
+ case TD_OR_TH:
+ clearStackBackTo(findLastOrRoot(TreeBuilder.TR));
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_CELL;
+ insertMarker();
+ attributes = null; // CPP
+ break starttagloop;
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ eltPos = findLastOrRoot(TreeBuilder.TR);
+ if (eltPos == 0) {
+ assert fragment || isTemplateContents();
+ errNoTableRowToClose();
+ break starttagloop;
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ continue;
+ default:
+ // fall through to IN_TABLE
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_TABLE_BODY:
+ switch (group) {
+ case TR:
+ clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_ROW;
+ attributes = null; // CPP
+ break starttagloop;
+ case TD_OR_TH:
+ errStartTagInTableBody(name);
+ clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
+ appendToCurrentNodeAndPushElement(
+ ElementName.TR,
+ HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_ROW;
+ continue;
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
+ if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) {
+ assert fragment || isTemplateContents();
+ errStrayStartTag(name);
+ break starttagloop;
+ } else {
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ default:
+ // fall through to IN_TABLE
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_TABLE:
+ intableloop: for (;;) {
+ switch (group) {
+ case CAPTION:
+ clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
+ insertMarker();
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_CAPTION;
+ attributes = null; // CPP
+ break starttagloop;
+ case COLGROUP:
+ clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_COLUMN_GROUP;
+ attributes = null; // CPP
+ break starttagloop;
+ case COL:
+ clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
+ appendToCurrentNodeAndPushElement(
+ ElementName.COLGROUP,
+ HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_COLUMN_GROUP;
+ continue starttagloop;
+ case TBODY_OR_THEAD_OR_TFOOT:
+ clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_TABLE_BODY;
+ attributes = null; // CPP
+ break starttagloop;
+ case TR:
+ case TD_OR_TH:
+ clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
+ appendToCurrentNodeAndPushElement(
+ ElementName.TBODY,
+ HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_TABLE_BODY;
+ continue starttagloop;
+ case TEMPLATE:
+ // fall through to IN_HEAD
+ break intableloop;
+ case TABLE:
+ errTableSeenWhileTableOpen();
+ eltPos = findLastInTableScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment || isTemplateContents();
+ break starttagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent("table")) {
+ errNoCheckUnclosedElementsOnStack();
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue starttagloop;
+ case SCRIPT:
+ // XXX need to manage much more stuff
+ // here if
+ // supporting
+ // document.write()
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.SCRIPT_DATA, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case STYLE:
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RAWTEXT, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case INPUT:
+ errStartTagInTable(name);
+ if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "hidden",
+ attributes.getValue(AttributeName.TYPE))) {
+ break intableloop;
+ }
+ appendVoidInputToCurrent(
+ attributes,
+ formPointer);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case FORM:
+ if (formPointer != null || isTemplateContents()) {
+ errFormWhenFormOpen();
+ break starttagloop;
+ } else {
+ errStartTagInTable(name);
+ appendVoidFormToCurrent(attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ default:
+ errStartTagInTable(name);
+ // fall through to IN_BODY
+ break intableloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_CAPTION:
+ switch (group) {
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ eltPos = findLastInTableScope("caption");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment || isTemplateContents();
+ errStrayStartTag(name);
+ break starttagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && currentPtr != eltPos) {
+ errNoCheckUnclosedElementsOnStack();
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_TABLE;
+ continue;
+ default:
+ // fall through to IN_BODY
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_CELL:
+ switch (group) {
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ eltPos = findLastInTableScopeTdTh();
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errNoCellToClose();
+ break starttagloop;
+ } else {
+ closeTheCell(eltPos);
+ continue;
+ }
+ default:
+ // fall through to IN_BODY
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case FRAMESET_OK:
+ switch (group) {
+ case FRAMESET:
+ if (mode == FRAMESET_OK) {
+ if (currentPtr == 0 || stack[1].getGroup() != BODY) {
+ assert fragment || isTemplateContents();
+ errStrayStartTag(name);
+ break starttagloop;
+ } else {
+ errFramesetStart();
+ detachFromParent(stack[1].node);
+ while (currentPtr > 0) {
+ pop();
+ }
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_FRAMESET;
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ } else {
+ errStrayStartTag(name);
+ break starttagloop;
+ }
+ // NOT falling through!
+ case PRE_OR_LISTING:
+ case LI:
+ case DD_OR_DT:
+ case BUTTON:
+ case MARQUEE_OR_APPLET:
+ case OBJECT:
+ case TABLE:
+ case AREA_OR_WBR:
+ case KEYGEN:
+ case BR:
+ case EMBED:
+ case IMG:
+ case INPUT:
+ case HR:
+ case TEXTAREA:
+ case XMP:
+ case IFRAME:
+ case SELECT:
+ if (mode == FRAMESET_OK
+ && !(group == INPUT && Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "hidden",
+ attributes.getValue(AttributeName.TYPE)))) {
+ framesetOk = false;
+ mode = IN_BODY;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ // fall through to IN_BODY
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_BODY:
+ inbodyloop: for (;;) {
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND:
+ case META:
+ case STYLE:
+ case SCRIPT:
+ case TITLE:
+ case TEMPLATE:
+ // Fall through to IN_HEAD
+ break inbodyloop;
+ case BODY:
+ if (currentPtr == 0 || stack[1].getGroup() != BODY || isTemplateContents()) {
+ assert fragment || isTemplateContents();
+ errStrayStartTag(name);
+ break starttagloop;
+ }
+ errFooSeenWhenFooOpen(name);
+ framesetOk = false;
+ if (mode == FRAMESET_OK) {
+ mode = IN_BODY;
+ }
+ if (addAttributesToBody(attributes)) {
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case P:
+ case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+ case UL_OR_OL_OR_DL:
+ case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY:
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
+ implicitlyCloseP();
+ if (stack[currentPtr].getGroup() == H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
+ errHeadingWhenHeadingOpen();
+ pop();
+ }
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case FIELDSET:
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes, formPointer);
+ attributes = null; // CPP
+ break starttagloop;
+ case PRE_OR_LISTING:
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ needToDropLF = true;
+ attributes = null; // CPP
+ break starttagloop;
+ case FORM:
+ if (formPointer != null && !isTemplateContents()) {
+ errFormWhenFormOpen();
+ break starttagloop;
+ } else {
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushFormElementMayFoster(attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ case LI:
+ case DD_OR_DT:
+ eltPos = currentPtr;
+ for (;;) {
+ StackNode<T> node = stack[eltPos]; // weak
+ // ref
+ if (node.getGroup() == group) { // LI or
+ // DD_OR_DT
+ generateImpliedEndTagsExceptFor(node.name);
+ if (errorHandler != null
+ && eltPos != currentPtr) {
+ errUnclosedElementsImplied(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ break;
+ } else if (eltPos == 0 || (node.isSpecial()
+ && (node.ns != "http://www.w3.org/1999/xhtml"
+ || (node.name != "p"
+ && node.name != "address"
+ && node.name != "div")))) {
+ break;
+ }
+ eltPos--;
+ }
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case PLAINTEXT:
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.PLAINTEXT, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case A:
+ int activeAPos = findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker("a");
+ if (activeAPos != -1) {
+ errFooSeenWhenFooOpen(name);
+ StackNode<T> activeA = listOfActiveFormattingElements[activeAPos];
+ activeA.retain();
+ adoptionAgencyEndTag("a");
+ removeFromStack(activeA);
+ activeAPos = findInListOfActiveFormattingElements(activeA);
+ if (activeAPos != -1) {
+ removeFromListOfActiveFormattingElements(activeAPos);
+ }
+ activeA.release(this);
+ }
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushFormattingElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+ case FONT:
+ reconstructTheActiveFormattingElements();
+ maybeForgetEarlierDuplicateFormattingElement(elementName.getName(), attributes);
+ appendToCurrentNodeAndPushFormattingElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case NOBR:
+ reconstructTheActiveFormattingElements();
+ if (TreeBuilder.NOT_FOUND_ON_STACK != findLastInScope("nobr")) {
+ errFooSeenWhenFooOpen(name);
+ adoptionAgencyEndTag("nobr");
+ reconstructTheActiveFormattingElements();
+ }
+ appendToCurrentNodeAndPushFormattingElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case BUTTON:
+ eltPos = findLastInScope(name);
+ if (eltPos != TreeBuilder.NOT_FOUND_ON_STACK) {
+ errFooSeenWhenFooOpen(name);
+ generateImpliedEndTags();
+ if (errorHandler != null
+ && !isCurrent(name)) {
+ errUnclosedElementsImplied(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ continue starttagloop;
+ } else {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes, formPointer);
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ case OBJECT:
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes, formPointer);
+ insertMarker();
+ attributes = null; // CPP
+ break starttagloop;
+ case MARQUEE_OR_APPLET:
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ insertMarker();
+ attributes = null; // CPP
+ break starttagloop;
+ case TABLE:
+ // The only quirk. Blame Hixie and
+ // Acid2.
+ if (!quirks) {
+ implicitlyCloseP();
+ }
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ mode = IN_TABLE;
+ attributes = null; // CPP
+ break starttagloop;
+ case BR:
+ case EMBED:
+ case AREA_OR_WBR:
+ case KEYGEN:
+ reconstructTheActiveFormattingElements();
+ // FALL THROUGH to PARAM_OR_SOURCE_OR_TRACK
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case PARAM_OR_SOURCE_OR_TRACK:
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case HR:
+ implicitlyCloseP();
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case IMAGE:
+ errImage();
+ elementName = ElementName.IMG;
+ continue starttagloop;
+ case IMG:
+ case INPUT:
+ reconstructTheActiveFormattingElements();
+ appendVoidElementToCurrentMayFoster(
+ elementName, attributes,
+ formPointer);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case TEXTAREA:
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes, formPointer);
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RCDATA, elementName);
+ originalMode = mode;
+ mode = TEXT;
+ needToDropLF = true;
+ attributes = null; // CPP
+ break starttagloop;
+ case XMP:
+ implicitlyCloseP();
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RAWTEXT, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case NOSCRIPT:
+ if (!scriptingEnabled) {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case NOFRAMES:
+ case IFRAME:
+ case NOEMBED:
+ startTagGenericRawText(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case SELECT:
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes, formPointer);
+ switch (mode) {
+ case IN_TABLE:
+ case IN_CAPTION:
+ case IN_COLUMN_GROUP:
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ case IN_CELL:
+ mode = IN_SELECT_IN_TABLE;
+ break;
+ default:
+ mode = IN_SELECT;
+ break;
+ }
+ attributes = null; // CPP
+ break starttagloop;
+ case OPTGROUP:
+ case OPTION:
+ if (isCurrent("option")) {
+ pop();
+ }
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case RB_OR_RTC:
+ eltPos = findLastInScope("ruby");
+ if (eltPos != NOT_FOUND_ON_STACK) {
+ generateImpliedEndTags();
+ }
+ if (eltPos != currentPtr) {
+ if (eltPos == NOT_FOUND_ON_STACK) {
+ errStartTagSeenWithoutRuby(name);
+ } else {
+ errUnclosedChildrenInRuby();
+ }
+ }
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case RT_OR_RP:
+ eltPos = findLastInScope("ruby");
+ if (eltPos != NOT_FOUND_ON_STACK) {
+ generateImpliedEndTagsExceptFor("rtc");
+ }
+ if (eltPos != currentPtr) {
+ if (!isCurrent("rtc")) {
+ if (eltPos == NOT_FOUND_ON_STACK) {
+ errStartTagSeenWithoutRuby(name);
+ } else {
+ errUnclosedChildrenInRuby();
+ }
+ }
+ }
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case MATH:
+ reconstructTheActiveFormattingElements();
+ attributes.adjustForMath();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterMathML(
+ elementName, attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterMathML(
+ elementName, attributes);
+ }
+ attributes = null; // CPP
+ break starttagloop;
+ case SVG:
+ reconstructTheActiveFormattingElements();
+ attributes.adjustForSvg();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterSVG(
+ elementName,
+ attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterSVG(
+ elementName, attributes);
+ }
+ attributes = null; // CPP
+ break starttagloop;
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ case FRAME:
+ case FRAMESET:
+ case HEAD:
+ errStrayStartTag(name);
+ break starttagloop;
+ case OUTPUT:
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes, formPointer);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_HEAD:
+ inheadloop: for (;;) {
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND:
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case META:
+ // Fall through to IN_HEAD_NOSCRIPT
+ break inheadloop;
+ case TITLE:
+ startTagTitleInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case NOSCRIPT:
+ if (scriptingEnabled) {
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RAWTEXT, elementName);
+ } else {
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName,
+ attributes);
+ mode = IN_HEAD_NOSCRIPT;
+ }
+ attributes = null; // CPP
+ break starttagloop;
+ case SCRIPT:
+ startTagScriptInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case STYLE:
+ case NOFRAMES:
+ startTagGenericRawText(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case HEAD:
+ /* Parse error. */
+ errFooSeenWhenFooOpen(name);
+ /* Ignore the token. */
+ break starttagloop;
+ case TEMPLATE:
+ startTagTemplateInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ pop();
+ mode = AFTER_HEAD;
+ continue starttagloop;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_HEAD_NOSCRIPT:
+ switch (group) {
+ case HTML:
+ // XXX did Hixie really mean to omit "base"
+ // here?
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case LINK_OR_BASEFONT_OR_BGSOUND:
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case META:
+ checkMetaCharset(attributes);
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case STYLE:
+ case NOFRAMES:
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RAWTEXT, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case HEAD:
+ errFooSeenWhenFooOpen(name);
+ break starttagloop;
+ case NOSCRIPT:
+ errFooSeenWhenFooOpen(name);
+ break starttagloop;
+ default:
+ errBadStartTagInNoscriptInHead(name);
+ pop();
+ mode = IN_HEAD;
+ continue;
+ }
+ case IN_COLUMN_GROUP:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case COL:
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ case TEMPLATE:
+ startTagTemplateInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ if (currentPtr == 0 || stack[currentPtr].getGroup() == TEMPLATE) {
+ assert fragment || isTemplateContents();
+ errGarbageInColgroup();
+ break starttagloop;
+ }
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ case IN_SELECT_IN_TABLE:
+ switch (group) {
+ case CAPTION:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ case TABLE:
+ errStartTagWithSelectOpen(name);
+ eltPos = findLastInTableScope("select");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment;
+ break starttagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue;
+ default:
+ // fall through to IN_SELECT
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_SELECT:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case OPTION:
+ if (isCurrent("option")) {
+ pop();
+ }
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case OPTGROUP:
+ if (isCurrent("option")) {
+ pop();
+ }
+ if (isCurrent("optgroup")) {
+ pop();
+ }
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case SELECT:
+ errStartSelectWhereEndSelectExpected();
+ eltPos = findLastInTableScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment;
+ errNoSelectInTableScope();
+ break starttagloop;
+ } else {
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ break starttagloop;
+ }
+ case INPUT:
+ case TEXTAREA:
+ errStartTagWithSelectOpen(name);
+ eltPos = findLastInTableScope("select");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment;
+ break starttagloop;
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue;
+ case SCRIPT:
+ startTagScriptInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case TEMPLATE:
+ startTagTemplateInHead(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ errStrayStartTag(name);
+ break starttagloop;
+ }
+ case AFTER_BODY:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ default:
+ errStrayStartTag(name);
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ case IN_FRAMESET:
+ switch (group) {
+ case FRAMESET:
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ case FRAME:
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ // fall through to AFTER_FRAMESET
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case AFTER_FRAMESET:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case NOFRAMES:
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RAWTEXT, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ errStrayStartTag(name);
+ break starttagloop;
+ }
+ case INITIAL:
+ /*
+ * Parse error.
+ */
+ errStartTagWithoutDoctype();
+ /*
+ *
+ * Set the document to quirks mode.
+ */
+ documentModeInternal(DocumentMode.QUIRKS_MODE, null, null);
+ /*
+ * Then, switch to the root element mode of the tree
+ * construction stage
+ */
+ mode = BEFORE_HTML;
+ /*
+ * and reprocess the current token.
+ */
+ continue;
+ case BEFORE_HTML:
+ switch (group) {
+ case HTML:
+ // optimize error check and streaming SAX by
+ // hoisting
+ // "html" handling here.
+ if (attributes == HtmlAttributes.EMPTY_ATTRIBUTES) {
+ // This has the right magic side effect
+ // that
+ // it
+ // makes attributes in SAX Tree mutable.
+ appendHtmlElementToDocumentAndPush();
+ } else {
+ appendHtmlElementToDocumentAndPush(attributes);
+ }
+ // XXX application cache should fire here
+ mode = BEFORE_HEAD;
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ /*
+ * Create an HTMLElement node with the tag name
+ * html, in the HTML namespace. Append it to the
+ * Document object.
+ */
+ appendHtmlElementToDocumentAndPush();
+ /* Switch to the main mode */
+ mode = BEFORE_HEAD;
+ /*
+ * reprocess the current token.
+ */
+ continue;
+ }
+ case BEFORE_HEAD:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case HEAD:
+ /*
+ * A start tag whose tag name is "head"
+ *
+ * Create an element for the token.
+ *
+ * Set the head element pointer to this new element
+ * node.
+ *
+ * Append the new element to the current node and
+ * push it onto the stack of open elements.
+ */
+ appendToCurrentNodeAndPushHeadElement(attributes);
+ /*
+ * Change the insertion mode to "in head".
+ */
+ mode = IN_HEAD;
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ /*
+ * Any other start tag token
+ *
+ * Act as if a start tag token with the tag name
+ * "head" and no attributes had been seen,
+ */
+ appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ /*
+ * then reprocess the current token.
+ *
+ * This will result in an empty head element being
+ * generated, with the current token being
+ * reprocessed in the "after head" insertion mode.
+ */
+ continue;
+ }
+ case AFTER_HEAD:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case BODY:
+ if (attributes.getLength() == 0) {
+ // This has the right magic side effect
+ // that
+ // it
+ // makes attributes in SAX Tree mutable.
+ appendToCurrentNodeAndPushBodyElement();
+ } else {
+ appendToCurrentNodeAndPushBodyElement(attributes);
+ }
+ framesetOk = false;
+ mode = IN_BODY;
+ attributes = null; // CPP
+ break starttagloop;
+ case FRAMESET:
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ mode = IN_FRAMESET;
+ attributes = null; // CPP
+ break starttagloop;
+ case TEMPLATE:
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ StackNode<T> headOnStack = stack[currentPtr];
+ startTagTemplateInHead(elementName, attributes);
+ removeFromStack(headOnStack);
+ attributes = null; // CPP
+ break starttagloop;
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND:
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ pop(); // head
+ attributes = null; // CPP
+ break starttagloop;
+ case META:
+ errFooBetweenHeadAndBody(name);
+ checkMetaCharset(attributes);
+ pushHeadPointerOntoStack();
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ attributes);
+ selfClosing = false;
+ pop(); // head
+ attributes = null; // CPP
+ break starttagloop;
+ case SCRIPT:
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.SCRIPT_DATA, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case STYLE:
+ case NOFRAMES:
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RAWTEXT, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case TITLE:
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendToCurrentNodeAndPushElement(
+ elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(
+ Tokenizer.RCDATA, elementName);
+ attributes = null; // CPP
+ break starttagloop;
+ case HEAD:
+ errStrayStartTag(name);
+ break starttagloop;
+ default:
+ appendToCurrentNodeAndPushBodyElement();
+ mode = FRAMESET_OK;
+ continue;
+ }
+ case AFTER_AFTER_BODY:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ default:
+ errStrayStartTag(name);
+ fatal();
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ case AFTER_AFTER_FRAMESET:
+ switch (group) {
+ case HTML:
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = null; // CPP
+ }
+ break starttagloop;
+ case NOFRAMES:
+ startTagGenericRawText(elementName, attributes);
+ attributes = null; // CPP
+ break starttagloop;
+ default:
+ errStrayStartTag(name);
+ break starttagloop;
+ }
+ case TEXT:
+ assert false;
+ break starttagloop; // Avoid infinite loop if the assertion
+ // fails
+ }
+ }
+ if (selfClosing) {
+ errSelfClosing();
+ }
+ // CPPONLY: if (mBuilder == null && attributes != HtmlAttributes.EMPTY_ATTRIBUTES) {
+ // CPPONLY: Portability.delete(attributes);
+ // CPPONLY: }
+ }
+
+ private void startTagTitleInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
+ appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(Tokenizer.RCDATA, elementName);
+ }
+
+ private void startTagGenericRawText(ElementName elementName, HtmlAttributes attributes) throws SAXException {
+ appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(Tokenizer.RAWTEXT, elementName);
+ }
+
+ private void startTagScriptInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
+ // XXX need to manage much more stuff here if supporting document.write()
+ appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer.setStateAndEndTagExpectation(Tokenizer.SCRIPT_DATA, elementName);
+ }
+
+ private void startTagTemplateInHead(ElementName elementName, HtmlAttributes attributes) throws SAXException {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ insertMarker();
+ framesetOk = false;
+ originalMode = mode;
+ mode = IN_TEMPLATE;
+ pushTemplateMode(IN_TEMPLATE);
+ }
+
+ private boolean isTemplateContents() {
+ return TreeBuilder.NOT_FOUND_ON_STACK != findLast("template");
+ }
+
+ private boolean isTemplateModeStackEmpty() {
+ return templateModePtr == -1;
+ }
+
+ private boolean isSpecialParentInForeign(StackNode<T> stackNode) {
+ @NsUri String ns = stackNode.ns;
+ return ("http://www.w3.org/1999/xhtml" == ns)
+ || (stackNode.isHtmlIntegrationPoint())
+ || (("http://www.w3.org/1998/Math/MathML" == ns) && (stackNode.getGroup() == MI_MO_MN_MS_MTEXT));
+ }
+
+ /**
+ *
+ * <p>
+ * C++ memory note: The return value must be released.
+ *
+ * @return
+ * @throws SAXException
+ * @throws StopSniffingException
+ */
+ public static String extractCharsetFromContent(String attributeValue
+ // CPPONLY: , TreeBuilder tb
+ ) {
+ // This is a bit ugly. Converting the string to char array in order to
+ // make the portability layer smaller.
+ int charsetState = CHARSET_INITIAL;
+ int start = -1;
+ int end = -1;
+ @Auto char[] buffer = Portability.newCharArrayFromString(attributeValue);
+
+ charsetloop: for (int i = 0; i < buffer.length; i++) {
+ char c = buffer[i];
+ switch (charsetState) {
+ case CHARSET_INITIAL:
+ switch (c) {
+ case 'c':
+ case 'C':
+ charsetState = CHARSET_C;
+ continue;
+ default:
+ continue;
+ }
+ case CHARSET_C:
+ switch (c) {
+ case 'h':
+ case 'H':
+ charsetState = CHARSET_H;
+ continue;
+ default:
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ case CHARSET_H:
+ switch (c) {
+ case 'a':
+ case 'A':
+ charsetState = CHARSET_A;
+ continue;
+ default:
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ case CHARSET_A:
+ switch (c) {
+ case 'r':
+ case 'R':
+ charsetState = CHARSET_R;
+ continue;
+ default:
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ case CHARSET_R:
+ switch (c) {
+ case 's':
+ case 'S':
+ charsetState = CHARSET_S;
+ continue;
+ default:
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ case CHARSET_S:
+ switch (c) {
+ case 'e':
+ case 'E':
+ charsetState = CHARSET_E;
+ continue;
+ default:
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ case CHARSET_E:
+ switch (c) {
+ case 't':
+ case 'T':
+ charsetState = CHARSET_T;
+ continue;
+ default:
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ case CHARSET_T:
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\u000C':
+ case '\r':
+ case ' ':
+ continue;
+ case '=':
+ charsetState = CHARSET_EQUALS;
+ continue;
+ default:
+ return null;
+ }
+ case CHARSET_EQUALS:
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\u000C':
+ case '\r':
+ case ' ':
+ continue;
+ case '\'':
+ start = i + 1;
+ charsetState = CHARSET_SINGLE_QUOTED;
+ continue;
+ case '\"':
+ start = i + 1;
+ charsetState = CHARSET_DOUBLE_QUOTED;
+ continue;
+ default:
+ start = i;
+ charsetState = CHARSET_UNQUOTED;
+ continue;
+ }
+ case CHARSET_SINGLE_QUOTED:
+ switch (c) {
+ case '\'':
+ end = i;
+ break charsetloop;
+ default:
+ continue;
+ }
+ case CHARSET_DOUBLE_QUOTED:
+ switch (c) {
+ case '\"':
+ end = i;
+ break charsetloop;
+ default:
+ continue;
+ }
+ case CHARSET_UNQUOTED:
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\u000C':
+ case '\r':
+ case ' ':
+ case ';':
+ end = i;
+ break charsetloop;
+ default:
+ continue;
+ }
+ }
+ }
+ if (start != -1) {
+ if (end == -1) {
+ if (charsetState == CHARSET_UNQUOTED) {
+ end = buffer.length;
+ } else {
+ return null;
+ }
+ }
+ return Portability.newStringFromBuffer(buffer, start, end
+ - start
+ // CPPONLY: , tb, false
+ );
+ }
+ return null;
+ }
+
+ private void checkMetaCharset(HtmlAttributes attributes)
+ throws SAXException {
+ String charset = attributes.getValue(AttributeName.CHARSET);
+ if (charset != null) {
+ if (tokenizer.internalEncodingDeclaration(charset)) {
+ requestSuspension();
+ return;
+ }
+ return;
+ }
+ if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "content-type",
+ attributes.getValue(AttributeName.HTTP_EQUIV))) {
+ return;
+ }
+ String content = attributes.getValue(AttributeName.CONTENT);
+ if (content != null) {
+ String extract = TreeBuilder.extractCharsetFromContent(content
+ // CPPONLY: , this
+ );
+ // remember not to return early without releasing the string
+ if (extract != null) {
+ if (tokenizer.internalEncodingDeclaration(extract)) {
+ requestSuspension();
+ }
+ }
+ Portability.releaseString(extract);
+ }
+ }
+
+ public final void endTag(ElementName elementName) throws SAXException {
+ flushCharacters();
+ needToDropLF = false;
+ int eltPos;
+ int group = elementName.getGroup();
+ @Local String name = elementName.getName();
+ endtagloop: for (;;) {
+ if (isInForeign()) {
+ if (stack[currentPtr].name != name) {
+ if (currentPtr == 0) {
+ errStrayEndTag(name);
+ } else {
+ errEndTagDidNotMatchCurrentOpenElement(name, stack[currentPtr].popName);
+ }
+ }
+ eltPos = currentPtr;
+ int origPos = currentPtr;
+ for (;;) {
+ if (eltPos == 0) {
+ assert fragment: "We can get this close to the root of the stack in foreign content only in the fragment case.";
+ break endtagloop;
+ }
+ if (stack[eltPos].name == name) {
+ while (currentPtr >= eltPos) {
+ popForeign(origPos, eltPos);
+ }
+ break endtagloop;
+ }
+ if (stack[--eltPos].ns == "http://www.w3.org/1999/xhtml") {
+ break;
+ }
+ }
+ }
+ switch (mode) {
+ case IN_TEMPLATE:
+ switch (group) {
+ case TEMPLATE:
+ // fall through to IN_HEAD
+ break;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_ROW:
+ switch (group) {
+ case TR:
+ eltPos = findLastOrRoot(TreeBuilder.TR);
+ if (eltPos == 0) {
+ assert fragment || isTemplateContents();
+ errNoTableRowToClose();
+ break endtagloop;
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ break endtagloop;
+ case TABLE:
+ eltPos = findLastOrRoot(TreeBuilder.TR);
+ if (eltPos == 0) {
+ assert fragment || isTemplateContents();
+ errNoTableRowToClose();
+ break endtagloop;
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ continue;
+ case TBODY_OR_THEAD_OR_TFOOT:
+ if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ eltPos = findLastOrRoot(TreeBuilder.TR);
+ if (eltPos == 0) {
+ assert fragment || isTemplateContents();
+ errNoTableRowToClose();
+ break endtagloop;
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ continue;
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TD_OR_TH:
+ errStrayEndTag(name);
+ break endtagloop;
+ default:
+ // fall through to IN_TABLE
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_TABLE_BODY:
+ switch (group) {
+ case TBODY_OR_THEAD_OR_TFOOT:
+ eltPos = findLastOrRoot(name);
+ if (eltPos == 0) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE;
+ break endtagloop;
+ case TABLE:
+ eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
+ if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) {
+ assert fragment || isTemplateContents();
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE;
+ continue;
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TD_OR_TH:
+ case TR:
+ errStrayEndTag(name);
+ break endtagloop;
+ default:
+ // fall through to IN_TABLE
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_TABLE:
+ switch (group) {
+ case TABLE:
+ eltPos = findLast("table");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment || isTemplateContents();
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ break endtagloop;
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case TR:
+ errStrayEndTag(name);
+ break endtagloop;
+ case TEMPLATE:
+ // fall through to IN_HEAD
+ break;
+ default:
+ errStrayEndTag(name);
+ // fall through to IN_BODY
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_CAPTION:
+ switch (group) {
+ case CAPTION:
+ eltPos = findLastInTableScope("caption");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ break endtagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && currentPtr != eltPos) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_TABLE;
+ break endtagloop;
+ case TABLE:
+ eltPos = findLastInTableScope("caption");
+
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment || isTemplateContents();
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && currentPtr != eltPos) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_TABLE;
+ continue;
+ case BODY:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case TR:
+ errStrayEndTag(name);
+ break endtagloop;
+ default:
+ // fall through to IN_BODY
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_CELL:
+ switch (group) {
+ case TD_OR_TH:
+ eltPos = findLastInTableScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_ROW;
+ break endtagloop;
+ case TABLE:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ if (findLastInTableScope(name) == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert name == "tbody" || name == "tfoot" || name == "thead" || fragment || isTemplateContents();
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ closeTheCell(findLastInTableScopeTdTh());
+ continue;
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ errStrayEndTag(name);
+ break endtagloop;
+ default:
+ // fall through to IN_BODY
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case FRAMESET_OK:
+ case IN_BODY:
+ switch (group) {
+ case BODY:
+ if (!isSecondOnStackBody()) {
+ assert fragment || isTemplateContents();
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ assert currentPtr >= 1;
+ if (errorHandler != null) {
+ uncloseloop1: for (int i = 2; i <= currentPtr; i++) {
+ switch (stack[i].getGroup()) {
+ case DD_OR_DT:
+ case LI:
+ case OPTGROUP:
+ case OPTION: // is this possible?
+ case P:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ case TD_OR_TH:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ break;
+ default:
+ errEndWithUnclosedElements(name);
+ break uncloseloop1;
+ }
+ }
+ }
+ mode = AFTER_BODY;
+ break endtagloop;
+ case HTML:
+ if (!isSecondOnStackBody()) {
+ assert fragment || isTemplateContents();
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ if (errorHandler != null) {
+ uncloseloop2: for (int i = 0; i <= currentPtr; i++) {
+ switch (stack[i].getGroup()) {
+ case DD_OR_DT:
+ case LI:
+ case P:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case BODY:
+ case HTML:
+ break;
+ default:
+ errEndWithUnclosedElements(name);
+ break uncloseloop2;
+ }
+ }
+ }
+ mode = AFTER_BODY;
+ continue;
+ case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+ case UL_OR_OL_OR_DL:
+ case PRE_OR_LISTING:
+ case FIELDSET:
+ case BUTTON:
+ case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY:
+ eltPos = findLastInScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ } else {
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ break endtagloop;
+ case FORM:
+ if (!isTemplateContents()) {
+ if (formPointer == null) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ formPointer = null;
+ eltPos = findLastInScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ removeFromStack(eltPos);
+ break endtagloop;
+ } else {
+ eltPos = findLastInScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ break endtagloop;
+ }
+ case P:
+ eltPos = findLastInButtonScope("p");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errNoElementToCloseButEndTagSeen("p");
+ // XXX Can the 'in foreign' case happen anymore?
+ if (isInForeign()) {
+ errHtmlStartTagInForeignContext(name);
+ // Check for currentPtr for the fragment
+ // case.
+ while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
+ pop();
+ }
+ }
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ HtmlAttributes.EMPTY_ATTRIBUTES);
+ break endtagloop;
+ }
+ generateImpliedEndTagsExceptFor("p");
+ assert eltPos != TreeBuilder.NOT_FOUND_ON_STACK;
+ if (errorHandler != null && eltPos != currentPtr) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ break endtagloop;
+ case LI:
+ eltPos = findLastInListScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errNoElementToCloseButEndTagSeen(name);
+ } else {
+ generateImpliedEndTagsExceptFor(name);
+ if (errorHandler != null
+ && eltPos != currentPtr) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ break endtagloop;
+ case DD_OR_DT:
+ eltPos = findLastInScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errNoElementToCloseButEndTagSeen(name);
+ } else {
+ generateImpliedEndTagsExceptFor(name);
+ if (errorHandler != null
+ && eltPos != currentPtr) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ break endtagloop;
+ case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
+ eltPos = findLastInScopeHn();
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ } else {
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ break endtagloop;
+ case OBJECT:
+ case MARQUEE_OR_APPLET:
+ eltPos = findLastInScope(name);
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ } else {
+ generateImpliedEndTags();
+ if (errorHandler != null && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ }
+ break endtagloop;
+ case BR:
+ errEndTagBr();
+ if (isInForeign()) {
+ // XXX can this happen anymore?
+ errHtmlStartTagInForeignContext(name);
+ // Check for currentPtr for the fragment
+ // case.
+ while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
+ pop();
+ }
+ }
+ reconstructTheActiveFormattingElements();
+ appendVoidElementToCurrentMayFoster(
+ elementName,
+ HtmlAttributes.EMPTY_ATTRIBUTES);
+ break endtagloop;
+ case TEMPLATE:
+ // fall through to IN_HEAD;
+ break;
+ case AREA_OR_WBR:
+ case KEYGEN: // XXX??
+ case PARAM_OR_SOURCE_OR_TRACK:
+ case EMBED:
+ case IMG:
+ case IMAGE:
+ case INPUT:
+ case HR:
+ case IFRAME:
+ case NOEMBED: // XXX???
+ case NOFRAMES: // XXX??
+ case SELECT:
+ case TABLE:
+ case TEXTAREA: // XXX??
+ errStrayEndTag(name);
+ break endtagloop;
+ case NOSCRIPT:
+ if (scriptingEnabled) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case A:
+ case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+ case FONT:
+ case NOBR:
+ if (adoptionAgencyEndTag(name)) {
+ break endtagloop;
+ }
+ // else handle like any other tag
+ // CPPONLY: MOZ_FALLTHROUGH;
+ default:
+ if (isCurrent(name)) {
+ pop();
+ break endtagloop;
+ }
+
+ eltPos = currentPtr;
+ for (;;) {
+ StackNode<T> node = stack[eltPos];
+ if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) {
+ generateImpliedEndTags();
+ if (errorHandler != null
+ && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ break endtagloop;
+ } else if (eltPos == 0 || node.isSpecial()) {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ eltPos--;
+ }
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_HEAD:
+ switch (group) {
+ case HEAD:
+ pop();
+ mode = AFTER_HEAD;
+ break endtagloop;
+ case BR:
+ case HTML:
+ case BODY:
+ pop();
+ mode = AFTER_HEAD;
+ continue;
+ case TEMPLATE:
+ endTagTemplateInHead();
+ break endtagloop;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case IN_HEAD_NOSCRIPT:
+ switch (group) {
+ case NOSCRIPT:
+ pop();
+ mode = IN_HEAD;
+ break endtagloop;
+ case BR:
+ errStrayEndTag(name);
+ pop();
+ mode = IN_HEAD;
+ continue;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case IN_COLUMN_GROUP:
+ switch (group) {
+ case COLGROUP:
+ if (currentPtr == 0 || stack[currentPtr].getGroup() ==
+ TreeBuilder.TEMPLATE) {
+ assert fragment || isTemplateContents();
+ errGarbageInColgroup();
+ break endtagloop;
+ }
+ pop();
+ mode = IN_TABLE;
+ break endtagloop;
+ case COL:
+ errStrayEndTag(name);
+ break endtagloop;
+ case TEMPLATE:
+ endTagTemplateInHead();
+ break endtagloop;
+ default:
+ if (currentPtr == 0 || stack[currentPtr].getGroup() ==
+ TreeBuilder.TEMPLATE) {
+ assert fragment || isTemplateContents();
+ errGarbageInColgroup();
+ break endtagloop;
+ }
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ case IN_SELECT_IN_TABLE:
+ switch (group) {
+ case CAPTION:
+ case TABLE:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ errEndTagSeenWithSelectOpen(name);
+ if (findLastInTableScope(name) != TreeBuilder.NOT_FOUND_ON_STACK) {
+ eltPos = findLastInTableScope("select");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment;
+ break endtagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue;
+ } else {
+ break endtagloop;
+ }
+ default:
+ // fall through to IN_SELECT
+ }
+ // CPPONLY: MOZ_FALLTHROUGH;
+ case IN_SELECT:
+ switch (group) {
+ case OPTION:
+ if (isCurrent("option")) {
+ pop();
+ break endtagloop;
+ } else {
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case OPTGROUP:
+ if (isCurrent("option")
+ && "optgroup" == stack[currentPtr - 1].name) {
+ pop();
+ }
+ if (isCurrent("optgroup")) {
+ pop();
+ } else {
+ errStrayEndTag(name);
+ }
+ break endtagloop;
+ case SELECT:
+ eltPos = findLastInTableScope("select");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ assert fragment;
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ break endtagloop;
+ case TEMPLATE:
+ endTagTemplateInHead();
+ break endtagloop;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case AFTER_BODY:
+ switch (group) {
+ case HTML:
+ if (fragment) {
+ errStrayEndTag(name);
+ break endtagloop;
+ } else {
+ mode = AFTER_AFTER_BODY;
+ break endtagloop;
+ }
+ default:
+ errEndTagAfterBody();
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ case IN_FRAMESET:
+ switch (group) {
+ case FRAMESET:
+ if (currentPtr == 0) {
+ assert fragment;
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ pop();
+ if ((!fragment) && !isCurrent("frameset")) {
+ mode = AFTER_FRAMESET;
+ }
+ break endtagloop;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case AFTER_FRAMESET:
+ switch (group) {
+ case HTML:
+ mode = AFTER_AFTER_FRAMESET;
+ break endtagloop;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case INITIAL:
+ /*
+ * Parse error.
+ */
+ errEndTagSeenWithoutDoctype();
+ /*
+ *
+ * Set the document to quirks mode.
+ */
+ documentModeInternal(DocumentMode.QUIRKS_MODE, null, null);
+ /*
+ * Then, switch to the root element mode of the tree
+ * construction stage
+ */
+ mode = BEFORE_HTML;
+ /*
+ * and reprocess the current token.
+ */
+ continue;
+ case BEFORE_HTML:
+ switch (group) {
+ case HEAD:
+ case BR:
+ case HTML:
+ case BODY:
+ /*
+ * Create an HTMLElement node with the tag name
+ * html, in the HTML namespace. Append it to the
+ * Document object.
+ */
+ appendHtmlElementToDocumentAndPush();
+ /* Switch to the main mode */
+ mode = BEFORE_HEAD;
+ /*
+ * reprocess the current token.
+ */
+ continue;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case BEFORE_HEAD:
+ switch (group) {
+ case HEAD:
+ case BR:
+ case HTML:
+ case BODY:
+ appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ continue;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case AFTER_HEAD:
+ switch (group) {
+ case TEMPLATE:
+ endTagTemplateInHead();
+ break endtagloop;
+ case HTML:
+ case BODY:
+ case BR:
+ appendToCurrentNodeAndPushBodyElement();
+ mode = FRAMESET_OK;
+ continue;
+ default:
+ errStrayEndTag(name);
+ break endtagloop;
+ }
+ case AFTER_AFTER_BODY:
+ errStrayEndTag(name);
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ case AFTER_AFTER_FRAMESET:
+ errStrayEndTag(name);
+ break endtagloop;
+ case TEXT:
+ // XXX need to manage insertion point here
+ pop();
+ if (originalMode == AFTER_HEAD) {
+ silentPop();
+ }
+ mode = originalMode;
+ break endtagloop;
+ }
+ } // endtagloop
+ }
+
+ private void endTagTemplateInHead() throws SAXException {
+ int eltPos = findLast("template");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ errStrayEndTag("template");
+ return;
+ }
+ generateImpliedEndTagsThoroughly();
+ if (errorHandler != null && !isCurrent("template")) {
+ errUnclosedElements(eltPos, "template");
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ popTemplateMode();
+ resetTheInsertionMode();
+ }
+
+ private int findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml"
+ && (stack[i].getGroup() == TreeBuilder.TBODY_OR_THEAD_OR_TFOOT
+ || stack[i].getGroup() == TreeBuilder.TEMPLATE)) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private int findLast(@Local String name) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) {
+ return i;
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private int findLastInTableScope(@Local String name) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
+ if (stack[i].name == name) {
+ return i;
+ } else if (stack[i].name == "table" || stack[i].name == "template") {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private int findLastInButtonScope(@Local String name) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
+ if (stack[i].name == name) {
+ return i;
+ } else if (stack[i].name == "button") {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+
+ if (stack[i].isScoping()) {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private int findLastInScope(@Local String name) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) {
+ return i;
+ } else if (stack[i].isScoping()) {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private int findLastInListScope(@Local String name) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
+ if (stack[i].name == name) {
+ return i;
+ } else if (stack[i].name == "ul" || stack[i].name == "ol") {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+
+ if (stack[i].isScoping()) {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private int findLastInScopeHn() {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].getGroup() == TreeBuilder.H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
+ return i;
+ } else if (stack[i].isScoping()) {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private void generateImpliedEndTagsExceptFor(@Local String name)
+ throws SAXException {
+ for (;;) {
+ StackNode<T> node = stack[currentPtr];
+ switch (node.getGroup()) {
+ case P:
+ case LI:
+ case DD_OR_DT:
+ case OPTION:
+ case OPTGROUP:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ if (node.ns == "http://www.w3.org/1999/xhtml" && node.name == name) {
+ return;
+ }
+ pop();
+ continue;
+ default:
+ return;
+ }
+ }
+ }
+
+ private void generateImpliedEndTags() throws SAXException {
+ for (;;) {
+ switch (stack[currentPtr].getGroup()) {
+ case P:
+ case LI:
+ case DD_OR_DT:
+ case OPTION:
+ case OPTGROUP:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ pop();
+ continue;
+ default:
+ return;
+ }
+ }
+ }
+
+ private void generateImpliedEndTagsThoroughly() throws SAXException {
+ for (;;) {
+ switch (stack[currentPtr].getGroup()) {
+ case CAPTION:
+ case COLGROUP:
+ case DD_OR_DT:
+ case LI:
+ case OPTGROUP:
+ case OPTION:
+ case P:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case TR:
+ pop();
+ continue;
+ default:
+ return;
+ }
+ }
+ }
+
+ private boolean isSecondOnStackBody() {
+ return currentPtr >= 1 && stack[1].getGroup() == TreeBuilder.BODY;
+ }
+
+ private void documentModeInternal(DocumentMode m, String publicIdentifier,
+ String systemIdentifier)
+ throws SAXException {
+
+ if (forceNoQuirks) {
+ // Srcdoc documents are always rendered in standards mode.
+ quirks = false;
+ if (documentModeHandler != null) {
+ documentModeHandler.documentMode(
+ DocumentMode.STANDARDS_MODE
+ // [NOCPP[
+ , null, null
+ // ]NOCPP]
+ );
+ }
+ return;
+ }
+
+ quirks = (m == DocumentMode.QUIRKS_MODE);
+ if (documentModeHandler != null) {
+ documentModeHandler.documentMode(
+ m
+ // [NOCPP[
+ , publicIdentifier, systemIdentifier
+ // ]NOCPP]
+ );
+ }
+ // [NOCPP[
+ documentMode(m, publicIdentifier, systemIdentifier);
+ // ]NOCPP]
+ }
+
+ private boolean isAlmostStandards(String publicIdentifier,
+ String systemIdentifier) {
+ if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier)) {
+ return true;
+ }
+ if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier)) {
+ return true;
+ }
+ if (systemIdentifier != null) {
+ if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
+ return true;
+ }
+ if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isQuirky(@Local String name, String publicIdentifier,
+ String systemIdentifier, boolean forceQuirks) {
+ if (forceQuirks) {
+ return true;
+ }
+ if (name != HTML_LOCAL) {
+ return true;
+ }
+ if (publicIdentifier != null) {
+ for (int i = 0; i < TreeBuilder.QUIRKY_PUBLIC_IDS.length; i++) {
+ if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ TreeBuilder.QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
+ return true;
+ }
+ }
+ if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier)
+ || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "-/w3c/dtd html 4.0 transitional/en",
+ publicIdentifier)
+ || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "html", publicIdentifier)) {
+ return true;
+ }
+ }
+ if (systemIdentifier == null) {
+ if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
+ return true;
+ } else if (Portability.lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
+ return true;
+ }
+ } else if (Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
+ systemIdentifier)) {
+ return true;
+ }
+ return false;
+ }
+
+ private void closeTheCell(int eltPos) throws SAXException {
+ generateImpliedEndTags();
+ if (errorHandler != null && eltPos != currentPtr) {
+ errUnclosedElementsCell(eltPos);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_ROW;
+ return;
+ }
+
+ private int findLastInTableScopeTdTh() {
+ for (int i = currentPtr; i > 0; i--) {
+ @Local String name = stack[i].name;
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml") {
+ if ("td" == name || "th" == name) {
+ return i;
+ } else if (name == "table" || name == "template") {
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+ }
+ }
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private void clearStackBackTo(int eltPos) throws SAXException {
+ int eltGroup = stack[eltPos].getGroup();
+ while (currentPtr > eltPos) { // > not >= intentional
+ if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml"
+ && stack[currentPtr].getGroup() == TEMPLATE
+ && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltPos == 0)) {
+ return;
+ }
+ pop();
+ }
+ }
+
+ private void resetTheInsertionMode() {
+ StackNode<T> node;
+ @Local String name;
+ @NsUri String ns;
+ for (int i = currentPtr; i >= 0; i--) {
+ node = stack[i];
+ name = node.name;
+ ns = node.ns;
+ if (i == 0) {
+ if (!(contextNamespace == "http://www.w3.org/1999/xhtml" && (contextName == "td" || contextName == "th"))) {
+ if (fragment) {
+ // Make sure we are parsing a fragment otherwise the context element doesn't make sense.
+ name = contextName;
+ ns = contextNamespace;
+ }
+ } else {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY; // XXX from Hixie's email
+ return;
+ }
+ }
+ if ("select" == name) {
+ int ancestorIndex = i;
+ while (ancestorIndex > 0) {
+ StackNode<T> ancestor = stack[ancestorIndex--];
+ if ("http://www.w3.org/1999/xhtml" == ancestor.ns) {
+ if ("template" == ancestor.name) {
+ break;
+ }
+ if ("table" == ancestor.name) {
+ mode = IN_SELECT_IN_TABLE;
+ return;
+ }
+ }
+ }
+ mode = IN_SELECT;
+ return;
+ } else if ("td" == name || "th" == name) {
+ mode = IN_CELL;
+ return;
+ } else if ("tr" == name) {
+ mode = IN_ROW;
+ return;
+ } else if ("tbody" == name || "thead" == name || "tfoot" == name) {
+ mode = IN_TABLE_BODY;
+ return;
+ } else if ("caption" == name) {
+ mode = IN_CAPTION;
+ return;
+ } else if ("colgroup" == name) {
+ mode = IN_COLUMN_GROUP;
+ return;
+ } else if ("table" == name) {
+ mode = IN_TABLE;
+ return;
+ } else if ("http://www.w3.org/1999/xhtml" != ns) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ } else if ("template" == name) {
+ assert templateModePtr >= 0;
+ mode = templateModeStack[templateModePtr];
+ return;
+ } else if ("head" == name) {
+ if (name == contextName) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY; // really
+ } else {
+ mode = IN_HEAD;
+ }
+ return;
+ } else if ("body" == name) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ } else if ("frameset" == name) {
+ // TODO: Fragment case. Add error reporting.
+ mode = IN_FRAMESET;
+ return;
+ } else if ("html" == name) {
+ if (headPointer == null) {
+ // TODO: Fragment case. Add error reporting.
+ mode = BEFORE_HEAD;
+ } else {
+ mode = AFTER_HEAD;
+ }
+ return;
+ } else if (i == 0) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ }
+ }
+ }
+
+ /**
+ * @throws SAXException
+ *
+ */
+ private void implicitlyCloseP() throws SAXException {
+ int eltPos = findLastInButtonScope("p");
+ if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
+ return;
+ }
+ generateImpliedEndTagsExceptFor("p");
+ if (errorHandler != null && eltPos != currentPtr) {
+ errUnclosedElementsImplied(eltPos, "p");
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+
+ private boolean debugOnlyClearLastStackSlot() {
+ stack[currentPtr] = null;
+ return true;
+ }
+
+ private boolean debugOnlyClearLastListSlot() {
+ listOfActiveFormattingElements[listPtr] = null;
+ return true;
+ }
+
+ private void pushTemplateMode(int mode) {
+ templateModePtr++;
+ if (templateModePtr == templateModeStack.length) {
+ int[] newStack = new int[templateModeStack.length + 64];
+ System.arraycopy(templateModeStack, 0, newStack, 0, templateModeStack.length);
+ templateModeStack = newStack;
+ }
+ templateModeStack[templateModePtr] = mode;
+ }
+
+ @SuppressWarnings("unchecked") private void push(StackNode<T> node) throws SAXException {
+ currentPtr++;
+ if (currentPtr == stack.length) {
+ StackNode<T>[] newStack = new StackNode[stack.length + 64];
+ System.arraycopy(stack, 0, newStack, 0, stack.length);
+ stack = newStack;
+ }
+ stack[currentPtr] = node;
+ elementPushed(node.ns, node.popName, node.node);
+ }
+
+ @SuppressWarnings("unchecked") private void silentPush(StackNode<T> node) throws SAXException {
+ currentPtr++;
+ if (currentPtr == stack.length) {
+ StackNode<T>[] newStack = new StackNode[stack.length + 64];
+ System.arraycopy(stack, 0, newStack, 0, stack.length);
+ stack = newStack;
+ }
+ stack[currentPtr] = node;
+ }
+
+ @SuppressWarnings("unchecked") private void append(StackNode<T> node) {
+ listPtr++;
+ if (listPtr == listOfActiveFormattingElements.length) {
+ StackNode<T>[] newList = new StackNode[listOfActiveFormattingElements.length + 64];
+ System.arraycopy(listOfActiveFormattingElements, 0, newList, 0,
+ listOfActiveFormattingElements.length);
+ listOfActiveFormattingElements = newList;
+ }
+ listOfActiveFormattingElements[listPtr] = node;
+ }
+
+ @Inline private void insertMarker() {
+ append(null);
+ }
+
+ private void clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
+ while (listPtr > -1) {
+ if (listOfActiveFormattingElements[listPtr] == null) {
+ --listPtr;
+ return;
+ }
+ listOfActiveFormattingElements[listPtr].release(this);
+ --listPtr;
+ }
+ }
+
+ @Inline private boolean isCurrent(@Local String name) {
+ return stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" &&
+ name == stack[currentPtr].name;
+ }
+
+ private void removeFromStack(int pos) throws SAXException {
+ if (currentPtr == pos) {
+ pop();
+ } else {
+ fatal();
+ stack[pos].release(this);
+ System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos);
+ assert debugOnlyClearLastStackSlot();
+ currentPtr--;
+ }
+ }
+
+ private void removeFromStack(StackNode<T> node) throws SAXException {
+ if (stack[currentPtr] == node) {
+ pop();
+ } else {
+ int pos = currentPtr - 1;
+ while (pos >= 0 && stack[pos] != node) {
+ pos--;
+ }
+ if (pos == -1) {
+ // dead code?
+ return;
+ }
+ fatal();
+ node.release(this);
+ System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos);
+ currentPtr--;
+ }
+ }
+
+ private void removeFromListOfActiveFormattingElements(int pos) {
+ assert listOfActiveFormattingElements[pos] != null;
+ listOfActiveFormattingElements[pos].release(this);
+ if (pos == listPtr) {
+ assert debugOnlyClearLastListSlot();
+ listPtr--;
+ return;
+ }
+ assert pos < listPtr;
+ System.arraycopy(listOfActiveFormattingElements, pos + 1,
+ listOfActiveFormattingElements, pos, listPtr - pos);
+ assert debugOnlyClearLastListSlot();
+ listPtr--;
+ }
+
+ /**
+ * Adoption agency algorithm.
+ *
+ * @param name subject as described in the specified algorithm.
+ * @return Returns true if the algorithm has completed and there is nothing remaining to
+ * be done. Returns false if the algorithm needs to "act as described in the 'any other
+ * end tag' entry" as described in the specified algorithm.
+ * @throws SAXException
+ */
+ private boolean adoptionAgencyEndTag(@Local String name) throws SAXException {
+ // This check intends to ensure that for properly nested tags, closing tags will match
+ // against the stack instead of the listOfActiveFormattingElements.
+ if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" &&
+ stack[currentPtr].name == name &&
+ findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
+ // If the current element matches the name but isn't on the list of active
+ // formatting elements, then it is possible that the list was mangled by the Noah's Ark
+ // clause. In this case, we want to match the end tag against the stack instead of
+ // proceeding with the AAA algorithm that may match against the list of
+ // active formatting elements (and possibly mangle the tree in unexpected ways).
+ pop();
+ return true;
+ }
+
+ // If you crash around here, perhaps some stack node variable claimed to
+ // be a weak ref isn't.
+ for (int i = 0; i < 8; ++i) {
+ int formattingEltListPos = listPtr;
+ while (formattingEltListPos > -1) {
+ StackNode<T> listNode = listOfActiveFormattingElements[formattingEltListPos]; // weak ref
+ if (listNode == null) {
+ formattingEltListPos = -1;
+ break;
+ } else if (listNode.name == name) {
+ break;
+ }
+ formattingEltListPos--;
+ }
+ if (formattingEltListPos == -1) {
+ return false;
+ }
+ // this *looks* like a weak ref to the list of formatting elements
+ StackNode<T> formattingElt = listOfActiveFormattingElements[formattingEltListPos];
+ int formattingEltStackPos = currentPtr;
+ boolean inScope = true;
+ while (formattingEltStackPos > -1) {
+ StackNode<T> node = stack[formattingEltStackPos]; // weak ref
+ if (node == formattingElt) {
+ break;
+ } else if (node.isScoping()) {
+ inScope = false;
+ }
+ formattingEltStackPos--;
+ }
+ if (formattingEltStackPos == -1) {
+ errNoElementToCloseButEndTagSeen(name);
+ removeFromListOfActiveFormattingElements(formattingEltListPos);
+ return true;
+ }
+ if (!inScope) {
+ errNoElementToCloseButEndTagSeen(name);
+ return true;
+ }
+ // stackPos now points to the formatting element and it is in scope
+ if (formattingEltStackPos != currentPtr) {
+ errEndTagViolatesNestingRules(name);
+ }
+ int furthestBlockPos = formattingEltStackPos + 1;
+ while (furthestBlockPos <= currentPtr) {
+ StackNode<T> node = stack[furthestBlockPos]; // weak ref
+ assert furthestBlockPos > 0: "How is formattingEltStackPos + 1 not > 0?";
+ if (node.isSpecial()) {
+ break;
+ }
+ furthestBlockPos++;
+ }
+ if (furthestBlockPos > currentPtr) {
+ // no furthest block
+ while (currentPtr >= formattingEltStackPos) {
+ pop();
+ }
+ removeFromListOfActiveFormattingElements(formattingEltListPos);
+ return true;
+ }
+ // commonAncestor is used for running the algorithm and
+ // insertionCommonAncestor is used for the actual insertions to
+ // keep them depth-limited.
+ StackNode<T> commonAncestor = stack[formattingEltStackPos - 1]; // weak ref
+ T insertionCommonAncestor = nodeFromStackWithBlinkCompat(formattingEltStackPos - 1); // weak ref
+ StackNode<T> furthestBlock = stack[furthestBlockPos]; // weak ref
+ // detachFromParent(furthestBlock.node); XXX AAA CHANGE
+ int bookmark = formattingEltListPos;
+ int nodePos = furthestBlockPos;
+ StackNode<T> lastNode = furthestBlock; // weak ref
+ int j = 0;
+ for (;;) {
+ ++j;
+ nodePos--;
+ if (nodePos == formattingEltStackPos) {
+ break;
+ }
+ StackNode<T> node = stack[nodePos]; // weak ref
+ int nodeListPos = findInListOfActiveFormattingElements(node);
+
+ if (j > 3 && nodeListPos != -1) {
+ removeFromListOfActiveFormattingElements(nodeListPos);
+
+ // Adjust the indices into the list to account
+ // for the removal of nodeListPos.
+ if (nodeListPos <= formattingEltListPos) {
+ formattingEltListPos--;
+ }
+ if (nodeListPos <= bookmark) {
+ bookmark--;
+ }
+
+ // Update position to reflect removal from list.
+ nodeListPos = -1;
+ }
+
+ if (nodeListPos == -1) {
+ assert formattingEltStackPos < nodePos;
+ assert bookmark < nodePos;
+ assert furthestBlockPos > nodePos;
+ removeFromStack(nodePos); // node is now a bad pointer in C++
+ furthestBlockPos--;
+ continue;
+ }
+ // now node is both on stack and in the list
+ if (nodePos == furthestBlockPos) {
+ bookmark = nodeListPos + 1;
+ }
+ // if (hasChildren(node.node)) { XXX AAA CHANGE
+ assert node == listOfActiveFormattingElements[nodeListPos];
+ assert node == stack[nodePos];
+ T clone = createElement("http://www.w3.org/1999/xhtml",
+ node.name, node.attributes.cloneAttributes(), insertionCommonAncestor
+ // CPPONLY: , htmlCreator(node.getHtmlCreator())
+ );
+ StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+ node.name, clone, node.popName, node.attributes
+ // CPPONLY: , node.getHtmlCreator()
+ // [NOCPP[
+ , node.getLocator()
+ // ]NOCPP]
+ ); // creation ownership goes to stack
+ node.dropAttributes(); // adopt ownership to newNode
+ stack[nodePos] = newNode;
+ newNode.retain(); // retain for list
+ listOfActiveFormattingElements[nodeListPos] = newNode;
+ node.release(this); // release from stack
+ node.release(this); // release from list
+ node = newNode;
+ // } XXX AAA CHANGE
+ detachFromParent(lastNode.node);
+ appendElement(lastNode.node, nodeFromStackWithBlinkCompat(nodePos));
+ lastNode = node;
+ }
+ // If we insert into a foster parent, for simplicity, we insert
+ // accoding to the spec without Blink's depth limit.
+ if (commonAncestor.isFosterParenting()) {
+ fatal();
+ detachFromParent(lastNode.node);
+ insertIntoFosterParent(lastNode.node);
+ } else {
+ detachFromParent(lastNode.node);
+ appendElement(lastNode.node, insertionCommonAncestor);
+ }
+ T clone = createElement("http://www.w3.org/1999/xhtml",
+ formattingElt.name,
+ formattingElt.attributes.cloneAttributes(), furthestBlock.node
+ // CPPONLY: , htmlCreator(formattingElt.getHtmlCreator())
+ );
+ StackNode<T> formattingClone = createStackNode(
+ formattingElt.getFlags(), formattingElt.ns,
+ formattingElt.name, clone, formattingElt.popName,
+ formattingElt.attributes
+ // CPPONLY: , formattingElt.getHtmlCreator()
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ ); // Ownership transfers to stack below
+ formattingElt.dropAttributes(); // transfer ownership to
+ // formattingClone
+ appendChildrenToNewParent(furthestBlock.node, clone);
+ appendElement(clone, furthestBlock.node);
+ removeFromListOfActiveFormattingElements(formattingEltListPos);
+ insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
+ assert formattingEltStackPos < furthestBlockPos;
+ removeFromStack(formattingEltStackPos);
+ // furthestBlockPos is now off by one and points to the slot after
+ // it
+ insertIntoStack(formattingClone, furthestBlockPos);
+ }
+ return true;
+ }
+
+ private void insertIntoStack(StackNode<T> node, int position)
+ throws SAXException {
+ assert currentPtr + 1 < stack.length;
+ assert position <= currentPtr + 1;
+ if (position == currentPtr + 1) {
+ push(node);
+ } else {
+ System.arraycopy(stack, position, stack, position + 1,
+ (currentPtr - position) + 1);
+ currentPtr++;
+ stack[position] = node;
+ }
+ }
+
+ private void insertIntoListOfActiveFormattingElements(
+ StackNode<T> formattingClone, int bookmark) {
+ formattingClone.retain();
+ assert listPtr + 1 < listOfActiveFormattingElements.length;
+ if (bookmark <= listPtr) {
+ System.arraycopy(listOfActiveFormattingElements, bookmark,
+ listOfActiveFormattingElements, bookmark + 1,
+ (listPtr - bookmark) + 1);
+ }
+ listPtr++;
+ listOfActiveFormattingElements[bookmark] = formattingClone;
+ }
+
+ private int findInListOfActiveFormattingElements(StackNode<T> node) {
+ for (int i = listPtr; i >= 0; i--) {
+ if (node == listOfActiveFormattingElements[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
+ @Local String name) {
+ for (int i = listPtr; i >= 0; i--) {
+ StackNode<T> node = listOfActiveFormattingElements[i];
+ if (node == null) {
+ return -1;
+ } else if (node.name == name) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ private void maybeForgetEarlierDuplicateFormattingElement(
+ @Local String name, HtmlAttributes attributes) throws SAXException {
+ int candidate = -1;
+ int count = 0;
+ for (int i = listPtr; i >= 0; i--) {
+ StackNode<T> node = listOfActiveFormattingElements[i];
+ if (node == null) {
+ break;
+ }
+ if (node.name == name && node.attributes.equalsAnother(attributes)) {
+ candidate = i;
+ ++count;
+ }
+ }
+ if (count >= 3) {
+ removeFromListOfActiveFormattingElements(candidate);
+ }
+ }
+
+ private int findLastOrRoot(@Local String name) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].name == name) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ private int findLastOrRoot(int group) {
+ for (int i = currentPtr; i > 0; i--) {
+ if (stack[i].ns == "http://www.w3.org/1999/xhtml" && stack[i].getGroup() == group) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Attempt to add attribute to the body element.
+ * @param attributes the attributes
+ * @return <code>true</code> iff the attributes were added
+ * @throws SAXException
+ */
+ private boolean addAttributesToBody(HtmlAttributes attributes)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ if (currentPtr >= 1) {
+ StackNode<T> body = stack[1];
+ if (body.getGroup() == TreeBuilder.BODY) {
+ addAttributesToElement(body.node, attributes);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void addAttributesToHtml(HtmlAttributes attributes)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ addAttributesToElement(stack[0].node, attributes);
+ }
+
+ private void pushHeadPointerOntoStack() throws SAXException {
+ assert headPointer != null;
+ assert mode == AFTER_HEAD;
+ fatal();
+ silentPush(createStackNode(ElementName.HEAD, headPointer
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ ));
+ }
+
+ /**
+ * @throws SAXException
+ *
+ */
+ private void reconstructTheActiveFormattingElements() throws SAXException {
+ if (listPtr == -1) {
+ return;
+ }
+ StackNode<T> mostRecent = listOfActiveFormattingElements[listPtr];
+ if (mostRecent == null || isInStack(mostRecent)) {
+ return;
+ }
+ int entryPos = listPtr;
+ for (;;) {
+ entryPos--;
+ if (entryPos == -1) {
+ break;
+ }
+ if (listOfActiveFormattingElements[entryPos] == null) {
+ break;
+ }
+ if (isInStack(listOfActiveFormattingElements[entryPos])) {
+ break;
+ }
+ }
+ while (entryPos < listPtr) {
+ entryPos++;
+ StackNode<T> entry = listOfActiveFormattingElements[entryPos];
+ StackNode<T> current = stack[currentPtr];
+
+ T clone;
+ if (current.isFosterParenting()) {
+ clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name,
+ entry.attributes.cloneAttributes()
+ // CPPONLY: , htmlCreator(entry.getHtmlCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
+ entry.attributes.cloneAttributes(), currentNode
+ // CPPONLY: , htmlCreator(entry.getHtmlCreator())
+ );
+ appendElement(clone, currentNode);
+ }
+
+ StackNode<T> entryClone = createStackNode(entry.getFlags(),
+ entry.ns, entry.name, clone, entry.popName,
+ entry.attributes
+ // CPPONLY: , entry.getHtmlCreator()
+ // [NOCPP[
+ , entry.getLocator()
+ // ]NOCPP]
+ );
+
+ entry.dropAttributes(); // transfer ownership to entryClone
+
+ push(entryClone);
+ // stack takes ownership of the local variable
+ listOfActiveFormattingElements[entryPos] = entryClone;
+ // overwriting the old entry on the list, so release & retain
+ entry.release(this);
+ entryClone.retain();
+ }
+ }
+
+ void notifyUnusedStackNode(int idxInStackNodes) {
+ // stackNodesIdx is the earliest possible index of a stack node that might be unused,
+ // so update the index if necessary.
+ if (idxInStackNodes < stackNodesIdx) {
+ stackNodesIdx = idxInStackNodes;
+ }
+ }
+
+ @SuppressWarnings("unchecked") private StackNode<T> getUnusedStackNode() {
+ // Search for an unused stack node.
+ while (stackNodesIdx < numStackNodes) {
+ if (stackNodes[stackNodesIdx].isUnused()) {
+ return stackNodes[stackNodesIdx++];
+ }
+ stackNodesIdx++;
+ }
+
+ if (stackNodesIdx < stackNodes.length) {
+ // No unused stack nodes, but there is still space in the storage array.
+ stackNodes[stackNodesIdx] = new StackNode<T>(stackNodesIdx);
+ numStackNodes++;
+ return stackNodes[stackNodesIdx++];
+ }
+
+ // Could not find an unused stack node and storage array is full.
+ StackNode<T>[] newStack = new StackNode[stackNodes.length + 64];
+ System.arraycopy(stackNodes, 0, newStack, 0, stackNodes.length);
+ stackNodes = newStack;
+
+ // Create a new stack node and return it.
+ stackNodes[stackNodesIdx] = new StackNode<T>(stackNodesIdx);
+ numStackNodes++;
+ return stackNodes[stackNodesIdx++];
+ }
+
+ private StackNode<T> createStackNode(int flags, @NsUri String ns, @Local String name, T node,
+ @Local String popName, HtmlAttributes attributes
+ // CPPONLY: , @HtmlCreator Object htmlCreator
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ StackNode<T> instance = getUnusedStackNode();
+ instance.setValues(flags, ns, name, node, popName, attributes
+ // CPPONLY: , htmlCreator
+ // [NOCPP[
+ , locator
+ // ]NOCPP]
+ );
+ return instance;
+ }
+
+ private StackNode<T> createStackNode(ElementName elementName, T node
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ StackNode<T> instance = getUnusedStackNode();
+ instance.setValues(elementName, node
+ // [NOCPP[
+ , locator
+ // ]NOCPP]
+ );
+ return instance;
+ }
+
+ private StackNode<T> createStackNode(ElementName elementName, T node, HtmlAttributes attributes
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ StackNode<T> instance = getUnusedStackNode();
+ instance.setValues(elementName, node, attributes
+ // [NOCPP[
+ , locator
+ // ]NOCPP]
+ );
+ return instance;
+ }
+
+ private StackNode<T> createStackNode(ElementName elementName, T node, @Local String popName
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ StackNode<T> instance = getUnusedStackNode();
+ instance.setValues(elementName, node, popName
+ // [NOCPP[
+ , locator
+ // ]NOCPP]
+ );
+ return instance;
+ }
+
+ private StackNode<T> createStackNode(ElementName elementName, @Local String popName, T node
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ StackNode<T> instance = getUnusedStackNode();
+ instance.setValues(elementName, popName, node
+ // [NOCPP[
+ , locator
+ // ]NOCPP]
+ );
+ return instance;
+ }
+
+ private StackNode<T> createStackNode(ElementName elementName, T node, @Local String popName,
+ boolean markAsIntegrationPoint
+ // [NOCPP[
+ , TaintableLocatorImpl locator
+ // ]NOCPP]
+ ) {
+ StackNode<T> instance = getUnusedStackNode();
+ instance.setValues(elementName, node, popName, markAsIntegrationPoint
+ // [NOCPP[
+ , locator
+ // ]NOCPP]
+ );
+ return instance;
+ }
+
+ private void insertIntoFosterParent(T child) throws SAXException {
+ int tablePos = findLastOrRoot(TreeBuilder.TABLE);
+ int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
+
+ if (templatePos >= tablePos) {
+ appendElement(child, stack[templatePos].node);
+ return;
+ }
+
+ StackNode<T> node = stack[tablePos];
+ insertFosterParentedChild(child, node.node, stack[tablePos - 1].node);
+ }
+
+ private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+ HtmlAttributes attributes
+ // CPPONLY: , @Creator Object creator
+ ) throws SAXException {
+ return createAndInsertFosterParentedElement(ns, name, attributes, null
+ // CPPONLY: , creator
+ );
+ }
+
+ private T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+ HtmlAttributes attributes, T form
+ // CPPONLY: , @Creator Object creator
+ ) throws SAXException {
+ int tablePos = findLastOrRoot(TreeBuilder.TABLE);
+ int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
+
+ if (templatePos >= tablePos) {
+ T child = createElement(ns, name, attributes, form, stack[templatePos].node
+ // CPPONLY: , creator
+ );
+ appendElement(child, stack[templatePos].node);
+ return child;
+ }
+
+ StackNode<T> node = stack[tablePos];
+ return createAndInsertFosterParentedElement(ns, name, attributes, form, node.node, stack[tablePos - 1].node
+ // CPPONLY: , creator
+ );
+ }
+
+ private boolean isInStack(StackNode<T> node) {
+ for (int i = currentPtr; i >= 0; i--) {
+ if (stack[i] == node) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void popTemplateMode() {
+ templateModePtr--;
+ }
+
+ private void pop() throws SAXException {
+ StackNode<T> node = stack[currentPtr];
+ assert debugOnlyClearLastStackSlot();
+ currentPtr--;
+ elementPopped(node.ns, node.popName, node.node);
+ node.release(this);
+ }
+
+ private void popForeign(int origPos, int eltPos) throws SAXException {
+ StackNode<T> node = stack[currentPtr];
+ if (origPos != currentPtr || eltPos != currentPtr) {
+ markMalformedIfScript(node.node);
+ }
+ assert debugOnlyClearLastStackSlot();
+ currentPtr--;
+ elementPopped(node.ns, node.popName, node.node);
+ node.release(this);
+ }
+
+ private void silentPop() throws SAXException {
+ StackNode<T> node = stack[currentPtr];
+ assert debugOnlyClearLastStackSlot();
+ currentPtr--;
+ node.release(this);
+ }
+
+ private void popOnEof() throws SAXException {
+ StackNode<T> node = stack[currentPtr];
+ assert debugOnlyClearLastStackSlot();
+ currentPtr--;
+ markMalformedIfScript(node.node);
+ elementPopped(node.ns, node.popName, node.node);
+ node.release(this);
+ }
+
+ // [NOCPP[
+ private void checkAttributes(HtmlAttributes attributes, @NsUri String ns)
+ throws SAXException {
+ if (errorHandler != null) {
+ int len = attributes.getXmlnsLength();
+ for (int i = 0; i < len; i++) {
+ AttributeName name = attributes.getXmlnsAttributeName(i);
+ if (name == AttributeName.XMLNS) {
+ String xmlns = attributes.getXmlnsValue(i);
+ if (!ns.equals(xmlns)) {
+ err("Bad value \u201C"
+ + xmlns
+ + "\u201D for the attribute \u201Cxmlns\u201D (only \u201C"
+ + ns + "\u201D permitted here).");
+ switch (namePolicy) {
+ case ALTER_INFOSET:
+ // fall through
+ case ALLOW:
+ warn("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0.");
+ break;
+ case FATAL:
+ fatal("Attribute \u201Cxmlns\u201D is not serializable as XML 1.0.");
+ break;
+ }
+ }
+ } else if (ns != "http://www.w3.org/1999/xhtml"
+ && name == AttributeName.XMLNS_XLINK) {
+ String xmlns = attributes.getXmlnsValue(i);
+ if (!"http://www.w3.org/1999/xlink".equals(xmlns)) {
+ err("Bad value \u201C"
+ + xmlns
+ + "\u201D for the attribute \u201Cxmlns:link\u201D (only \u201Chttp://www.w3.org/1999/xlink\u201D permitted here).");
+ switch (namePolicy) {
+ case ALTER_INFOSET:
+ // fall through
+ case ALLOW:
+ warn("Attribute \u201Cxmlns:xlink\u201D with a value other than \u201Chttp://www.w3.org/1999/xlink\u201D is not serializable as XML 1.0 without changing document semantics.");
+ break;
+ case FATAL:
+ fatal("Attribute \u201Cxmlns:xlink\u201D with a value other than \u201Chttp://www.w3.org/1999/xlink\u201D is not serializable as XML 1.0 without changing document semantics.");
+ break;
+ }
+ }
+ } else {
+ err("Attribute \u201C" + attributes.getXmlnsLocalName(i)
+ + "\u201D not allowed here.");
+ switch (namePolicy) {
+ case ALTER_INFOSET:
+ // fall through
+ case ALLOW:
+ warn("Attribute with the local name \u201C"
+ + attributes.getXmlnsLocalName(i)
+ + "\u201D is not serializable as XML 1.0.");
+ break;
+ case FATAL:
+ fatal("Attribute with the local name \u201C"
+ + attributes.getXmlnsLocalName(i)
+ + "\u201D is not serializable as XML 1.0.");
+ break;
+ }
+ }
+ }
+ }
+ attributes.processNonNcNames(this, namePolicy);
+ }
+
+ private String checkPopName(@Local String name) throws SAXException {
+ if (NCName.isNCName(name)) {
+ return name;
+ } else {
+ switch (namePolicy) {
+ case ALLOW:
+ warn("Element name \u201C" + name
+ + "\u201D cannot be represented as XML 1.0.");
+ return name;
+ case ALTER_INFOSET:
+ warn("Element name \u201C" + name
+ + "\u201D cannot be represented as XML 1.0.");
+ return NCName.escapeName(name);
+ case FATAL:
+ fatal("Element name \u201C" + name
+ + "\u201D cannot be represented as XML 1.0.");
+ }
+ }
+ return null; // keep compiler happy
+ }
+
+ // ]NOCPP]
+
+ private void appendHtmlElementToDocumentAndPush(HtmlAttributes attributes)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ T elt = createHtmlElementSetAsRoot(attributes);
+ StackNode<T> node = createStackNode(ElementName.HTML,
+ elt
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendHtmlElementToDocumentAndPush() throws SAXException {
+ appendHtmlElementToDocumentAndPush(tokenizer.emptyAttributes());
+ }
+
+ private void appendToCurrentNodeAndPushHeadElement(HtmlAttributes attributes)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode
+ /*
+ * head uses NS_NewHTMLSharedElement creator
+ */
+ // CPPONLY: , htmlCreator(NS_NewHTMLSharedElement)
+ );
+ appendElement(elt, currentNode);
+ headPointer = elt;
+ StackNode<T> node = createStackNode(ElementName.HEAD,
+ elt
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendToCurrentNodeAndPushBodyElement(HtmlAttributes attributes)
+ throws SAXException {
+ appendToCurrentNodeAndPushElement(ElementName.BODY,
+ attributes);
+ }
+
+ private void appendToCurrentNodeAndPushBodyElement() throws SAXException {
+ appendToCurrentNodeAndPushBodyElement(tokenizer.emptyAttributes());
+ }
+
+ private void appendToCurrentNodeAndPushFormElementMayFoster(
+ HtmlAttributes attributes) throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", "form", attributes
+ // CPPONLY: , htmlCreator(NS_NewHTMLFormElement)
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, currentNode
+ // CPPONLY: , htmlCreator(NS_NewHTMLFormElement)
+ );
+ appendElement(elt, currentNode);
+ }
+
+ if (!isTemplateContents()) {
+ formPointer = elt;
+ }
+
+ StackNode<T> node = createStackNode(ElementName.FORM,
+ elt
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendToCurrentNodeAndPushFormattingElementMayFoster(
+ ElementName elementName, HtmlAttributes attributes)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ // This method can't be called for custom elements
+ HtmlAttributes clone = attributes.cloneAttributes();
+ // Attributes must not be read after calling createElement, because
+ // createElement may delete attributes in C++.
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, currentNode
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ StackNode<T> node = createStackNode(elementName, elt, clone
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ append(node);
+ node.retain(); // append doesn't retain itself
+ }
+
+ private void appendToCurrentNodeAndPushElement(ElementName elementName,
+ HtmlAttributes attributes)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ // This method can't be called for custom elements
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ T elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, currentNode
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ appendElement(elt, currentNode);
+ if (ElementName.TEMPLATE == elementName) {
+ elt = getDocumentFragmentForTemplate(elt);
+ }
+ StackNode<T> node = createStackNode(elementName, elt
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
+ HtmlAttributes attributes)
+ throws SAXException {
+ @Local String popName = elementName.getName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ if (!elementName.isInterned()) {
+ popName = checkPopName(popName);
+ }
+ // ]NOCPP]
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, currentNode
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ StackNode<T> node = createStackNode(elementName, elt, popName
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendToCurrentNodeAndPushElementMayFosterMathML(
+ ElementName elementName, HtmlAttributes attributes)
+ throws SAXException {
+ @Local String popName = elementName.getName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
+ if (!elementName.isInterned()) {
+ popName = checkPopName(popName);
+ }
+ // ]NOCPP]
+ boolean markAsHtmlIntegrationPoint = false;
+ if (ElementName.ANNOTATION_XML == elementName
+ && annotationXmlEncodingPermitsHtml(attributes)) {
+ markAsHtmlIntegrationPoint = true;
+ }
+ // Attributes must not be read after calling createElement(), since
+ // createElement may delete the object in C++.
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes
+ // CPPONLY: , htmlCreator(null)
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, currentNode
+ // CPPONLY: , htmlCreator(null)
+ );
+ appendElement(elt, currentNode);
+ }
+ StackNode<T> node = createStackNode(elementName, elt, popName,
+ markAsHtmlIntegrationPoint
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ // [NOCPP[
+ T getDocumentFragmentForTemplate(T template) {
+ return template;
+ }
+
+ T getFormPointerForContext(T context) {
+ return null;
+ }
+ // ]NOCPP]
+
+ private boolean annotationXmlEncodingPermitsHtml(HtmlAttributes attributes) {
+ String encoding = attributes.getValue(AttributeName.ENCODING);
+ if (encoding == null) {
+ return false;
+ }
+ return Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "application/xhtml+xml", encoding)
+ || Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "text/html", encoding);
+ }
+
+ private void appendToCurrentNodeAndPushElementMayFosterSVG(
+ ElementName elementName, HtmlAttributes attributes)
+ throws SAXException {
+ @Local String popName = elementName.getCamelCaseName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/2000/svg");
+ if (!elementName.isInterned()) {
+ popName = checkPopName(popName);
+ }
+ // ]NOCPP]
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes
+ // CPPONLY: , svgCreator(elementName.getSvgCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/2000/svg", popName, attributes, currentNode
+ // CPPONLY: , svgCreator(elementName.getSvgCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ StackNode<T> node = createStackNode(elementName, popName, elt
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
+ HtmlAttributes attributes, T form)
+ throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ // Can't be called for custom elements
+ T elt;
+ T formOwner = form == null || fragment || isTemplateContents() ? null : form;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(),
+ attributes, formOwner
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(),
+ attributes, formOwner, currentNode
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ StackNode<T> node = createStackNode(elementName, elt
+ // [NOCPP[
+ , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
+ // ]NOCPP]
+ );
+ push(node);
+ }
+
+ private void appendVoidElementToCurrentMayFoster(
+ ElementName elementName, HtmlAttributes attributes, T form) throws SAXException {
+ @Local String name = elementName.getName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ // Can't be called for custom elements
+ T elt;
+ T formOwner = form == null || fragment || isTemplateContents() ? null : form;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", name,
+ attributes, formOwner
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1999/xhtml", name,
+ attributes, formOwner, currentNode
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ elementPushed("http://www.w3.org/1999/xhtml", name, elt);
+ elementPopped("http://www.w3.org/1999/xhtml", name, elt);
+ }
+
+ private void appendVoidElementToCurrentMayFoster(
+ ElementName elementName, HtmlAttributes attributes)
+ throws SAXException {
+ @Local String popName = elementName.getName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ if (!elementName.isInterned()) {
+ popName = checkPopName(popName);
+ }
+ // ]NOCPP]
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, currentNode
+ // CPPONLY: , htmlCreator(elementName.getHtmlCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ elementPushed("http://www.w3.org/1999/xhtml", popName, elt);
+ elementPopped("http://www.w3.org/1999/xhtml", popName, elt);
+ }
+
+ private void appendVoidElementToCurrentMayFosterSVG(
+ ElementName elementName, HtmlAttributes attributes)
+ throws SAXException {
+ @Local String popName = elementName.getCamelCaseName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/2000/svg");
+ if (!elementName.isInterned()) {
+ popName = checkPopName(popName);
+ }
+ // ]NOCPP]
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes
+ // CPPONLY: , svgCreator(elementName.getSvgCreator())
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/2000/svg", popName, attributes, currentNode
+ // CPPONLY: , svgCreator(elementName.getSvgCreator())
+ );
+ appendElement(elt, currentNode);
+ }
+ elementPushed("http://www.w3.org/2000/svg", popName, elt);
+ elementPopped("http://www.w3.org/2000/svg", popName, elt);
+ }
+
+ private void appendVoidElementToCurrentMayFosterMathML(
+ ElementName elementName, HtmlAttributes attributes)
+ throws SAXException {
+ @Local String popName = elementName.getName();
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
+ if (!elementName.isInterned()) {
+ popName = checkPopName(popName);
+ }
+ // ]NOCPP]
+ T elt;
+ StackNode<T> current = stack[currentPtr];
+ if (current.isFosterParenting()) {
+ fatal();
+ elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes
+ // CPPONLY: , htmlCreator(null)
+ );
+ } else {
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, currentNode
+ // CPPONLY: , htmlCreator(null)
+ );
+ appendElement(elt, currentNode);
+ }
+ elementPushed("http://www.w3.org/1998/Math/MathML", popName, elt);
+ elementPopped("http://www.w3.org/1998/Math/MathML", popName, elt);
+ }
+
+ private void appendVoidInputToCurrent(HtmlAttributes attributes, T form) throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ // Can't be called for custom elements
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ T elt = createElement("http://www.w3.org/1999/xhtml", "input", attributes,
+ form == null || fragment || isTemplateContents() ? null : form, currentNode
+ // CPPONLY: , htmlCreator(NS_NewHTMLInputElement)
+ );
+ appendElement(elt, currentNode);
+ elementPushed("http://www.w3.org/1999/xhtml", "input", elt);
+ elementPopped("http://www.w3.org/1999/xhtml", "input", elt);
+ }
+
+ private void appendVoidFormToCurrent(HtmlAttributes attributes) throws SAXException {
+ // [NOCPP[
+ checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
+ // ]NOCPP]
+ T currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ T elt = createElement("http://www.w3.org/1999/xhtml", "form",
+ attributes, currentNode
+ // CPPONLY: , htmlCreator(NS_NewHTMLFormElement)
+ );
+ formPointer = elt;
+ // ownership transferred to form pointer
+ appendElement(elt, currentNode);
+ elementPushed("http://www.w3.org/1999/xhtml", "form", elt);
+ elementPopped("http://www.w3.org/1999/xhtml", "form", elt);
+ }
+
+ // [NOCPP[
+
+ private final void accumulateCharactersForced(@Const @NoLength char[] buf,
+ int start, int length) throws SAXException {
+ System.arraycopy(buf, start, charBuffer, charBufferLen, length);
+ charBufferLen += length;
+ }
+
+ @Override public void ensureBufferSpace(int inputLength)
+ throws SAXException {
+ // TODO: Unify Tokenizer.strBuf and TreeBuilder.charBuffer so that
+ // this method becomes unnecessary.
+ int worstCase = charBufferLen + inputLength;
+ if (charBuffer == null) {
+ // Add an arbitrary small value to avoid immediate reallocation
+ // once there are a few characters in the buffer.
+ charBuffer = new char[worstCase + 128];
+ } else if (worstCase > charBuffer.length) {
+ // HotSpot reportedly allocates memory with 8-byte accuracy, so
+ // there's no point in trying to do math here to avoid slop.
+ // Maybe we should add some small constant to worstCase here
+ // but not doing that without profiling. In C++ with jemalloc,
+ // the corresponding method should do math to round up here
+ // to avoid slop.
+ char[] newBuf = new char[worstCase];
+ System.arraycopy(charBuffer, 0, newBuf, 0, charBufferLen);
+ charBuffer = newBuf;
+ }
+ }
+
+ // ]NOCPP]
+
+ protected void accumulateCharacters(@Const @NoLength char[] buf, int start,
+ int length) throws SAXException {
+ appendCharacters(stack[currentPtr].node, buf, start, length);
+ }
+
+ // ------------------------------- //
+
+ protected final void requestSuspension() {
+ tokenizer.requestSuspension();
+ }
+
+ protected abstract T createElement(@NsUri String ns, @Local String name,
+ HtmlAttributes attributes, T intendedParent
+ // CPPONLY: , @Creator Object creator
+ ) throws SAXException;
+
+ protected T createElement(@NsUri String ns, @Local String name,
+ HtmlAttributes attributes, T form, T intendedParent
+ // CPPONLY: , @Creator Object creator
+ ) throws SAXException {
+ return createElement("http://www.w3.org/1999/xhtml", name, attributes, intendedParent
+ // CPPONLY: , creator
+ );
+ }
+
+ protected abstract T createHtmlElementSetAsRoot(HtmlAttributes attributes)
+ throws SAXException;
+
+ protected abstract void detachFromParent(T element) throws SAXException;
+
+ protected abstract boolean hasChildren(T element) throws SAXException;
+
+ protected abstract void appendElement(T child, T newParent)
+ throws SAXException;
+
+ protected abstract void appendChildrenToNewParent(T oldParent, T newParent)
+ throws SAXException;
+
+ protected abstract void insertFosterParentedChild(T child, T table,
+ T stackParent) throws SAXException;
+
+ // We don't generate CPP code for this method because it is not used in generated CPP
+ // code. Instead, the form owner version of this method is called with a null form owner.
+ // [NOCPP[
+
+ protected abstract T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+ HtmlAttributes attributes, T table, T stackParent) throws SAXException;
+
+ // ]NOCPP]
+
+ protected T createAndInsertFosterParentedElement(@NsUri String ns, @Local String name,
+ HtmlAttributes attributes, T form, T table, T stackParent
+ // CPPONLY: , @Creator Object creator
+ ) throws SAXException {
+ return createAndInsertFosterParentedElement(ns, name, attributes, table, stackParent);
+ };
+
+ protected abstract void insertFosterParentedCharacters(
+ @NoLength char[] buf, int start, int length, T table, T stackParent)
+ throws SAXException;
+
+ protected abstract void appendCharacters(T parent, @NoLength char[] buf,
+ int start, int length) throws SAXException;
+
+ protected abstract void appendComment(T parent, @NoLength char[] buf,
+ int start, int length) throws SAXException;
+
+ protected abstract void appendCommentToDocument(@NoLength char[] buf,
+ int start, int length) throws SAXException;
+
+ protected abstract void addAttributesToElement(T element,
+ HtmlAttributes attributes) throws SAXException;
+
+ protected void markMalformedIfScript(T elt) throws SAXException {
+
+ }
+
+ protected void start(boolean fragmentMode) throws SAXException {
+
+ }
+
+ protected void end() throws SAXException {
+
+ }
+
+ protected void appendDoctypeToDocument(@Local String name,
+ String publicIdentifier, String systemIdentifier)
+ throws SAXException {
+
+ }
+
+ protected void elementPushed(@NsUri String ns, @Local String name, T node)
+ throws SAXException {
+
+ }
+
+ protected void elementPopped(@NsUri String ns, @Local String name, T node)
+ throws SAXException {
+
+ }
+
+ // [NOCPP[
+
+ protected void documentMode(DocumentMode m, String publicIdentifier,
+ String systemIdentifier)
+ throws SAXException {
+
+ }
+
+ /**
+ * @see nu.validator.htmlparser.common.TokenHandler#wantsComments()
+ */
+ public boolean wantsComments() {
+ return wantingComments;
+ }
+
+ public void setIgnoringComments(boolean ignoreComments) {
+ wantingComments = !ignoreComments;
+ }
+
+ /**
+ * Sets the errorHandler.
+ *
+ * @param errorHandler
+ * the errorHandler to set
+ */
+ public final void setErrorHandler(ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ /**
+ * Returns the errorHandler.
+ *
+ * @return the errorHandler
+ */
+ public ErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
+
+ /**
+ * The argument MUST be an interned string or <code>null</code>.
+ *
+ * @param context
+ */
+ public final void setFragmentContext(@Local String context) {
+ this.contextName = context;
+ this.contextNamespace = "http://www.w3.org/1999/xhtml";
+ this.contextNode = null;
+ this.fragment = (contextName != null);
+ this.quirks = false;
+ }
+
+ // ]NOCPP]
+
+ /**
+ * @see nu.validator.htmlparser.common.TokenHandler#cdataSectionAllowed()
+ */
+ @Inline public boolean cdataSectionAllowed() throws SAXException {
+ return isInForeign();
+ }
+
+ private boolean isInForeign() {
+ return currentPtr >= 0
+ && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml";
+ }
+
+ private boolean isInForeignButNotHtmlOrMathTextIntegrationPoint() {
+ if (currentPtr < 0) {
+ return false;
+ }
+ return !isSpecialParentInForeign(stack[currentPtr]);
+ }
+
+ /**
+ * The argument MUST be an interned string or <code>null</code>.
+ *
+ * @param context
+ */
+ public final void setFragmentContext(@Local String context,
+ @NsUri String ns, T node, boolean quirks) {
+ // [NOCPP[
+ if (!((context == null && ns == null)
+ || "http://www.w3.org/1999/xhtml" == ns
+ || "http://www.w3.org/2000/svg" == ns || "http://www.w3.org/1998/Math/MathML" == ns)) {
+ throw new IllegalArgumentException(
+ "The namespace must be the HTML, SVG or MathML namespace (or null when the local name is null). Got: "
+ + ns);
+ }
+ // ]NOCPP]
+ this.contextName = context;
+ this.contextNamespace = ns;
+ this.contextNode = node;
+ this.fragment = (contextName != null);
+ this.quirks = quirks;
+ }
+
+ protected final T currentNode() {
+ return stack[currentPtr].node;
+ }
+
+ /**
+ * Returns the scriptingEnabled.
+ *
+ * @return the scriptingEnabled
+ */
+ public boolean isScriptingEnabled() {
+ return scriptingEnabled;
+ }
+
+ /**
+ * Sets the scriptingEnabled.
+ *
+ * @param scriptingEnabled
+ * the scriptingEnabled to set
+ */
+ public void setScriptingEnabled(boolean scriptingEnabled) {
+ this.scriptingEnabled = scriptingEnabled;
+ }
+
+ public void setForceNoQuirks(boolean forceNoQuirks) {
+ this.forceNoQuirks = forceNoQuirks;
+ }
+
+ // Redundant method retained because previously public.
+ public void setIsSrcdocDocument(boolean isSrcdocDocument) {
+ this.setForceNoQuirks(isSrcdocDocument);
+ }
+
+ // [NOCPP[
+
+ public void setNamePolicy(XmlViolationPolicy namePolicy) {
+ this.namePolicy = namePolicy;
+ }
+
+ /**
+ * Sets the documentModeHandler.
+ *
+ * @param documentModeHandler
+ * the documentModeHandler to set
+ */
+ public void setDocumentModeHandler(DocumentModeHandler documentModeHandler) {
+ this.documentModeHandler = documentModeHandler;
+ }
+
+ /**
+ * Sets the reportingDoctype.
+ *
+ * @param reportingDoctype
+ * the reportingDoctype to set
+ */
+ public void setReportingDoctype(boolean reportingDoctype) {
+ this.reportingDoctype = reportingDoctype;
+ }
+
+ // ]NOCPP]
+
+ /**
+ * Flushes the pending characters. Public for document.write use cases only.
+ * @throws SAXException
+ */
+ public final void flushCharacters() throws SAXException {
+ if (charBufferLen > 0) {
+ if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW)
+ && charBufferContainsNonWhitespace()) {
+ errNonSpaceInTable();
+ reconstructTheActiveFormattingElements();
+ if (!stack[currentPtr].isFosterParenting()) {
+ // reconstructing gave us a new current node
+ appendCharacters(currentNode(), charBuffer, 0,
+ charBufferLen);
+ charBufferLen = 0;
+ return;
+ }
+
+ int tablePos = findLastOrRoot(TreeBuilder.TABLE);
+ int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
+
+ if (templatePos >= tablePos) {
+ appendCharacters(stack[templatePos].node, charBuffer, 0, charBufferLen);
+ charBufferLen = 0;
+ return;
+ }
+
+ StackNode<T> tableElt = stack[tablePos];
+ insertFosterParentedCharacters(charBuffer, 0, charBufferLen,
+ tableElt.node, stack[tablePos - 1].node);
+ charBufferLen = 0;
+ return;
+ }
+ appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
+ charBufferLen = 0;
+ }
+ }
+
+ private boolean charBufferContainsNonWhitespace() {
+ for (int i = 0; i < charBufferLen; i++) {
+ switch (charBuffer[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\u000C':
+ continue;
+ default:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a comparable snapshot of the tree builder state. Snapshot
+ * creation is only supported immediately after a script end tag has been
+ * processed. In C++ the caller is responsible for calling
+ * <code>delete</code> on the returned object.
+ *
+ * @return a snapshot.
+ * @throws SAXException
+ */
+ @SuppressWarnings("unchecked") public TreeBuilderState<T> newSnapshot()
+ throws SAXException {
+ StackNode<T>[] listCopy = new StackNode[listPtr + 1];
+ for (int i = 0; i < listCopy.length; i++) {
+ StackNode<T> node = listOfActiveFormattingElements[i];
+ if (node != null) {
+ StackNode<T> newNode = new StackNode<T>(-1);
+ newNode.setValues(node.getFlags(), node.ns,
+ node.name, node.node, node.popName,
+ node.attributes.cloneAttributes()
+ // CPPONLY: , node.getHtmlCreator()
+ // [NOCPP[
+ , node.getLocator()
+ // ]NOCPP]
+ );
+ listCopy[i] = newNode;
+ } else {
+ listCopy[i] = null;
+ }
+ }
+ StackNode<T>[] stackCopy = new StackNode[currentPtr + 1];
+ for (int i = 0; i < stackCopy.length; i++) {
+ StackNode<T> node = stack[i];
+ int listIndex = findInListOfActiveFormattingElements(node);
+ if (listIndex == -1) {
+ StackNode<T> newNode = new StackNode<T>(-1);
+ newNode.setValues(node.getFlags(), node.ns,
+ node.name, node.node, node.popName,
+ null
+ // CPPONLY: , node.getHtmlCreator()
+ // [NOCPP[
+ , node.getLocator()
+ // ]NOCPP]
+ );
+ stackCopy[i] = newNode;
+ } else {
+ stackCopy[i] = listCopy[listIndex];
+ stackCopy[i].retain();
+ }
+ }
+ int[] templateModeStackCopy = new int[templateModePtr + 1];
+ System.arraycopy(templateModeStack, 0, templateModeStackCopy, 0,
+ templateModeStackCopy.length);
+ return new StateSnapshot<T>(stackCopy, listCopy, templateModeStackCopy, formPointer,
+ headPointer, mode, originalMode, framesetOk,
+ needToDropLF, quirks);
+ }
+
+ public boolean snapshotMatches(TreeBuilderState<T> snapshot) {
+ StackNode<T>[] stackCopy = snapshot.getStack();
+ int stackLen = snapshot.getStackLength();
+ StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
+ int listLen = snapshot.getListOfActiveFormattingElementsLength();
+ int[] templateModeStackCopy = snapshot.getTemplateModeStack();
+ int templateModeStackLen = snapshot.getTemplateModeStackLength();
+
+ if (stackLen != currentPtr + 1
+ || listLen != listPtr + 1
+ || templateModeStackLen != templateModePtr + 1
+ || formPointer != snapshot.getFormPointer()
+ || headPointer != snapshot.getHeadPointer()
+ || mode != snapshot.getMode()
+ || originalMode != snapshot.getOriginalMode()
+ || framesetOk != snapshot.isFramesetOk()
+ || needToDropLF != snapshot.isNeedToDropLF()
+ || quirks != snapshot.isQuirks()) { // maybe just assert quirks
+ return false;
+ }
+ for (int i = listLen - 1; i >= 0; i--) {
+ if (listCopy[i] == null
+ && listOfActiveFormattingElements[i] == null) {
+ continue;
+ } else if (listCopy[i] == null
+ || listOfActiveFormattingElements[i] == null) {
+ return false;
+ }
+ if (listCopy[i].node != listOfActiveFormattingElements[i].node) {
+ return false; // it's possible that this condition is overly
+ // strict
+ }
+ }
+ for (int i = stackLen - 1; i >= 0; i--) {
+ if (stackCopy[i].node != stack[i].node) {
+ return false;
+ }
+ }
+ for (int i = templateModeStackLen - 1; i >=0; i--) {
+ if (templateModeStackCopy[i] != templateModeStack[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked") public void loadState(
+ TreeBuilderState<T> snapshot)
+ throws SAXException {
+ // CPPONLY: mCurrentHtmlScriptIsAsyncOrDefer = false;
+ StackNode<T>[] stackCopy = snapshot.getStack();
+ int stackLen = snapshot.getStackLength();
+ StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
+ int listLen = snapshot.getListOfActiveFormattingElementsLength();
+ int[] templateModeStackCopy = snapshot.getTemplateModeStack();
+ int templateModeStackLen = snapshot.getTemplateModeStackLength();
+
+ for (int i = 0; i <= listPtr; i++) {
+ if (listOfActiveFormattingElements[i] != null) {
+ listOfActiveFormattingElements[i].release(this);
+ }
+ }
+ if (listOfActiveFormattingElements.length < listLen) {
+ listOfActiveFormattingElements = new StackNode[listLen];
+ }
+ listPtr = listLen - 1;
+
+ for (int i = 0; i <= currentPtr; i++) {
+ stack[i].release(this);
+ }
+ if (stack.length < stackLen) {
+ stack = new StackNode[stackLen];
+ }
+ currentPtr = stackLen - 1;
+
+ if (templateModeStack.length < templateModeStackLen) {
+ templateModeStack = new int[templateModeStackLen];
+ }
+ templateModePtr = templateModeStackLen - 1;
+
+ for (int i = 0; i < listLen; i++) {
+ StackNode<T> node = listCopy[i];
+ if (node != null) {
+ StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+ node.name, node.node,
+ node.popName,
+ node.attributes.cloneAttributes()
+ // CPPONLY: , node.getHtmlCreator()
+ // [NOCPP[
+ , node.getLocator()
+ // ]NOCPP]
+ );
+ listOfActiveFormattingElements[i] = newNode;
+ } else {
+ listOfActiveFormattingElements[i] = null;
+ }
+ }
+ for (int i = 0; i < stackLen; i++) {
+ StackNode<T> node = stackCopy[i];
+ int listIndex = findInArray(node, listCopy);
+ if (listIndex == -1) {
+ StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+ node.name, node.node,
+ node.popName,
+ null
+ // CPPONLY: , node.getHtmlCreator()
+ // [NOCPP[
+ , node.getLocator()
+ // ]NOCPP]
+ );
+ stack[i] = newNode;
+ } else {
+ stack[i] = listOfActiveFormattingElements[listIndex];
+ stack[i].retain();
+ }
+ }
+ System.arraycopy(templateModeStackCopy, 0, templateModeStack, 0, templateModeStackLen);
+ formPointer = snapshot.getFormPointer();
+ headPointer = snapshot.getHeadPointer();
+ mode = snapshot.getMode();
+ originalMode = snapshot.getOriginalMode();
+ framesetOk = snapshot.isFramesetOk();
+ needToDropLF = snapshot.isNeedToDropLF();
+ quirks = snapshot.isQuirks();
+ }
+
+ private int findInArray(StackNode<T> node, StackNode<T>[] arr) {
+ for (int i = listPtr; i >= 0; i--) {
+ if (node == arr[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns <code>stack[stackPos].node</code> if <code>stackPos</code> is
+ * smaller than Blink's magic limit or the node at Blink's magic limit
+ * otherwise.
+ *
+ * In order to get Blink-compatible handling of excessive deeply-nested
+ * markup, this method must be used to obtain the node that is used as the
+ * parent node of an insertion.
+ *
+ * Blink's magic number is 512, but our counting is off by one compared to
+ * Blink's way of counting, so in order to get the same
+ * externally-observable outcome, we use 511 as our magic number.
+ *
+ * @param stackPos the stack position to attempt to read
+ * @return node at the position capped to Blink's magic number
+ * @throws SAXException
+ */
+ private T nodeFromStackWithBlinkCompat(int stackPos) throws SAXException {
+ // Magic number if off by one relative to Blink's magic number, but the
+ // outcome is the same, because the counting is different by one.
+ if (stackPos > 511) {
+ errDeepTree();
+ return stack[511].node;
+ }
+ return stack[stackPos].node;
+ }
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getFormPointer()
+ */
+ @Override
+ public T getFormPointer() {
+ return formPointer;
+ }
+
+ /**
+ * Returns the headPointer.
+ *
+ * @return the headPointer
+ */
+ @Override
+ public T getHeadPointer() {
+ return headPointer;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElements()
+ */
+ @Override
+ public StackNode<T>[] getListOfActiveFormattingElements() {
+ return listOfActiveFormattingElements;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getStack()
+ */
+ @Override
+ public StackNode<T>[] getStack() {
+ return stack;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStack()
+ */
+ @Override
+ public int[] getTemplateModeStack() {
+ return templateModeStack;
+ }
+
+ /**
+ * Returns the mode.
+ *
+ * @return the mode
+ */
+ @Override
+ public int getMode() {
+ return mode;
+ }
+
+ /**
+ * Returns the originalMode.
+ *
+ * @return the originalMode
+ */
+ @Override
+ public int getOriginalMode() {
+ return originalMode;
+ }
+
+ /**
+ * Returns the framesetOk.
+ *
+ * @return the framesetOk
+ */
+ @Override
+ public boolean isFramesetOk() {
+ return framesetOk;
+ }
+
+ /**
+ * Returns the needToDropLF.
+ *
+ * @return the needToDropLF
+ */
+ @Override
+ public boolean isNeedToDropLF() {
+ return needToDropLF;
+ }
+
+ /**
+ * Returns the quirks.
+ *
+ * @return the quirks
+ */
+ @Override
+ public boolean isQuirks() {
+ return quirks;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getListOfActiveFormattingElementsLength()
+ */
+ @Override
+ public int getListOfActiveFormattingElementsLength() {
+ return listPtr + 1;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getStackLength()
+ */
+ @Override
+ public int getStackLength() {
+ return currentPtr + 1;
+ }
+
+ /**
+ * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength()
+ */
+ @Override
+ public int getTemplateModeStackLength() {
+ return templateModePtr + 1;
+ }
+
+ /**
+ * Complains about an over-deep tree. Theoretically this should just be
+ * a warning, but in practice authors should take this as an error.
+ *
+ * @throws SAXException
+ */
+ private void errDeepTree() throws SAXException {
+ err("The document tree is more than 513 elements deep, which causes Firefox and Chrome to flatten the tree.");
+ }
+
+ /**
+ * Reports a stray start tag.
+ * @param name the name of the stray tag
+ *
+ * @throws SAXException
+ */
+ private void errStrayStartTag(@Local String name) throws SAXException {
+ err("Stray start tag \u201C" + name + "\u201D.");
+ }
+
+ /**
+ * Reports a stray end tag.
+ * @param name the name of the stray tag
+ *
+ * @throws SAXException
+ */
+ private void errStrayEndTag(@Local String name) throws SAXException {
+ err("Stray end tag \u201C" + name + "\u201D.");
+ }
+
+ /**
+ * Reports a state when elements expected to be closed were not.
+ *
+ * @param eltPos the position of the start tag on the stack of the element
+ * being closed.
+ * @param name the name of the end tag
+ *
+ * @throws SAXException
+ */
+ private void errUnclosedElements(int eltPos, @Local String name) throws SAXException {
+ errNoCheck("End tag \u201C" + name + "\u201D seen, but there were open elements.");
+ errListUnclosedStartTags(eltPos);
+ }
+
+ /**
+ * Reports a state when elements expected to be closed ahead of an implied
+ * end tag but were not.
+ *
+ * @param eltPos the position of the start tag on the stack of the element
+ * being closed.
+ * @param name the name of the end tag
+ *
+ * @throws SAXException
+ */
+ private void errUnclosedElementsImplied(int eltPos, String name) throws SAXException {
+ errNoCheck("End tag \u201C" + name + "\u201D implied, but there were open elements.");
+ errListUnclosedStartTags(eltPos);
+ }
+
+ /**
+ * Reports a state when elements expected to be closed ahead of an implied
+ * table cell close.
+ *
+ * @param eltPos the position of the start tag on the stack of the element
+ * being closed.
+ * @throws SAXException
+ */
+ private void errUnclosedElementsCell(int eltPos) throws SAXException {
+ errNoCheck("A table cell was implicitly closed, but there were open elements.");
+ errListUnclosedStartTags(eltPos);
+ }
+
+ private void errStrayDoctype() throws SAXException {
+ err("Stray doctype.");
+ }
+
+ private void errAlmostStandardsDoctype() throws SAXException {
+ if (!forceNoQuirks) {
+ err("Almost standards mode doctype. Expected \u201C<!DOCTYPE html>\u201D.");
+ }
+ }
+
+ private void errQuirkyDoctype() throws SAXException {
+ if (!forceNoQuirks) {
+ err("Quirky doctype. Expected \u201C<!DOCTYPE html>\u201D.");
+ }
+ }
+
+ private void errNonSpaceInTrailer() throws SAXException {
+ err("Non-space character in page trailer.");
+ }
+
+ private void errNonSpaceAfterFrameset() throws SAXException {
+ err("Non-space after \u201Cframeset\u201D.");
+ }
+
+ private void errNonSpaceInFrameset() throws SAXException {
+ err("Non-space in \u201Cframeset\u201D.");
+ }
+
+ private void errNonSpaceAfterBody() throws SAXException {
+ err("Non-space character after body.");
+ }
+
+ private void errNonSpaceInColgroupInFragment() throws SAXException {
+ err("Non-space in \u201Ccolgroup\u201D when parsing fragment.");
+ }
+
+ private void errNonSpaceInNoscriptInHead() throws SAXException {
+ err("Non-space character inside \u201Cnoscript\u201D inside \u201Chead\u201D.");
+ }
+
+ private void errFooBetweenHeadAndBody(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("\u201C" + name + "\u201D element between \u201Chead\u201D and \u201Cbody\u201D.");
+ }
+
+ private void errStartTagWithoutDoctype() throws SAXException {
+ if (!forceNoQuirks) {
+ err("Start tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
+ }
+ }
+
+ private void errNoSelectInTableScope() throws SAXException {
+ err("No \u201Cselect\u201D in table scope.");
+ }
+
+ private void errStartSelectWhereEndSelectExpected() throws SAXException {
+ err("\u201Cselect\u201D start tag where end tag expected.");
+ }
+
+ private void errStartTagWithSelectOpen(@Local String name)
+ throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("\u201C" + name
+ + "\u201D start tag with \u201Cselect\u201D open.");
+ }
+
+ private void errBadStartTagInNoscriptInHead(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("Bad start tag in \u201C" + name
+ + "\u201D in \u201Cnoscript\u201D in \u201Chead\u201D.");
+ }
+
+ private void errImage() throws SAXException {
+ err("Saw a start tag \u201Cimage\u201D.");
+ }
+
+ private void errFooSeenWhenFooOpen(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("Start tag \u201C" + name + "\u201D seen but an element of the same type was already open.");
+ }
+
+ private void errHeadingWhenHeadingOpen() throws SAXException {
+ err("Heading cannot be a child of another heading.");
+ }
+
+ private void errFramesetStart() throws SAXException {
+ err("\u201Cframeset\u201D start tag seen.");
+ }
+
+ private void errNoCellToClose() throws SAXException {
+ err("No cell to close.");
+ }
+
+ private void errStartTagInTable(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("Start tag \u201C" + name
+ + "\u201D seen in \u201Ctable\u201D.");
+ }
+
+ private void errFormWhenFormOpen() throws SAXException {
+ err("Saw a \u201Cform\u201D start tag, but there was already an active \u201Cform\u201D element. Nested forms are not allowed. Ignoring the tag.");
+ }
+
+ private void errTableSeenWhileTableOpen() throws SAXException {
+ err("Start tag for \u201Ctable\u201D seen but the previous \u201Ctable\u201D is still open.");
+ }
+
+ private void errStartTagInTableBody(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("\u201C" + name + "\u201D start tag in table body.");
+ }
+
+ private void errEndTagSeenWithoutDoctype() throws SAXException {
+ if (!forceNoQuirks) {
+ err("End tag seen without seeing a doctype first. Expected \u201C<!DOCTYPE html>\u201D.");
+ }
+ }
+
+ private void errEndTagAfterBody() throws SAXException {
+ err("Saw an end tag after \u201Cbody\u201D had been closed.");
+ }
+
+ private void errEndTagSeenWithSelectOpen(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("\u201C" + name
+ + "\u201D end tag with \u201Cselect\u201D open.");
+ }
+
+ private void errGarbageInColgroup() throws SAXException {
+ err("Garbage in \u201Ccolgroup\u201D fragment.");
+ }
+
+ private void errEndTagBr() throws SAXException {
+ err("End tag \u201Cbr\u201D.");
+ }
+
+ private void errNoElementToCloseButEndTagSeen(@Local String name)
+ throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("No \u201C" + name + "\u201D element in scope but a \u201C"
+ + name + "\u201D end tag seen.");
+ }
+
+ private void errHtmlStartTagInForeignContext(@Local String name)
+ throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("HTML start tag \u201C" + name
+ + "\u201D in a foreign namespace context.");
+ }
+
+ private void errNoTableRowToClose() throws SAXException {
+ err("No table row to close.");
+ }
+
+ private void errNonSpaceInTable() throws SAXException {
+ err("Misplaced non-space characters inside a table.");
+ }
+
+ private void errUnclosedChildrenInRuby() throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("Unclosed children in \u201Cruby\u201D.");
+ }
+
+ private void errStartTagSeenWithoutRuby(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("Start tag \u201C"
+ + name
+ + "\u201D seen without a \u201Cruby\u201D element being open.");
+ }
+
+ private void errSelfClosing() throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("Self-closing syntax (\u201C/>\u201D) used on a non-void HTML element. Ignoring the slash and treating as a start tag.");
+ }
+
+ private void errNoCheckUnclosedElementsOnStack() throws SAXException {
+ errNoCheck("Unclosed elements on stack.");
+ }
+
+ private void errEndTagDidNotMatchCurrentOpenElement(@Local String name,
+ @Local String currOpenName) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("End tag \u201C"
+ + name
+ + "\u201D did not match the name of the current open element (\u201C"
+ + currOpenName + "\u201D).");
+ }
+
+ private void errEndTagViolatesNestingRules(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("End tag \u201C" + name + "\u201D violates nesting rules.");
+ }
+
+ private void errEofWithUnclosedElements() throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("End of file seen and there were open elements.");
+ // just report all remaining unclosed elements
+ errListUnclosedStartTags(0);
+ }
+
+ /**
+ * Reports arriving at/near end of document with unclosed elements remaining.
+ *
+ * @param message
+ * the message
+ * @throws SAXException
+ */
+ private void errEndWithUnclosedElements(@Local String name) throws SAXException {
+ if (errorHandler == null) {
+ return;
+ }
+ errNoCheck("End tag for \u201C"
+ + name
+ + "\u201D seen, but there were unclosed elements.");
+ // just report all remaining unclosed elements
+ errListUnclosedStartTags(0);
+ }
+}
diff --git a/parser/html/javasrc/UTF16Buffer.java b/parser/html/javasrc/UTF16Buffer.java
new file mode 100644
index 0000000000..ec79185ec2
--- /dev/null
+++ b/parser/html/javasrc/UTF16Buffer.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2008-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package nu.validator.htmlparser.impl;
+
+import nu.validator.htmlparser.annotation.NoLength;
+
+/**
+ * An UTF-16 buffer that knows the start and end indeces of its unconsumed
+ * content.
+ *
+ * @version $Id$
+ * @author hsivonen
+ */
+public final class UTF16Buffer {
+
+ /**
+ * The backing store of the buffer. May be larger than the logical content
+ * of this <code>UTF16Buffer</code>.
+ */
+ private final @NoLength char[] buffer;
+
+ /**
+ * The index of the first unconsumed character in the backing buffer.
+ */
+ private int start;
+
+ /**
+ * The index of the slot immediately after the last character in the backing
+ * buffer that is part of the logical content of this
+ * <code>UTF16Buffer</code>.
+ */
+ private int end;
+
+ //[NOCPP[
+
+ /**
+ * Constructor for wrapping an existing UTF-16 code unit array.
+ *
+ * @param buffer
+ * the backing buffer
+ * @param start
+ * the index of the first character to consume
+ * @param end
+ * the index immediately after the last character to consume
+ */
+ public UTF16Buffer(@NoLength char[] buffer, int start, int end) {
+ this.buffer = buffer;
+ this.start = start;
+ this.end = end;
+ }
+
+ // ]NOCPP]
+
+ /**
+ * Returns the start index.
+ *
+ * @return the start index
+ */
+ public int getStart() {
+ return start;
+ }
+
+ /**
+ * Sets the start index.
+ *
+ * @param start
+ * the start index
+ */
+ public void setStart(int start) {
+ this.start = start;
+ }
+
+ /**
+ * Returns the backing buffer.
+ *
+ * @return the backing buffer
+ */
+ public @NoLength char[] getBuffer() {
+ return buffer;
+ }
+
+ /**
+ * Returns the end index.
+ *
+ * @return the end index
+ */
+ public int getEnd() {
+ return end;
+ }
+
+ /**
+ * Checks if the buffer has data left.
+ *
+ * @return <code>true</code> if there's data left
+ */
+ public boolean hasMore() {
+ return start < end;
+ }
+
+ /**
+ * Returns <code>end - start</code>.
+ *
+ * @return <code>end - start</code>
+ */
+ public int getLength() {
+ return end - start;
+ }
+
+ /**
+ * Adjusts the start index to skip over the first character if it is a line
+ * feed and the previous character was a carriage return.
+ *
+ * @param lastWasCR
+ * whether the previous character was a carriage return
+ */
+ public void adjust(boolean lastWasCR) {
+ if (lastWasCR && buffer[start] == '\n') {
+ start++;
+ }
+ }
+
+ /**
+ * Sets the end index.
+ *
+ * @param end
+ * the end index
+ */
+ public void setEnd(int end) {
+ this.end = end;
+ }
+}
diff --git a/parser/html/moz.build b/parser/html/moz.build
new file mode 100644
index 0000000000..12fe8c8ada
--- /dev/null
+++ b/parser/html/moz.build
@@ -0,0 +1,92 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+XPIDL_SOURCES += ["nsIParserUtils.idl"]
+
+XPIDL_MODULE = "html5"
+
+EXPORTS += [
+ "jArray.h",
+ "nsAHtml5TreeBuilderState.h",
+ "nsAHtml5TreeOpSink.h",
+ "nsHtml5ArrayCopy.h",
+ "nsHtml5AtomTable.h",
+ "nsHtml5AttributeEntry.h",
+ "nsHtml5AttributeName.h",
+ "nsHtml5ByteReadable.h",
+ "nsHtml5ContentCreatorFunction.h",
+ "nsHtml5DependentUTF16Buffer.h",
+ "nsHtml5DocumentBuilder.h",
+ "nsHtml5DocumentMode.h",
+ "nsHtml5HtmlAttributes.h",
+ "nsHtml5Macros.h",
+ "nsHtml5Module.h",
+ "nsHtml5NamedCharacters.h",
+ "nsHtml5NamedCharactersAccel.h",
+ "nsHtml5OplessBuilder.h",
+ "nsHtml5OwningUTF16Buffer.h",
+ "nsHtml5Parser.h",
+ "nsHtml5PlainTextUtils.h",
+ "nsHtml5Portability.h",
+ "nsHtml5Speculation.h",
+ "nsHtml5SpeculativeLoad.h",
+ "nsHtml5StreamListener.h",
+ "nsHtml5StreamParser.h",
+ "nsHtml5StreamParserPtr.h",
+ "nsHtml5StreamParserReleaser.h",
+ "nsHtml5String.h",
+ "nsHtml5StringParser.h",
+ "nsHtml5SVGLoadDispatcher.h",
+ "nsHtml5TreeOperation.h",
+ "nsHtml5TreeOpExecutor.h",
+ "nsHtml5TreeOpStage.h",
+ "nsHtml5UTF16Buffer.h",
+ "nsHtml5UTF16BufferHSupplement.h",
+ "nsHtml5ViewSourceUtils.h",
+ "nsIContentHandle.h",
+ "nsParserUtils.h",
+]
+
+UNIFIED_SOURCES += [
+ "nsHtml5AtomTable.cpp",
+ "nsHtml5AttributeName.cpp",
+ "nsHtml5DependentUTF16Buffer.cpp",
+ "nsHtml5DocumentBuilder.cpp",
+ "nsHtml5ElementName.cpp",
+ "nsHtml5Highlighter.cpp",
+ "nsHtml5HtmlAttributes.cpp",
+ "nsHtml5Module.cpp",
+ "nsHtml5NamedCharacters.cpp",
+ "nsHtml5NamedCharactersAccel.cpp",
+ "nsHtml5OplessBuilder.cpp",
+ "nsHtml5OwningUTF16Buffer.cpp",
+ "nsHtml5Parser.cpp",
+ "nsHtml5PlainTextUtils.cpp",
+ "nsHtml5Portability.cpp",
+ "nsHtml5Speculation.cpp",
+ "nsHtml5SpeculativeLoad.cpp",
+ "nsHtml5StackNode.cpp",
+ "nsHtml5StateSnapshot.cpp",
+ "nsHtml5StreamListener.cpp",
+ "nsHtml5StreamParser.cpp",
+ "nsHtml5String.cpp",
+ "nsHtml5StringParser.cpp",
+ "nsHtml5SVGLoadDispatcher.cpp",
+ "nsHtml5Tokenizer.cpp",
+ "nsHtml5TreeBuilder.cpp",
+ "nsHtml5TreeOperation.cpp",
+ "nsHtml5TreeOpExecutor.cpp",
+ "nsHtml5TreeOpStage.cpp",
+ "nsHtml5UTF16Buffer.cpp",
+ "nsHtml5ViewSourceUtils.cpp",
+ "nsParserUtils.cpp",
+]
+
+FINAL_LIBRARY = "xul"
+
+LOCAL_INCLUDES += [
+ "/dom/base",
+]
diff --git a/parser/html/nsAHtml5TreeBuilderState.h b/parser/html/nsAHtml5TreeBuilderState.h
new file mode 100644
index 0000000000..0de332b93c
--- /dev/null
+++ b/parser/html/nsAHtml5TreeBuilderState.h
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsAHtml5TreeBuilderState_h
+#define nsAHtml5TreeBuilderState_h
+
+#include <cstdint>
+#include "nsIContentHandle.h"
+
+template <class T, class L>
+class jArray;
+class nsHtml5StackNode;
+
+/**
+ * Interface for exposing the internal state of the HTML5 tree builder.
+ * For more documentation, please see
+ * https://hg.mozilla.org/projects/htmlparser/file/tip/src/nu/validator/htmlparser/impl/StateSnapshot.java
+ */
+class nsAHtml5TreeBuilderState {
+ public:
+ virtual jArray<nsHtml5StackNode*, int32_t> getStack() = 0;
+
+ virtual jArray<nsHtml5StackNode*, int32_t>
+ getListOfActiveFormattingElements() = 0;
+
+ virtual jArray<int32_t, int32_t> getTemplateModeStack() = 0;
+
+ virtual int32_t getStackLength() = 0;
+
+ virtual int32_t getListOfActiveFormattingElementsLength() = 0;
+
+ virtual int32_t getTemplateModeStackLength() = 0;
+
+ virtual nsIContentHandle* getFormPointer() = 0;
+
+ virtual nsIContentHandle* getHeadPointer() = 0;
+
+ virtual int32_t getMode() = 0;
+
+ virtual int32_t getOriginalMode() = 0;
+
+ virtual bool isFramesetOk() = 0;
+
+ virtual bool isNeedToDropLF() = 0;
+
+ virtual bool isQuirks() = 0;
+
+ virtual ~nsAHtml5TreeBuilderState() {}
+};
+
+#endif /* nsAHtml5TreeBuilderState_h */
diff --git a/parser/html/nsAHtml5TreeOpSink.h b/parser/html/nsAHtml5TreeOpSink.h
new file mode 100644
index 0000000000..a09971a2e8
--- /dev/null
+++ b/parser/html/nsAHtml5TreeOpSink.h
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsAHtml5TreeOpSink_h
+#define nsAHtml5TreeOpSink_h
+
+#include "nsTArrayForwardDeclare.h"
+
+class nsHtml5TreeOperation;
+
+/**
+ * The purpose of this interface is to connect a tree op executor
+ * (main-thread case), a tree op stage (non-speculative off-the-main-thread
+ * case) or a speculation (speculative case).
+ */
+class nsAHtml5TreeOpSink {
+ public:
+ /**
+ * Flush the operations from the tree operations from the argument
+ * queue into this sink unconditionally.
+ *
+ * Returns `true` on success and `false` on OOM.
+ */
+ [[nodiscard]] virtual bool MoveOpsFrom(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) = 0;
+};
+
+#endif /* nsAHtml5TreeOpSink_h */
diff --git a/parser/html/nsHtml5ArrayCopy.h b/parser/html/nsHtml5ArrayCopy.h
new file mode 100644
index 0000000000..78c2d9c1b3
--- /dev/null
+++ b/parser/html/nsHtml5ArrayCopy.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef nsHtml5ArrayCopy_h
+#define nsHtml5ArrayCopy_h
+
+class nsHtml5StackNode;
+
+// Unfortunately, these don't work as template functions because the arguments
+// would need coercion from a template class, which complicates things.
+class nsHtml5ArrayCopy {
+ public:
+ static inline void arraycopy(char16_t* source, int32_t sourceOffset,
+ char16_t* target, int32_t targetOffset,
+ int32_t length) {
+ memcpy(&(target[targetOffset]), &(source[sourceOffset]),
+ size_t(length) * sizeof(char16_t));
+ }
+
+ static inline void arraycopy(char16_t* source, char16_t* target,
+ int32_t length) {
+ memcpy(target, source, size_t(length) * sizeof(char16_t));
+ }
+
+ static inline void arraycopy(int32_t* source, int32_t* target,
+ int32_t length) {
+ memcpy(target, source, size_t(length) * sizeof(int32_t));
+ }
+
+ static inline void arraycopy(nsHtml5StackNode** source,
+ nsHtml5StackNode** target, int32_t length) {
+ memcpy(target, source, size_t(length) * sizeof(nsHtml5StackNode*));
+ }
+
+ static inline void arraycopy(nsHtml5StackNode** arr, int32_t sourceOffset,
+ int32_t targetOffset, int32_t length) {
+ memmove(&(arr[targetOffset]), &(arr[sourceOffset]),
+ size_t(length) * sizeof(nsHtml5StackNode*));
+ }
+};
+#endif // nsHtml5ArrayCopy_h
diff --git a/parser/html/nsHtml5AtomTable.cpp b/parser/html/nsHtml5AtomTable.cpp
new file mode 100644
index 0000000000..06bad88bf4
--- /dev/null
+++ b/parser/html/nsHtml5AtomTable.cpp
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5AtomTable.h"
+#include "nsThreadUtils.h"
+
+nsHtml5AtomTable::nsHtml5AtomTable() : mRecentlyUsedParserAtoms{} {
+#ifdef DEBUG
+ mPermittedLookupEventTarget = mozilla::GetCurrentSerialEventTarget();
+#endif
+}
+
+nsHtml5AtomTable::~nsHtml5AtomTable() {}
+
+nsAtom* nsHtml5AtomTable::GetAtom(const nsAString& aKey) {
+#ifdef DEBUG
+ MOZ_ASSERT(mPermittedLookupEventTarget->IsOnCurrentThread());
+#endif
+
+ uint32_t index = mozilla::HashString(aKey) % RECENTLY_USED_PARSER_ATOMS_SIZE;
+ if (nsAtom* atom = mRecentlyUsedParserAtoms[index]) {
+ if (atom->Equals(aKey)) {
+ return atom;
+ }
+ }
+
+ RefPtr<nsAtom> atom = NS_Atomize(aKey);
+ nsAtom* ret = atom.get();
+ mRecentlyUsedParserAtoms[index] = std::move(atom);
+ return ret;
+}
diff --git a/parser/html/nsHtml5AtomTable.h b/parser/html/nsHtml5AtomTable.h
new file mode 100644
index 0000000000..4130f05745
--- /dev/null
+++ b/parser/html/nsHtml5AtomTable.h
@@ -0,0 +1,91 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5AtomTable_h
+#define nsHtml5AtomTable_h
+
+#include "nsHashKeys.h"
+#include "nsTHashtable.h"
+#include "nsAtom.h"
+#include "nsISerialEventTarget.h"
+
+#define RECENTLY_USED_PARSER_ATOMS_SIZE 31
+
+/**
+ * nsHtml5AtomTable provides non-locking lookup and creation of atoms for
+ * nsHtml5Parser or nsHtml5StreamParser.
+ *
+ * The hashtable holds dynamically allocated atoms that are private to an
+ * instance of nsHtml5Parser or nsHtml5StreamParser. (Static atoms are used on
+ * interned nsHtml5ElementNames and interned nsHtml5AttributeNames. Also, when
+ * the doctype name is 'html', that identifier needs to be represented as a
+ * static atom.)
+ *
+ * Each instance of nsHtml5Parser has a single instance of nsHtml5AtomTable,
+ * and each instance of nsHtml5StreamParser has a single instance of
+ * nsHtml5AtomTable. Dynamic atoms obtained from an nsHtml5AtomTable are valid
+ * for == comparison with each other or with atoms declared in nsHtml5Atoms
+ * within the nsHtml5Tokenizer and the nsHtml5TreeBuilder instances owned by
+ * the same nsHtml5Parser/nsHtml5StreamParser instance that owns the
+ * nsHtml5AtomTable instance.
+ *
+ * Dynamic atoms (atoms whose IsStatic() returns false) obtained from
+ * nsHtml5AtomTable must be re-obtained from another atom table when there's a
+ * need to migrate atoms from an nsHtml5Parser to its nsHtml5StreamParser
+ * (re-obtain from the other nsHtml5AtomTable), from an nsHtml5Parser to its
+ * owner nsHtml5Parser (re-obtain from the other nsHtml5AtomTable) or from the
+ * parser to the DOM (re-obtain from the application-wide atom table). To
+ * re-obtain an atom from another atom table, obtain a string from the atom
+ * using ToString(nsAString&) and look up an atom in the other table using that
+ * string.
+ *
+ * An instance of nsHtml5AtomTable that belongs to an nsHtml5Parser is only
+ * accessed from the main thread. An instance of nsHtml5AtomTable that belongs
+ * to an nsHtml5StreamParser is accessed both from the main thread and from the
+ * thread that executes the runnables of the nsHtml5StreamParser instance.
+ * However, the threads never access the nsHtml5AtomTable instance concurrently
+ * in the nsHtml5StreamParser case.
+ *
+ * Methods on the atoms obtained from nsHtml5AtomTable may be called on any
+ * thread, although they only need to be called on the main thread or on the
+ * thread working for the nsHtml5StreamParser when nsHtml5AtomTable belongs to
+ * an nsHtml5StreamParser.
+ *
+ * Dynamic atoms obtained from nsHtml5AtomTable are deleted when the
+ * nsHtml5AtomTable itself is destructed, which happens when the owner
+ * nsHtml5Parser or nsHtml5StreamParser is destructed.
+ */
+class nsHtml5AtomTable {
+ public:
+ nsHtml5AtomTable();
+ ~nsHtml5AtomTable();
+
+ // NOTE: We rely on mRecentlyUsedParserAtoms keeping alive the returned atom,
+ // but the caller is responsible to take a reference before calling GetAtom
+ // again.
+ nsAtom* GetAtom(const nsAString& aKey);
+
+ /**
+ * Empties the table.
+ */
+ void Clear() {
+ for (uint32_t i = 0; i < RECENTLY_USED_PARSER_ATOMS_SIZE; ++i) {
+ mRecentlyUsedParserAtoms[i] = nullptr;
+ }
+ }
+
+#ifdef DEBUG
+ void SetPermittedLookupEventTarget(nsISerialEventTarget* aEventTarget) {
+ mPermittedLookupEventTarget = aEventTarget;
+ }
+#endif
+
+ private:
+ RefPtr<nsAtom> mRecentlyUsedParserAtoms[RECENTLY_USED_PARSER_ATOMS_SIZE];
+#ifdef DEBUG
+ nsCOMPtr<nsISerialEventTarget> mPermittedLookupEventTarget;
+#endif
+};
+
+#endif // nsHtml5AtomTable_h
diff --git a/parser/html/nsHtml5AttributeEntry.h b/parser/html/nsHtml5AttributeEntry.h
new file mode 100644
index 0000000000..6fbca7f1cb
--- /dev/null
+++ b/parser/html/nsHtml5AttributeEntry.h
@@ -0,0 +1,70 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5AttributeEntry_h
+#define nsHtml5AttributeEntry_h
+
+#include "nsHtml5AttributeName.h"
+
+class nsHtml5AttributeEntry final {
+ public:
+ nsHtml5AttributeEntry(nsHtml5AttributeName* aName, nsHtml5String aValue,
+ int32_t aLine)
+ : mLine(aLine), mValue(aValue) {
+ // Let's hope the compiler coalesces the following as appropriate.
+ mLocals[0] = aName->getLocal(0);
+ mLocals[1] = aName->getLocal(1);
+ mLocals[2] = aName->getLocal(2);
+ mPrefixes[0] = aName->getPrefix(0);
+ mPrefixes[1] = aName->getPrefix(1);
+ mPrefixes[2] = aName->getPrefix(2);
+ mUris[0] = aName->getUri(0);
+ mUris[1] = aName->getUri(1);
+ mUris[2] = aName->getUri(2);
+ }
+
+ // Isindex-only so doesn't need to deal with SVG and MathML
+ nsHtml5AttributeEntry(nsAtom* aName, nsHtml5String aValue, int32_t aLine)
+ : mLine(aLine), mValue(aValue) {
+ // Let's hope the compiler coalesces the following as appropriate.
+ mLocals[0] = aName;
+ mLocals[1] = aName;
+ mLocals[2] = aName;
+ mPrefixes[0] = nullptr;
+ mPrefixes[1] = nullptr;
+ mPrefixes[2] = nullptr;
+ mUris[0] = kNameSpaceID_None;
+ mUris[1] = kNameSpaceID_None;
+ mUris[2] = kNameSpaceID_None;
+ }
+
+ inline nsAtom* GetLocal(int32_t aMode) { return mLocals[aMode]; }
+
+ inline nsAtom* GetPrefix(int32_t aMode) { return mPrefixes[aMode]; }
+
+ inline int32_t GetUri(int32_t aMode) { return mUris[aMode]; }
+
+ inline nsHtml5String GetValue() { return mValue; }
+
+ inline int32_t GetLine() { return mLine; }
+
+ inline void ReleaseValue() { mValue.Release(); }
+
+ inline nsHtml5AttributeEntry Clone() {
+ // Copy the memory
+ nsHtml5AttributeEntry clone(*this);
+ // Increment refcount for value
+ clone.mValue = this->mValue.Clone();
+ return clone;
+ }
+
+ private:
+ RefPtr<nsAtom> mLocals[3];
+ RefPtr<nsAtom> mPrefixes[3];
+ int32_t mUris[3];
+ int32_t mLine;
+ nsHtml5String mValue;
+};
+
+#endif // nsHtml5AttributeEntry_h
diff --git a/parser/html/nsHtml5AttributeName.cpp b/parser/html/nsHtml5AttributeName.cpp
new file mode 100644
index 0000000000..00ef41cef0
--- /dev/null
+++ b/parser/html/nsHtml5AttributeName.cpp
@@ -0,0 +1,2875 @@
+/*
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit AttributeName.java instead and regenerate.
+ */
+
+#define nsHtml5AttributeName_cpp__
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+#include "nsHtml5ElementName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5AttributeName.h"
+
+int32_t* nsHtml5AttributeName::ALL_NO_NS = 0;
+int32_t* nsHtml5AttributeName::XMLNS_NS = 0;
+int32_t* nsHtml5AttributeName::XML_NS = 0;
+int32_t* nsHtml5AttributeName::XLINK_NS = 0;
+nsStaticAtom** nsHtml5AttributeName::ALL_NO_PREFIX = 0;
+nsStaticAtom** nsHtml5AttributeName::XMLNS_PREFIX = 0;
+nsStaticAtom** nsHtml5AttributeName::XLINK_PREFIX = 0;
+nsStaticAtom** nsHtml5AttributeName::XML_PREFIX = 0;
+RefPtr<nsAtom>* nsHtml5AttributeName::SVG_DIFFERENT(nsAtom* name,
+ nsAtom* camel) {
+ RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4];
+ arr[0] = name;
+ arr[1] = name;
+ arr[2] = camel;
+ return arr;
+}
+
+RefPtr<nsAtom>* nsHtml5AttributeName::MATH_DIFFERENT(nsAtom* name,
+ nsAtom* camel) {
+ RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4];
+ arr[0] = name;
+ arr[1] = camel;
+ arr[2] = name;
+ return arr;
+}
+
+RefPtr<nsAtom>* nsHtml5AttributeName::COLONIFIED_LOCAL(nsAtom* name,
+ nsAtom* suffix) {
+ RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4];
+ arr[0] = name;
+ arr[1] = suffix;
+ arr[2] = suffix;
+ return arr;
+}
+
+RefPtr<nsAtom>* nsHtml5AttributeName::SAME_LOCAL(nsAtom* name) {
+ RefPtr<nsAtom>* arr = new RefPtr<nsAtom>[4];
+ arr[0] = name;
+ arr[1] = name;
+ arr[2] = name;
+ return arr;
+}
+
+nsHtml5AttributeName::nsHtml5AttributeName(int32_t* uri, RefPtr<nsAtom>* local,
+ nsStaticAtom** prefix)
+ : uri(uri), local(local), prefix(prefix), custom(false) {
+ MOZ_COUNT_CTOR(nsHtml5AttributeName);
+}
+
+nsHtml5AttributeName::nsHtml5AttributeName()
+ : uri(nsHtml5AttributeName::ALL_NO_NS),
+ local(nsHtml5AttributeName::SAME_LOCAL(nullptr)),
+ prefix(ALL_NO_PREFIX),
+ custom(true) {
+ MOZ_COUNT_CTOR(nsHtml5AttributeName);
+}
+
+nsHtml5AttributeName* nsHtml5AttributeName::createAttributeName(nsAtom* name) {
+ return new nsHtml5AttributeName(nsHtml5AttributeName::ALL_NO_NS,
+ nsHtml5AttributeName::SAME_LOCAL(name),
+ ALL_NO_PREFIX);
+}
+
+nsHtml5AttributeName::~nsHtml5AttributeName() {
+ MOZ_COUNT_DTOR(nsHtml5AttributeName);
+ delete[] local;
+}
+
+int32_t nsHtml5AttributeName::getUri(int32_t mode) { return uri[mode]; }
+
+nsAtom* nsHtml5AttributeName::getLocal(int32_t mode) { return local[mode]; }
+
+nsStaticAtom* nsHtml5AttributeName::getPrefix(int32_t mode) {
+ return prefix[mode];
+}
+
+bool nsHtml5AttributeName::equalsAnother(nsHtml5AttributeName* another) {
+ return this->getLocal(nsHtml5AttributeName::HTML) ==
+ another->getLocal(nsHtml5AttributeName::HTML);
+}
+
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DUR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_END = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IN2 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOW = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MAX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REV = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SRC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_D = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_R = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_X = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Y = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Z = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K1 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_X1 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Y1 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K2 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_X2 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_Y2 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K3 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_K4 = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XML_SPACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XML_LANG = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_GRAB = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_VALUEMAX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_LABELLEDBY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DESCRIBEDBY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DISABLED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_CHECKED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SELECTED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DROPEFFECT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_REQUIRED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_EXPANDED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_PRESSED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_LEVEL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_CHANNEL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_HIDDEN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SECRET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_POSINSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_ATOMIC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_INVALID = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_TEMPLATEID = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_VALUEMIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_MULTISELECTABLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_CONTROLS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_MULTILINE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_READONLY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_OWNS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_ACTIVEDESCENDANT =
+ nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_RELEVANT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_DATATYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_VALUENOW = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SORT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_AUTOCOMPLETE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_FLOWTO = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_BUSY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_LIVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_HASPOPUP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARIA_SETSIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLEAR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DISABLED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEFAULT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DATA = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EQUALCOLUMNS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EQUALROWS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HSPACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ISMAP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOCAL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LSPACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MOVABLELIMITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOTATION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDATAAVAILABLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONPASTE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RSPACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWALIGN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROTATE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SEPARATOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SEPARATORS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VSPACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XCHANNELSELECTOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_YCHANNELSELECTOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENABLE_BACKGROUND = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDBLCLICK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONABORT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CALCMODE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHECKED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FENCE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSCROLL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONACTIVATE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPACITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPECULAREXPONENT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPECULARCONSTANT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BORDER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ID = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GRADIENTTRANSFORM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GRADIENTUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HIDDEN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HEADERS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOADING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_READONLY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RENDERING_INTENT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SEED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SRCDOC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STDDEVIATION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SANDBOX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WORD_SPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCENTUNDER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCEPT_CHARSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCESSKEY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCENT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCEPT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BEVELLED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASEFREQUENCY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASELINE_SHIFT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASEPROFILE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASELINE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BASE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CODE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CODETYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CODEBASE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CITE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEFER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DATETIME = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIRECTION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EDGEMODE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EDGE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENTERKEYHINT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INDEX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INTERCEPT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INTEGRITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LINEBREAK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LABEL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LINETHICKNESS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MODE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NAME = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NORESIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFOREUNLOAD = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONREPEAT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OBJECT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSELECT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORDER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OTHER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONRESET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONREADYSTATECHANGE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMESSAGE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEGIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFOREPRINT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORIENT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORIENTATION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFORECOPY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSELECTSTART = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFOREPASTE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONKEYPRESS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONKEYUP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBEFORECUT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONKEYDOWN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONRESIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPEAT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REFERRERPOLICY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RULES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPEATCOUNT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPEATDUR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SELECTED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SIZES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SUPERSCRIPTSHIFT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STRETCHY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCHEME = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPREADMETHOD = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SELECTION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIFFUSECONSTANT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HREF = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HREFLANG = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONAFTERPRINT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PROFILE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SURFACESCALE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XREF = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALIGN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALIGNMENT_BASELINE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALIGNMENTSCOPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DRAGGABLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HEIGHT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IMAGESIZES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IMAGESRCSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IMAGE_RENDERING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LANGUAGE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LANG = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LARGEOP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LONGDESC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LENGTHADJUST = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARGINHEIGHT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARGINWIDTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ORIGIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TARGET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TARGETX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TARGETY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ARCHIVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HIGH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LIGHTING_COLOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHBACKGROUND = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_METHOD = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHVARIANT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHCOLOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MATHSIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOSHADE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCHANGE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATHLENGTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALTIMG = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACTIONTYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACTION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACTIVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ADDITIVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BEGIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DOMINANT_BASELINE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DIVISOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEFINITIONURL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LIMITINGCONEANGLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MEDIA = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MANIFEST = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFINISH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPTIMUM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RADIOGROUP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RADIUS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCRIPTLEVEL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCRIPTSIZEMULTIPLIER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCRIPTMINSIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TABINDEX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALIGN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VISIBILITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BACKGROUND = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LINK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKER_MID = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKERHEIGHT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKER_END = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MASK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKER_START = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKERWIDTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MASKUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MARKERUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MASKCONTENTUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AMPLITUDE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CELLSPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CELLPADDING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DECLARE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILL_RULE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILL_OPACITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MAXLENGTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCLICK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONBLUR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REPLACE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWLINES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCALE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STYLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TABLEVALUES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TITLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AZIMUTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FORMAT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FRAMEBORDER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FRAME = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FRAMESPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FROM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FORM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PROMPT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PRIMITIVEUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SYMMETRIC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SUMMARY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_USEMAP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ZOOMANDPAN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ASYNC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALINK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ICON = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KERNELMATRIX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KERNING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KERNELUNITLENGTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONUNLOAD = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPEN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONINVALID = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONEND = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONINPUT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTER_EVENTS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTSATX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTSATY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POINTSATZ = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SPAN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STANDBY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TRANSFORM_ORIGIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TRANSFORM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VLINK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WHEN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_HREF = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_TITLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_ROLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_ARCROLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XMLNS_XLINK = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XMLNS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_TYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_SHOW = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_XLINK_ACTUATE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOPLAY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOCOMPLETE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOFOCUS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AUTOCAPITALIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BGCOLOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_PROFILE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_RENDERING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_INTERPOLATION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLOR_INTERPOLATION_FILTERS =
+ nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENCODING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_EXPONENT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FLOOD_COLOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FLOOD_OPACITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LQUOTE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NUMOCTAVES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOMODULE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONLOAD = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEWHEEL = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEENTER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEOVER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFOCUSIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCONTEXTMENU = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONZOOM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCOPY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSELEAVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEMOVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEUP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFOCUS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEOUT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONFOCUSOUT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONMOUSEDOWN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TO = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RQUOTE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_LINECAP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_DASHARRAY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_DASHOFFSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_LINEJOIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_MITERLIMIT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCROLLING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_WIDTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STROKE_OPACITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COMPACT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIP_RULE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIP_PATH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLIPPATHUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DISPLAY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DISPLAYSTYLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GLYPH_ORIENTATION_VERTICAL =
+ nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GLYPH_ORIENTATION_HORIZONTAL =
+ nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GLYPHREF = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_HTTP_EQUIV = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYPOINTS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOOP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PROPERTY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCOPED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STEP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SHAPE_RENDERING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SCOPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SHAPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SLOPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STOP_COLOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STOP_OPACITY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEMPLATE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WRAP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ABBR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ATTRIBUTENAME = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ATTRIBUTETYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHAR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COORDS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHAROFF = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CHARSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOWRAP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_NOHREF = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAG = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGENTER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGOVER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGEND = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDROP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGDROP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONERROR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OPERATOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OVERFLOW = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGSTART = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONDRAGLEAVE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STARTOFFSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_START = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_AXIS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BIAS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLSPAN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLASSID = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CROSSORIGIN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CURSOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLOSURE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLOSE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CLASS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_IS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYSYSTEM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYSPLINES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LOWSRC = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MAXSIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MINSIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_OFFSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PRESERVEALPHA = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PRESERVEASPECTRATIO = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWSPAN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWSPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ROWS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SRCSET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SUBSCRIPTSHIFT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VERSION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ALTTEXT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTENTEDITABLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTROLS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTENT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CONTEXTMENU = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DEPTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ENCTYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_STRETCH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILTER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTWEIGHT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_WEIGHT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTSTYLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_STYLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTFAMILY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_FAMILY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_VARIANT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_SIZE_ADJUST = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FILTERUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONTSIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FONT_SIZE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_KEYTIMES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LETTER_SPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_LIST = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_MULTIPLE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSTOP = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSTART = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_POSTER = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERNTRANSFORM = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERNUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_PATTERNCONTENTUNITS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RESTART = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_STITCHTILES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_SYSTEMLANGUAGE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT_RENDERING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT_DECORATION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT_ANCHOR = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXTLENGTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_TEXT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WRITING_MODE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_WIDTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ACCUMULATE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNSPAN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNLINES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNALIGN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNSPACING = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_COLUMNWIDTH = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_GROUPALIGN = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_INPUTMODE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONSUBMIT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ONCUT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REQUIRED = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REQUIREDFEATURES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RESULT = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REQUIREDEXTENSIONS = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALUES = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALUETYPE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VALUE = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_ELEVATION = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VIEWTARGET = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_VIEWBOX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REFX = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_BY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_CY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_DY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_FY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_RY = nullptr;
+nsHtml5AttributeName* nsHtml5AttributeName::ATTR_REFY = nullptr;
+nsHtml5AttributeName** nsHtml5AttributeName::ATTRIBUTE_NAMES = 0;
+static int32_t const ATTRIBUTE_HASHES_DATA[] = {
+ 1867462756, 1748971848, 1966442279, 1681174213, 1785053243, 1916286197,
+ 2004846654, 1680165421, 1723336432, 1754899031, 1816104145, 1905628916,
+ 1924629705, 1988784439, 2024647008, 71827457, 1680282148, 1689324870,
+ 1747295467, 1754579720, 1756889417, 1803561214, 1848600826, 1884295780,
+ 1910441627, 1922607670, 1939976792, 1975062341, 2000752725, 2009079867,
+ 2073034754, 57205395, 911736834, 1680181996, 1680368221, 1685882101,
+ 1704526375, 1736416327, 1747906667, 1751755561, 1754698327, 1756360955,
+ 1773606972, 1787365531, 1805715690, 1823574314, 1854497001, 1874270021,
+ 1898415413, 1906423097, 1915025672, 1921977416, 1923088386, 1933369607,
+ 1941550652, 1972904518, 1983398182, 1991625270, 2001710298, 2007021895,
+ 2016810187, 2060474743, 2082471938, 53006051, 60345635, 885522434,
+ 1680095865, 1680165533, 1680229115, 1680343801, 1680437801, 1682440540,
+ 1687620127, 1692408896, 1721189160, 1733874289, 1740096054, 1747479606,
+ 1748503880, 1749549708, 1753550036, 1754644293, 1754835516, 1756147974,
+ 1756762256, 1767725700, 1781007934, 1786775671, 1791068279, 1804081401,
+ 1814560070, 1820727381, 1824159037, 1854366938, 1865910331, 1872343590,
+ 1884079398, 1890996553, 1903612236, 1906408542, 1908462185, 1910503637,
+ 1915757815, 1917857531, 1922413307, 1922677495, 1924517489, 1932959284,
+ 1934970504, 1941435445, 1965512429, 1972656710, 1972922984, 1983157559,
+ 1984430082, 1990107683, 2000096287, 2001634458, 2001826027, 2006459190,
+ 2008401563, 2010716309, 2019887833, 2026893641, 2065694722, 2081423362,
+ 2089811970, 52488851, 55077603, 59825747, 68157441, 878182402,
+ 901775362, 1037879561, 1680159327, 1680165437, 1680165692, 1680198203,
+ 1680231247, 1680315086, 1680345965, 1680413393, 1680452349, 1681879063,
+ 1683805446, 1686731997, 1689048326, 1689839946, 1699185409, 1714763319,
+ 1721347639, 1731048742, 1734182982, 1739583824, 1740130375, 1747309881,
+ 1747800157, 1748021284, 1748566068, 1749350104, 1751507685, 1753049109,
+ 1754434872, 1754612424, 1754647074, 1754794646, 1754860061, 1754927689,
+ 1756219733, 1756704824, 1756836998, 1757421892, 1771569964, 1780879045,
+ 1784574102, 1786622296, 1786851500, 1788842244, 1797886599, 1804054854,
+ 1804405895, 1814517574, 1814656840, 1816178925, 1821958888, 1823829083,
+ 1825437894, 1854285018, 1854466380, 1854497008, 1866496199, 1871251689,
+ 1873656984, 1874788501, 1884246821, 1889569526, 1891937366, 1900544002,
+ 1903759600, 1905754853, 1906419001, 1907701479, 1909819252, 1910441773,
+ 1910527802, 1915341049, 1916247343, 1917295176, 1921061206, 1922400908,
+ 1922566877, 1922665179, 1922679610, 1924443742, 1924583073, 1924773438,
+ 1933123337, 1934917290, 1937336473, 1941286708, 1941440197, 1943317364,
+ 1966384692, 1972151670, 1972744954, 1972908839, 1972996699, 1982254612,
+ 1983290011, 1983432389, 1987422362, 1989522022, 1991220282, 1993343287,
+ 2000160071, 2001527900, 2001669449, 2001732764, 2001898809, 2005342360,
+ 2006824246, 2007064819, 2009041198, 2009231684, 2016711994, 2017010843,
+ 2023342821, 2024794274, 2034765641, 2065170434, 2066743298, 2075005220,
+ 2081947650, 2083520514, 2091784484, 50917059, 52489043, 53537523,
+ 56685811, 57210387, 59830867, 60817409, 71303169, 72351745,
+ 884998146, 894959618, 902299650, 928514050, 1038063816, 1680140893,
+ 1680159328, 1680165436, 1680165487, 1680165613, 1680181850, 1680185931,
+ 1680198381, 1680230940, 1680251485, 1680311085, 1680323325, 1680345685,
+ 1680347981, 1680411449, 1680433915, 1680446153, 1680511804, 1681733672,
+ 1681969220, 1682587945, 1684319541, 1685902598, 1687164232, 1687751191,
+ 1689130184, 1689788441, 1691145478, 1692933184, 1704262346, 1714745560,
+ 1716303957, 1721305962, 1723309623, 1723336528, 1732771842, 1733919469,
+ 1734404167, 1739561208, 1739927860, 1740119884, 1742183484, 1747299630,
+ 1747446838, 1747792072, 1747839118, 1747939528, 1748306996, 1748552744,
+ 1748869205, 1749027145, 1749399124, 1749856356, 1751679545, 1752985897,
+ 1753297133, 1754214628, 1754546894, 1754606246, 1754643237, 1754645079,
+ 1754647353, 1754792749, 1754798923, 1754858317, 1754872618, 1754907227,
+ 1754958648, 1756190926, 1756302628, 1756471625, 1756737685, 1756804936,
+ 1756874572, 1757053236, 1765800271, 1767875272, 1772032615, 1776114564,
+ 1780975314, 1782518297, 1785051290, 1785174319, 1786740932, 1786821704,
+ 1787193500, 1788254870, 1790814502, 1791070327, 1801312388, 1804036350,
+ 1804069019, 1804235064, 1804978712, 1805715716, 1814558026, 1814656326,
+ 1814986837, 1816144023, 1820262641, 1820928104, 1822002839, 1823580230,
+ 1823841492, 1824377064, 1825677514, 1853862084, 1854302364, 1854464212,
+ 1854474395, 1854497003, 1864698185, 1865910347, 1867448617, 1867620412,
+ 1872034503, 1873590471, 1874261045, 1874698443, 1881750231, 1884142379,
+ 1884267068, 1884343396, 1889633006, 1891186903, 1894552650, 1898428101,
+ 1902640276, 1903659239, 1905541832, 1905672729, 1905902311, 1906408598,
+ 1906421049, 1907660596, 1908316832, 1909438149, 1910328970, 1910441770,
+ 1910487243, 1910507338, 1910572893, 1915295948, 1915394254, 1916210285,
+ 1916278099, 1916337499, 1917327080, 1917953597, 1921894426, 1922319046,
+ 1922413292, 1922470745, 1922567078, 1922665052, 1922671417, 1922679386,
+ 1922699851, 1924206934, 1924462384, 1924570799, 1924585254, 1924738716,
+ 1932870919, 1932986153, 1933145837, 1933508940, 1934917372, 1935597338,
+ 1937777860, 1941253366, 1941409583, 1941438085, 1941454586, 1942026440,
+ 1965349396, 1965561677, 1966439670, 1966454567, 1972196486, 1972744939,
+ 1972863609, 1972904522, 1972909592, 1972962123, 1974849131, 1980235778,
+ 1982640164, 1983266615, 1983347764, 1983416119, 1983461061, 1987410233,
+ 1988132214, 1988788535, 1990062797, 1991021879, 1991392548, 1991643278,
+ 1999273799, 2000125224, 2000162011, 2001210183, 2001578182, 2001634459,
+ 2001669450, 2001710299, 2001814704, 2001898808, 2004199576, 2004957380,
+ 2005925890, 2006516551, 2007019632, 2007064812, 2008084807, 2008408414,
+ 2009071951, 2009141482, 2010452700, 2015950026, 2016787611, 2016910397,
+ 2018908874, 2023146024, 2024616088, 2024763702, 2026741958, 2026975253,
+ 2060302634};
+staticJArray<int32_t, int32_t> nsHtml5AttributeName::ATTRIBUTE_HASHES = {
+ ATTRIBUTE_HASHES_DATA, MOZ_ARRAY_LENGTH(ATTRIBUTE_HASHES_DATA)};
+void nsHtml5AttributeName::initializeStatics() {
+ ALL_NO_NS = new int32_t[3];
+ ALL_NO_NS[0] = kNameSpaceID_None;
+ ALL_NO_NS[1] = kNameSpaceID_None;
+ ALL_NO_NS[2] = kNameSpaceID_None;
+ XMLNS_NS = new int32_t[3];
+ XMLNS_NS[0] = kNameSpaceID_None;
+ XMLNS_NS[1] = kNameSpaceID_XMLNS;
+ XMLNS_NS[2] = kNameSpaceID_XMLNS;
+ XML_NS = new int32_t[3];
+ XML_NS[0] = kNameSpaceID_None;
+ XML_NS[1] = kNameSpaceID_XML;
+ XML_NS[2] = kNameSpaceID_XML;
+ XLINK_NS = new int32_t[3];
+ XLINK_NS[0] = kNameSpaceID_None;
+ XLINK_NS[1] = kNameSpaceID_XLink;
+ XLINK_NS[2] = kNameSpaceID_XLink;
+ ALL_NO_PREFIX = new nsStaticAtom*[3];
+ ALL_NO_PREFIX[0] = nullptr;
+ ALL_NO_PREFIX[1] = nullptr;
+ ALL_NO_PREFIX[2] = nullptr;
+ XMLNS_PREFIX = new nsStaticAtom*[3];
+ XMLNS_PREFIX[0] = nullptr;
+ XMLNS_PREFIX[1] = nsGkAtoms::xmlns;
+ XMLNS_PREFIX[2] = nsGkAtoms::xmlns;
+ XLINK_PREFIX = new nsStaticAtom*[3];
+ XLINK_PREFIX[0] = nullptr;
+ XLINK_PREFIX[1] = nsGkAtoms::xlink;
+ XLINK_PREFIX[2] = nsGkAtoms::xlink;
+ XML_PREFIX = new nsStaticAtom*[3];
+ XML_PREFIX[0] = nullptr;
+ XML_PREFIX[1] = nsGkAtoms::xml;
+ XML_PREFIX[2] = nsGkAtoms::xml;
+ ATTR_ALT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alt),
+ ALL_NO_PREFIX);
+ ATTR_DIR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dir),
+ ALL_NO_PREFIX);
+ ATTR_DUR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dur),
+ ALL_NO_PREFIX);
+ ATTR_END = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::end),
+ ALL_NO_PREFIX);
+ ATTR_FOR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_for),
+ ALL_NO_PREFIX);
+ ATTR_IN2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::in2),
+ ALL_NO_PREFIX);
+ ATTR_LOW = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::low),
+ ALL_NO_PREFIX);
+ ATTR_MIN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::min),
+ ALL_NO_PREFIX);
+ ATTR_MAX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::max),
+ ALL_NO_PREFIX);
+ ATTR_REL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rel),
+ ALL_NO_PREFIX);
+ ATTR_REV = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rev),
+ ALL_NO_PREFIX);
+ ATTR_SRC = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::src),
+ ALL_NO_PREFIX);
+ ATTR_D = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::d),
+ ALL_NO_PREFIX);
+ ATTR_R = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::r),
+ ALL_NO_PREFIX);
+ ATTR_X = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::x),
+ ALL_NO_PREFIX);
+ ATTR_Y = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::y),
+ ALL_NO_PREFIX);
+ ATTR_Z = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::z),
+ ALL_NO_PREFIX);
+ ATTR_K1 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k1),
+ ALL_NO_PREFIX);
+ ATTR_X1 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::x1),
+ ALL_NO_PREFIX);
+ ATTR_Y1 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::y1),
+ ALL_NO_PREFIX);
+ ATTR_K2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k2),
+ ALL_NO_PREFIX);
+ ATTR_X2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::x2),
+ ALL_NO_PREFIX);
+ ATTR_Y2 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::y2),
+ ALL_NO_PREFIX);
+ ATTR_K3 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k3),
+ ALL_NO_PREFIX);
+ ATTR_K4 = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::k4),
+ ALL_NO_PREFIX);
+ ATTR_XML_SPACE = new nsHtml5AttributeName(
+ XML_NS, COLONIFIED_LOCAL(nsGkAtoms::xml_space, nsGkAtoms::space),
+ XML_PREFIX);
+ ATTR_XML_LANG = new nsHtml5AttributeName(
+ XML_NS, COLONIFIED_LOCAL(nsGkAtoms::xml_lang, nsGkAtoms::lang),
+ XML_PREFIX);
+ ATTR_ARIA_GRAB = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_grab), ALL_NO_PREFIX);
+ ATTR_ARIA_VALUEMAX = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_valuemax), ALL_NO_PREFIX);
+ ATTR_ARIA_LABELLEDBY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_labelledby), ALL_NO_PREFIX);
+ ATTR_ARIA_DESCRIBEDBY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_describedby), ALL_NO_PREFIX);
+ ATTR_ARIA_DISABLED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_disabled), ALL_NO_PREFIX);
+ ATTR_ARIA_CHECKED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_checked), ALL_NO_PREFIX);
+ ATTR_ARIA_SELECTED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_selected), ALL_NO_PREFIX);
+ ATTR_ARIA_DROPEFFECT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_dropeffect), ALL_NO_PREFIX);
+ ATTR_ARIA_REQUIRED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_required), ALL_NO_PREFIX);
+ ATTR_ARIA_EXPANDED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_expanded), ALL_NO_PREFIX);
+ ATTR_ARIA_PRESSED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_pressed), ALL_NO_PREFIX);
+ ATTR_ARIA_LEVEL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_level), ALL_NO_PREFIX);
+ ATTR_ARIA_CHANNEL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_channel), ALL_NO_PREFIX);
+ ATTR_ARIA_HIDDEN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_hidden), ALL_NO_PREFIX);
+ ATTR_ARIA_SECRET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_secret), ALL_NO_PREFIX);
+ ATTR_ARIA_POSINSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_posinset), ALL_NO_PREFIX);
+ ATTR_ARIA_ATOMIC = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_atomic), ALL_NO_PREFIX);
+ ATTR_ARIA_INVALID = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_invalid), ALL_NO_PREFIX);
+ ATTR_ARIA_TEMPLATEID = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_templateid), ALL_NO_PREFIX);
+ ATTR_ARIA_VALUEMIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_valuemin), ALL_NO_PREFIX);
+ ATTR_ARIA_MULTISELECTABLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_multiselectable), ALL_NO_PREFIX);
+ ATTR_ARIA_CONTROLS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_controls), ALL_NO_PREFIX);
+ ATTR_ARIA_MULTILINE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_multiline), ALL_NO_PREFIX);
+ ATTR_ARIA_READONLY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_readonly), ALL_NO_PREFIX);
+ ATTR_ARIA_OWNS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_owns), ALL_NO_PREFIX);
+ ATTR_ARIA_ACTIVEDESCENDANT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_activedescendant), ALL_NO_PREFIX);
+ ATTR_ARIA_RELEVANT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_relevant), ALL_NO_PREFIX);
+ ATTR_ARIA_DATATYPE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_datatype), ALL_NO_PREFIX);
+ ATTR_ARIA_VALUENOW = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_valuenow), ALL_NO_PREFIX);
+ ATTR_ARIA_SORT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_sort), ALL_NO_PREFIX);
+ ATTR_ARIA_AUTOCOMPLETE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_autocomplete), ALL_NO_PREFIX);
+ ATTR_ARIA_FLOWTO = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_flowto), ALL_NO_PREFIX);
+ ATTR_ARIA_BUSY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_busy), ALL_NO_PREFIX);
+ ATTR_ARIA_LIVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_live), ALL_NO_PREFIX);
+ ATTR_ARIA_HASPOPUP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_haspopup), ALL_NO_PREFIX);
+ ATTR_ARIA_SETSIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::aria_setsize), ALL_NO_PREFIX);
+ ATTR_CLEAR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clear),
+ ALL_NO_PREFIX);
+ ATTR_DISABLED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::disabled), ALL_NO_PREFIX);
+ ATTR_DEFAULT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_default), ALL_NO_PREFIX);
+ ATTR_DATA = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::data),
+ ALL_NO_PREFIX);
+ ATTR_EQUALCOLUMNS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::equalcolumns_), ALL_NO_PREFIX);
+ ATTR_EQUALROWS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::equalrows_), ALL_NO_PREFIX);
+ ATTR_HSPACE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::hspace), ALL_NO_PREFIX);
+ ATTR_ISMAP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ismap),
+ ALL_NO_PREFIX);
+ ATTR_LOCAL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::local),
+ ALL_NO_PREFIX);
+ ATTR_LSPACE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lspace_), ALL_NO_PREFIX);
+ ATTR_MOVABLELIMITS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::movablelimits_), ALL_NO_PREFIX);
+ ATTR_NOTATION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::notation_), ALL_NO_PREFIX);
+ ATTR_ONDATAAVAILABLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondataavailable), ALL_NO_PREFIX);
+ ATTR_ONPASTE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onpaste), ALL_NO_PREFIX);
+ ATTR_RSPACE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rspace_), ALL_NO_PREFIX);
+ ATTR_ROWALIGN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowalign_), ALL_NO_PREFIX);
+ ATTR_ROTATE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rotate), ALL_NO_PREFIX);
+ ATTR_SEPARATOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::separator_), ALL_NO_PREFIX);
+ ATTR_SEPARATORS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::separators_), ALL_NO_PREFIX);
+ ATTR_VSPACE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::vspace), ALL_NO_PREFIX);
+ ATTR_XCHANNELSELECTOR = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::xchannelselector, nsGkAtoms::xChannelSelector),
+ ALL_NO_PREFIX);
+ ATTR_YCHANNELSELECTOR = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::ychannelselector, nsGkAtoms::yChannelSelector),
+ ALL_NO_PREFIX);
+ ATTR_ENABLE_BACKGROUND = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::enable_background), ALL_NO_PREFIX);
+ ATTR_ONDBLCLICK = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondblclick), ALL_NO_PREFIX);
+ ATTR_ONABORT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onabort), ALL_NO_PREFIX);
+ ATTR_CALCMODE = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::calcmode, nsGkAtoms::calcMode),
+ ALL_NO_PREFIX);
+ ATTR_CHECKED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::checked), ALL_NO_PREFIX);
+ ATTR_FENCE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fence_), ALL_NO_PREFIX);
+ ATTR_ONSCROLL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onscroll), ALL_NO_PREFIX);
+ ATTR_ONACTIVATE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onactivate), ALL_NO_PREFIX);
+ ATTR_OPACITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::opacity), ALL_NO_PREFIX);
+ ATTR_SPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::spacing), ALL_NO_PREFIX);
+ ATTR_SPECULAREXPONENT = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::specularexponent, nsGkAtoms::specularExponent),
+ ALL_NO_PREFIX);
+ ATTR_SPECULARCONSTANT = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::specularconstant, nsGkAtoms::specularConstant),
+ ALL_NO_PREFIX);
+ ATTR_BORDER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::border), ALL_NO_PREFIX);
+ ATTR_ID = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::id),
+ ALL_NO_PREFIX);
+ ATTR_GRADIENTTRANSFORM = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::gradienttransform, nsGkAtoms::gradientTransform),
+ ALL_NO_PREFIX);
+ ATTR_GRADIENTUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::gradientunits, nsGkAtoms::gradientUnits),
+ ALL_NO_PREFIX);
+ ATTR_HIDDEN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::hidden), ALL_NO_PREFIX);
+ ATTR_HEADERS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::headers), ALL_NO_PREFIX);
+ ATTR_LOADING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::loading), ALL_NO_PREFIX);
+ ATTR_READONLY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::readonly), ALL_NO_PREFIX);
+ ATTR_RENDERING_INTENT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rendering_intent), ALL_NO_PREFIX);
+ ATTR_SEED = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::seed),
+ ALL_NO_PREFIX);
+ ATTR_SRCDOC = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::srcdoc), ALL_NO_PREFIX);
+ ATTR_STDDEVIATION = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::stddeviation, nsGkAtoms::stdDeviation),
+ ALL_NO_PREFIX);
+ ATTR_SANDBOX = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::sandbox), ALL_NO_PREFIX);
+ ATTR_WORD_SPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::word_spacing), ALL_NO_PREFIX);
+ ATTR_ACCENTUNDER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accentunder_), ALL_NO_PREFIX);
+ ATTR_ACCEPT_CHARSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::acceptcharset), ALL_NO_PREFIX);
+ ATTR_ACCESSKEY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accesskey), ALL_NO_PREFIX);
+ ATTR_ACCENT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accent_), ALL_NO_PREFIX);
+ ATTR_ACCEPT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accept), ALL_NO_PREFIX);
+ ATTR_BEVELLED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::bevelled_), ALL_NO_PREFIX);
+ ATTR_BASEFREQUENCY = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::basefrequency, nsGkAtoms::baseFrequency),
+ ALL_NO_PREFIX);
+ ATTR_BASELINE_SHIFT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::baseline_shift), ALL_NO_PREFIX);
+ ATTR_BASEPROFILE = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::baseprofile, nsGkAtoms::baseProfile),
+ ALL_NO_PREFIX);
+ ATTR_BASELINE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::baseline), ALL_NO_PREFIX);
+ ATTR_BASE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::base),
+ ALL_NO_PREFIX);
+ ATTR_CODE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::code),
+ ALL_NO_PREFIX);
+ ATTR_CODETYPE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::codetype), ALL_NO_PREFIX);
+ ATTR_CODEBASE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::codebase), ALL_NO_PREFIX);
+ ATTR_CITE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cite),
+ ALL_NO_PREFIX);
+ ATTR_DEFER = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::defer),
+ ALL_NO_PREFIX);
+ ATTR_DATETIME = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::datetime), ALL_NO_PREFIX);
+ ATTR_DIRECTION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::direction), ALL_NO_PREFIX);
+ ATTR_EDGEMODE = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::edgemode, nsGkAtoms::edgeMode),
+ ALL_NO_PREFIX);
+ ATTR_EDGE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::edge_),
+ ALL_NO_PREFIX);
+ ATTR_ENTERKEYHINT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::enterkeyhint), ALL_NO_PREFIX);
+ ATTR_FACE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::face),
+ ALL_NO_PREFIX);
+ ATTR_INDEX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::index),
+ ALL_NO_PREFIX);
+ ATTR_INTERCEPT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::intercept), ALL_NO_PREFIX);
+ ATTR_INTEGRITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::integrity), ALL_NO_PREFIX);
+ ATTR_LINEBREAK = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::linebreak_), ALL_NO_PREFIX);
+ ATTR_LABEL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::label),
+ ALL_NO_PREFIX);
+ ATTR_LINETHICKNESS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::linethickness_), ALL_NO_PREFIX);
+ ATTR_MODE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mode),
+ ALL_NO_PREFIX);
+ ATTR_NAME = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::name),
+ ALL_NO_PREFIX);
+ ATTR_NORESIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::noresize), ALL_NO_PREFIX);
+ ATTR_ONBEFOREUNLOAD = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforeunload), ALL_NO_PREFIX);
+ ATTR_ONREPEAT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onrepeat), ALL_NO_PREFIX);
+ ATTR_OBJECT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::object), ALL_NO_PREFIX);
+ ATTR_ONSELECT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onselect), ALL_NO_PREFIX);
+ ATTR_ORDER = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::order),
+ ALL_NO_PREFIX);
+ ATTR_OTHER = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::other),
+ ALL_NO_PREFIX);
+ ATTR_ONRESET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onreset), ALL_NO_PREFIX);
+ ATTR_ONREADYSTATECHANGE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onreadystatechange), ALL_NO_PREFIX);
+ ATTR_ONMESSAGE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmessage), ALL_NO_PREFIX);
+ ATTR_ONBEGIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbegin), ALL_NO_PREFIX);
+ ATTR_ONBEFOREPRINT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforeprint), ALL_NO_PREFIX);
+ ATTR_ORIENT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::orient), ALL_NO_PREFIX);
+ ATTR_ORIENTATION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::orientation), ALL_NO_PREFIX);
+ ATTR_ONBEFORECOPY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforecopy), ALL_NO_PREFIX);
+ ATTR_ONSELECTSTART = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onselectstart), ALL_NO_PREFIX);
+ ATTR_ONBEFOREPASTE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforepaste), ALL_NO_PREFIX);
+ ATTR_ONKEYPRESS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onkeypress), ALL_NO_PREFIX);
+ ATTR_ONKEYUP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onkeyup), ALL_NO_PREFIX);
+ ATTR_ONBEFORECUT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onbeforecut), ALL_NO_PREFIX);
+ ATTR_ONKEYDOWN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onkeydown), ALL_NO_PREFIX);
+ ATTR_ONRESIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onresize), ALL_NO_PREFIX);
+ ATTR_REPEAT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::repeat), ALL_NO_PREFIX);
+ ATTR_REFERRERPOLICY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::referrerpolicy), ALL_NO_PREFIX);
+ ATTR_RULES = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rules),
+ ALL_NO_PREFIX);
+ ATTR_ROLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::role),
+ ALL_NO_PREFIX);
+ ATTR_REPEATCOUNT = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::repeatcount, nsGkAtoms::repeatCount),
+ ALL_NO_PREFIX);
+ ATTR_REPEATDUR = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::repeatdur, nsGkAtoms::repeatDur),
+ ALL_NO_PREFIX);
+ ATTR_SELECTED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::selected), ALL_NO_PREFIX);
+ ATTR_SIZES = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::sizes),
+ ALL_NO_PREFIX);
+ ATTR_SUPERSCRIPTSHIFT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::superscriptshift_), ALL_NO_PREFIX);
+ ATTR_STRETCHY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stretchy_), ALL_NO_PREFIX);
+ ATTR_SCHEME = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scheme), ALL_NO_PREFIX);
+ ATTR_SPREADMETHOD = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::spreadmethod, nsGkAtoms::spreadMethod),
+ ALL_NO_PREFIX);
+ ATTR_SELECTION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::selection_), ALL_NO_PREFIX);
+ ATTR_SIZE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::size),
+ ALL_NO_PREFIX);
+ ATTR_TYPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::type),
+ ALL_NO_PREFIX);
+ ATTR_DIFFUSECONSTANT = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::diffuseconstant, nsGkAtoms::diffuseConstant),
+ ALL_NO_PREFIX);
+ ATTR_HREF = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::href),
+ ALL_NO_PREFIX);
+ ATTR_HREFLANG = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::hreflang), ALL_NO_PREFIX);
+ ATTR_ONAFTERPRINT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onafterprint), ALL_NO_PREFIX);
+ ATTR_PROFILE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::profile), ALL_NO_PREFIX);
+ ATTR_SURFACESCALE = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::surfacescale, nsGkAtoms::surfaceScale),
+ ALL_NO_PREFIX);
+ ATTR_XREF = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::xref_),
+ ALL_NO_PREFIX);
+ ATTR_ALIGN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::align),
+ ALL_NO_PREFIX);
+ ATTR_ALIGNMENT_BASELINE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alignment_baseline), ALL_NO_PREFIX);
+ ATTR_ALIGNMENTSCOPE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alignmentscope_), ALL_NO_PREFIX);
+ ATTR_DRAGGABLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::draggable), ALL_NO_PREFIX);
+ ATTR_HEIGHT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::height), ALL_NO_PREFIX);
+ ATTR_IMAGESIZES = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::imagesizes), ALL_NO_PREFIX);
+ ATTR_IMAGESRCSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::imagesrcset), ALL_NO_PREFIX);
+ ATTR_IMAGE_RENDERING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::image_rendering), ALL_NO_PREFIX);
+ ATTR_LANGUAGE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::language), ALL_NO_PREFIX);
+ ATTR_LANG = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lang),
+ ALL_NO_PREFIX);
+ ATTR_LARGEOP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::largeop_), ALL_NO_PREFIX);
+ ATTR_LONGDESC = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::longdesc), ALL_NO_PREFIX);
+ ATTR_LENGTHADJUST = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::lengthadjust, nsGkAtoms::lengthAdjust),
+ ALL_NO_PREFIX);
+ ATTR_MARGINHEIGHT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marginheight), ALL_NO_PREFIX);
+ ATTR_MARGINWIDTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marginwidth), ALL_NO_PREFIX);
+ ATTR_ORIGIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::origin), ALL_NO_PREFIX);
+ ATTR_PING = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ping),
+ ALL_NO_PREFIX);
+ ATTR_TARGET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::target), ALL_NO_PREFIX);
+ ATTR_TARGETX = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::targetx, nsGkAtoms::targetX),
+ ALL_NO_PREFIX);
+ ATTR_TARGETY = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::targety, nsGkAtoms::targetY),
+ ALL_NO_PREFIX);
+ ATTR_ARCHIVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::archive), ALL_NO_PREFIX);
+ ATTR_HIGH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::high),
+ ALL_NO_PREFIX);
+ ATTR_LIGHTING_COLOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lighting_color), ALL_NO_PREFIX);
+ ATTR_MATHBACKGROUND = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathbackground_), ALL_NO_PREFIX);
+ ATTR_METHOD = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::method), ALL_NO_PREFIX);
+ ATTR_MATHVARIANT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathvariant_), ALL_NO_PREFIX);
+ ATTR_MATHCOLOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathcolor_), ALL_NO_PREFIX);
+ ATTR_MATHSIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mathsize_), ALL_NO_PREFIX);
+ ATTR_NOSHADE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::noshade), ALL_NO_PREFIX);
+ ATTR_ONCHANGE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onchange), ALL_NO_PREFIX);
+ ATTR_PATHLENGTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pathlength, nsGkAtoms::pathLength),
+ ALL_NO_PREFIX);
+ ATTR_PATH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::path),
+ ALL_NO_PREFIX);
+ ATTR_ALTIMG = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::altimg_), ALL_NO_PREFIX);
+ ATTR_ACTIONTYPE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::actiontype_), ALL_NO_PREFIX);
+ ATTR_ACTION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::action), ALL_NO_PREFIX);
+ ATTR_ACTIVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::active), ALL_NO_PREFIX);
+ ATTR_ADDITIVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::additive), ALL_NO_PREFIX);
+ ATTR_BEGIN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::begin),
+ ALL_NO_PREFIX);
+ ATTR_DOMINANT_BASELINE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dominant_baseline), ALL_NO_PREFIX);
+ ATTR_DIVISOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::divisor), ALL_NO_PREFIX);
+ ATTR_DEFINITIONURL = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ MATH_DIFFERENT(nsGkAtoms::definitionurl, nsGkAtoms::definitionURL_),
+ ALL_NO_PREFIX);
+ ATTR_LIMITINGCONEANGLE = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::limitingconeangle, nsGkAtoms::limitingConeAngle),
+ ALL_NO_PREFIX);
+ ATTR_MEDIA = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::media),
+ ALL_NO_PREFIX);
+ ATTR_MANIFEST = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::manifest), ALL_NO_PREFIX);
+ ATTR_ONFINISH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfinish), ALL_NO_PREFIX);
+ ATTR_OPTIMUM = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::optimum), ALL_NO_PREFIX);
+ ATTR_RADIOGROUP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::radiogroup), ALL_NO_PREFIX);
+ ATTR_RADIUS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::radius), ALL_NO_PREFIX);
+ ATTR_SCRIPTLEVEL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scriptlevel_), ALL_NO_PREFIX);
+ ATTR_SCRIPTSIZEMULTIPLIER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scriptsizemultiplier_), ALL_NO_PREFIX);
+ ATTR_SCRIPTMINSIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scriptminsize_), ALL_NO_PREFIX);
+ ATTR_TABINDEX = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::tabindex), ALL_NO_PREFIX);
+ ATTR_VALIGN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::valign), ALL_NO_PREFIX);
+ ATTR_VISIBILITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::visibility), ALL_NO_PREFIX);
+ ATTR_BACKGROUND = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::background), ALL_NO_PREFIX);
+ ATTR_LINK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::link),
+ ALL_NO_PREFIX);
+ ATTR_MARKER_MID = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marker_mid), ALL_NO_PREFIX);
+ ATTR_MARKERHEIGHT = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::markerheight, nsGkAtoms::markerHeight),
+ ALL_NO_PREFIX);
+ ATTR_MARKER_END = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marker_end), ALL_NO_PREFIX);
+ ATTR_MASK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::mask),
+ ALL_NO_PREFIX);
+ ATTR_MARKER_START = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::marker_start), ALL_NO_PREFIX);
+ ATTR_MARKERWIDTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::markerwidth, nsGkAtoms::markerWidth),
+ ALL_NO_PREFIX);
+ ATTR_MASKUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::maskunits, nsGkAtoms::maskUnits),
+ ALL_NO_PREFIX);
+ ATTR_MARKERUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::markerunits, nsGkAtoms::markerUnits),
+ ALL_NO_PREFIX);
+ ATTR_MASKCONTENTUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::maskcontentunits, nsGkAtoms::maskContentUnits),
+ ALL_NO_PREFIX);
+ ATTR_AMPLITUDE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::amplitude), ALL_NO_PREFIX);
+ ATTR_CELLSPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cellspacing), ALL_NO_PREFIX);
+ ATTR_CELLPADDING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cellpadding), ALL_NO_PREFIX);
+ ATTR_DECLARE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::declare), ALL_NO_PREFIX);
+ ATTR_FILL_RULE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fill_rule), ALL_NO_PREFIX);
+ ATTR_FILL = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fill),
+ ALL_NO_PREFIX);
+ ATTR_FILL_OPACITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fill_opacity), ALL_NO_PREFIX);
+ ATTR_MAXLENGTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::maxlength), ALL_NO_PREFIX);
+ ATTR_ONCLICK = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onclick), ALL_NO_PREFIX);
+ ATTR_ONBLUR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onblur), ALL_NO_PREFIX);
+ ATTR_REPLACE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::replace), ALL_NO_PREFIX);
+ ATTR_ROWLINES = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowlines_), ALL_NO_PREFIX);
+ ATTR_SCALE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scale),
+ ALL_NO_PREFIX);
+ ATTR_STYLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::style),
+ ALL_NO_PREFIX);
+ ATTR_TABLEVALUES = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::tablevalues, nsGkAtoms::tableValues),
+ ALL_NO_PREFIX);
+ ATTR_TITLE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::title),
+ ALL_NO_PREFIX);
+ ATTR_AZIMUTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::azimuth), ALL_NO_PREFIX);
+ ATTR_FORMAT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::format), ALL_NO_PREFIX);
+ ATTR_FRAMEBORDER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::frameborder), ALL_NO_PREFIX);
+ ATTR_FRAME = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::frame),
+ ALL_NO_PREFIX);
+ ATTR_FRAMESPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::framespacing_), ALL_NO_PREFIX);
+ ATTR_FROM = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::from),
+ ALL_NO_PREFIX);
+ ATTR_FORM = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::form),
+ ALL_NO_PREFIX);
+ ATTR_PROMPT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::prompt), ALL_NO_PREFIX);
+ ATTR_PRIMITIVEUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::primitiveunits, nsGkAtoms::primitiveUnits),
+ ALL_NO_PREFIX);
+ ATTR_SYMMETRIC = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::symmetric_), ALL_NO_PREFIX);
+ ATTR_SUMMARY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::summary), ALL_NO_PREFIX);
+ ATTR_USEMAP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::usemap), ALL_NO_PREFIX);
+ ATTR_ZOOMANDPAN = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::zoomandpan, nsGkAtoms::zoomAndPan),
+ ALL_NO_PREFIX);
+ ATTR_ASYNC = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::async),
+ ALL_NO_PREFIX);
+ ATTR_ALINK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alink),
+ ALL_NO_PREFIX);
+ ATTR_IN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::in),
+ ALL_NO_PREFIX);
+ ATTR_ICON = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::icon),
+ ALL_NO_PREFIX);
+ ATTR_KERNELMATRIX = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::kernelmatrix, nsGkAtoms::kernelMatrix),
+ ALL_NO_PREFIX);
+ ATTR_KERNING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::kerning), ALL_NO_PREFIX);
+ ATTR_KERNELUNITLENGTH = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::kernelunitlength, nsGkAtoms::kernelUnitLength),
+ ALL_NO_PREFIX);
+ ATTR_ONUNLOAD = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onunload), ALL_NO_PREFIX);
+ ATTR_OPEN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::open),
+ ALL_NO_PREFIX);
+ ATTR_ONINVALID = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oninvalid), ALL_NO_PREFIX);
+ ATTR_ONEND = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onend),
+ ALL_NO_PREFIX);
+ ATTR_ONINPUT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oninput), ALL_NO_PREFIX);
+ ATTR_POINTER_EVENTS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::pointer_events), ALL_NO_PREFIX);
+ ATTR_POINTS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::points), ALL_NO_PREFIX);
+ ATTR_POINTSATX = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pointsatx, nsGkAtoms::pointsAtX),
+ ALL_NO_PREFIX);
+ ATTR_POINTSATY = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pointsaty, nsGkAtoms::pointsAtY),
+ ALL_NO_PREFIX);
+ ATTR_POINTSATZ = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::pointsatz, nsGkAtoms::pointsAtZ),
+ ALL_NO_PREFIX);
+ ATTR_SPAN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::span),
+ ALL_NO_PREFIX);
+ ATTR_STANDBY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::standby), ALL_NO_PREFIX);
+ ATTR_TRANSFORM_ORIGIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::transform_origin), ALL_NO_PREFIX);
+ ATTR_TRANSFORM = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::transform), ALL_NO_PREFIX);
+ ATTR_VLINK = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::vlink),
+ ALL_NO_PREFIX);
+ ATTR_WHEN = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::when),
+ ALL_NO_PREFIX);
+ ATTR_XLINK_HREF = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_href, nsGkAtoms::href),
+ XLINK_PREFIX);
+ ATTR_XLINK_TITLE = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_title, nsGkAtoms::title),
+ XLINK_PREFIX);
+ ATTR_XLINK_ROLE = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_role, nsGkAtoms::role),
+ XLINK_PREFIX);
+ ATTR_XLINK_ARCROLE = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_arcrole, nsGkAtoms::arcrole),
+ XLINK_PREFIX);
+ ATTR_XMLNS_XLINK = new nsHtml5AttributeName(
+ XMLNS_NS, COLONIFIED_LOCAL(nsGkAtoms::xmlns_xlink, nsGkAtoms::xlink),
+ XMLNS_PREFIX);
+ ATTR_XMLNS = new nsHtml5AttributeName(XMLNS_NS, SAME_LOCAL(nsGkAtoms::xmlns),
+ ALL_NO_PREFIX);
+ ATTR_XLINK_TYPE = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_type, nsGkAtoms::type),
+ XLINK_PREFIX);
+ ATTR_XLINK_SHOW = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_show, nsGkAtoms::show),
+ XLINK_PREFIX);
+ ATTR_XLINK_ACTUATE = new nsHtml5AttributeName(
+ XLINK_NS, COLONIFIED_LOCAL(nsGkAtoms::xlink_actuate, nsGkAtoms::actuate),
+ XLINK_PREFIX);
+ ATTR_AUTOPLAY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autoplay), ALL_NO_PREFIX);
+ ATTR_AUTOCOMPLETE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autocomplete), ALL_NO_PREFIX);
+ ATTR_AUTOFOCUS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autofocus), ALL_NO_PREFIX);
+ ATTR_AUTOCAPITALIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::autocapitalize), ALL_NO_PREFIX);
+ ATTR_BGCOLOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::bgcolor), ALL_NO_PREFIX);
+ ATTR_COLOR_PROFILE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colorProfile), ALL_NO_PREFIX);
+ ATTR_COLOR_RENDERING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::color_rendering), ALL_NO_PREFIX);
+ ATTR_COLOR_INTERPOLATION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colorInterpolation), ALL_NO_PREFIX);
+ ATTR_COLOR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::color),
+ ALL_NO_PREFIX);
+ ATTR_COLOR_INTERPOLATION_FILTERS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colorInterpolationFilters),
+ ALL_NO_PREFIX);
+ ATTR_ENCODING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::encoding), ALL_NO_PREFIX);
+ ATTR_EXPONENT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::exponent), ALL_NO_PREFIX);
+ ATTR_FLOOD_COLOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::flood_color), ALL_NO_PREFIX);
+ ATTR_FLOOD_OPACITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::flood_opacity), ALL_NO_PREFIX);
+ ATTR_LQUOTE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lquote_), ALL_NO_PREFIX);
+ ATTR_NUMOCTAVES = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::numoctaves, nsGkAtoms::numOctaves),
+ ALL_NO_PREFIX);
+ ATTR_NOMODULE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::nomodule), ALL_NO_PREFIX);
+ ATTR_ONLOAD = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onload), ALL_NO_PREFIX);
+ ATTR_ONMOUSEWHEEL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmousewheel), ALL_NO_PREFIX);
+ ATTR_ONMOUSEENTER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseenter), ALL_NO_PREFIX);
+ ATTR_ONMOUSEOVER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseover), ALL_NO_PREFIX);
+ ATTR_ONFOCUSIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfocusin), ALL_NO_PREFIX);
+ ATTR_ONCONTEXTMENU = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oncontextmenu), ALL_NO_PREFIX);
+ ATTR_ONZOOM = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onzoom), ALL_NO_PREFIX);
+ ATTR_ONCOPY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oncopy), ALL_NO_PREFIX);
+ ATTR_ONMOUSELEAVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseleave), ALL_NO_PREFIX);
+ ATTR_ONMOUSEMOVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmousemove), ALL_NO_PREFIX);
+ ATTR_ONMOUSEUP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseup), ALL_NO_PREFIX);
+ ATTR_ONFOCUS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfocus), ALL_NO_PREFIX);
+ ATTR_ONMOUSEOUT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmouseout), ALL_NO_PREFIX);
+ ATTR_ONFOCUSOUT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onfocusout), ALL_NO_PREFIX);
+ ATTR_ONMOUSEDOWN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onmousedown), ALL_NO_PREFIX);
+ ATTR_TO = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::to),
+ ALL_NO_PREFIX);
+ ATTR_RQUOTE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rquote_), ALL_NO_PREFIX);
+ ATTR_STROKE_LINECAP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_linecap), ALL_NO_PREFIX);
+ ATTR_STROKE_DASHARRAY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_dasharray), ALL_NO_PREFIX);
+ ATTR_STROKE_DASHOFFSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_dashoffset), ALL_NO_PREFIX);
+ ATTR_STROKE_LINEJOIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_linejoin), ALL_NO_PREFIX);
+ ATTR_STROKE_MITERLIMIT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_miterlimit), ALL_NO_PREFIX);
+ ATTR_STROKE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke), ALL_NO_PREFIX);
+ ATTR_SCROLLING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scrolling), ALL_NO_PREFIX);
+ ATTR_STROKE_WIDTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_width), ALL_NO_PREFIX);
+ ATTR_STROKE_OPACITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stroke_opacity), ALL_NO_PREFIX);
+ ATTR_COMPACT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::compact), ALL_NO_PREFIX);
+ ATTR_CLIP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clip),
+ ALL_NO_PREFIX);
+ ATTR_CLIP_RULE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clip_rule), ALL_NO_PREFIX);
+ ATTR_CLIP_PATH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::clip_path), ALL_NO_PREFIX);
+ ATTR_CLIPPATHUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::clippathunits, nsGkAtoms::clipPathUnits),
+ ALL_NO_PREFIX);
+ ATTR_DISPLAY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::display), ALL_NO_PREFIX);
+ ATTR_DISPLAYSTYLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::displaystyle_), ALL_NO_PREFIX);
+ ATTR_GLYPH_ORIENTATION_VERTICAL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::glyph_orientation_vertical),
+ ALL_NO_PREFIX);
+ ATTR_GLYPH_ORIENTATION_HORIZONTAL = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::glyph_orientation_horizontal),
+ ALL_NO_PREFIX);
+ ATTR_GLYPHREF = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::glyphref, nsGkAtoms::glyphRef),
+ ALL_NO_PREFIX);
+ ATTR_HTTP_EQUIV = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::httpEquiv), ALL_NO_PREFIX);
+ ATTR_KEYPOINTS = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::keypoints, nsGkAtoms::keyPoints),
+ ALL_NO_PREFIX);
+ ATTR_LOOP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::loop),
+ ALL_NO_PREFIX);
+ ATTR_PROPERTY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::property), ALL_NO_PREFIX);
+ ATTR_SCOPED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scoped), ALL_NO_PREFIX);
+ ATTR_STEP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::step),
+ ALL_NO_PREFIX);
+ ATTR_SHAPE_RENDERING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::shape_rendering), ALL_NO_PREFIX);
+ ATTR_SCOPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::scope),
+ ALL_NO_PREFIX);
+ ATTR_SHAPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::shape),
+ ALL_NO_PREFIX);
+ ATTR_SLOPE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::slope),
+ ALL_NO_PREFIX);
+ ATTR_STOP_COLOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stop_color), ALL_NO_PREFIX);
+ ATTR_STOP_OPACITY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::stop_opacity), ALL_NO_PREFIX);
+ ATTR_TEMPLATE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_template), ALL_NO_PREFIX);
+ ATTR_WRAP = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::wrap),
+ ALL_NO_PREFIX);
+ ATTR_ABBR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::abbr),
+ ALL_NO_PREFIX);
+ ATTR_ATTRIBUTENAME = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::attributename, nsGkAtoms::attributeName),
+ ALL_NO_PREFIX);
+ ATTR_ATTRIBUTETYPE = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::attributetype, nsGkAtoms::attributeType),
+ ALL_NO_PREFIX);
+ ATTR_CHAR = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_char),
+ ALL_NO_PREFIX);
+ ATTR_COORDS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::coords), ALL_NO_PREFIX);
+ ATTR_CHAROFF = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::charoff), ALL_NO_PREFIX);
+ ATTR_CHARSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::charset), ALL_NO_PREFIX);
+ ATTR_NOWRAP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::nowrap), ALL_NO_PREFIX);
+ ATTR_NOHREF = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::nohref), ALL_NO_PREFIX);
+ ATTR_ONDRAG = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondrag), ALL_NO_PREFIX);
+ ATTR_ONDRAGENTER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragenter), ALL_NO_PREFIX);
+ ATTR_ONDRAGOVER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragover), ALL_NO_PREFIX);
+ ATTR_ONDRAGEND = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragend), ALL_NO_PREFIX);
+ ATTR_ONDROP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondrop), ALL_NO_PREFIX);
+ ATTR_ONDRAGDROP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragdrop), ALL_NO_PREFIX);
+ ATTR_ONERROR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onerror), ALL_NO_PREFIX);
+ ATTR_OPERATOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_operator), ALL_NO_PREFIX);
+ ATTR_OVERFLOW = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::overflow), ALL_NO_PREFIX);
+ ATTR_ONDRAGSTART = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragstart), ALL_NO_PREFIX);
+ ATTR_ONDRAGLEAVE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ondragleave), ALL_NO_PREFIX);
+ ATTR_STARTOFFSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::startoffset, nsGkAtoms::startOffset),
+ ALL_NO_PREFIX);
+ ATTR_START = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::start),
+ ALL_NO_PREFIX);
+ ATTR_AS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::as),
+ ALL_NO_PREFIX);
+ ATTR_AXIS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::axis),
+ ALL_NO_PREFIX);
+ ATTR_BIAS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::bias),
+ ALL_NO_PREFIX);
+ ATTR_COLSPAN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::colspan), ALL_NO_PREFIX);
+ ATTR_CLASSID = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::classid), ALL_NO_PREFIX);
+ ATTR_CROSSORIGIN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::crossorigin), ALL_NO_PREFIX);
+ ATTR_COLS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cols),
+ ALL_NO_PREFIX);
+ ATTR_CURSOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cursor), ALL_NO_PREFIX);
+ ATTR_CLOSURE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::closure_), ALL_NO_PREFIX);
+ ATTR_CLOSE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::close),
+ ALL_NO_PREFIX);
+ ATTR_CLASS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::_class), ALL_NO_PREFIX);
+ ATTR_IS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::is),
+ ALL_NO_PREFIX);
+ ATTR_KEYSYSTEM = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::keysystem), ALL_NO_PREFIX);
+ ATTR_KEYSPLINES = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::keysplines, nsGkAtoms::keySplines),
+ ALL_NO_PREFIX);
+ ATTR_LOWSRC = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::lowsrc), ALL_NO_PREFIX);
+ ATTR_MAXSIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::maxsize_), ALL_NO_PREFIX);
+ ATTR_MINSIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::minsize_), ALL_NO_PREFIX);
+ ATTR_OFFSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::offset), ALL_NO_PREFIX);
+ ATTR_PRESERVEALPHA = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::preservealpha, nsGkAtoms::preserveAlpha),
+ ALL_NO_PREFIX);
+ ATTR_PRESERVEASPECTRATIO =
+ new nsHtml5AttributeName(ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::preserveaspectratio,
+ nsGkAtoms::preserveAspectRatio),
+ ALL_NO_PREFIX);
+ ATTR_ROWSPAN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowspan), ALL_NO_PREFIX);
+ ATTR_ROWSPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rowspacing_), ALL_NO_PREFIX);
+ ATTR_ROWS = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rows),
+ ALL_NO_PREFIX);
+ ATTR_SRCSET = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::srcset), ALL_NO_PREFIX);
+ ATTR_SUBSCRIPTSHIFT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::subscriptshift_), ALL_NO_PREFIX);
+ ATTR_VERSION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::version), ALL_NO_PREFIX);
+ ATTR_ALTTEXT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::alttext), ALL_NO_PREFIX);
+ ATTR_CONTENTEDITABLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::contenteditable), ALL_NO_PREFIX);
+ ATTR_CONTROLS = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::controls), ALL_NO_PREFIX);
+ ATTR_CONTENT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::content), ALL_NO_PREFIX);
+ ATTR_CONTEXTMENU = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::contextmenu), ALL_NO_PREFIX);
+ ATTR_DEPTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::depth_), ALL_NO_PREFIX);
+ ATTR_ENCTYPE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::enctype), ALL_NO_PREFIX);
+ ATTR_FONT_STRETCH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_stretch), ALL_NO_PREFIX);
+ ATTR_FILTER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::filter), ALL_NO_PREFIX);
+ ATTR_FONTWEIGHT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontweight_), ALL_NO_PREFIX);
+ ATTR_FONT_WEIGHT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontWeight), ALL_NO_PREFIX);
+ ATTR_FONTSTYLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontstyle_), ALL_NO_PREFIX);
+ ATTR_FONT_STYLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_style), ALL_NO_PREFIX);
+ ATTR_FONTFAMILY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontfamily_), ALL_NO_PREFIX);
+ ATTR_FONT_FAMILY = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_family), ALL_NO_PREFIX);
+ ATTR_FONT_VARIANT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_variant), ALL_NO_PREFIX);
+ ATTR_FONT_SIZE_ADJUST = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_size_adjust), ALL_NO_PREFIX);
+ ATTR_FILTERUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::filterunits, nsGkAtoms::filterUnits),
+ ALL_NO_PREFIX);
+ ATTR_FONTSIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fontsize_), ALL_NO_PREFIX);
+ ATTR_FONT_SIZE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::font_size), ALL_NO_PREFIX);
+ ATTR_KEYTIMES = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::keytimes, nsGkAtoms::keyTimes),
+ ALL_NO_PREFIX);
+ ATTR_LETTER_SPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::letter_spacing), ALL_NO_PREFIX);
+ ATTR_LIST = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::list_),
+ ALL_NO_PREFIX);
+ ATTR_MULTIPLE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::multiple), ALL_NO_PREFIX);
+ ATTR_RT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rt),
+ ALL_NO_PREFIX);
+ ATTR_ONSTOP = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onstop), ALL_NO_PREFIX);
+ ATTR_ONSTART = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onstart), ALL_NO_PREFIX);
+ ATTR_POSTER = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::poster), ALL_NO_PREFIX);
+ ATTR_PATTERNTRANSFORM = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::patterntransform, nsGkAtoms::patternTransform),
+ ALL_NO_PREFIX);
+ ATTR_PATTERN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::pattern), ALL_NO_PREFIX);
+ ATTR_PATTERNUNITS = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::patternunits, nsGkAtoms::patternUnits),
+ ALL_NO_PREFIX);
+ ATTR_PATTERNCONTENTUNITS =
+ new nsHtml5AttributeName(ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::patterncontentunits,
+ nsGkAtoms::patternContentUnits),
+ ALL_NO_PREFIX);
+ ATTR_RESTART = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::restart), ALL_NO_PREFIX);
+ ATTR_STITCHTILES = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::stitchtiles, nsGkAtoms::stitchTiles),
+ ALL_NO_PREFIX);
+ ATTR_SYSTEMLANGUAGE = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::systemlanguage, nsGkAtoms::systemLanguage),
+ ALL_NO_PREFIX);
+ ATTR_TEXT_RENDERING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text_rendering), ALL_NO_PREFIX);
+ ATTR_TEXT_DECORATION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text_decoration), ALL_NO_PREFIX);
+ ATTR_TEXT_ANCHOR = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text_anchor), ALL_NO_PREFIX);
+ ATTR_TEXTLENGTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::textlength, nsGkAtoms::textLength),
+ ALL_NO_PREFIX);
+ ATTR_TEXT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::text),
+ ALL_NO_PREFIX);
+ ATTR_WRITING_MODE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::writing_mode), ALL_NO_PREFIX);
+ ATTR_WIDTH = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::width),
+ ALL_NO_PREFIX);
+ ATTR_ACCUMULATE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::accumulate), ALL_NO_PREFIX);
+ ATTR_COLUMNSPAN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnspan_), ALL_NO_PREFIX);
+ ATTR_COLUMNLINES = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnlines_), ALL_NO_PREFIX);
+ ATTR_COLUMNALIGN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnalign_), ALL_NO_PREFIX);
+ ATTR_COLUMNSPACING = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnspacing_), ALL_NO_PREFIX);
+ ATTR_COLUMNWIDTH = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::columnwidth_), ALL_NO_PREFIX);
+ ATTR_GROUPALIGN = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::groupalign_), ALL_NO_PREFIX);
+ ATTR_INPUTMODE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::inputmode), ALL_NO_PREFIX);
+ ATTR_ONSUBMIT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::onsubmit), ALL_NO_PREFIX);
+ ATTR_ONCUT = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::oncut),
+ ALL_NO_PREFIX);
+ ATTR_REQUIRED = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::required), ALL_NO_PREFIX);
+ ATTR_REQUIREDFEATURES = new nsHtml5AttributeName(
+ ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::requiredfeatures, nsGkAtoms::requiredFeatures),
+ ALL_NO_PREFIX);
+ ATTR_RESULT = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::result), ALL_NO_PREFIX);
+ ATTR_REQUIREDEXTENSIONS =
+ new nsHtml5AttributeName(ALL_NO_NS,
+ SVG_DIFFERENT(nsGkAtoms::requiredextensions,
+ nsGkAtoms::requiredExtensions),
+ ALL_NO_PREFIX);
+ ATTR_VALUES = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::values), ALL_NO_PREFIX);
+ ATTR_VALUETYPE = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::valuetype), ALL_NO_PREFIX);
+ ATTR_VALUE = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::value),
+ ALL_NO_PREFIX);
+ ATTR_ELEVATION = new nsHtml5AttributeName(
+ ALL_NO_NS, SAME_LOCAL(nsGkAtoms::elevation), ALL_NO_PREFIX);
+ ATTR_VIEWTARGET = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::viewtarget, nsGkAtoms::viewTarget),
+ ALL_NO_PREFIX);
+ ATTR_VIEWBOX = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::viewbox, nsGkAtoms::viewBox),
+ ALL_NO_PREFIX);
+ ATTR_CX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cx),
+ ALL_NO_PREFIX);
+ ATTR_DX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dx),
+ ALL_NO_PREFIX);
+ ATTR_FX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fx),
+ ALL_NO_PREFIX);
+ ATTR_RX = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::rx),
+ ALL_NO_PREFIX);
+ ATTR_REFX = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::refx, nsGkAtoms::refX),
+ ALL_NO_PREFIX);
+ ATTR_BY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::by),
+ ALL_NO_PREFIX);
+ ATTR_CY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::cy),
+ ALL_NO_PREFIX);
+ ATTR_DY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::dy),
+ ALL_NO_PREFIX);
+ ATTR_FY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::fy),
+ ALL_NO_PREFIX);
+ ATTR_RY = new nsHtml5AttributeName(ALL_NO_NS, SAME_LOCAL(nsGkAtoms::ry),
+ ALL_NO_PREFIX);
+ ATTR_REFY = new nsHtml5AttributeName(
+ ALL_NO_NS, SVG_DIFFERENT(nsGkAtoms::refy, nsGkAtoms::refY),
+ ALL_NO_PREFIX);
+ ATTRIBUTE_NAMES = new nsHtml5AttributeName*[499];
+ ATTRIBUTE_NAMES[0] = ATTR_FILL;
+ ATTRIBUTE_NAMES[1] = ATTR_DATETIME;
+ ATTRIBUTE_NAMES[2] = ATTR_CHAROFF;
+ ATTRIBUTE_NAMES[3] = ATTR_CLEAR;
+ ATTRIBUTE_NAMES[4] = ATTR_IMAGESRCSET;
+ ATTRIBUTE_NAMES[5] = ATTR_COLOR;
+ ATTRIBUTE_NAMES[6] = ATTR_LETTER_SPACING;
+ ATTRIBUTE_NAMES[7] = ATTR_ARIA_DISABLED;
+ ATTRIBUTE_NAMES[8] = ATTR_SPECULAREXPONENT;
+ ATTRIBUTE_NAMES[9] = ATTR_ONKEYUP;
+ ATTRIBUTE_NAMES[10] = ATTR_DOMINANT_BASELINE;
+ ATTRIBUTE_NAMES[11] = ATTR_OPEN;
+ ATTRIBUTE_NAMES[12] = ATTR_SCROLLING;
+ ATTRIBUTE_NAMES[13] = ATTR_MAXSIZE;
+ ATTRIBUTE_NAMES[14] = ATTR_REQUIREDFEATURES;
+ ATTRIBUTE_NAMES[15] = ATTR_Y;
+ ATTRIBUTE_NAMES[16] = ATTR_ARIA_MULTISELECTABLE;
+ ATTRIBUTE_NAMES[17] = ATTR_ROTATE;
+ ATTRIBUTE_NAMES[18] = ATTR_ACCENTUNDER;
+ ATTRIBUTE_NAMES[19] = ATTR_ONREPEAT;
+ ATTRIBUTE_NAMES[20] = ATTR_SELECTION;
+ ATTRIBUTE_NAMES[21] = ATTR_LIGHTING_COLOR;
+ ATTRIBUTE_NAMES[22] = ATTR_BACKGROUND;
+ ATTRIBUTE_NAMES[23] = ATTR_FROM;
+ ATTRIBUTE_NAMES[24] = ATTR_XLINK_TITLE;
+ ATTRIBUTE_NAMES[25] = ATTR_ONCOPY;
+ ATTRIBUTE_NAMES[26] = ATTR_PROPERTY;
+ ATTRIBUTE_NAMES[27] = ATTR_START;
+ ATTRIBUTE_NAMES[28] = ATTR_DEPTH;
+ ATTRIBUTE_NAMES[29] = ATTR_TEXT_ANCHOR;
+ ATTRIBUTE_NAMES[30] = ATTR_RX;
+ ATTRIBUTE_NAMES[31] = ATTR_MIN;
+ ATTRIBUTE_NAMES[32] = ATTR_K3;
+ ATTRIBUTE_NAMES[33] = ATTR_ARIA_CHANNEL;
+ ATTRIBUTE_NAMES[34] = ATTR_ARIA_VALUENOW;
+ ATTRIBUTE_NAMES[35] = ATTR_LOCAL;
+ ATTRIBUTE_NAMES[36] = ATTR_ONABORT;
+ ATTRIBUTE_NAMES[37] = ATTR_LOADING;
+ ATTRIBUTE_NAMES[38] = ATTR_BASEPROFILE;
+ ATTRIBUTE_NAMES[39] = ATTR_INTEGRITY;
+ ATTRIBUTE_NAMES[40] = ATTR_ONBEGIN;
+ ATTRIBUTE_NAMES[41] = ATTR_REPEATCOUNT;
+ ATTRIBUTE_NAMES[42] = ATTR_SURFACESCALE;
+ ATTRIBUTE_NAMES[43] = ATTR_MARGINWIDTH;
+ ATTRIBUTE_NAMES[44] = ATTR_PATHLENGTH;
+ ATTRIBUTE_NAMES[45] = ATTR_RADIOGROUP;
+ ATTRIBUTE_NAMES[46] = ATTR_MASKUNITS;
+ ATTRIBUTE_NAMES[47] = ATTR_STYLE;
+ ATTRIBUTE_NAMES[48] = ATTR_ASYNC;
+ ATTRIBUTE_NAMES[49] = ATTR_POINTSATZ;
+ ATTRIBUTE_NAMES[50] = ATTR_AUTOPLAY;
+ ATTRIBUTE_NAMES[51] = ATTR_NOMODULE;
+ ATTRIBUTE_NAMES[52] = ATTR_TO;
+ ATTRIBUTE_NAMES[53] = ATTR_DISPLAY;
+ ATTRIBUTE_NAMES[54] = ATTR_STOP_OPACITY;
+ ATTRIBUTE_NAMES[55] = ATTR_ONDROP;
+ ATTRIBUTE_NAMES[56] = ATTR_CURSOR;
+ ATTRIBUTE_NAMES[57] = ATTR_SRCSET;
+ ATTRIBUTE_NAMES[58] = ATTR_FONTFAMILY;
+ ATTRIBUTE_NAMES[59] = ATTR_PATTERN;
+ ATTRIBUTE_NAMES[60] = ATTR_COLUMNALIGN;
+ ATTRIBUTE_NAMES[61] = ATTR_VIEWBOX;
+ ATTRIBUTE_NAMES[62] = ATTR_DY;
+ ATTRIBUTE_NAMES[63] = ATTR_END;
+ ATTRIBUTE_NAMES[64] = ATTR_SRC;
+ ATTRIBUTE_NAMES[65] = ATTR_Y1;
+ ATTRIBUTE_NAMES[66] = ATTR_ARIA_GRAB;
+ ATTRIBUTE_NAMES[67] = ATTR_ARIA_REQUIRED;
+ ATTRIBUTE_NAMES[68] = ATTR_ARIA_ATOMIC;
+ ATTRIBUTE_NAMES[69] = ATTR_ARIA_OWNS;
+ ATTRIBUTE_NAMES[70] = ATTR_ARIA_BUSY;
+ ATTRIBUTE_NAMES[71] = ATTR_EQUALCOLUMNS;
+ ATTRIBUTE_NAMES[72] = ATTR_ONDATAAVAILABLE;
+ ATTRIBUTE_NAMES[73] = ATTR_XCHANNELSELECTOR;
+ ATTRIBUTE_NAMES[74] = ATTR_ONSCROLL;
+ ATTRIBUTE_NAMES[75] = ATTR_GRADIENTTRANSFORM;
+ ATTRIBUTE_NAMES[76] = ATTR_SRCDOC;
+ ATTRIBUTE_NAMES[77] = ATTR_ACCEPT;
+ ATTRIBUTE_NAMES[78] = ATTR_CODETYPE;
+ ATTRIBUTE_NAMES[79] = ATTR_ENTERKEYHINT;
+ ATTRIBUTE_NAMES[80] = ATTR_MODE;
+ ATTRIBUTE_NAMES[81] = ATTR_OTHER;
+ ATTRIBUTE_NAMES[82] = ATTR_ONBEFORECOPY;
+ ATTRIBUTE_NAMES[83] = ATTR_REPEAT;
+ ATTRIBUTE_NAMES[84] = ATTR_SUPERSCRIPTSHIFT;
+ ATTRIBUTE_NAMES[85] = ATTR_HREF;
+ ATTRIBUTE_NAMES[86] = ATTR_ALIGNMENTSCOPE;
+ ATTRIBUTE_NAMES[87] = ATTR_LARGEOP;
+ ATTRIBUTE_NAMES[88] = ATTR_TARGETX;
+ ATTRIBUTE_NAMES[89] = ATTR_MATHCOLOR;
+ ATTRIBUTE_NAMES[90] = ATTR_ACTION;
+ ATTRIBUTE_NAMES[91] = ATTR_MEDIA;
+ ATTRIBUTE_NAMES[92] = ATTR_SCRIPTMINSIZE;
+ ATTRIBUTE_NAMES[93] = ATTR_MARKER_END;
+ ATTRIBUTE_NAMES[94] = ATTR_CELLSPACING;
+ ATTRIBUTE_NAMES[95] = ATTR_ONBLUR;
+ ATTRIBUTE_NAMES[96] = ATTR_FORMAT;
+ ATTRIBUTE_NAMES[97] = ATTR_SYMMETRIC;
+ ATTRIBUTE_NAMES[98] = ATTR_KERNELMATRIX;
+ ATTRIBUTE_NAMES[99] = ATTR_POINTER_EVENTS;
+ ATTRIBUTE_NAMES[100] = ATTR_TRANSFORM;
+ ATTRIBUTE_NAMES[101] = ATTR_XMLNS;
+ ATTRIBUTE_NAMES[102] = ATTR_BGCOLOR;
+ ATTRIBUTE_NAMES[103] = ATTR_FLOOD_COLOR;
+ ATTRIBUTE_NAMES[104] = ATTR_ONMOUSEOVER;
+ ATTRIBUTE_NAMES[105] = ATTR_ONFOCUS;
+ ATTRIBUTE_NAMES[106] = ATTR_STROKE_DASHOFFSET;
+ ATTRIBUTE_NAMES[107] = ATTR_CLIP;
+ ATTRIBUTE_NAMES[108] = ATTR_GLYPHREF;
+ ATTRIBUTE_NAMES[109] = ATTR_SCOPE;
+ ATTRIBUTE_NAMES[110] = ATTR_ATTRIBUTENAME;
+ ATTRIBUTE_NAMES[111] = ATTR_ONDRAG;
+ ATTRIBUTE_NAMES[112] = ATTR_OVERFLOW;
+ ATTRIBUTE_NAMES[113] = ATTR_COLSPAN;
+ ATTRIBUTE_NAMES[114] = ATTR_IS;
+ ATTRIBUTE_NAMES[115] = ATTR_PRESERVEASPECTRATIO;
+ ATTRIBUTE_NAMES[116] = ATTR_CONTENTEDITABLE;
+ ATTRIBUTE_NAMES[117] = ATTR_FONTWEIGHT;
+ ATTRIBUTE_NAMES[118] = ATTR_FILTERUNITS;
+ ATTRIBUTE_NAMES[119] = ATTR_ONSTOP;
+ ATTRIBUTE_NAMES[120] = ATTR_STITCHTILES;
+ ATTRIBUTE_NAMES[121] = ATTR_WIDTH;
+ ATTRIBUTE_NAMES[122] = ATTR_INPUTMODE;
+ ATTRIBUTE_NAMES[123] = ATTR_VALUETYPE;
+ ATTRIBUTE_NAMES[124] = ATTR_DX;
+ ATTRIBUTE_NAMES[125] = ATTR_BY;
+ ATTRIBUTE_NAMES[126] = ATTR_RY;
+ ATTRIBUTE_NAMES[127] = ATTR_DIR;
+ ATTRIBUTE_NAMES[128] = ATTR_IN2;
+ ATTRIBUTE_NAMES[129] = ATTR_REL;
+ ATTRIBUTE_NAMES[130] = ATTR_R;
+ ATTRIBUTE_NAMES[131] = ATTR_K1;
+ ATTRIBUTE_NAMES[132] = ATTR_X2;
+ ATTRIBUTE_NAMES[133] = ATTR_XML_SPACE;
+ ATTRIBUTE_NAMES[134] = ATTR_ARIA_LABELLEDBY;
+ ATTRIBUTE_NAMES[135] = ATTR_ARIA_SELECTED;
+ ATTRIBUTE_NAMES[136] = ATTR_ARIA_PRESSED;
+ ATTRIBUTE_NAMES[137] = ATTR_ARIA_SECRET;
+ ATTRIBUTE_NAMES[138] = ATTR_ARIA_TEMPLATEID;
+ ATTRIBUTE_NAMES[139] = ATTR_ARIA_MULTILINE;
+ ATTRIBUTE_NAMES[140] = ATTR_ARIA_RELEVANT;
+ ATTRIBUTE_NAMES[141] = ATTR_ARIA_AUTOCOMPLETE;
+ ATTRIBUTE_NAMES[142] = ATTR_ARIA_HASPOPUP;
+ ATTRIBUTE_NAMES[143] = ATTR_DEFAULT;
+ ATTRIBUTE_NAMES[144] = ATTR_HSPACE;
+ ATTRIBUTE_NAMES[145] = ATTR_MOVABLELIMITS;
+ ATTRIBUTE_NAMES[146] = ATTR_RSPACE;
+ ATTRIBUTE_NAMES[147] = ATTR_SEPARATORS;
+ ATTRIBUTE_NAMES[148] = ATTR_ENABLE_BACKGROUND;
+ ATTRIBUTE_NAMES[149] = ATTR_CHECKED;
+ ATTRIBUTE_NAMES[150] = ATTR_OPACITY;
+ ATTRIBUTE_NAMES[151] = ATTR_BORDER;
+ ATTRIBUTE_NAMES[152] = ATTR_HIDDEN;
+ ATTRIBUTE_NAMES[153] = ATTR_RENDERING_INTENT;
+ ATTRIBUTE_NAMES[154] = ATTR_SANDBOX;
+ ATTRIBUTE_NAMES[155] = ATTR_ACCESSKEY;
+ ATTRIBUTE_NAMES[156] = ATTR_BASEFREQUENCY;
+ ATTRIBUTE_NAMES[157] = ATTR_BASE;
+ ATTRIBUTE_NAMES[158] = ATTR_CITE;
+ ATTRIBUTE_NAMES[159] = ATTR_EDGEMODE;
+ ATTRIBUTE_NAMES[160] = ATTR_INDEX;
+ ATTRIBUTE_NAMES[161] = ATTR_LABEL;
+ ATTRIBUTE_NAMES[162] = ATTR_NORESIZE;
+ ATTRIBUTE_NAMES[163] = ATTR_ONSELECT;
+ ATTRIBUTE_NAMES[164] = ATTR_ONREADYSTATECHANGE;
+ ATTRIBUTE_NAMES[165] = ATTR_ORIENT;
+ ATTRIBUTE_NAMES[166] = ATTR_ONBEFOREPASTE;
+ ATTRIBUTE_NAMES[167] = ATTR_ONKEYDOWN;
+ ATTRIBUTE_NAMES[168] = ATTR_RULES;
+ ATTRIBUTE_NAMES[169] = ATTR_SELECTED;
+ ATTRIBUTE_NAMES[170] = ATTR_SCHEME;
+ ATTRIBUTE_NAMES[171] = ATTR_TYPE;
+ ATTRIBUTE_NAMES[172] = ATTR_ONAFTERPRINT;
+ ATTRIBUTE_NAMES[173] = ATTR_ALIGN;
+ ATTRIBUTE_NAMES[174] = ATTR_HEIGHT;
+ ATTRIBUTE_NAMES[175] = ATTR_LANGUAGE;
+ ATTRIBUTE_NAMES[176] = ATTR_LENGTHADJUST;
+ ATTRIBUTE_NAMES[177] = ATTR_PING;
+ ATTRIBUTE_NAMES[178] = ATTR_ARCHIVE;
+ ATTRIBUTE_NAMES[179] = ATTR_METHOD;
+ ATTRIBUTE_NAMES[180] = ATTR_NOSHADE;
+ ATTRIBUTE_NAMES[181] = ATTR_ALTIMG;
+ ATTRIBUTE_NAMES[182] = ATTR_ADDITIVE;
+ ATTRIBUTE_NAMES[183] = ATTR_DEFINITIONURL;
+ ATTRIBUTE_NAMES[184] = ATTR_ONFINISH;
+ ATTRIBUTE_NAMES[185] = ATTR_SCRIPTLEVEL;
+ ATTRIBUTE_NAMES[186] = ATTR_VALIGN;
+ ATTRIBUTE_NAMES[187] = ATTR_MARKER_MID;
+ ATTRIBUTE_NAMES[188] = ATTR_MARKER_START;
+ ATTRIBUTE_NAMES[189] = ATTR_MASKCONTENTUNITS;
+ ATTRIBUTE_NAMES[190] = ATTR_DECLARE;
+ ATTRIBUTE_NAMES[191] = ATTR_MAXLENGTH;
+ ATTRIBUTE_NAMES[192] = ATTR_ROWLINES;
+ ATTRIBUTE_NAMES[193] = ATTR_TITLE;
+ ATTRIBUTE_NAMES[194] = ATTR_FRAME;
+ ATTRIBUTE_NAMES[195] = ATTR_PROMPT;
+ ATTRIBUTE_NAMES[196] = ATTR_USEMAP;
+ ATTRIBUTE_NAMES[197] = ATTR_IN;
+ ATTRIBUTE_NAMES[198] = ATTR_KERNELUNITLENGTH;
+ ATTRIBUTE_NAMES[199] = ATTR_ONEND;
+ ATTRIBUTE_NAMES[200] = ATTR_POINTSATX;
+ ATTRIBUTE_NAMES[201] = ATTR_STANDBY;
+ ATTRIBUTE_NAMES[202] = ATTR_WHEN;
+ ATTRIBUTE_NAMES[203] = ATTR_XLINK_ARCROLE;
+ ATTRIBUTE_NAMES[204] = ATTR_XLINK_SHOW;
+ ATTRIBUTE_NAMES[205] = ATTR_AUTOFOCUS;
+ ATTRIBUTE_NAMES[206] = ATTR_COLOR_RENDERING;
+ ATTRIBUTE_NAMES[207] = ATTR_ENCODING;
+ ATTRIBUTE_NAMES[208] = ATTR_LQUOTE;
+ ATTRIBUTE_NAMES[209] = ATTR_ONMOUSEWHEEL;
+ ATTRIBUTE_NAMES[210] = ATTR_ONCONTEXTMENU;
+ ATTRIBUTE_NAMES[211] = ATTR_ONMOUSEMOVE;
+ ATTRIBUTE_NAMES[212] = ATTR_ONFOCUSOUT;
+ ATTRIBUTE_NAMES[213] = ATTR_STROKE_LINECAP;
+ ATTRIBUTE_NAMES[214] = ATTR_STROKE_MITERLIMIT;
+ ATTRIBUTE_NAMES[215] = ATTR_STROKE_OPACITY;
+ ATTRIBUTE_NAMES[216] = ATTR_CLIP_PATH;
+ ATTRIBUTE_NAMES[217] = ATTR_GLYPH_ORIENTATION_VERTICAL;
+ ATTRIBUTE_NAMES[218] = ATTR_KEYPOINTS;
+ ATTRIBUTE_NAMES[219] = ATTR_STEP;
+ ATTRIBUTE_NAMES[220] = ATTR_SLOPE;
+ ATTRIBUTE_NAMES[221] = ATTR_WRAP;
+ ATTRIBUTE_NAMES[222] = ATTR_CHAR;
+ ATTRIBUTE_NAMES[223] = ATTR_NOWRAP;
+ ATTRIBUTE_NAMES[224] = ATTR_ONDRAGOVER;
+ ATTRIBUTE_NAMES[225] = ATTR_ONERROR;
+ ATTRIBUTE_NAMES[226] = ATTR_ONDRAGLEAVE;
+ ATTRIBUTE_NAMES[227] = ATTR_AXIS;
+ ATTRIBUTE_NAMES[228] = ATTR_CROSSORIGIN;
+ ATTRIBUTE_NAMES[229] = ATTR_CLOSE;
+ ATTRIBUTE_NAMES[230] = ATTR_KEYSPLINES;
+ ATTRIBUTE_NAMES[231] = ATTR_OFFSET;
+ ATTRIBUTE_NAMES[232] = ATTR_ROWSPACING;
+ ATTRIBUTE_NAMES[233] = ATTR_VERSION;
+ ATTRIBUTE_NAMES[234] = ATTR_CONTENT;
+ ATTRIBUTE_NAMES[235] = ATTR_FONT_STRETCH;
+ ATTRIBUTE_NAMES[236] = ATTR_FONTSTYLE;
+ ATTRIBUTE_NAMES[237] = ATTR_FONT_VARIANT;
+ ATTRIBUTE_NAMES[238] = ATTR_FONT_SIZE;
+ ATTRIBUTE_NAMES[239] = ATTR_MULTIPLE;
+ ATTRIBUTE_NAMES[240] = ATTR_POSTER;
+ ATTRIBUTE_NAMES[241] = ATTR_PATTERNCONTENTUNITS;
+ ATTRIBUTE_NAMES[242] = ATTR_TEXT_RENDERING;
+ ATTRIBUTE_NAMES[243] = ATTR_TEXT;
+ ATTRIBUTE_NAMES[244] = ATTR_COLUMNSPAN;
+ ATTRIBUTE_NAMES[245] = ATTR_COLUMNWIDTH;
+ ATTRIBUTE_NAMES[246] = ATTR_ONCUT;
+ ATTRIBUTE_NAMES[247] = ATTR_REQUIREDEXTENSIONS;
+ ATTRIBUTE_NAMES[248] = ATTR_ELEVATION;
+ ATTRIBUTE_NAMES[249] = ATTR_CX;
+ ATTRIBUTE_NAMES[250] = ATTR_FX;
+ ATTRIBUTE_NAMES[251] = ATTR_REFX;
+ ATTRIBUTE_NAMES[252] = ATTR_CY;
+ ATTRIBUTE_NAMES[253] = ATTR_FY;
+ ATTRIBUTE_NAMES[254] = ATTR_REFY;
+ ATTRIBUTE_NAMES[255] = ATTR_ALT;
+ ATTRIBUTE_NAMES[256] = ATTR_DUR;
+ ATTRIBUTE_NAMES[257] = ATTR_FOR;
+ ATTRIBUTE_NAMES[258] = ATTR_LOW;
+ ATTRIBUTE_NAMES[259] = ATTR_MAX;
+ ATTRIBUTE_NAMES[260] = ATTR_REV;
+ ATTRIBUTE_NAMES[261] = ATTR_D;
+ ATTRIBUTE_NAMES[262] = ATTR_X;
+ ATTRIBUTE_NAMES[263] = ATTR_Z;
+ ATTRIBUTE_NAMES[264] = ATTR_X1;
+ ATTRIBUTE_NAMES[265] = ATTR_K2;
+ ATTRIBUTE_NAMES[266] = ATTR_Y2;
+ ATTRIBUTE_NAMES[267] = ATTR_K4;
+ ATTRIBUTE_NAMES[268] = ATTR_XML_LANG;
+ ATTRIBUTE_NAMES[269] = ATTR_ARIA_VALUEMAX;
+ ATTRIBUTE_NAMES[270] = ATTR_ARIA_DESCRIBEDBY;
+ ATTRIBUTE_NAMES[271] = ATTR_ARIA_CHECKED;
+ ATTRIBUTE_NAMES[272] = ATTR_ARIA_DROPEFFECT;
+ ATTRIBUTE_NAMES[273] = ATTR_ARIA_EXPANDED;
+ ATTRIBUTE_NAMES[274] = ATTR_ARIA_LEVEL;
+ ATTRIBUTE_NAMES[275] = ATTR_ARIA_HIDDEN;
+ ATTRIBUTE_NAMES[276] = ATTR_ARIA_POSINSET;
+ ATTRIBUTE_NAMES[277] = ATTR_ARIA_INVALID;
+ ATTRIBUTE_NAMES[278] = ATTR_ARIA_VALUEMIN;
+ ATTRIBUTE_NAMES[279] = ATTR_ARIA_CONTROLS;
+ ATTRIBUTE_NAMES[280] = ATTR_ARIA_READONLY;
+ ATTRIBUTE_NAMES[281] = ATTR_ARIA_ACTIVEDESCENDANT;
+ ATTRIBUTE_NAMES[282] = ATTR_ARIA_DATATYPE;
+ ATTRIBUTE_NAMES[283] = ATTR_ARIA_SORT;
+ ATTRIBUTE_NAMES[284] = ATTR_ARIA_FLOWTO;
+ ATTRIBUTE_NAMES[285] = ATTR_ARIA_LIVE;
+ ATTRIBUTE_NAMES[286] = ATTR_ARIA_SETSIZE;
+ ATTRIBUTE_NAMES[287] = ATTR_DISABLED;
+ ATTRIBUTE_NAMES[288] = ATTR_DATA;
+ ATTRIBUTE_NAMES[289] = ATTR_EQUALROWS;
+ ATTRIBUTE_NAMES[290] = ATTR_ISMAP;
+ ATTRIBUTE_NAMES[291] = ATTR_LSPACE;
+ ATTRIBUTE_NAMES[292] = ATTR_NOTATION;
+ ATTRIBUTE_NAMES[293] = ATTR_ONPASTE;
+ ATTRIBUTE_NAMES[294] = ATTR_ROWALIGN;
+ ATTRIBUTE_NAMES[295] = ATTR_SEPARATOR;
+ ATTRIBUTE_NAMES[296] = ATTR_VSPACE;
+ ATTRIBUTE_NAMES[297] = ATTR_YCHANNELSELECTOR;
+ ATTRIBUTE_NAMES[298] = ATTR_ONDBLCLICK;
+ ATTRIBUTE_NAMES[299] = ATTR_CALCMODE;
+ ATTRIBUTE_NAMES[300] = ATTR_FENCE;
+ ATTRIBUTE_NAMES[301] = ATTR_ONACTIVATE;
+ ATTRIBUTE_NAMES[302] = ATTR_SPACING;
+ ATTRIBUTE_NAMES[303] = ATTR_SPECULARCONSTANT;
+ ATTRIBUTE_NAMES[304] = ATTR_ID;
+ ATTRIBUTE_NAMES[305] = ATTR_GRADIENTUNITS;
+ ATTRIBUTE_NAMES[306] = ATTR_HEADERS;
+ ATTRIBUTE_NAMES[307] = ATTR_READONLY;
+ ATTRIBUTE_NAMES[308] = ATTR_SEED;
+ ATTRIBUTE_NAMES[309] = ATTR_STDDEVIATION;
+ ATTRIBUTE_NAMES[310] = ATTR_WORD_SPACING;
+ ATTRIBUTE_NAMES[311] = ATTR_ACCEPT_CHARSET;
+ ATTRIBUTE_NAMES[312] = ATTR_ACCENT;
+ ATTRIBUTE_NAMES[313] = ATTR_BEVELLED;
+ ATTRIBUTE_NAMES[314] = ATTR_BASELINE_SHIFT;
+ ATTRIBUTE_NAMES[315] = ATTR_BASELINE;
+ ATTRIBUTE_NAMES[316] = ATTR_CODE;
+ ATTRIBUTE_NAMES[317] = ATTR_CODEBASE;
+ ATTRIBUTE_NAMES[318] = ATTR_DEFER;
+ ATTRIBUTE_NAMES[319] = ATTR_DIRECTION;
+ ATTRIBUTE_NAMES[320] = ATTR_EDGE;
+ ATTRIBUTE_NAMES[321] = ATTR_FACE;
+ ATTRIBUTE_NAMES[322] = ATTR_INTERCEPT;
+ ATTRIBUTE_NAMES[323] = ATTR_LINEBREAK;
+ ATTRIBUTE_NAMES[324] = ATTR_LINETHICKNESS;
+ ATTRIBUTE_NAMES[325] = ATTR_NAME;
+ ATTRIBUTE_NAMES[326] = ATTR_ONBEFOREUNLOAD;
+ ATTRIBUTE_NAMES[327] = ATTR_OBJECT;
+ ATTRIBUTE_NAMES[328] = ATTR_ORDER;
+ ATTRIBUTE_NAMES[329] = ATTR_ONRESET;
+ ATTRIBUTE_NAMES[330] = ATTR_ONMESSAGE;
+ ATTRIBUTE_NAMES[331] = ATTR_ONBEFOREPRINT;
+ ATTRIBUTE_NAMES[332] = ATTR_ORIENTATION;
+ ATTRIBUTE_NAMES[333] = ATTR_ONSELECTSTART;
+ ATTRIBUTE_NAMES[334] = ATTR_ONKEYPRESS;
+ ATTRIBUTE_NAMES[335] = ATTR_ONBEFORECUT;
+ ATTRIBUTE_NAMES[336] = ATTR_ONRESIZE;
+ ATTRIBUTE_NAMES[337] = ATTR_REFERRERPOLICY;
+ ATTRIBUTE_NAMES[338] = ATTR_ROLE;
+ ATTRIBUTE_NAMES[339] = ATTR_REPEATDUR;
+ ATTRIBUTE_NAMES[340] = ATTR_SIZES;
+ ATTRIBUTE_NAMES[341] = ATTR_STRETCHY;
+ ATTRIBUTE_NAMES[342] = ATTR_SPREADMETHOD;
+ ATTRIBUTE_NAMES[343] = ATTR_SIZE;
+ ATTRIBUTE_NAMES[344] = ATTR_DIFFUSECONSTANT;
+ ATTRIBUTE_NAMES[345] = ATTR_HREFLANG;
+ ATTRIBUTE_NAMES[346] = ATTR_PROFILE;
+ ATTRIBUTE_NAMES[347] = ATTR_XREF;
+ ATTRIBUTE_NAMES[348] = ATTR_ALIGNMENT_BASELINE;
+ ATTRIBUTE_NAMES[349] = ATTR_DRAGGABLE;
+ ATTRIBUTE_NAMES[350] = ATTR_IMAGESIZES;
+ ATTRIBUTE_NAMES[351] = ATTR_IMAGE_RENDERING;
+ ATTRIBUTE_NAMES[352] = ATTR_LANG;
+ ATTRIBUTE_NAMES[353] = ATTR_LONGDESC;
+ ATTRIBUTE_NAMES[354] = ATTR_MARGINHEIGHT;
+ ATTRIBUTE_NAMES[355] = ATTR_ORIGIN;
+ ATTRIBUTE_NAMES[356] = ATTR_TARGET;
+ ATTRIBUTE_NAMES[357] = ATTR_TARGETY;
+ ATTRIBUTE_NAMES[358] = ATTR_HIGH;
+ ATTRIBUTE_NAMES[359] = ATTR_MATHBACKGROUND;
+ ATTRIBUTE_NAMES[360] = ATTR_MATHVARIANT;
+ ATTRIBUTE_NAMES[361] = ATTR_MATHSIZE;
+ ATTRIBUTE_NAMES[362] = ATTR_ONCHANGE;
+ ATTRIBUTE_NAMES[363] = ATTR_PATH;
+ ATTRIBUTE_NAMES[364] = ATTR_ACTIONTYPE;
+ ATTRIBUTE_NAMES[365] = ATTR_ACTIVE;
+ ATTRIBUTE_NAMES[366] = ATTR_BEGIN;
+ ATTRIBUTE_NAMES[367] = ATTR_DIVISOR;
+ ATTRIBUTE_NAMES[368] = ATTR_LIMITINGCONEANGLE;
+ ATTRIBUTE_NAMES[369] = ATTR_MANIFEST;
+ ATTRIBUTE_NAMES[370] = ATTR_OPTIMUM;
+ ATTRIBUTE_NAMES[371] = ATTR_RADIUS;
+ ATTRIBUTE_NAMES[372] = ATTR_SCRIPTSIZEMULTIPLIER;
+ ATTRIBUTE_NAMES[373] = ATTR_TABINDEX;
+ ATTRIBUTE_NAMES[374] = ATTR_VISIBILITY;
+ ATTRIBUTE_NAMES[375] = ATTR_LINK;
+ ATTRIBUTE_NAMES[376] = ATTR_MARKERHEIGHT;
+ ATTRIBUTE_NAMES[377] = ATTR_MASK;
+ ATTRIBUTE_NAMES[378] = ATTR_MARKERWIDTH;
+ ATTRIBUTE_NAMES[379] = ATTR_MARKERUNITS;
+ ATTRIBUTE_NAMES[380] = ATTR_AMPLITUDE;
+ ATTRIBUTE_NAMES[381] = ATTR_CELLPADDING;
+ ATTRIBUTE_NAMES[382] = ATTR_FILL_RULE;
+ ATTRIBUTE_NAMES[383] = ATTR_FILL_OPACITY;
+ ATTRIBUTE_NAMES[384] = ATTR_ONCLICK;
+ ATTRIBUTE_NAMES[385] = ATTR_REPLACE;
+ ATTRIBUTE_NAMES[386] = ATTR_SCALE;
+ ATTRIBUTE_NAMES[387] = ATTR_TABLEVALUES;
+ ATTRIBUTE_NAMES[388] = ATTR_AZIMUTH;
+ ATTRIBUTE_NAMES[389] = ATTR_FRAMEBORDER;
+ ATTRIBUTE_NAMES[390] = ATTR_FRAMESPACING;
+ ATTRIBUTE_NAMES[391] = ATTR_FORM;
+ ATTRIBUTE_NAMES[392] = ATTR_PRIMITIVEUNITS;
+ ATTRIBUTE_NAMES[393] = ATTR_SUMMARY;
+ ATTRIBUTE_NAMES[394] = ATTR_ZOOMANDPAN;
+ ATTRIBUTE_NAMES[395] = ATTR_ALINK;
+ ATTRIBUTE_NAMES[396] = ATTR_ICON;
+ ATTRIBUTE_NAMES[397] = ATTR_KERNING;
+ ATTRIBUTE_NAMES[398] = ATTR_ONUNLOAD;
+ ATTRIBUTE_NAMES[399] = ATTR_ONINVALID;
+ ATTRIBUTE_NAMES[400] = ATTR_ONINPUT;
+ ATTRIBUTE_NAMES[401] = ATTR_POINTS;
+ ATTRIBUTE_NAMES[402] = ATTR_POINTSATY;
+ ATTRIBUTE_NAMES[403] = ATTR_SPAN;
+ ATTRIBUTE_NAMES[404] = ATTR_TRANSFORM_ORIGIN;
+ ATTRIBUTE_NAMES[405] = ATTR_VLINK;
+ ATTRIBUTE_NAMES[406] = ATTR_XLINK_HREF;
+ ATTRIBUTE_NAMES[407] = ATTR_XLINK_ROLE;
+ ATTRIBUTE_NAMES[408] = ATTR_XMLNS_XLINK;
+ ATTRIBUTE_NAMES[409] = ATTR_XLINK_TYPE;
+ ATTRIBUTE_NAMES[410] = ATTR_XLINK_ACTUATE;
+ ATTRIBUTE_NAMES[411] = ATTR_AUTOCOMPLETE;
+ ATTRIBUTE_NAMES[412] = ATTR_AUTOCAPITALIZE;
+ ATTRIBUTE_NAMES[413] = ATTR_COLOR_PROFILE;
+ ATTRIBUTE_NAMES[414] = ATTR_COLOR_INTERPOLATION;
+ ATTRIBUTE_NAMES[415] = ATTR_COLOR_INTERPOLATION_FILTERS;
+ ATTRIBUTE_NAMES[416] = ATTR_EXPONENT;
+ ATTRIBUTE_NAMES[417] = ATTR_FLOOD_OPACITY;
+ ATTRIBUTE_NAMES[418] = ATTR_NUMOCTAVES;
+ ATTRIBUTE_NAMES[419] = ATTR_ONLOAD;
+ ATTRIBUTE_NAMES[420] = ATTR_ONMOUSEENTER;
+ ATTRIBUTE_NAMES[421] = ATTR_ONFOCUSIN;
+ ATTRIBUTE_NAMES[422] = ATTR_ONZOOM;
+ ATTRIBUTE_NAMES[423] = ATTR_ONMOUSELEAVE;
+ ATTRIBUTE_NAMES[424] = ATTR_ONMOUSEUP;
+ ATTRIBUTE_NAMES[425] = ATTR_ONMOUSEOUT;
+ ATTRIBUTE_NAMES[426] = ATTR_ONMOUSEDOWN;
+ ATTRIBUTE_NAMES[427] = ATTR_RQUOTE;
+ ATTRIBUTE_NAMES[428] = ATTR_STROKE_DASHARRAY;
+ ATTRIBUTE_NAMES[429] = ATTR_STROKE_LINEJOIN;
+ ATTRIBUTE_NAMES[430] = ATTR_STROKE;
+ ATTRIBUTE_NAMES[431] = ATTR_STROKE_WIDTH;
+ ATTRIBUTE_NAMES[432] = ATTR_COMPACT;
+ ATTRIBUTE_NAMES[433] = ATTR_CLIP_RULE;
+ ATTRIBUTE_NAMES[434] = ATTR_CLIPPATHUNITS;
+ ATTRIBUTE_NAMES[435] = ATTR_DISPLAYSTYLE;
+ ATTRIBUTE_NAMES[436] = ATTR_GLYPH_ORIENTATION_HORIZONTAL;
+ ATTRIBUTE_NAMES[437] = ATTR_HTTP_EQUIV;
+ ATTRIBUTE_NAMES[438] = ATTR_LOOP;
+ ATTRIBUTE_NAMES[439] = ATTR_SCOPED;
+ ATTRIBUTE_NAMES[440] = ATTR_SHAPE_RENDERING;
+ ATTRIBUTE_NAMES[441] = ATTR_SHAPE;
+ ATTRIBUTE_NAMES[442] = ATTR_STOP_COLOR;
+ ATTRIBUTE_NAMES[443] = ATTR_TEMPLATE;
+ ATTRIBUTE_NAMES[444] = ATTR_ABBR;
+ ATTRIBUTE_NAMES[445] = ATTR_ATTRIBUTETYPE;
+ ATTRIBUTE_NAMES[446] = ATTR_COORDS;
+ ATTRIBUTE_NAMES[447] = ATTR_CHARSET;
+ ATTRIBUTE_NAMES[448] = ATTR_NOHREF;
+ ATTRIBUTE_NAMES[449] = ATTR_ONDRAGENTER;
+ ATTRIBUTE_NAMES[450] = ATTR_ONDRAGEND;
+ ATTRIBUTE_NAMES[451] = ATTR_ONDRAGDROP;
+ ATTRIBUTE_NAMES[452] = ATTR_OPERATOR;
+ ATTRIBUTE_NAMES[453] = ATTR_ONDRAGSTART;
+ ATTRIBUTE_NAMES[454] = ATTR_STARTOFFSET;
+ ATTRIBUTE_NAMES[455] = ATTR_AS;
+ ATTRIBUTE_NAMES[456] = ATTR_BIAS;
+ ATTRIBUTE_NAMES[457] = ATTR_CLASSID;
+ ATTRIBUTE_NAMES[458] = ATTR_COLS;
+ ATTRIBUTE_NAMES[459] = ATTR_CLOSURE;
+ ATTRIBUTE_NAMES[460] = ATTR_CLASS;
+ ATTRIBUTE_NAMES[461] = ATTR_KEYSYSTEM;
+ ATTRIBUTE_NAMES[462] = ATTR_LOWSRC;
+ ATTRIBUTE_NAMES[463] = ATTR_MINSIZE;
+ ATTRIBUTE_NAMES[464] = ATTR_PRESERVEALPHA;
+ ATTRIBUTE_NAMES[465] = ATTR_ROWSPAN;
+ ATTRIBUTE_NAMES[466] = ATTR_ROWS;
+ ATTRIBUTE_NAMES[467] = ATTR_SUBSCRIPTSHIFT;
+ ATTRIBUTE_NAMES[468] = ATTR_ALTTEXT;
+ ATTRIBUTE_NAMES[469] = ATTR_CONTROLS;
+ ATTRIBUTE_NAMES[470] = ATTR_CONTEXTMENU;
+ ATTRIBUTE_NAMES[471] = ATTR_ENCTYPE;
+ ATTRIBUTE_NAMES[472] = ATTR_FILTER;
+ ATTRIBUTE_NAMES[473] = ATTR_FONT_WEIGHT;
+ ATTRIBUTE_NAMES[474] = ATTR_FONT_STYLE;
+ ATTRIBUTE_NAMES[475] = ATTR_FONT_FAMILY;
+ ATTRIBUTE_NAMES[476] = ATTR_FONT_SIZE_ADJUST;
+ ATTRIBUTE_NAMES[477] = ATTR_FONTSIZE;
+ ATTRIBUTE_NAMES[478] = ATTR_KEYTIMES;
+ ATTRIBUTE_NAMES[479] = ATTR_LIST;
+ ATTRIBUTE_NAMES[480] = ATTR_RT;
+ ATTRIBUTE_NAMES[481] = ATTR_ONSTART;
+ ATTRIBUTE_NAMES[482] = ATTR_PATTERNTRANSFORM;
+ ATTRIBUTE_NAMES[483] = ATTR_PATTERNUNITS;
+ ATTRIBUTE_NAMES[484] = ATTR_RESTART;
+ ATTRIBUTE_NAMES[485] = ATTR_SYSTEMLANGUAGE;
+ ATTRIBUTE_NAMES[486] = ATTR_TEXT_DECORATION;
+ ATTRIBUTE_NAMES[487] = ATTR_TEXTLENGTH;
+ ATTRIBUTE_NAMES[488] = ATTR_WRITING_MODE;
+ ATTRIBUTE_NAMES[489] = ATTR_ACCUMULATE;
+ ATTRIBUTE_NAMES[490] = ATTR_COLUMNLINES;
+ ATTRIBUTE_NAMES[491] = ATTR_COLUMNSPACING;
+ ATTRIBUTE_NAMES[492] = ATTR_GROUPALIGN;
+ ATTRIBUTE_NAMES[493] = ATTR_ONSUBMIT;
+ ATTRIBUTE_NAMES[494] = ATTR_REQUIRED;
+ ATTRIBUTE_NAMES[495] = ATTR_RESULT;
+ ATTRIBUTE_NAMES[496] = ATTR_VALUES;
+ ATTRIBUTE_NAMES[497] = ATTR_VALUE;
+ ATTRIBUTE_NAMES[498] = ATTR_VIEWTARGET;
+}
+
+void nsHtml5AttributeName::releaseStatics() {
+ delete[] ALL_NO_NS;
+ delete[] XMLNS_NS;
+ delete[] XML_NS;
+ delete[] XLINK_NS;
+ delete[] ALL_NO_PREFIX;
+ delete[] XMLNS_PREFIX;
+ delete[] XLINK_PREFIX;
+ delete[] XML_PREFIX;
+ delete ATTR_ALT;
+ delete ATTR_DIR;
+ delete ATTR_DUR;
+ delete ATTR_END;
+ delete ATTR_FOR;
+ delete ATTR_IN2;
+ delete ATTR_LOW;
+ delete ATTR_MIN;
+ delete ATTR_MAX;
+ delete ATTR_REL;
+ delete ATTR_REV;
+ delete ATTR_SRC;
+ delete ATTR_D;
+ delete ATTR_R;
+ delete ATTR_X;
+ delete ATTR_Y;
+ delete ATTR_Z;
+ delete ATTR_K1;
+ delete ATTR_X1;
+ delete ATTR_Y1;
+ delete ATTR_K2;
+ delete ATTR_X2;
+ delete ATTR_Y2;
+ delete ATTR_K3;
+ delete ATTR_K4;
+ delete ATTR_XML_SPACE;
+ delete ATTR_XML_LANG;
+ delete ATTR_ARIA_GRAB;
+ delete ATTR_ARIA_VALUEMAX;
+ delete ATTR_ARIA_LABELLEDBY;
+ delete ATTR_ARIA_DESCRIBEDBY;
+ delete ATTR_ARIA_DISABLED;
+ delete ATTR_ARIA_CHECKED;
+ delete ATTR_ARIA_SELECTED;
+ delete ATTR_ARIA_DROPEFFECT;
+ delete ATTR_ARIA_REQUIRED;
+ delete ATTR_ARIA_EXPANDED;
+ delete ATTR_ARIA_PRESSED;
+ delete ATTR_ARIA_LEVEL;
+ delete ATTR_ARIA_CHANNEL;
+ delete ATTR_ARIA_HIDDEN;
+ delete ATTR_ARIA_SECRET;
+ delete ATTR_ARIA_POSINSET;
+ delete ATTR_ARIA_ATOMIC;
+ delete ATTR_ARIA_INVALID;
+ delete ATTR_ARIA_TEMPLATEID;
+ delete ATTR_ARIA_VALUEMIN;
+ delete ATTR_ARIA_MULTISELECTABLE;
+ delete ATTR_ARIA_CONTROLS;
+ delete ATTR_ARIA_MULTILINE;
+ delete ATTR_ARIA_READONLY;
+ delete ATTR_ARIA_OWNS;
+ delete ATTR_ARIA_ACTIVEDESCENDANT;
+ delete ATTR_ARIA_RELEVANT;
+ delete ATTR_ARIA_DATATYPE;
+ delete ATTR_ARIA_VALUENOW;
+ delete ATTR_ARIA_SORT;
+ delete ATTR_ARIA_AUTOCOMPLETE;
+ delete ATTR_ARIA_FLOWTO;
+ delete ATTR_ARIA_BUSY;
+ delete ATTR_ARIA_LIVE;
+ delete ATTR_ARIA_HASPOPUP;
+ delete ATTR_ARIA_SETSIZE;
+ delete ATTR_CLEAR;
+ delete ATTR_DISABLED;
+ delete ATTR_DEFAULT;
+ delete ATTR_DATA;
+ delete ATTR_EQUALCOLUMNS;
+ delete ATTR_EQUALROWS;
+ delete ATTR_HSPACE;
+ delete ATTR_ISMAP;
+ delete ATTR_LOCAL;
+ delete ATTR_LSPACE;
+ delete ATTR_MOVABLELIMITS;
+ delete ATTR_NOTATION;
+ delete ATTR_ONDATAAVAILABLE;
+ delete ATTR_ONPASTE;
+ delete ATTR_RSPACE;
+ delete ATTR_ROWALIGN;
+ delete ATTR_ROTATE;
+ delete ATTR_SEPARATOR;
+ delete ATTR_SEPARATORS;
+ delete ATTR_VSPACE;
+ delete ATTR_XCHANNELSELECTOR;
+ delete ATTR_YCHANNELSELECTOR;
+ delete ATTR_ENABLE_BACKGROUND;
+ delete ATTR_ONDBLCLICK;
+ delete ATTR_ONABORT;
+ delete ATTR_CALCMODE;
+ delete ATTR_CHECKED;
+ delete ATTR_FENCE;
+ delete ATTR_ONSCROLL;
+ delete ATTR_ONACTIVATE;
+ delete ATTR_OPACITY;
+ delete ATTR_SPACING;
+ delete ATTR_SPECULAREXPONENT;
+ delete ATTR_SPECULARCONSTANT;
+ delete ATTR_BORDER;
+ delete ATTR_ID;
+ delete ATTR_GRADIENTTRANSFORM;
+ delete ATTR_GRADIENTUNITS;
+ delete ATTR_HIDDEN;
+ delete ATTR_HEADERS;
+ delete ATTR_LOADING;
+ delete ATTR_READONLY;
+ delete ATTR_RENDERING_INTENT;
+ delete ATTR_SEED;
+ delete ATTR_SRCDOC;
+ delete ATTR_STDDEVIATION;
+ delete ATTR_SANDBOX;
+ delete ATTR_WORD_SPACING;
+ delete ATTR_ACCENTUNDER;
+ delete ATTR_ACCEPT_CHARSET;
+ delete ATTR_ACCESSKEY;
+ delete ATTR_ACCENT;
+ delete ATTR_ACCEPT;
+ delete ATTR_BEVELLED;
+ delete ATTR_BASEFREQUENCY;
+ delete ATTR_BASELINE_SHIFT;
+ delete ATTR_BASEPROFILE;
+ delete ATTR_BASELINE;
+ delete ATTR_BASE;
+ delete ATTR_CODE;
+ delete ATTR_CODETYPE;
+ delete ATTR_CODEBASE;
+ delete ATTR_CITE;
+ delete ATTR_DEFER;
+ delete ATTR_DATETIME;
+ delete ATTR_DIRECTION;
+ delete ATTR_EDGEMODE;
+ delete ATTR_EDGE;
+ delete ATTR_ENTERKEYHINT;
+ delete ATTR_FACE;
+ delete ATTR_INDEX;
+ delete ATTR_INTERCEPT;
+ delete ATTR_INTEGRITY;
+ delete ATTR_LINEBREAK;
+ delete ATTR_LABEL;
+ delete ATTR_LINETHICKNESS;
+ delete ATTR_MODE;
+ delete ATTR_NAME;
+ delete ATTR_NORESIZE;
+ delete ATTR_ONBEFOREUNLOAD;
+ delete ATTR_ONREPEAT;
+ delete ATTR_OBJECT;
+ delete ATTR_ONSELECT;
+ delete ATTR_ORDER;
+ delete ATTR_OTHER;
+ delete ATTR_ONRESET;
+ delete ATTR_ONREADYSTATECHANGE;
+ delete ATTR_ONMESSAGE;
+ delete ATTR_ONBEGIN;
+ delete ATTR_ONBEFOREPRINT;
+ delete ATTR_ORIENT;
+ delete ATTR_ORIENTATION;
+ delete ATTR_ONBEFORECOPY;
+ delete ATTR_ONSELECTSTART;
+ delete ATTR_ONBEFOREPASTE;
+ delete ATTR_ONKEYPRESS;
+ delete ATTR_ONKEYUP;
+ delete ATTR_ONBEFORECUT;
+ delete ATTR_ONKEYDOWN;
+ delete ATTR_ONRESIZE;
+ delete ATTR_REPEAT;
+ delete ATTR_REFERRERPOLICY;
+ delete ATTR_RULES;
+ delete ATTR_ROLE;
+ delete ATTR_REPEATCOUNT;
+ delete ATTR_REPEATDUR;
+ delete ATTR_SELECTED;
+ delete ATTR_SIZES;
+ delete ATTR_SUPERSCRIPTSHIFT;
+ delete ATTR_STRETCHY;
+ delete ATTR_SCHEME;
+ delete ATTR_SPREADMETHOD;
+ delete ATTR_SELECTION;
+ delete ATTR_SIZE;
+ delete ATTR_TYPE;
+ delete ATTR_DIFFUSECONSTANT;
+ delete ATTR_HREF;
+ delete ATTR_HREFLANG;
+ delete ATTR_ONAFTERPRINT;
+ delete ATTR_PROFILE;
+ delete ATTR_SURFACESCALE;
+ delete ATTR_XREF;
+ delete ATTR_ALIGN;
+ delete ATTR_ALIGNMENT_BASELINE;
+ delete ATTR_ALIGNMENTSCOPE;
+ delete ATTR_DRAGGABLE;
+ delete ATTR_HEIGHT;
+ delete ATTR_IMAGESIZES;
+ delete ATTR_IMAGESRCSET;
+ delete ATTR_IMAGE_RENDERING;
+ delete ATTR_LANGUAGE;
+ delete ATTR_LANG;
+ delete ATTR_LARGEOP;
+ delete ATTR_LONGDESC;
+ delete ATTR_LENGTHADJUST;
+ delete ATTR_MARGINHEIGHT;
+ delete ATTR_MARGINWIDTH;
+ delete ATTR_ORIGIN;
+ delete ATTR_PING;
+ delete ATTR_TARGET;
+ delete ATTR_TARGETX;
+ delete ATTR_TARGETY;
+ delete ATTR_ARCHIVE;
+ delete ATTR_HIGH;
+ delete ATTR_LIGHTING_COLOR;
+ delete ATTR_MATHBACKGROUND;
+ delete ATTR_METHOD;
+ delete ATTR_MATHVARIANT;
+ delete ATTR_MATHCOLOR;
+ delete ATTR_MATHSIZE;
+ delete ATTR_NOSHADE;
+ delete ATTR_ONCHANGE;
+ delete ATTR_PATHLENGTH;
+ delete ATTR_PATH;
+ delete ATTR_ALTIMG;
+ delete ATTR_ACTIONTYPE;
+ delete ATTR_ACTION;
+ delete ATTR_ACTIVE;
+ delete ATTR_ADDITIVE;
+ delete ATTR_BEGIN;
+ delete ATTR_DOMINANT_BASELINE;
+ delete ATTR_DIVISOR;
+ delete ATTR_DEFINITIONURL;
+ delete ATTR_LIMITINGCONEANGLE;
+ delete ATTR_MEDIA;
+ delete ATTR_MANIFEST;
+ delete ATTR_ONFINISH;
+ delete ATTR_OPTIMUM;
+ delete ATTR_RADIOGROUP;
+ delete ATTR_RADIUS;
+ delete ATTR_SCRIPTLEVEL;
+ delete ATTR_SCRIPTSIZEMULTIPLIER;
+ delete ATTR_SCRIPTMINSIZE;
+ delete ATTR_TABINDEX;
+ delete ATTR_VALIGN;
+ delete ATTR_VISIBILITY;
+ delete ATTR_BACKGROUND;
+ delete ATTR_LINK;
+ delete ATTR_MARKER_MID;
+ delete ATTR_MARKERHEIGHT;
+ delete ATTR_MARKER_END;
+ delete ATTR_MASK;
+ delete ATTR_MARKER_START;
+ delete ATTR_MARKERWIDTH;
+ delete ATTR_MASKUNITS;
+ delete ATTR_MARKERUNITS;
+ delete ATTR_MASKCONTENTUNITS;
+ delete ATTR_AMPLITUDE;
+ delete ATTR_CELLSPACING;
+ delete ATTR_CELLPADDING;
+ delete ATTR_DECLARE;
+ delete ATTR_FILL_RULE;
+ delete ATTR_FILL;
+ delete ATTR_FILL_OPACITY;
+ delete ATTR_MAXLENGTH;
+ delete ATTR_ONCLICK;
+ delete ATTR_ONBLUR;
+ delete ATTR_REPLACE;
+ delete ATTR_ROWLINES;
+ delete ATTR_SCALE;
+ delete ATTR_STYLE;
+ delete ATTR_TABLEVALUES;
+ delete ATTR_TITLE;
+ delete ATTR_AZIMUTH;
+ delete ATTR_FORMAT;
+ delete ATTR_FRAMEBORDER;
+ delete ATTR_FRAME;
+ delete ATTR_FRAMESPACING;
+ delete ATTR_FROM;
+ delete ATTR_FORM;
+ delete ATTR_PROMPT;
+ delete ATTR_PRIMITIVEUNITS;
+ delete ATTR_SYMMETRIC;
+ delete ATTR_SUMMARY;
+ delete ATTR_USEMAP;
+ delete ATTR_ZOOMANDPAN;
+ delete ATTR_ASYNC;
+ delete ATTR_ALINK;
+ delete ATTR_IN;
+ delete ATTR_ICON;
+ delete ATTR_KERNELMATRIX;
+ delete ATTR_KERNING;
+ delete ATTR_KERNELUNITLENGTH;
+ delete ATTR_ONUNLOAD;
+ delete ATTR_OPEN;
+ delete ATTR_ONINVALID;
+ delete ATTR_ONEND;
+ delete ATTR_ONINPUT;
+ delete ATTR_POINTER_EVENTS;
+ delete ATTR_POINTS;
+ delete ATTR_POINTSATX;
+ delete ATTR_POINTSATY;
+ delete ATTR_POINTSATZ;
+ delete ATTR_SPAN;
+ delete ATTR_STANDBY;
+ delete ATTR_TRANSFORM_ORIGIN;
+ delete ATTR_TRANSFORM;
+ delete ATTR_VLINK;
+ delete ATTR_WHEN;
+ delete ATTR_XLINK_HREF;
+ delete ATTR_XLINK_TITLE;
+ delete ATTR_XLINK_ROLE;
+ delete ATTR_XLINK_ARCROLE;
+ delete ATTR_XMLNS_XLINK;
+ delete ATTR_XMLNS;
+ delete ATTR_XLINK_TYPE;
+ delete ATTR_XLINK_SHOW;
+ delete ATTR_XLINK_ACTUATE;
+ delete ATTR_AUTOPLAY;
+ delete ATTR_AUTOCOMPLETE;
+ delete ATTR_AUTOFOCUS;
+ delete ATTR_AUTOCAPITALIZE;
+ delete ATTR_BGCOLOR;
+ delete ATTR_COLOR_PROFILE;
+ delete ATTR_COLOR_RENDERING;
+ delete ATTR_COLOR_INTERPOLATION;
+ delete ATTR_COLOR;
+ delete ATTR_COLOR_INTERPOLATION_FILTERS;
+ delete ATTR_ENCODING;
+ delete ATTR_EXPONENT;
+ delete ATTR_FLOOD_COLOR;
+ delete ATTR_FLOOD_OPACITY;
+ delete ATTR_LQUOTE;
+ delete ATTR_NUMOCTAVES;
+ delete ATTR_NOMODULE;
+ delete ATTR_ONLOAD;
+ delete ATTR_ONMOUSEWHEEL;
+ delete ATTR_ONMOUSEENTER;
+ delete ATTR_ONMOUSEOVER;
+ delete ATTR_ONFOCUSIN;
+ delete ATTR_ONCONTEXTMENU;
+ delete ATTR_ONZOOM;
+ delete ATTR_ONCOPY;
+ delete ATTR_ONMOUSELEAVE;
+ delete ATTR_ONMOUSEMOVE;
+ delete ATTR_ONMOUSEUP;
+ delete ATTR_ONFOCUS;
+ delete ATTR_ONMOUSEOUT;
+ delete ATTR_ONFOCUSOUT;
+ delete ATTR_ONMOUSEDOWN;
+ delete ATTR_TO;
+ delete ATTR_RQUOTE;
+ delete ATTR_STROKE_LINECAP;
+ delete ATTR_STROKE_DASHARRAY;
+ delete ATTR_STROKE_DASHOFFSET;
+ delete ATTR_STROKE_LINEJOIN;
+ delete ATTR_STROKE_MITERLIMIT;
+ delete ATTR_STROKE;
+ delete ATTR_SCROLLING;
+ delete ATTR_STROKE_WIDTH;
+ delete ATTR_STROKE_OPACITY;
+ delete ATTR_COMPACT;
+ delete ATTR_CLIP;
+ delete ATTR_CLIP_RULE;
+ delete ATTR_CLIP_PATH;
+ delete ATTR_CLIPPATHUNITS;
+ delete ATTR_DISPLAY;
+ delete ATTR_DISPLAYSTYLE;
+ delete ATTR_GLYPH_ORIENTATION_VERTICAL;
+ delete ATTR_GLYPH_ORIENTATION_HORIZONTAL;
+ delete ATTR_GLYPHREF;
+ delete ATTR_HTTP_EQUIV;
+ delete ATTR_KEYPOINTS;
+ delete ATTR_LOOP;
+ delete ATTR_PROPERTY;
+ delete ATTR_SCOPED;
+ delete ATTR_STEP;
+ delete ATTR_SHAPE_RENDERING;
+ delete ATTR_SCOPE;
+ delete ATTR_SHAPE;
+ delete ATTR_SLOPE;
+ delete ATTR_STOP_COLOR;
+ delete ATTR_STOP_OPACITY;
+ delete ATTR_TEMPLATE;
+ delete ATTR_WRAP;
+ delete ATTR_ABBR;
+ delete ATTR_ATTRIBUTENAME;
+ delete ATTR_ATTRIBUTETYPE;
+ delete ATTR_CHAR;
+ delete ATTR_COORDS;
+ delete ATTR_CHAROFF;
+ delete ATTR_CHARSET;
+ delete ATTR_NOWRAP;
+ delete ATTR_NOHREF;
+ delete ATTR_ONDRAG;
+ delete ATTR_ONDRAGENTER;
+ delete ATTR_ONDRAGOVER;
+ delete ATTR_ONDRAGEND;
+ delete ATTR_ONDROP;
+ delete ATTR_ONDRAGDROP;
+ delete ATTR_ONERROR;
+ delete ATTR_OPERATOR;
+ delete ATTR_OVERFLOW;
+ delete ATTR_ONDRAGSTART;
+ delete ATTR_ONDRAGLEAVE;
+ delete ATTR_STARTOFFSET;
+ delete ATTR_START;
+ delete ATTR_AS;
+ delete ATTR_AXIS;
+ delete ATTR_BIAS;
+ delete ATTR_COLSPAN;
+ delete ATTR_CLASSID;
+ delete ATTR_CROSSORIGIN;
+ delete ATTR_COLS;
+ delete ATTR_CURSOR;
+ delete ATTR_CLOSURE;
+ delete ATTR_CLOSE;
+ delete ATTR_CLASS;
+ delete ATTR_IS;
+ delete ATTR_KEYSYSTEM;
+ delete ATTR_KEYSPLINES;
+ delete ATTR_LOWSRC;
+ delete ATTR_MAXSIZE;
+ delete ATTR_MINSIZE;
+ delete ATTR_OFFSET;
+ delete ATTR_PRESERVEALPHA;
+ delete ATTR_PRESERVEASPECTRATIO;
+ delete ATTR_ROWSPAN;
+ delete ATTR_ROWSPACING;
+ delete ATTR_ROWS;
+ delete ATTR_SRCSET;
+ delete ATTR_SUBSCRIPTSHIFT;
+ delete ATTR_VERSION;
+ delete ATTR_ALTTEXT;
+ delete ATTR_CONTENTEDITABLE;
+ delete ATTR_CONTROLS;
+ delete ATTR_CONTENT;
+ delete ATTR_CONTEXTMENU;
+ delete ATTR_DEPTH;
+ delete ATTR_ENCTYPE;
+ delete ATTR_FONT_STRETCH;
+ delete ATTR_FILTER;
+ delete ATTR_FONTWEIGHT;
+ delete ATTR_FONT_WEIGHT;
+ delete ATTR_FONTSTYLE;
+ delete ATTR_FONT_STYLE;
+ delete ATTR_FONTFAMILY;
+ delete ATTR_FONT_FAMILY;
+ delete ATTR_FONT_VARIANT;
+ delete ATTR_FONT_SIZE_ADJUST;
+ delete ATTR_FILTERUNITS;
+ delete ATTR_FONTSIZE;
+ delete ATTR_FONT_SIZE;
+ delete ATTR_KEYTIMES;
+ delete ATTR_LETTER_SPACING;
+ delete ATTR_LIST;
+ delete ATTR_MULTIPLE;
+ delete ATTR_RT;
+ delete ATTR_ONSTOP;
+ delete ATTR_ONSTART;
+ delete ATTR_POSTER;
+ delete ATTR_PATTERNTRANSFORM;
+ delete ATTR_PATTERN;
+ delete ATTR_PATTERNUNITS;
+ delete ATTR_PATTERNCONTENTUNITS;
+ delete ATTR_RESTART;
+ delete ATTR_STITCHTILES;
+ delete ATTR_SYSTEMLANGUAGE;
+ delete ATTR_TEXT_RENDERING;
+ delete ATTR_TEXT_DECORATION;
+ delete ATTR_TEXT_ANCHOR;
+ delete ATTR_TEXTLENGTH;
+ delete ATTR_TEXT;
+ delete ATTR_WRITING_MODE;
+ delete ATTR_WIDTH;
+ delete ATTR_ACCUMULATE;
+ delete ATTR_COLUMNSPAN;
+ delete ATTR_COLUMNLINES;
+ delete ATTR_COLUMNALIGN;
+ delete ATTR_COLUMNSPACING;
+ delete ATTR_COLUMNWIDTH;
+ delete ATTR_GROUPALIGN;
+ delete ATTR_INPUTMODE;
+ delete ATTR_ONSUBMIT;
+ delete ATTR_ONCUT;
+ delete ATTR_REQUIRED;
+ delete ATTR_REQUIREDFEATURES;
+ delete ATTR_RESULT;
+ delete ATTR_REQUIREDEXTENSIONS;
+ delete ATTR_VALUES;
+ delete ATTR_VALUETYPE;
+ delete ATTR_VALUE;
+ delete ATTR_ELEVATION;
+ delete ATTR_VIEWTARGET;
+ delete ATTR_VIEWBOX;
+ delete ATTR_CX;
+ delete ATTR_DX;
+ delete ATTR_FX;
+ delete ATTR_RX;
+ delete ATTR_REFX;
+ delete ATTR_BY;
+ delete ATTR_CY;
+ delete ATTR_DY;
+ delete ATTR_FY;
+ delete ATTR_RY;
+ delete ATTR_REFY;
+ delete[] ATTRIBUTE_NAMES;
+}
diff --git a/parser/html/nsHtml5AttributeName.h b/parser/html/nsHtml5AttributeName.h
new file mode 100644
index 0000000000..a6efc82786
--- /dev/null
+++ b/parser/html/nsHtml5AttributeName.h
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit AttributeName.java instead and regenerate.
+ */
+
+#ifndef nsHtml5AttributeName_h
+#define nsHtml5AttributeName_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5ElementName;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5AttributeName {
+ public:
+ static int32_t* ALL_NO_NS;
+
+ private:
+ static int32_t* XMLNS_NS;
+ static int32_t* XML_NS;
+ static int32_t* XLINK_NS;
+
+ public:
+ static nsStaticAtom** ALL_NO_PREFIX;
+
+ private:
+ static nsStaticAtom** XMLNS_PREFIX;
+ static nsStaticAtom** XLINK_PREFIX;
+ static nsStaticAtom** XML_PREFIX;
+ static RefPtr<nsAtom>* SVG_DIFFERENT(nsAtom* name, nsAtom* camel);
+ static RefPtr<nsAtom>* MATH_DIFFERENT(nsAtom* name, nsAtom* camel);
+ static RefPtr<nsAtom>* COLONIFIED_LOCAL(nsAtom* name, nsAtom* suffix);
+
+ public:
+ static RefPtr<nsAtom>* SAME_LOCAL(nsAtom* name);
+ inline static int32_t levelOrderBinarySearch(jArray<int32_t, int32_t> data,
+ int32_t key) {
+ int32_t n = data.length;
+ int32_t i = 0;
+ while (i < n) {
+ int32_t val = data[i];
+ if (val < key) {
+ i = 2 * i + 2;
+ } else if (val > key) {
+ i = 2 * i + 1;
+ } else {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ inline static nsHtml5AttributeName* nameByBuffer(char16_t* buf,
+ int32_t length,
+ nsHtml5AtomTable* interner) {
+ uint32_t hash = nsHtml5AttributeName::bufToHash(buf, length);
+ jArray<int32_t, int32_t> hashes;
+ hashes = nsHtml5AttributeName::ATTRIBUTE_HASHES;
+ int32_t index = levelOrderBinarySearch(hashes, hash);
+ if (index < 0) {
+ return nullptr;
+ }
+ nsHtml5AttributeName* attributeName =
+ nsHtml5AttributeName::ATTRIBUTE_NAMES[index];
+ nsAtom* name = attributeName->getLocal(0);
+ if (!nsHtml5Portability::localEqualsBuffer(name, buf, length)) {
+ return nullptr;
+ }
+ return attributeName;
+ }
+
+ private:
+ inline static uint32_t bufToHash(char16_t* buf, int32_t length) {
+ uint32_t len = length;
+ uint32_t first = buf[0];
+ first <<= 19;
+ uint32_t second = 1 << 23;
+ uint32_t third = 0;
+ uint32_t fourth = 0;
+ uint32_t fifth = 0;
+ uint32_t sixth = 0;
+ if (length >= 4) {
+ second = buf[length - 4];
+ second <<= 4;
+ third = buf[1];
+ third <<= 9;
+ fourth = buf[length - 2];
+ fourth <<= 14;
+ fifth = buf[3];
+ fifth <<= 24;
+ sixth = buf[length - 1];
+ sixth <<= 11;
+ } else if (length == 3) {
+ second = buf[1];
+ second <<= 4;
+ third = buf[2];
+ third <<= 9;
+ } else if (length == 2) {
+ second = buf[1];
+ second <<= 24;
+ }
+ return len + first + second + third + fourth + fifth + sixth;
+ }
+
+ public:
+ static const int32_t HTML = 0;
+
+ static const int32_t MATHML = 1;
+
+ static const int32_t SVG = 2;
+
+ private:
+ int32_t* uri;
+ RefPtr<nsAtom>* local;
+ nsStaticAtom** prefix;
+ bool custom;
+ nsHtml5AttributeName(int32_t* uri, RefPtr<nsAtom>* local,
+ nsStaticAtom** prefix);
+
+ public:
+ nsHtml5AttributeName();
+ inline bool isInterned() { return !custom; }
+
+ inline void setNameForNonInterned(nsAtom* name) {
+ MOZ_ASSERT(custom);
+ local[0] = name;
+ local[1] = name;
+ local[2] = name;
+ }
+
+ static nsHtml5AttributeName* createAttributeName(nsAtom* name);
+ ~nsHtml5AttributeName();
+ int32_t getUri(int32_t mode);
+ nsAtom* getLocal(int32_t mode);
+ nsStaticAtom* getPrefix(int32_t mode);
+ bool equalsAnother(nsHtml5AttributeName* another);
+ static nsHtml5AttributeName* ATTR_ALT;
+ static nsHtml5AttributeName* ATTR_DIR;
+ static nsHtml5AttributeName* ATTR_DUR;
+ static nsHtml5AttributeName* ATTR_END;
+ static nsHtml5AttributeName* ATTR_FOR;
+ static nsHtml5AttributeName* ATTR_IN2;
+ static nsHtml5AttributeName* ATTR_LOW;
+ static nsHtml5AttributeName* ATTR_MIN;
+ static nsHtml5AttributeName* ATTR_MAX;
+ static nsHtml5AttributeName* ATTR_REL;
+ static nsHtml5AttributeName* ATTR_REV;
+ static nsHtml5AttributeName* ATTR_SRC;
+ static nsHtml5AttributeName* ATTR_D;
+ static nsHtml5AttributeName* ATTR_R;
+ static nsHtml5AttributeName* ATTR_X;
+ static nsHtml5AttributeName* ATTR_Y;
+ static nsHtml5AttributeName* ATTR_Z;
+ static nsHtml5AttributeName* ATTR_K1;
+ static nsHtml5AttributeName* ATTR_X1;
+ static nsHtml5AttributeName* ATTR_Y1;
+ static nsHtml5AttributeName* ATTR_K2;
+ static nsHtml5AttributeName* ATTR_X2;
+ static nsHtml5AttributeName* ATTR_Y2;
+ static nsHtml5AttributeName* ATTR_K3;
+ static nsHtml5AttributeName* ATTR_K4;
+ static nsHtml5AttributeName* ATTR_XML_SPACE;
+ static nsHtml5AttributeName* ATTR_XML_LANG;
+ static nsHtml5AttributeName* ATTR_ARIA_GRAB;
+ static nsHtml5AttributeName* ATTR_ARIA_VALUEMAX;
+ static nsHtml5AttributeName* ATTR_ARIA_LABELLEDBY;
+ static nsHtml5AttributeName* ATTR_ARIA_DESCRIBEDBY;
+ static nsHtml5AttributeName* ATTR_ARIA_DISABLED;
+ static nsHtml5AttributeName* ATTR_ARIA_CHECKED;
+ static nsHtml5AttributeName* ATTR_ARIA_SELECTED;
+ static nsHtml5AttributeName* ATTR_ARIA_DROPEFFECT;
+ static nsHtml5AttributeName* ATTR_ARIA_REQUIRED;
+ static nsHtml5AttributeName* ATTR_ARIA_EXPANDED;
+ static nsHtml5AttributeName* ATTR_ARIA_PRESSED;
+ static nsHtml5AttributeName* ATTR_ARIA_LEVEL;
+ static nsHtml5AttributeName* ATTR_ARIA_CHANNEL;
+ static nsHtml5AttributeName* ATTR_ARIA_HIDDEN;
+ static nsHtml5AttributeName* ATTR_ARIA_SECRET;
+ static nsHtml5AttributeName* ATTR_ARIA_POSINSET;
+ static nsHtml5AttributeName* ATTR_ARIA_ATOMIC;
+ static nsHtml5AttributeName* ATTR_ARIA_INVALID;
+ static nsHtml5AttributeName* ATTR_ARIA_TEMPLATEID;
+ static nsHtml5AttributeName* ATTR_ARIA_VALUEMIN;
+ static nsHtml5AttributeName* ATTR_ARIA_MULTISELECTABLE;
+ static nsHtml5AttributeName* ATTR_ARIA_CONTROLS;
+ static nsHtml5AttributeName* ATTR_ARIA_MULTILINE;
+ static nsHtml5AttributeName* ATTR_ARIA_READONLY;
+ static nsHtml5AttributeName* ATTR_ARIA_OWNS;
+ static nsHtml5AttributeName* ATTR_ARIA_ACTIVEDESCENDANT;
+ static nsHtml5AttributeName* ATTR_ARIA_RELEVANT;
+ static nsHtml5AttributeName* ATTR_ARIA_DATATYPE;
+ static nsHtml5AttributeName* ATTR_ARIA_VALUENOW;
+ static nsHtml5AttributeName* ATTR_ARIA_SORT;
+ static nsHtml5AttributeName* ATTR_ARIA_AUTOCOMPLETE;
+ static nsHtml5AttributeName* ATTR_ARIA_FLOWTO;
+ static nsHtml5AttributeName* ATTR_ARIA_BUSY;
+ static nsHtml5AttributeName* ATTR_ARIA_LIVE;
+ static nsHtml5AttributeName* ATTR_ARIA_HASPOPUP;
+ static nsHtml5AttributeName* ATTR_ARIA_SETSIZE;
+ static nsHtml5AttributeName* ATTR_CLEAR;
+ static nsHtml5AttributeName* ATTR_DISABLED;
+ static nsHtml5AttributeName* ATTR_DEFAULT;
+ static nsHtml5AttributeName* ATTR_DATA;
+ static nsHtml5AttributeName* ATTR_EQUALCOLUMNS;
+ static nsHtml5AttributeName* ATTR_EQUALROWS;
+ static nsHtml5AttributeName* ATTR_HSPACE;
+ static nsHtml5AttributeName* ATTR_ISMAP;
+ static nsHtml5AttributeName* ATTR_LOCAL;
+ static nsHtml5AttributeName* ATTR_LSPACE;
+ static nsHtml5AttributeName* ATTR_MOVABLELIMITS;
+ static nsHtml5AttributeName* ATTR_NOTATION;
+ static nsHtml5AttributeName* ATTR_ONDATAAVAILABLE;
+ static nsHtml5AttributeName* ATTR_ONPASTE;
+ static nsHtml5AttributeName* ATTR_RSPACE;
+ static nsHtml5AttributeName* ATTR_ROWALIGN;
+ static nsHtml5AttributeName* ATTR_ROTATE;
+ static nsHtml5AttributeName* ATTR_SEPARATOR;
+ static nsHtml5AttributeName* ATTR_SEPARATORS;
+ static nsHtml5AttributeName* ATTR_VSPACE;
+ static nsHtml5AttributeName* ATTR_XCHANNELSELECTOR;
+ static nsHtml5AttributeName* ATTR_YCHANNELSELECTOR;
+ static nsHtml5AttributeName* ATTR_ENABLE_BACKGROUND;
+ static nsHtml5AttributeName* ATTR_ONDBLCLICK;
+ static nsHtml5AttributeName* ATTR_ONABORT;
+ static nsHtml5AttributeName* ATTR_CALCMODE;
+ static nsHtml5AttributeName* ATTR_CHECKED;
+ static nsHtml5AttributeName* ATTR_FENCE;
+ static nsHtml5AttributeName* ATTR_ONSCROLL;
+ static nsHtml5AttributeName* ATTR_ONACTIVATE;
+ static nsHtml5AttributeName* ATTR_OPACITY;
+ static nsHtml5AttributeName* ATTR_SPACING;
+ static nsHtml5AttributeName* ATTR_SPECULAREXPONENT;
+ static nsHtml5AttributeName* ATTR_SPECULARCONSTANT;
+ static nsHtml5AttributeName* ATTR_BORDER;
+ static nsHtml5AttributeName* ATTR_ID;
+ static nsHtml5AttributeName* ATTR_GRADIENTTRANSFORM;
+ static nsHtml5AttributeName* ATTR_GRADIENTUNITS;
+ static nsHtml5AttributeName* ATTR_HIDDEN;
+ static nsHtml5AttributeName* ATTR_HEADERS;
+ static nsHtml5AttributeName* ATTR_LOADING;
+ static nsHtml5AttributeName* ATTR_READONLY;
+ static nsHtml5AttributeName* ATTR_RENDERING_INTENT;
+ static nsHtml5AttributeName* ATTR_SEED;
+ static nsHtml5AttributeName* ATTR_SRCDOC;
+ static nsHtml5AttributeName* ATTR_STDDEVIATION;
+ static nsHtml5AttributeName* ATTR_SANDBOX;
+ static nsHtml5AttributeName* ATTR_WORD_SPACING;
+ static nsHtml5AttributeName* ATTR_ACCENTUNDER;
+ static nsHtml5AttributeName* ATTR_ACCEPT_CHARSET;
+ static nsHtml5AttributeName* ATTR_ACCESSKEY;
+ static nsHtml5AttributeName* ATTR_ACCENT;
+ static nsHtml5AttributeName* ATTR_ACCEPT;
+ static nsHtml5AttributeName* ATTR_BEVELLED;
+ static nsHtml5AttributeName* ATTR_BASEFREQUENCY;
+ static nsHtml5AttributeName* ATTR_BASELINE_SHIFT;
+ static nsHtml5AttributeName* ATTR_BASEPROFILE;
+ static nsHtml5AttributeName* ATTR_BASELINE;
+ static nsHtml5AttributeName* ATTR_BASE;
+ static nsHtml5AttributeName* ATTR_CODE;
+ static nsHtml5AttributeName* ATTR_CODETYPE;
+ static nsHtml5AttributeName* ATTR_CODEBASE;
+ static nsHtml5AttributeName* ATTR_CITE;
+ static nsHtml5AttributeName* ATTR_DEFER;
+ static nsHtml5AttributeName* ATTR_DATETIME;
+ static nsHtml5AttributeName* ATTR_DIRECTION;
+ static nsHtml5AttributeName* ATTR_EDGEMODE;
+ static nsHtml5AttributeName* ATTR_EDGE;
+ static nsHtml5AttributeName* ATTR_ENTERKEYHINT;
+ static nsHtml5AttributeName* ATTR_FACE;
+ static nsHtml5AttributeName* ATTR_INDEX;
+ static nsHtml5AttributeName* ATTR_INTERCEPT;
+ static nsHtml5AttributeName* ATTR_INTEGRITY;
+ static nsHtml5AttributeName* ATTR_LINEBREAK;
+ static nsHtml5AttributeName* ATTR_LABEL;
+ static nsHtml5AttributeName* ATTR_LINETHICKNESS;
+ static nsHtml5AttributeName* ATTR_MODE;
+ static nsHtml5AttributeName* ATTR_NAME;
+ static nsHtml5AttributeName* ATTR_NORESIZE;
+ static nsHtml5AttributeName* ATTR_ONBEFOREUNLOAD;
+ static nsHtml5AttributeName* ATTR_ONREPEAT;
+ static nsHtml5AttributeName* ATTR_OBJECT;
+ static nsHtml5AttributeName* ATTR_ONSELECT;
+ static nsHtml5AttributeName* ATTR_ORDER;
+ static nsHtml5AttributeName* ATTR_OTHER;
+ static nsHtml5AttributeName* ATTR_ONRESET;
+ static nsHtml5AttributeName* ATTR_ONREADYSTATECHANGE;
+ static nsHtml5AttributeName* ATTR_ONMESSAGE;
+ static nsHtml5AttributeName* ATTR_ONBEGIN;
+ static nsHtml5AttributeName* ATTR_ONBEFOREPRINT;
+ static nsHtml5AttributeName* ATTR_ORIENT;
+ static nsHtml5AttributeName* ATTR_ORIENTATION;
+ static nsHtml5AttributeName* ATTR_ONBEFORECOPY;
+ static nsHtml5AttributeName* ATTR_ONSELECTSTART;
+ static nsHtml5AttributeName* ATTR_ONBEFOREPASTE;
+ static nsHtml5AttributeName* ATTR_ONKEYPRESS;
+ static nsHtml5AttributeName* ATTR_ONKEYUP;
+ static nsHtml5AttributeName* ATTR_ONBEFORECUT;
+ static nsHtml5AttributeName* ATTR_ONKEYDOWN;
+ static nsHtml5AttributeName* ATTR_ONRESIZE;
+ static nsHtml5AttributeName* ATTR_REPEAT;
+ static nsHtml5AttributeName* ATTR_REFERRERPOLICY;
+ static nsHtml5AttributeName* ATTR_RULES;
+ static nsHtml5AttributeName* ATTR_ROLE;
+ static nsHtml5AttributeName* ATTR_REPEATCOUNT;
+ static nsHtml5AttributeName* ATTR_REPEATDUR;
+ static nsHtml5AttributeName* ATTR_SELECTED;
+ static nsHtml5AttributeName* ATTR_SIZES;
+ static nsHtml5AttributeName* ATTR_SUPERSCRIPTSHIFT;
+ static nsHtml5AttributeName* ATTR_STRETCHY;
+ static nsHtml5AttributeName* ATTR_SCHEME;
+ static nsHtml5AttributeName* ATTR_SPREADMETHOD;
+ static nsHtml5AttributeName* ATTR_SELECTION;
+ static nsHtml5AttributeName* ATTR_SIZE;
+ static nsHtml5AttributeName* ATTR_TYPE;
+ static nsHtml5AttributeName* ATTR_DIFFUSECONSTANT;
+ static nsHtml5AttributeName* ATTR_HREF;
+ static nsHtml5AttributeName* ATTR_HREFLANG;
+ static nsHtml5AttributeName* ATTR_ONAFTERPRINT;
+ static nsHtml5AttributeName* ATTR_PROFILE;
+ static nsHtml5AttributeName* ATTR_SURFACESCALE;
+ static nsHtml5AttributeName* ATTR_XREF;
+ static nsHtml5AttributeName* ATTR_ALIGN;
+ static nsHtml5AttributeName* ATTR_ALIGNMENT_BASELINE;
+ static nsHtml5AttributeName* ATTR_ALIGNMENTSCOPE;
+ static nsHtml5AttributeName* ATTR_DRAGGABLE;
+ static nsHtml5AttributeName* ATTR_HEIGHT;
+ static nsHtml5AttributeName* ATTR_IMAGESIZES;
+ static nsHtml5AttributeName* ATTR_IMAGESRCSET;
+ static nsHtml5AttributeName* ATTR_IMAGE_RENDERING;
+ static nsHtml5AttributeName* ATTR_LANGUAGE;
+ static nsHtml5AttributeName* ATTR_LANG;
+ static nsHtml5AttributeName* ATTR_LARGEOP;
+ static nsHtml5AttributeName* ATTR_LONGDESC;
+ static nsHtml5AttributeName* ATTR_LENGTHADJUST;
+ static nsHtml5AttributeName* ATTR_MARGINHEIGHT;
+ static nsHtml5AttributeName* ATTR_MARGINWIDTH;
+ static nsHtml5AttributeName* ATTR_ORIGIN;
+ static nsHtml5AttributeName* ATTR_PING;
+ static nsHtml5AttributeName* ATTR_TARGET;
+ static nsHtml5AttributeName* ATTR_TARGETX;
+ static nsHtml5AttributeName* ATTR_TARGETY;
+ static nsHtml5AttributeName* ATTR_ARCHIVE;
+ static nsHtml5AttributeName* ATTR_HIGH;
+ static nsHtml5AttributeName* ATTR_LIGHTING_COLOR;
+ static nsHtml5AttributeName* ATTR_MATHBACKGROUND;
+ static nsHtml5AttributeName* ATTR_METHOD;
+ static nsHtml5AttributeName* ATTR_MATHVARIANT;
+ static nsHtml5AttributeName* ATTR_MATHCOLOR;
+ static nsHtml5AttributeName* ATTR_MATHSIZE;
+ static nsHtml5AttributeName* ATTR_NOSHADE;
+ static nsHtml5AttributeName* ATTR_ONCHANGE;
+ static nsHtml5AttributeName* ATTR_PATHLENGTH;
+ static nsHtml5AttributeName* ATTR_PATH;
+ static nsHtml5AttributeName* ATTR_ALTIMG;
+ static nsHtml5AttributeName* ATTR_ACTIONTYPE;
+ static nsHtml5AttributeName* ATTR_ACTION;
+ static nsHtml5AttributeName* ATTR_ACTIVE;
+ static nsHtml5AttributeName* ATTR_ADDITIVE;
+ static nsHtml5AttributeName* ATTR_BEGIN;
+ static nsHtml5AttributeName* ATTR_DOMINANT_BASELINE;
+ static nsHtml5AttributeName* ATTR_DIVISOR;
+ static nsHtml5AttributeName* ATTR_DEFINITIONURL;
+ static nsHtml5AttributeName* ATTR_LIMITINGCONEANGLE;
+ static nsHtml5AttributeName* ATTR_MEDIA;
+ static nsHtml5AttributeName* ATTR_MANIFEST;
+ static nsHtml5AttributeName* ATTR_ONFINISH;
+ static nsHtml5AttributeName* ATTR_OPTIMUM;
+ static nsHtml5AttributeName* ATTR_RADIOGROUP;
+ static nsHtml5AttributeName* ATTR_RADIUS;
+ static nsHtml5AttributeName* ATTR_SCRIPTLEVEL;
+ static nsHtml5AttributeName* ATTR_SCRIPTSIZEMULTIPLIER;
+ static nsHtml5AttributeName* ATTR_SCRIPTMINSIZE;
+ static nsHtml5AttributeName* ATTR_TABINDEX;
+ static nsHtml5AttributeName* ATTR_VALIGN;
+ static nsHtml5AttributeName* ATTR_VISIBILITY;
+ static nsHtml5AttributeName* ATTR_BACKGROUND;
+ static nsHtml5AttributeName* ATTR_LINK;
+ static nsHtml5AttributeName* ATTR_MARKER_MID;
+ static nsHtml5AttributeName* ATTR_MARKERHEIGHT;
+ static nsHtml5AttributeName* ATTR_MARKER_END;
+ static nsHtml5AttributeName* ATTR_MASK;
+ static nsHtml5AttributeName* ATTR_MARKER_START;
+ static nsHtml5AttributeName* ATTR_MARKERWIDTH;
+ static nsHtml5AttributeName* ATTR_MASKUNITS;
+ static nsHtml5AttributeName* ATTR_MARKERUNITS;
+ static nsHtml5AttributeName* ATTR_MASKCONTENTUNITS;
+ static nsHtml5AttributeName* ATTR_AMPLITUDE;
+ static nsHtml5AttributeName* ATTR_CELLSPACING;
+ static nsHtml5AttributeName* ATTR_CELLPADDING;
+ static nsHtml5AttributeName* ATTR_DECLARE;
+ static nsHtml5AttributeName* ATTR_FILL_RULE;
+ static nsHtml5AttributeName* ATTR_FILL;
+ static nsHtml5AttributeName* ATTR_FILL_OPACITY;
+ static nsHtml5AttributeName* ATTR_MAXLENGTH;
+ static nsHtml5AttributeName* ATTR_ONCLICK;
+ static nsHtml5AttributeName* ATTR_ONBLUR;
+ static nsHtml5AttributeName* ATTR_REPLACE;
+ static nsHtml5AttributeName* ATTR_ROWLINES;
+ static nsHtml5AttributeName* ATTR_SCALE;
+ static nsHtml5AttributeName* ATTR_STYLE;
+ static nsHtml5AttributeName* ATTR_TABLEVALUES;
+ static nsHtml5AttributeName* ATTR_TITLE;
+ static nsHtml5AttributeName* ATTR_AZIMUTH;
+ static nsHtml5AttributeName* ATTR_FORMAT;
+ static nsHtml5AttributeName* ATTR_FRAMEBORDER;
+ static nsHtml5AttributeName* ATTR_FRAME;
+ static nsHtml5AttributeName* ATTR_FRAMESPACING;
+ static nsHtml5AttributeName* ATTR_FROM;
+ static nsHtml5AttributeName* ATTR_FORM;
+ static nsHtml5AttributeName* ATTR_PROMPT;
+ static nsHtml5AttributeName* ATTR_PRIMITIVEUNITS;
+ static nsHtml5AttributeName* ATTR_SYMMETRIC;
+ static nsHtml5AttributeName* ATTR_SUMMARY;
+ static nsHtml5AttributeName* ATTR_USEMAP;
+ static nsHtml5AttributeName* ATTR_ZOOMANDPAN;
+ static nsHtml5AttributeName* ATTR_ASYNC;
+ static nsHtml5AttributeName* ATTR_ALINK;
+ static nsHtml5AttributeName* ATTR_IN;
+ static nsHtml5AttributeName* ATTR_ICON;
+ static nsHtml5AttributeName* ATTR_KERNELMATRIX;
+ static nsHtml5AttributeName* ATTR_KERNING;
+ static nsHtml5AttributeName* ATTR_KERNELUNITLENGTH;
+ static nsHtml5AttributeName* ATTR_ONUNLOAD;
+ static nsHtml5AttributeName* ATTR_OPEN;
+ static nsHtml5AttributeName* ATTR_ONINVALID;
+ static nsHtml5AttributeName* ATTR_ONEND;
+ static nsHtml5AttributeName* ATTR_ONINPUT;
+ static nsHtml5AttributeName* ATTR_POINTER_EVENTS;
+ static nsHtml5AttributeName* ATTR_POINTS;
+ static nsHtml5AttributeName* ATTR_POINTSATX;
+ static nsHtml5AttributeName* ATTR_POINTSATY;
+ static nsHtml5AttributeName* ATTR_POINTSATZ;
+ static nsHtml5AttributeName* ATTR_SPAN;
+ static nsHtml5AttributeName* ATTR_STANDBY;
+ static nsHtml5AttributeName* ATTR_TRANSFORM_ORIGIN;
+ static nsHtml5AttributeName* ATTR_TRANSFORM;
+ static nsHtml5AttributeName* ATTR_VLINK;
+ static nsHtml5AttributeName* ATTR_WHEN;
+ static nsHtml5AttributeName* ATTR_XLINK_HREF;
+ static nsHtml5AttributeName* ATTR_XLINK_TITLE;
+ static nsHtml5AttributeName* ATTR_XLINK_ROLE;
+ static nsHtml5AttributeName* ATTR_XLINK_ARCROLE;
+ static nsHtml5AttributeName* ATTR_XMLNS_XLINK;
+ static nsHtml5AttributeName* ATTR_XMLNS;
+ static nsHtml5AttributeName* ATTR_XLINK_TYPE;
+ static nsHtml5AttributeName* ATTR_XLINK_SHOW;
+ static nsHtml5AttributeName* ATTR_XLINK_ACTUATE;
+ static nsHtml5AttributeName* ATTR_AUTOPLAY;
+ static nsHtml5AttributeName* ATTR_AUTOCOMPLETE;
+ static nsHtml5AttributeName* ATTR_AUTOFOCUS;
+ static nsHtml5AttributeName* ATTR_AUTOCAPITALIZE;
+ static nsHtml5AttributeName* ATTR_BGCOLOR;
+ static nsHtml5AttributeName* ATTR_COLOR_PROFILE;
+ static nsHtml5AttributeName* ATTR_COLOR_RENDERING;
+ static nsHtml5AttributeName* ATTR_COLOR_INTERPOLATION;
+ static nsHtml5AttributeName* ATTR_COLOR;
+ static nsHtml5AttributeName* ATTR_COLOR_INTERPOLATION_FILTERS;
+ static nsHtml5AttributeName* ATTR_ENCODING;
+ static nsHtml5AttributeName* ATTR_EXPONENT;
+ static nsHtml5AttributeName* ATTR_FLOOD_COLOR;
+ static nsHtml5AttributeName* ATTR_FLOOD_OPACITY;
+ static nsHtml5AttributeName* ATTR_LQUOTE;
+ static nsHtml5AttributeName* ATTR_NUMOCTAVES;
+ static nsHtml5AttributeName* ATTR_NOMODULE;
+ static nsHtml5AttributeName* ATTR_ONLOAD;
+ static nsHtml5AttributeName* ATTR_ONMOUSEWHEEL;
+ static nsHtml5AttributeName* ATTR_ONMOUSEENTER;
+ static nsHtml5AttributeName* ATTR_ONMOUSEOVER;
+ static nsHtml5AttributeName* ATTR_ONFOCUSIN;
+ static nsHtml5AttributeName* ATTR_ONCONTEXTMENU;
+ static nsHtml5AttributeName* ATTR_ONZOOM;
+ static nsHtml5AttributeName* ATTR_ONCOPY;
+ static nsHtml5AttributeName* ATTR_ONMOUSELEAVE;
+ static nsHtml5AttributeName* ATTR_ONMOUSEMOVE;
+ static nsHtml5AttributeName* ATTR_ONMOUSEUP;
+ static nsHtml5AttributeName* ATTR_ONFOCUS;
+ static nsHtml5AttributeName* ATTR_ONMOUSEOUT;
+ static nsHtml5AttributeName* ATTR_ONFOCUSOUT;
+ static nsHtml5AttributeName* ATTR_ONMOUSEDOWN;
+ static nsHtml5AttributeName* ATTR_TO;
+ static nsHtml5AttributeName* ATTR_RQUOTE;
+ static nsHtml5AttributeName* ATTR_STROKE_LINECAP;
+ static nsHtml5AttributeName* ATTR_STROKE_DASHARRAY;
+ static nsHtml5AttributeName* ATTR_STROKE_DASHOFFSET;
+ static nsHtml5AttributeName* ATTR_STROKE_LINEJOIN;
+ static nsHtml5AttributeName* ATTR_STROKE_MITERLIMIT;
+ static nsHtml5AttributeName* ATTR_STROKE;
+ static nsHtml5AttributeName* ATTR_SCROLLING;
+ static nsHtml5AttributeName* ATTR_STROKE_WIDTH;
+ static nsHtml5AttributeName* ATTR_STROKE_OPACITY;
+ static nsHtml5AttributeName* ATTR_COMPACT;
+ static nsHtml5AttributeName* ATTR_CLIP;
+ static nsHtml5AttributeName* ATTR_CLIP_RULE;
+ static nsHtml5AttributeName* ATTR_CLIP_PATH;
+ static nsHtml5AttributeName* ATTR_CLIPPATHUNITS;
+ static nsHtml5AttributeName* ATTR_DISPLAY;
+ static nsHtml5AttributeName* ATTR_DISPLAYSTYLE;
+ static nsHtml5AttributeName* ATTR_GLYPH_ORIENTATION_VERTICAL;
+ static nsHtml5AttributeName* ATTR_GLYPH_ORIENTATION_HORIZONTAL;
+ static nsHtml5AttributeName* ATTR_GLYPHREF;
+ static nsHtml5AttributeName* ATTR_HTTP_EQUIV;
+ static nsHtml5AttributeName* ATTR_KEYPOINTS;
+ static nsHtml5AttributeName* ATTR_LOOP;
+ static nsHtml5AttributeName* ATTR_PROPERTY;
+ static nsHtml5AttributeName* ATTR_SCOPED;
+ static nsHtml5AttributeName* ATTR_STEP;
+ static nsHtml5AttributeName* ATTR_SHAPE_RENDERING;
+ static nsHtml5AttributeName* ATTR_SCOPE;
+ static nsHtml5AttributeName* ATTR_SHAPE;
+ static nsHtml5AttributeName* ATTR_SLOPE;
+ static nsHtml5AttributeName* ATTR_STOP_COLOR;
+ static nsHtml5AttributeName* ATTR_STOP_OPACITY;
+ static nsHtml5AttributeName* ATTR_TEMPLATE;
+ static nsHtml5AttributeName* ATTR_WRAP;
+ static nsHtml5AttributeName* ATTR_ABBR;
+ static nsHtml5AttributeName* ATTR_ATTRIBUTENAME;
+ static nsHtml5AttributeName* ATTR_ATTRIBUTETYPE;
+ static nsHtml5AttributeName* ATTR_CHAR;
+ static nsHtml5AttributeName* ATTR_COORDS;
+ static nsHtml5AttributeName* ATTR_CHAROFF;
+ static nsHtml5AttributeName* ATTR_CHARSET;
+ static nsHtml5AttributeName* ATTR_NOWRAP;
+ static nsHtml5AttributeName* ATTR_NOHREF;
+ static nsHtml5AttributeName* ATTR_ONDRAG;
+ static nsHtml5AttributeName* ATTR_ONDRAGENTER;
+ static nsHtml5AttributeName* ATTR_ONDRAGOVER;
+ static nsHtml5AttributeName* ATTR_ONDRAGEND;
+ static nsHtml5AttributeName* ATTR_ONDROP;
+ static nsHtml5AttributeName* ATTR_ONDRAGDROP;
+ static nsHtml5AttributeName* ATTR_ONERROR;
+ static nsHtml5AttributeName* ATTR_OPERATOR;
+ static nsHtml5AttributeName* ATTR_OVERFLOW;
+ static nsHtml5AttributeName* ATTR_ONDRAGSTART;
+ static nsHtml5AttributeName* ATTR_ONDRAGLEAVE;
+ static nsHtml5AttributeName* ATTR_STARTOFFSET;
+ static nsHtml5AttributeName* ATTR_START;
+ static nsHtml5AttributeName* ATTR_AS;
+ static nsHtml5AttributeName* ATTR_AXIS;
+ static nsHtml5AttributeName* ATTR_BIAS;
+ static nsHtml5AttributeName* ATTR_COLSPAN;
+ static nsHtml5AttributeName* ATTR_CLASSID;
+ static nsHtml5AttributeName* ATTR_CROSSORIGIN;
+ static nsHtml5AttributeName* ATTR_COLS;
+ static nsHtml5AttributeName* ATTR_CURSOR;
+ static nsHtml5AttributeName* ATTR_CLOSURE;
+ static nsHtml5AttributeName* ATTR_CLOSE;
+ static nsHtml5AttributeName* ATTR_CLASS;
+ static nsHtml5AttributeName* ATTR_IS;
+ static nsHtml5AttributeName* ATTR_KEYSYSTEM;
+ static nsHtml5AttributeName* ATTR_KEYSPLINES;
+ static nsHtml5AttributeName* ATTR_LOWSRC;
+ static nsHtml5AttributeName* ATTR_MAXSIZE;
+ static nsHtml5AttributeName* ATTR_MINSIZE;
+ static nsHtml5AttributeName* ATTR_OFFSET;
+ static nsHtml5AttributeName* ATTR_PRESERVEALPHA;
+ static nsHtml5AttributeName* ATTR_PRESERVEASPECTRATIO;
+ static nsHtml5AttributeName* ATTR_ROWSPAN;
+ static nsHtml5AttributeName* ATTR_ROWSPACING;
+ static nsHtml5AttributeName* ATTR_ROWS;
+ static nsHtml5AttributeName* ATTR_SRCSET;
+ static nsHtml5AttributeName* ATTR_SUBSCRIPTSHIFT;
+ static nsHtml5AttributeName* ATTR_VERSION;
+ static nsHtml5AttributeName* ATTR_ALTTEXT;
+ static nsHtml5AttributeName* ATTR_CONTENTEDITABLE;
+ static nsHtml5AttributeName* ATTR_CONTROLS;
+ static nsHtml5AttributeName* ATTR_CONTENT;
+ static nsHtml5AttributeName* ATTR_CONTEXTMENU;
+ static nsHtml5AttributeName* ATTR_DEPTH;
+ static nsHtml5AttributeName* ATTR_ENCTYPE;
+ static nsHtml5AttributeName* ATTR_FONT_STRETCH;
+ static nsHtml5AttributeName* ATTR_FILTER;
+ static nsHtml5AttributeName* ATTR_FONTWEIGHT;
+ static nsHtml5AttributeName* ATTR_FONT_WEIGHT;
+ static nsHtml5AttributeName* ATTR_FONTSTYLE;
+ static nsHtml5AttributeName* ATTR_FONT_STYLE;
+ static nsHtml5AttributeName* ATTR_FONTFAMILY;
+ static nsHtml5AttributeName* ATTR_FONT_FAMILY;
+ static nsHtml5AttributeName* ATTR_FONT_VARIANT;
+ static nsHtml5AttributeName* ATTR_FONT_SIZE_ADJUST;
+ static nsHtml5AttributeName* ATTR_FILTERUNITS;
+ static nsHtml5AttributeName* ATTR_FONTSIZE;
+ static nsHtml5AttributeName* ATTR_FONT_SIZE;
+ static nsHtml5AttributeName* ATTR_KEYTIMES;
+ static nsHtml5AttributeName* ATTR_LETTER_SPACING;
+ static nsHtml5AttributeName* ATTR_LIST;
+ static nsHtml5AttributeName* ATTR_MULTIPLE;
+ static nsHtml5AttributeName* ATTR_RT;
+ static nsHtml5AttributeName* ATTR_ONSTOP;
+ static nsHtml5AttributeName* ATTR_ONSTART;
+ static nsHtml5AttributeName* ATTR_POSTER;
+ static nsHtml5AttributeName* ATTR_PATTERNTRANSFORM;
+ static nsHtml5AttributeName* ATTR_PATTERN;
+ static nsHtml5AttributeName* ATTR_PATTERNUNITS;
+ static nsHtml5AttributeName* ATTR_PATTERNCONTENTUNITS;
+ static nsHtml5AttributeName* ATTR_RESTART;
+ static nsHtml5AttributeName* ATTR_STITCHTILES;
+ static nsHtml5AttributeName* ATTR_SYSTEMLANGUAGE;
+ static nsHtml5AttributeName* ATTR_TEXT_RENDERING;
+ static nsHtml5AttributeName* ATTR_TEXT_DECORATION;
+ static nsHtml5AttributeName* ATTR_TEXT_ANCHOR;
+ static nsHtml5AttributeName* ATTR_TEXTLENGTH;
+ static nsHtml5AttributeName* ATTR_TEXT;
+ static nsHtml5AttributeName* ATTR_WRITING_MODE;
+ static nsHtml5AttributeName* ATTR_WIDTH;
+ static nsHtml5AttributeName* ATTR_ACCUMULATE;
+ static nsHtml5AttributeName* ATTR_COLUMNSPAN;
+ static nsHtml5AttributeName* ATTR_COLUMNLINES;
+ static nsHtml5AttributeName* ATTR_COLUMNALIGN;
+ static nsHtml5AttributeName* ATTR_COLUMNSPACING;
+ static nsHtml5AttributeName* ATTR_COLUMNWIDTH;
+ static nsHtml5AttributeName* ATTR_GROUPALIGN;
+ static nsHtml5AttributeName* ATTR_INPUTMODE;
+ static nsHtml5AttributeName* ATTR_ONSUBMIT;
+ static nsHtml5AttributeName* ATTR_ONCUT;
+ static nsHtml5AttributeName* ATTR_REQUIRED;
+ static nsHtml5AttributeName* ATTR_REQUIREDFEATURES;
+ static nsHtml5AttributeName* ATTR_RESULT;
+ static nsHtml5AttributeName* ATTR_REQUIREDEXTENSIONS;
+ static nsHtml5AttributeName* ATTR_VALUES;
+ static nsHtml5AttributeName* ATTR_VALUETYPE;
+ static nsHtml5AttributeName* ATTR_VALUE;
+ static nsHtml5AttributeName* ATTR_ELEVATION;
+ static nsHtml5AttributeName* ATTR_VIEWTARGET;
+ static nsHtml5AttributeName* ATTR_VIEWBOX;
+ static nsHtml5AttributeName* ATTR_CX;
+ static nsHtml5AttributeName* ATTR_DX;
+ static nsHtml5AttributeName* ATTR_FX;
+ static nsHtml5AttributeName* ATTR_RX;
+ static nsHtml5AttributeName* ATTR_REFX;
+ static nsHtml5AttributeName* ATTR_BY;
+ static nsHtml5AttributeName* ATTR_CY;
+ static nsHtml5AttributeName* ATTR_DY;
+ static nsHtml5AttributeName* ATTR_FY;
+ static nsHtml5AttributeName* ATTR_RY;
+ static nsHtml5AttributeName* ATTR_REFY;
+
+ private:
+ static nsHtml5AttributeName** ATTRIBUTE_NAMES;
+ static staticJArray<int32_t, int32_t> ATTRIBUTE_HASHES;
+
+ public:
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif
diff --git a/parser/html/nsHtml5AutoPauseUpdate.h b/parser/html/nsHtml5AutoPauseUpdate.h
new file mode 100644
index 0000000000..16c298111d
--- /dev/null
+++ b/parser/html/nsHtml5AutoPauseUpdate.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5AutoPauseUpdate_h
+#define nsHtml5AutoPauseUpdate_h
+
+#include "nsHtml5DocumentBuilder.h"
+
+class MOZ_RAII nsHtml5AutoPauseUpdate final {
+ private:
+ RefPtr<nsHtml5DocumentBuilder> mBuilder;
+
+ public:
+ explicit nsHtml5AutoPauseUpdate(nsHtml5DocumentBuilder* aBuilder)
+ : mBuilder(aBuilder) {
+ mBuilder->EndDocUpdate();
+ }
+ ~nsHtml5AutoPauseUpdate() {
+ // Something may have terminated the parser during the update pause.
+ if (!mBuilder->IsComplete()) {
+ mBuilder->BeginDocUpdate();
+ }
+ }
+};
+
+#endif // nsHtml5AutoPauseUpdate_h
diff --git a/parser/html/nsHtml5ByteReadable.h b/parser/html/nsHtml5ByteReadable.h
new file mode 100644
index 0000000000..e2e318364c
--- /dev/null
+++ b/parser/html/nsHtml5ByteReadable.h
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5ByteReadable_h
+#define nsHtml5ByteReadable_h
+
+/**
+ * A weak reference wrapper around a byte array.
+ */
+class nsHtml5ByteReadable {
+ public:
+ nsHtml5ByteReadable(const uint8_t* aCurrent, const uint8_t* aEnd)
+ : current(aCurrent), end(aEnd) {}
+
+ inline int32_t read() {
+ if (current < end) {
+ return *(current++);
+ } else {
+ return -1;
+ }
+ }
+
+ private:
+ const uint8_t* current;
+ const uint8_t* end;
+};
+#endif
diff --git a/parser/html/nsHtml5ContentCreatorFunction.h b/parser/html/nsHtml5ContentCreatorFunction.h
new file mode 100644
index 0000000000..32c23afa47
--- /dev/null
+++ b/parser/html/nsHtml5ContentCreatorFunction.h
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5ContentCreatorFunction_h
+#define nsHtml5ContentCreatorFunction_h
+
+#include "nsGenericHTMLElement.h"
+#include "mozilla/dom/SVGElementFactory.h"
+
+union nsHtml5ContentCreatorFunction {
+ mozilla::dom::HTMLContentCreatorFunction html;
+ mozilla::dom::SVGContentCreatorFunction svg;
+};
+
+#endif // nsHtml5ContentCreatorFunction_h
diff --git a/parser/html/nsHtml5DependentUTF16Buffer.cpp b/parser/html/nsHtml5DependentUTF16Buffer.cpp
new file mode 100644
index 0000000000..6372b6923b
--- /dev/null
+++ b/parser/html/nsHtml5DependentUTF16Buffer.cpp
@@ -0,0 +1,30 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5DependentUTF16Buffer.h"
+
+nsHtml5DependentUTF16Buffer::nsHtml5DependentUTF16Buffer(
+ const nsAString& aToWrap)
+ : nsHtml5UTF16Buffer(const_cast<char16_t*>(aToWrap.BeginReading()),
+ aToWrap.Length()) {
+ MOZ_COUNT_CTOR(nsHtml5DependentUTF16Buffer);
+}
+
+nsHtml5DependentUTF16Buffer::~nsHtml5DependentUTF16Buffer() {
+ MOZ_COUNT_DTOR(nsHtml5DependentUTF16Buffer);
+}
+
+already_AddRefed<nsHtml5OwningUTF16Buffer>
+nsHtml5DependentUTF16Buffer::FalliblyCopyAsOwningBuffer() {
+ int32_t newLength = getEnd() - getStart();
+ RefPtr<nsHtml5OwningUTF16Buffer> newObj =
+ nsHtml5OwningUTF16Buffer::FalliblyCreate(newLength);
+ if (!newObj) {
+ return nullptr;
+ }
+ newObj->setEnd(newLength);
+ memcpy(newObj->getBuffer(), getBuffer() + getStart(),
+ newLength * sizeof(char16_t));
+ return newObj.forget();
+}
diff --git a/parser/html/nsHtml5DependentUTF16Buffer.h b/parser/html/nsHtml5DependentUTF16Buffer.h
new file mode 100644
index 0000000000..3713de8aca
--- /dev/null
+++ b/parser/html/nsHtml5DependentUTF16Buffer.h
@@ -0,0 +1,30 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5DependentUTF16Buffer_h
+#define nsHtml5DependentUTF16Buffer_h
+
+#include "nscore.h"
+#include "nsHtml5OwningUTF16Buffer.h"
+
+class MOZ_STACK_CLASS nsHtml5DependentUTF16Buffer : public nsHtml5UTF16Buffer {
+ public:
+ /**
+ * Wraps a string without taking ownership of the buffer. aToWrap MUST NOT
+ * go away or be shortened while nsHtml5DependentUTF16Buffer is in use.
+ */
+ explicit nsHtml5DependentUTF16Buffer(const nsAString& aToWrap);
+
+ ~nsHtml5DependentUTF16Buffer();
+
+ /**
+ * Copies the currently unconsumed part of this buffer into a new
+ * heap-allocated nsHtml5OwningUTF16Buffer. The new object is allocated
+ * with a fallible allocator. If the allocation fails, nullptr is returned.
+ * @return heap-allocated copy or nullptr if memory allocation failed
+ */
+ already_AddRefed<nsHtml5OwningUTF16Buffer> FalliblyCopyAsOwningBuffer();
+};
+
+#endif // nsHtml5DependentUTF16Buffer_h
diff --git a/parser/html/nsHtml5DocumentBuilder.cpp b/parser/html/nsHtml5DocumentBuilder.cpp
new file mode 100644
index 0000000000..e896edde56
--- /dev/null
+++ b/parser/html/nsHtml5DocumentBuilder.cpp
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5DocumentBuilder.h"
+
+#include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/dom/LinkStyle.h"
+#include "nsNameSpaceManager.h"
+
+using mozilla::dom::LinkStyle;
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHtml5DocumentBuilder, nsContentSink,
+ mOwnedElements)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHtml5DocumentBuilder)
+NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
+
+NS_IMPL_ADDREF_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
+NS_IMPL_RELEASE_INHERITED(nsHtml5DocumentBuilder, nsContentSink)
+
+nsHtml5DocumentBuilder::nsHtml5DocumentBuilder(bool aRunsToCompletion)
+ : mBroken(NS_OK), mFlushState(eHtml5FlushState::eNotFlushing) {
+ mRunsToCompletion = aRunsToCompletion;
+}
+
+nsresult nsHtml5DocumentBuilder::Init(mozilla::dom::Document* aDoc,
+ nsIURI* aURI, nsISupports* aContainer,
+ nsIChannel* aChannel) {
+ return nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
+}
+
+nsHtml5DocumentBuilder::~nsHtml5DocumentBuilder() {}
+
+nsresult nsHtml5DocumentBuilder::MarkAsBroken(nsresult aReason) {
+ mBroken = aReason;
+ return aReason;
+}
+
+void nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement) {
+ auto* linkStyle = LinkStyle::FromNode(*aElement);
+ if (!linkStyle) {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to style, but SVG wasn't disabled.");
+ return;
+ }
+
+ // Break out of the doc update created by Flush() to zap a runnable
+ // waiting to call UpdateStyleSheet without the right observer
+ EndDocUpdate();
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // EndDocUpdate ran stuff that called nsIParser::Terminate()
+ return;
+ }
+
+ linkStyle->SetEnableUpdates(true);
+
+ auto updateOrError =
+ linkStyle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this);
+
+ if (updateOrError.isOk() && updateOrError.unwrap().ShouldBlock() &&
+ !mRunsToCompletion) {
+ ++mPendingSheetCount;
+ mScriptLoader->AddParserBlockingScriptExecutionBlocker();
+ }
+
+ // Re-open update
+ BeginDocUpdate();
+}
+
+void nsHtml5DocumentBuilder::SetDocumentMode(nsHtml5DocumentMode m) {
+ nsCompatibility mode = eCompatibility_NavQuirks;
+ const char* errMsgId = nullptr;
+
+ switch (m) {
+ case STANDARDS_MODE:
+ mode = eCompatibility_FullStandards;
+ break;
+ case ALMOST_STANDARDS_MODE:
+ mode = eCompatibility_AlmostStandards;
+ errMsgId = "errAlmostStandardsDoctypeVerbose";
+ break;
+ case QUIRKS_MODE:
+ mode = eCompatibility_NavQuirks;
+ errMsgId = "errQuirkyDoctypeVerbose";
+ break;
+ }
+ mDocument->SetCompatibilityMode(mode);
+
+ if (errMsgId) {
+ nsCOMPtr<nsIURI> docURI = mDocument->GetDocumentURI();
+ bool isData = false;
+ docURI->SchemeIs("data", &isData);
+ bool isHttp = false;
+ docURI->SchemeIs("http", &isHttp);
+ bool isHttps = false;
+ docURI->SchemeIs("https", &isHttps);
+
+ nsCOMPtr<nsIPrincipal> principal = mDocument->GetPrincipal();
+ if (principal->GetIsNullPrincipal() && !isData && !isHttp && !isHttps) {
+ // Don't normally warn for null principals. It may well be internal
+ // documents for which the warning is not applicable.
+ return;
+ }
+
+ nsContentUtils::ReportToConsole(
+ nsIScriptError::warningFlag, "HTML_PARSER__DOCTYPE"_ns, mDocument,
+ nsContentUtils::eHTMLPARSER_PROPERTIES, errMsgId);
+ }
+}
+
+// nsContentSink overrides
+
+void nsHtml5DocumentBuilder::UpdateChildCounts() {
+ // No-op
+}
+
+nsresult nsHtml5DocumentBuilder::FlushTags() { return NS_OK; }
diff --git a/parser/html/nsHtml5DocumentBuilder.h b/parser/html/nsHtml5DocumentBuilder.h
new file mode 100644
index 0000000000..16d7d7238b
--- /dev/null
+++ b/parser/html/nsHtml5DocumentBuilder.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5DocumentBuilder_h
+#define nsHtml5DocumentBuilder_h
+
+#include "mozilla/dom/Document.h"
+#include "nsContentSink.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsIContent.h"
+
+namespace mozilla::dom {
+class Document;
+}
+
+typedef nsIContent* nsIContentPtr;
+
+enum eHtml5FlushState {
+ eNotFlushing = 0, // not flushing
+ eInFlush = 1, // the Flush() method is on the call stack
+ eInDocUpdate = 2, // inside an update batch on the document
+};
+
+class nsHtml5DocumentBuilder : public nsContentSink {
+ using Encoding = mozilla::Encoding;
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+
+ public:
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHtml5DocumentBuilder,
+ nsContentSink)
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ inline void HoldElement(already_AddRefed<nsIContent> aContent) {
+ *(mOwnedElements.AppendElement()) = aContent;
+ }
+
+ nsresult Init(Document* aDoc, nsIURI* aURI, nsISupports* aContainer,
+ nsIChannel* aChannel);
+
+ // Getters and setters for fields from nsContentSink
+ Document* GetDocument() { return mDocument; }
+
+ nsNodeInfoManager* GetNodeInfoManager() { return mNodeInfoManager; }
+
+ /**
+ * Marks this parser as broken and tells the stream parser (if any) to
+ * terminate.
+ *
+ * @return aReason for convenience
+ */
+ virtual nsresult MarkAsBroken(nsresult aReason);
+
+ /**
+ * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
+ * value if broken.
+ */
+ inline nsresult IsBroken() { return mBroken; }
+
+ inline bool IsComplete() { return !mParser; }
+
+ inline void BeginDocUpdate() {
+ MOZ_RELEASE_ASSERT(IsInFlush(), "Tried to double-open doc update.");
+ MOZ_RELEASE_ASSERT(mParser, "Started doc update without parser.");
+ mFlushState = eInDocUpdate;
+ mDocument->BeginUpdate();
+ }
+
+ inline void EndDocUpdate() {
+ MOZ_RELEASE_ASSERT(IsInDocUpdate(),
+ "Tried to end doc update without one open.");
+ mFlushState = eInFlush;
+ mDocument->EndUpdate();
+ }
+
+ inline void BeginFlush() {
+ MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
+ "Tried to start a flush when already flushing.");
+ MOZ_RELEASE_ASSERT(mParser, "Started a flush without parser.");
+ mFlushState = eInFlush;
+ }
+
+ inline void EndFlush() {
+ MOZ_RELEASE_ASSERT(IsInFlush(), "Tried to end flush when not flushing.");
+ mFlushState = eNotFlushing;
+ }
+
+ inline bool IsInDocUpdate() { return mFlushState == eInDocUpdate; }
+
+ inline bool IsInFlush() { return mFlushState == eInFlush; }
+
+ /**
+ * Sets up style sheet load / parse
+ */
+ void UpdateStyleSheet(nsIContent* aElement);
+
+ void SetDocumentMode(nsHtml5DocumentMode m);
+
+ void SetNodeInfoManager(nsNodeInfoManager* aManager) {
+ mNodeInfoManager = aManager;
+ }
+
+ // nsContentSink methods
+ virtual void UpdateChildCounts() override;
+ virtual nsresult FlushTags() override;
+
+ protected:
+ explicit nsHtml5DocumentBuilder(bool aRunsToCompletion);
+ virtual ~nsHtml5DocumentBuilder();
+
+ protected:
+ AutoTArray<nsCOMPtr<nsIContent>, 32> mOwnedElements;
+ /**
+ * Non-NS_OK if this parser should refuse to process any more input.
+ * For example, the parser needs to be marked as broken if it drops some
+ * input due to a memory allocation failure. In such a case, the whole
+ * parser needs to be marked as broken, because some input has been lost
+ * and parsing more input could lead to a DOM where pieces of HTML source
+ * that weren't supposed to become scripts become scripts.
+ */
+ nsresult mBroken;
+ eHtml5FlushState mFlushState;
+};
+
+#endif // nsHtml5DocumentBuilder_h
diff --git a/parser/html/nsHtml5DocumentMode.h b/parser/html/nsHtml5DocumentMode.h
new file mode 100644
index 0000000000..962c7a66b4
--- /dev/null
+++ b/parser/html/nsHtml5DocumentMode.h
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5DocumentMode_h
+#define nsHtml5DocumentMode_h
+
+enum nsHtml5DocumentMode { STANDARDS_MODE, ALMOST_STANDARDS_MODE, QUIRKS_MODE };
+
+#endif // nsHtml5DocumentMode_h
diff --git a/parser/html/nsHtml5ElementName.cpp b/parser/html/nsHtml5ElementName.cpp
new file mode 100644
index 0000000000..93a6407d38
--- /dev/null
+++ b/parser/html/nsHtml5ElementName.cpp
@@ -0,0 +1,1495 @@
+/*
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit ElementName.java instead and regenerate.
+ */
+
+#define nsHtml5ElementName_cpp__
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5ElementName.h"
+
+nsHtml5ElementName::nsHtml5ElementName(
+ nsAtom* name, nsAtom* camelCaseName,
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator,
+ mozilla::dom::SVGContentCreatorFunction svgCreator, int32_t flags)
+ : name(name),
+ camelCaseName(camelCaseName),
+ htmlCreator(htmlCreator),
+ svgCreator(svgCreator),
+ flags(flags) {
+ MOZ_COUNT_CTOR(nsHtml5ElementName);
+}
+
+nsHtml5ElementName::nsHtml5ElementName()
+ : name(nullptr),
+ camelCaseName(nullptr),
+ htmlCreator(NS_NewHTMLUnknownElement),
+ svgCreator(NS_NewSVGUnknownElement),
+ flags(nsHtml5TreeBuilder::OTHER | NOT_INTERNED) {
+ MOZ_COUNT_CTOR(nsHtml5ElementName);
+}
+
+nsHtml5ElementName::~nsHtml5ElementName() {
+ MOZ_COUNT_DTOR(nsHtml5ElementName);
+}
+
+nsHtml5ElementName* nsHtml5ElementName::ELT_ANNOTATION_XML = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BIG = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BDI = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BDO = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_COL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DEL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DFN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DIR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DIV = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_IMG = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_INS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_KBD = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MAP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_NAV = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PRE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_A = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_B = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RTC = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SUB = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SVG = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SUP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SET = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_USE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_VAR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_G = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_WBR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_XMP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_I = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_P = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_Q = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_S = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_U = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_H1 = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_H2 = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_H3 = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_H4 = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_H5 = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_H6 = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_AREA = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DATA = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCA = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_METADATA = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_META = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TEXTAREA = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCB = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RB = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DESC = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DD = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BGSOUND = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_EMBED = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEBLEND = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEFLOOD = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_HEAD = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LEGEND = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_NOEMBED = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TD = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_THEAD = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ASIDE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ARTICLE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BASE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BLOCKQUOTE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CODE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CIRCLE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CITE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ELLIPSE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FETURBULENCE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEMERGENODE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEIMAGE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEMERGE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FETILE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FRAME = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FIGURE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FECOMPOSITE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_IMAGE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_IFRAME = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LINE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MARQUEE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_POLYLINE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PICTURE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SOURCE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_STRIKE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_STYLE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TABLE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TITLE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TIME = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TEMPLATE = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPHDEF = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_GLYPHREF = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DIALOG = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCG = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEDIFFUSELIGHTING = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FESPECULARLIGHTING = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LISTING = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_STRONG = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CLIPPATH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MGLYPH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MATH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MPATH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PATH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SWITCH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TEXTPATH = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LI = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MI = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LINK = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MARK = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MALIGNMARK = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MASK = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TRACK = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_HTML = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_OL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LABEL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_UL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SMALL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SYMBOL = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ALTGLYPHITEM = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATETRANSFORM = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ACRONYM = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_EM = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FORM = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PARAM = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATEMOTION = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BUTTON = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CAPTION = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FIGCAPTION = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_KEYGEN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MAIN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_OPTION = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_POLYGON = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PATTERN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SPAN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SECTION = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TSPAN = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_AUDIO = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MO = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_VIDEO = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_COLGROUP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEDISPLACEMENTMAP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_HGROUP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_OPTGROUP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SAMP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_STOP = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ABBR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ANIMATECOLOR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CENTER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_HR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEFUNCR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FECOMPONENTTRANSFER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FILTER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FOOTER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEGAUSSIANBLUR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_HEADER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MARKER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_METER = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_NOBR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TR = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_ADDRESS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_CANVAS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DEFS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DETAILS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_NOFRAMES = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PROGRESS = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_APPLET = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BASEFONT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_DATALIST = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FOREIGNOBJECT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FIELDSET = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FRAMESET = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEOFFSET = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FESPOTLIGHT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEPOINTLIGHT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEDISTANTLIGHT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FONT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_INPUT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_LINEARGRADIENT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MTEXT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_NOSCRIPT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_OBJECT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_OUTPUT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_PLAINTEXT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RECT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RADIALGRADIENT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SELECT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SLOT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SCRIPT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TFOOT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TEXT = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_MENU = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEDROPSHADOW = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_VIEW = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FECOLORMATRIX = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FECONVOLVEMATRIX = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_BODY = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_FEMORPHOLOGY = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_RUBY = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_SUMMARY = nullptr;
+nsHtml5ElementName* nsHtml5ElementName::ELT_TBODY = nullptr;
+nsHtml5ElementName** nsHtml5ElementName::ELEMENT_NAMES = 0;
+static int32_t const ELEMENT_HASHES_DATA[] = {
+ 1902641154, 1748359220, 2001349720, 876609538, 1798686984, 1971465813,
+ 2007781534, 59768833, 1730965751, 1756474198, 1868312196, 1939219752,
+ 1988763672, 2005324101, 2060065124, 52490899, 62390273, 1682547543,
+ 1740181637, 1749905526, 1766992520, 1818230786, 1881613047, 1907959605,
+ 1967760215, 1982935782, 1999397992, 2001392798, 2006329158, 2008851557,
+ 2085266636, 51961587, 57206291, 60352339, 67108865, 943718402,
+ 1699324759, 1733890180, 1747814436, 1749715159, 1752979652, 1757146773,
+ 1783388498, 1805502724, 1854228698, 1874053333, 1898223949, 1906087319,
+ 1932928296, 1965115924, 1968053806, 1973420034, 1983633431, 1998585858,
+ 2001309869, 2001392795, 2003183333, 2005925890, 2006974466, 2008325940,
+ 2021937364, 2068523856, 2092255447, 51435587, 52486755, 55110883,
+ 58773795, 60345171, 61395251, 62973651, 68681729, 910163970,
+ 1679960596, 1686491348, 1715310660, 1733054663, 1737099991, 1747176599,
+ 1748100148, 1749656156, 1749801286, 1751288021, 1755076808, 1756625221,
+ 1757268168, 1783210839, 1790207270, 1803929812, 1806806678, 1853642948,
+ 1857653029, 1870268949, 1881288348, 1884120164, 1899272519, 1904412884,
+ 1907435316, 1919418370, 1935549734, 1941221172, 1966223078, 1967795910,
+ 1971461414, 1971938532, 1982173479, 1983533124, 1986527234, 1990037800,
+ 1998724870, 2000525512, 2001349704, 2001349736, 2001392796, 2001495140,
+ 2004635806, 2005719336, 2006028454, 2006896969, 2007601444, 2008125638,
+ 2008340774, 2008994116, 2051837468, 2068523853, 2083120164, 2091479332,
+ 2092557349, 51434643, 51438659, 52485715, 52488851, 55104723,
+ 56151587, 57733651, 59244545, 59821379, 60347747, 60354131,
+ 61925907, 62450211, 63438849, 67633153, 69730305, 893386754,
+ 926941186, 960495618, 1681770564, 1686489160, 1689922072, 1703936002,
+ 1730150402, 1732381397, 1733076167, 1736200310, 1738539010, 1747048757,
+ 1747306711, 1747838298, 1748225318, 1749395095, 1749673195, 1749723735,
+ 1749813541, 1749932347, 1751386406, 1753362711, 1755148615, 1756600614,
+ 1757137429, 1757157700, 1763839627, 1782357526, 1783388497, 1786534215,
+ 1797585096, 1803876550, 1803929861, 1805647874, 1807599880, 1818755074,
+ 1854228692, 1854245076, 1864368130, 1870135298, 1873281026, 1874102998,
+ 1881498736, 1881669634, 1889085973, 1898753862, 1900845386, 1903302038,
+ 1905563974, 1906135367, 1907661127, 1914900309, 1925844629, 1934172497,
+ 1938817026, 1941178676, 1963982850, 1965334268, 1967128578, 1967788867,
+ 1967795958, 1968836118};
+staticJArray<int32_t, int32_t> nsHtml5ElementName::ELEMENT_HASHES = {
+ ELEMENT_HASHES_DATA, MOZ_ARRAY_LENGTH(ELEMENT_HASHES_DATA)};
+void nsHtml5ElementName::initializeStatics() {
+ ELT_ANNOTATION_XML = new nsHtml5ElementName(
+ nsGkAtoms::annotation_xml_, nsGkAtoms::annotation_xml_,
+ NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::ANNOTATION_XML | SCOPING_AS_MATHML);
+ ELT_BIG = new nsHtml5ElementName(
+ nsGkAtoms::big, nsGkAtoms::big, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_BDI = new nsHtml5ElementName(nsGkAtoms::bdi, nsGkAtoms::bdi,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_BDO = new nsHtml5ElementName(nsGkAtoms::bdo, nsGkAtoms::bdo,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_COL = new nsHtml5ElementName(
+ nsGkAtoms::col, nsGkAtoms::col, NS_NewHTMLTableColElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::COL | SPECIAL);
+ ELT_DEL = new nsHtml5ElementName(
+ nsGkAtoms::del, nsGkAtoms::del, NS_NewHTMLModElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_DFN = new nsHtml5ElementName(nsGkAtoms::dfn, nsGkAtoms::dfn,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_DIR = new nsHtml5ElementName(
+ nsGkAtoms::dir, nsGkAtoms::dir, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_DIV = new nsHtml5ElementName(
+ nsGkAtoms::div, nsGkAtoms::div, NS_NewHTMLDivElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+ ELT_IMG = new nsHtml5ElementName(
+ nsGkAtoms::img, nsGkAtoms::img, NS_NewHTMLImageElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::IMG | SPECIAL);
+ ELT_INS = new nsHtml5ElementName(
+ nsGkAtoms::ins, nsGkAtoms::ins, NS_NewHTMLModElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_KBD = new nsHtml5ElementName(nsGkAtoms::kbd, nsGkAtoms::kbd,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_MAP = new nsHtml5ElementName(
+ nsGkAtoms::map, nsGkAtoms::map, NS_NewHTMLMapElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_NAV = new nsHtml5ElementName(
+ nsGkAtoms::nav, nsGkAtoms::nav, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_PRE = new nsHtml5ElementName(
+ nsGkAtoms::pre, nsGkAtoms::pre, NS_NewHTMLPreElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PRE_OR_LISTING | SPECIAL);
+ ELT_A = new nsHtml5ElementName(nsGkAtoms::a, nsGkAtoms::a,
+ NS_NewHTMLAnchorElement, NS_NewSVGAElement,
+ nsHtml5TreeBuilder::A);
+ ELT_B = new nsHtml5ElementName(
+ nsGkAtoms::b, nsGkAtoms::b, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_RTC =
+ new nsHtml5ElementName(nsGkAtoms::rtc, nsGkAtoms::rtc, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RB_OR_RTC | OPTIONAL_END_TAG);
+ ELT_SUB = new nsHtml5ElementName(
+ nsGkAtoms::sub, nsGkAtoms::sub, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+ ELT_SVG = new nsHtml5ElementName(
+ nsGkAtoms::svg, nsGkAtoms::svg, NS_NewHTMLUnknownElement,
+ NS_NewSVGSVGElement, nsHtml5TreeBuilder::SVG);
+ ELT_SUP = new nsHtml5ElementName(
+ nsGkAtoms::sup, nsGkAtoms::sup, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+ ELT_SET = new nsHtml5ElementName(
+ nsGkAtoms::set, nsGkAtoms::set, NS_NewHTMLUnknownElement,
+ NS_NewSVGSetElement, nsHtml5TreeBuilder::OTHER);
+ ELT_USE = new nsHtml5ElementName(
+ nsGkAtoms::use, nsGkAtoms::use, NS_NewHTMLUnknownElement,
+ NS_NewSVGUseElement, nsHtml5TreeBuilder::OTHER);
+ ELT_VAR = new nsHtml5ElementName(
+ nsGkAtoms::var, nsGkAtoms::var, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+ ELT_G = new nsHtml5ElementName(nsGkAtoms::g, nsGkAtoms::g,
+ NS_NewHTMLUnknownElement, NS_NewSVGGElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_WBR = new nsHtml5ElementName(nsGkAtoms::wbr, nsGkAtoms::wbr,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::AREA_OR_WBR | SPECIAL);
+ ELT_XMP = new nsHtml5ElementName(
+ nsGkAtoms::xmp, nsGkAtoms::xmp, NS_NewHTMLPreElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::XMP | SPECIAL);
+ ELT_I = new nsHtml5ElementName(
+ nsGkAtoms::i, nsGkAtoms::i, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_P = new nsHtml5ElementName(
+ nsGkAtoms::p, nsGkAtoms::p, NS_NewHTMLParagraphElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::P | SPECIAL | OPTIONAL_END_TAG);
+ ELT_Q = new nsHtml5ElementName(
+ nsGkAtoms::q, nsGkAtoms::q, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_S = new nsHtml5ElementName(
+ nsGkAtoms::s, nsGkAtoms::s, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_U = new nsHtml5ElementName(
+ nsGkAtoms::u, nsGkAtoms::u, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_H1 = new nsHtml5ElementName(
+ nsGkAtoms::h1, nsGkAtoms::h1, NS_NewHTMLHeadingElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+ ELT_H2 = new nsHtml5ElementName(
+ nsGkAtoms::h2, nsGkAtoms::h2, NS_NewHTMLHeadingElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+ ELT_H3 = new nsHtml5ElementName(
+ nsGkAtoms::h3, nsGkAtoms::h3, NS_NewHTMLHeadingElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+ ELT_H4 = new nsHtml5ElementName(
+ nsGkAtoms::h4, nsGkAtoms::h4, NS_NewHTMLHeadingElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+ ELT_H5 = new nsHtml5ElementName(
+ nsGkAtoms::h5, nsGkAtoms::h5, NS_NewHTMLHeadingElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+ ELT_H6 = new nsHtml5ElementName(
+ nsGkAtoms::h6, nsGkAtoms::h6, NS_NewHTMLHeadingElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 | SPECIAL);
+ ELT_AREA = new nsHtml5ElementName(
+ nsGkAtoms::area, nsGkAtoms::area, NS_NewHTMLAreaElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::AREA_OR_WBR | SPECIAL);
+ ELT_DATA = new nsHtml5ElementName(
+ nsGkAtoms::data, nsGkAtoms::data, NS_NewHTMLDataElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FEFUNCA = new nsHtml5ElementName(
+ nsGkAtoms::fefunca, nsGkAtoms::feFuncA, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEFuncAElement, nsHtml5TreeBuilder::OTHER);
+ ELT_METADATA = new nsHtml5ElementName(
+ nsGkAtoms::metadata, nsGkAtoms::metadata, NS_NewHTMLUnknownElement,
+ NS_NewSVGMetadataElement, nsHtml5TreeBuilder::OTHER);
+ ELT_META = new nsHtml5ElementName(
+ nsGkAtoms::meta, nsGkAtoms::meta, NS_NewHTMLMetaElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::META | SPECIAL);
+ ELT_TEXTAREA = new nsHtml5ElementName(
+ nsGkAtoms::textarea, nsGkAtoms::textarea, NS_NewHTMLTextAreaElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::TEXTAREA | SPECIAL);
+ ELT_FEFUNCB = new nsHtml5ElementName(
+ nsGkAtoms::fefuncb, nsGkAtoms::feFuncB, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEFuncBElement, nsHtml5TreeBuilder::OTHER);
+ ELT_RB = new nsHtml5ElementName(
+ nsGkAtoms::rb, nsGkAtoms::rb, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RB_OR_RTC | OPTIONAL_END_TAG);
+ ELT_DESC = new nsHtml5ElementName(
+ nsGkAtoms::desc, nsGkAtoms::desc, NS_NewHTMLUnknownElement,
+ NS_NewSVGDescElement,
+ nsHtml5TreeBuilder::FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG);
+ ELT_DD = new nsHtml5ElementName(
+ nsGkAtoms::dd, nsGkAtoms::dd, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::DD_OR_DT | SPECIAL | OPTIONAL_END_TAG);
+ ELT_BGSOUND = new nsHtml5ElementName(
+ nsGkAtoms::bgsound, nsGkAtoms::bgsound, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL);
+ ELT_EMBED = new nsHtml5ElementName(
+ nsGkAtoms::embed, nsGkAtoms::embed, NS_NewHTMLEmbedElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::EMBED | SPECIAL);
+ ELT_FEBLEND = new nsHtml5ElementName(
+ nsGkAtoms::feblend, nsGkAtoms::feBlend, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEBlendElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FEFLOOD = new nsHtml5ElementName(
+ nsGkAtoms::feflood, nsGkAtoms::feFlood, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEFloodElement, nsHtml5TreeBuilder::OTHER);
+ ELT_HEAD = new nsHtml5ElementName(
+ nsGkAtoms::head, nsGkAtoms::head, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::HEAD | SPECIAL | OPTIONAL_END_TAG);
+ ELT_LEGEND = new nsHtml5ElementName(
+ nsGkAtoms::legend, nsGkAtoms::legend, NS_NewHTMLLegendElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_NOEMBED = new nsHtml5ElementName(
+ nsGkAtoms::noembed, nsGkAtoms::noembed, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::NOEMBED | SPECIAL);
+ ELT_TD = new nsHtml5ElementName(
+ nsGkAtoms::td, nsGkAtoms::td, NS_NewHTMLTableCellElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG);
+ ELT_THEAD = new nsHtml5ElementName(
+ nsGkAtoms::thead, nsGkAtoms::thead, NS_NewHTMLTableSectionElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING |
+ OPTIONAL_END_TAG);
+ ELT_ASIDE = new nsHtml5ElementName(
+ nsGkAtoms::aside, nsGkAtoms::aside, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_ARTICLE = new nsHtml5ElementName(
+ nsGkAtoms::article, nsGkAtoms::article, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_ANIMATE = new nsHtml5ElementName(
+ nsGkAtoms::animate, nsGkAtoms::animate, NS_NewHTMLUnknownElement,
+ NS_NewSVGAnimateElement, nsHtml5TreeBuilder::OTHER);
+ ELT_BASE = new nsHtml5ElementName(
+ nsGkAtoms::base, nsGkAtoms::base, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::BASE | SPECIAL);
+ ELT_BLOCKQUOTE = new nsHtml5ElementName(
+ nsGkAtoms::blockquote, nsGkAtoms::blockquote, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+ ELT_CODE = new nsHtml5ElementName(
+ nsGkAtoms::code, nsGkAtoms::code, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_CIRCLE = new nsHtml5ElementName(
+ nsGkAtoms::circle, nsGkAtoms::circle, NS_NewHTMLUnknownElement,
+ NS_NewSVGCircleElement, nsHtml5TreeBuilder::OTHER);
+ ELT_CITE = new nsHtml5ElementName(nsGkAtoms::cite, nsGkAtoms::cite,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_ELLIPSE = new nsHtml5ElementName(
+ nsGkAtoms::ellipse, nsGkAtoms::ellipse, NS_NewHTMLUnknownElement,
+ NS_NewSVGEllipseElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FETURBULENCE = new nsHtml5ElementName(
+ nsGkAtoms::feturbulence, nsGkAtoms::feTurbulence,
+ NS_NewHTMLUnknownElement, NS_NewSVGFETurbulenceElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_FEMERGENODE = new nsHtml5ElementName(
+ nsGkAtoms::femergenode, nsGkAtoms::feMergeNode, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEMergeNodeElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FEIMAGE = new nsHtml5ElementName(
+ nsGkAtoms::feimage, nsGkAtoms::feImage, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEImageElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FEMERGE = new nsHtml5ElementName(
+ nsGkAtoms::femerge, nsGkAtoms::feMerge, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEMergeElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FETILE = new nsHtml5ElementName(
+ nsGkAtoms::fetile, nsGkAtoms::feTile, NS_NewHTMLUnknownElement,
+ NS_NewSVGFETileElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FRAME = new nsHtml5ElementName(
+ nsGkAtoms::frame, nsGkAtoms::frame, NS_NewHTMLFrameElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FRAME | SPECIAL);
+ ELT_FIGURE = new nsHtml5ElementName(
+ nsGkAtoms::figure, nsGkAtoms::figure, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_FECOMPOSITE = new nsHtml5ElementName(
+ nsGkAtoms::fecomposite, nsGkAtoms::feComposite, NS_NewHTMLUnknownElement,
+ NS_NewSVGFECompositeElement, nsHtml5TreeBuilder::OTHER);
+ ELT_IMAGE = new nsHtml5ElementName(nsGkAtoms::image, nsGkAtoms::image,
+ NS_NewHTMLElement, NS_NewSVGImageElement,
+ nsHtml5TreeBuilder::IMAGE);
+ ELT_IFRAME = new nsHtml5ElementName(
+ nsGkAtoms::iframe, nsGkAtoms::iframe, NS_NewHTMLIFrameElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::IFRAME | SPECIAL);
+ ELT_LINE = new nsHtml5ElementName(
+ nsGkAtoms::line, nsGkAtoms::line, NS_NewHTMLUnknownElement,
+ NS_NewSVGLineElement, nsHtml5TreeBuilder::OTHER);
+ ELT_MARQUEE = new nsHtml5ElementName(
+ nsGkAtoms::marquee, nsGkAtoms::marquee, NS_NewHTMLMarqueeElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MARQUEE_OR_APPLET | SPECIAL | SCOPING);
+ ELT_POLYLINE = new nsHtml5ElementName(
+ nsGkAtoms::polyline, nsGkAtoms::polyline, NS_NewHTMLUnknownElement,
+ NS_NewSVGPolylineElement, nsHtml5TreeBuilder::OTHER);
+ ELT_PICTURE = new nsHtml5ElementName(
+ nsGkAtoms::picture, nsGkAtoms::picture, NS_NewHTMLPictureElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_SOURCE = new nsHtml5ElementName(
+ nsGkAtoms::source, nsGkAtoms::source, NS_NewHTMLSourceElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PARAM_OR_SOURCE_OR_TRACK);
+ ELT_STRIKE = new nsHtml5ElementName(
+ nsGkAtoms::strike, nsGkAtoms::strike, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_STYLE = new nsHtml5ElementName(
+ nsGkAtoms::style, nsGkAtoms::style, NS_NewHTMLStyleElement,
+ NS_NewSVGStyleElement, nsHtml5TreeBuilder::STYLE | SPECIAL);
+ ELT_TABLE = new nsHtml5ElementName(
+ nsGkAtoms::table, nsGkAtoms::table, NS_NewHTMLTableElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TABLE | SPECIAL | FOSTER_PARENTING | SCOPING);
+ ELT_TITLE = new nsHtml5ElementName(
+ nsGkAtoms::title, nsGkAtoms::title, NS_NewHTMLTitleElement,
+ NS_NewSVGTitleElement,
+ nsHtml5TreeBuilder::TITLE | SPECIAL | SCOPING_AS_SVG);
+ ELT_TIME = new nsHtml5ElementName(
+ nsGkAtoms::time, nsGkAtoms::time, NS_NewHTMLTimeElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_TEMPLATE =
+ new nsHtml5ElementName(nsGkAtoms::_template, nsGkAtoms::_template,
+ NS_NewHTMLTemplateElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TEMPLATE | SPECIAL | SCOPING);
+ ELT_ALTGLYPHDEF = new nsHtml5ElementName(
+ nsGkAtoms::altglyphdef, nsGkAtoms::altGlyphDef, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_GLYPHREF = new nsHtml5ElementName(
+ nsGkAtoms::glyphref, nsGkAtoms::glyphRef, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_DIALOG = new nsHtml5ElementName(
+ nsGkAtoms::dialog, nsGkAtoms::dialog, NS_NewHTMLDialogElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_FEFUNCG = new nsHtml5ElementName(
+ nsGkAtoms::fefuncg, nsGkAtoms::feFuncG, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEFuncGElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FEDIFFUSELIGHTING = new nsHtml5ElementName(
+ nsGkAtoms::fediffuselighting, nsGkAtoms::feDiffuseLighting,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEDiffuseLightingElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_FESPECULARLIGHTING = new nsHtml5ElementName(
+ nsGkAtoms::fespecularlighting, nsGkAtoms::feSpecularLighting,
+ NS_NewHTMLUnknownElement, NS_NewSVGFESpecularLightingElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_LISTING = new nsHtml5ElementName(
+ nsGkAtoms::listing, nsGkAtoms::listing, NS_NewHTMLPreElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PRE_OR_LISTING | SPECIAL);
+ ELT_STRONG = new nsHtml5ElementName(
+ nsGkAtoms::strong, nsGkAtoms::strong, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_ALTGLYPH = new nsHtml5ElementName(
+ nsGkAtoms::altglyph, nsGkAtoms::altGlyph, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_CLIPPATH = new nsHtml5ElementName(
+ nsGkAtoms::clippath, nsGkAtoms::clipPath, NS_NewHTMLUnknownElement,
+ NS_NewSVGClipPathElement, nsHtml5TreeBuilder::OTHER);
+ ELT_MGLYPH = new nsHtml5ElementName(
+ nsGkAtoms::mglyph_, nsGkAtoms::mglyph_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::MGLYPH_OR_MALIGNMARK);
+ ELT_MATH = new nsHtml5ElementName(
+ nsGkAtoms::math, nsGkAtoms::math, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::MATH);
+ ELT_MPATH = new nsHtml5ElementName(
+ nsGkAtoms::mpath, nsGkAtoms::mpath, NS_NewHTMLUnknownElement,
+ NS_NewSVGMPathElement, nsHtml5TreeBuilder::OTHER);
+ ELT_PATH = new nsHtml5ElementName(
+ nsGkAtoms::path, nsGkAtoms::path, NS_NewHTMLUnknownElement,
+ NS_NewSVGPathElement, nsHtml5TreeBuilder::OTHER);
+ ELT_TH = new nsHtml5ElementName(
+ nsGkAtoms::th, nsGkAtoms::th, NS_NewHTMLTableCellElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TD_OR_TH | SPECIAL | SCOPING | OPTIONAL_END_TAG);
+ ELT_SWITCH = new nsHtml5ElementName(
+ nsGkAtoms::svgSwitch, nsGkAtoms::svgSwitch, NS_NewHTMLUnknownElement,
+ NS_NewSVGSwitchElement, nsHtml5TreeBuilder::OTHER);
+ ELT_TEXTPATH = new nsHtml5ElementName(
+ nsGkAtoms::textpath, nsGkAtoms::textPath, NS_NewHTMLUnknownElement,
+ NS_NewSVGTextPathElement, nsHtml5TreeBuilder::OTHER);
+ ELT_LI = new nsHtml5ElementName(
+ nsGkAtoms::li, nsGkAtoms::li, NS_NewHTMLLIElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::LI | SPECIAL | OPTIONAL_END_TAG);
+ ELT_MI = new nsHtml5ElementName(
+ nsGkAtoms::mi_, nsGkAtoms::mi_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+ ELT_LINK = new nsHtml5ElementName(
+ nsGkAtoms::link, nsGkAtoms::link, NS_NewHTMLLinkElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL);
+ ELT_MARK = new nsHtml5ElementName(nsGkAtoms::mark, nsGkAtoms::mark,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_MALIGNMARK = new nsHtml5ElementName(
+ nsGkAtoms::malignmark_, nsGkAtoms::malignmark_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::MGLYPH_OR_MALIGNMARK);
+ ELT_MASK = new nsHtml5ElementName(
+ nsGkAtoms::mask, nsGkAtoms::mask, NS_NewHTMLUnknownElement,
+ NS_NewSVGMaskElement, nsHtml5TreeBuilder::OTHER);
+ ELT_TRACK = new nsHtml5ElementName(
+ nsGkAtoms::track, nsGkAtoms::track, NS_NewHTMLTrackElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::PARAM_OR_SOURCE_OR_TRACK | SPECIAL);
+ ELT_DL = new nsHtml5ElementName(
+ nsGkAtoms::dl, nsGkAtoms::dl, NS_NewHTMLSharedListElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::UL_OR_OL_OR_DL | SPECIAL);
+ ELT_HTML = new nsHtml5ElementName(
+ nsGkAtoms::html, nsGkAtoms::html, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::HTML | SPECIAL | SCOPING | OPTIONAL_END_TAG);
+ ELT_OL = new nsHtml5ElementName(
+ nsGkAtoms::ol, nsGkAtoms::ol, NS_NewHTMLSharedListElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::UL_OR_OL_OR_DL | SPECIAL);
+ ELT_LABEL = new nsHtml5ElementName(
+ nsGkAtoms::label, nsGkAtoms::label, NS_NewHTMLLabelElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_UL = new nsHtml5ElementName(
+ nsGkAtoms::ul, nsGkAtoms::ul, NS_NewHTMLSharedListElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::UL_OR_OL_OR_DL | SPECIAL);
+ ELT_SMALL = new nsHtml5ElementName(
+ nsGkAtoms::small, nsGkAtoms::small, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_SYMBOL = new nsHtml5ElementName(
+ nsGkAtoms::symbol, nsGkAtoms::symbol, NS_NewHTMLUnknownElement,
+ NS_NewSVGSymbolElement, nsHtml5TreeBuilder::OTHER);
+ ELT_ALTGLYPHITEM =
+ new nsHtml5ElementName(nsGkAtoms::altglyphitem, nsGkAtoms::altGlyphItem,
+ NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_ANIMATETRANSFORM = new nsHtml5ElementName(
+ nsGkAtoms::animatetransform, nsGkAtoms::animateTransform,
+ NS_NewHTMLUnknownElement, NS_NewSVGAnimateTransformElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_ACRONYM = new nsHtml5ElementName(
+ nsGkAtoms::acronym, nsGkAtoms::acronym, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_EM = new nsHtml5ElementName(
+ nsGkAtoms::em, nsGkAtoms::em, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_FORM = new nsHtml5ElementName(
+ nsGkAtoms::form, nsGkAtoms::form, NS_NewHTMLFormElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FORM | SPECIAL);
+ ELT_PARAM = new nsHtml5ElementName(
+ nsGkAtoms::param, nsGkAtoms::param, NS_NewHTMLSharedElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::PARAM_OR_SOURCE_OR_TRACK | SPECIAL);
+ ELT_ANIMATEMOTION = new nsHtml5ElementName(
+ nsGkAtoms::animatemotion, nsGkAtoms::animateMotion,
+ NS_NewHTMLUnknownElement, NS_NewSVGAnimateMotionElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_BUTTON = new nsHtml5ElementName(
+ nsGkAtoms::button, nsGkAtoms::button, NS_NewHTMLButtonElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::BUTTON | SPECIAL);
+ ELT_CAPTION = new nsHtml5ElementName(
+ nsGkAtoms::caption, nsGkAtoms::caption, NS_NewHTMLTableCaptionElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::CAPTION | SPECIAL | SCOPING);
+ ELT_FIGCAPTION = new nsHtml5ElementName(
+ nsGkAtoms::figcaption, nsGkAtoms::figcaption, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_MN = new nsHtml5ElementName(
+ nsGkAtoms::mn_, nsGkAtoms::mn_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+ ELT_KEYGEN = new nsHtml5ElementName(
+ nsGkAtoms::keygen, nsGkAtoms::keygen, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::KEYGEN | SPECIAL);
+ ELT_MAIN = new nsHtml5ElementName(
+ nsGkAtoms::main, nsGkAtoms::main, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_OPTION = new nsHtml5ElementName(
+ nsGkAtoms::option, nsGkAtoms::option, NS_NewHTMLOptionElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OPTION | OPTIONAL_END_TAG);
+ ELT_POLYGON = new nsHtml5ElementName(
+ nsGkAtoms::polygon, nsGkAtoms::polygon, NS_NewHTMLUnknownElement,
+ NS_NewSVGPolygonElement, nsHtml5TreeBuilder::OTHER);
+ ELT_PATTERN = new nsHtml5ElementName(
+ nsGkAtoms::pattern, nsGkAtoms::pattern, NS_NewHTMLUnknownElement,
+ NS_NewSVGPatternElement, nsHtml5TreeBuilder::OTHER);
+ ELT_SPAN = new nsHtml5ElementName(
+ nsGkAtoms::span, nsGkAtoms::span, NS_NewHTMLSpanElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+ ELT_SECTION = new nsHtml5ElementName(
+ nsGkAtoms::section, nsGkAtoms::section, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_TSPAN = new nsHtml5ElementName(
+ nsGkAtoms::tspan, nsGkAtoms::tspan, NS_NewHTMLUnknownElement,
+ NS_NewSVGTSpanElement, nsHtml5TreeBuilder::OTHER);
+ ELT_AUDIO = new nsHtml5ElementName(
+ nsGkAtoms::audio, nsGkAtoms::audio, NS_NewHTMLAudioElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_MO = new nsHtml5ElementName(
+ nsGkAtoms::mo_, nsGkAtoms::mo_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+ ELT_VIDEO = new nsHtml5ElementName(
+ nsGkAtoms::video, nsGkAtoms::video, NS_NewHTMLVideoElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_COLGROUP = new nsHtml5ElementName(
+ nsGkAtoms::colgroup, nsGkAtoms::colgroup, NS_NewHTMLTableColElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::COLGROUP | SPECIAL | OPTIONAL_END_TAG);
+ ELT_FEDISPLACEMENTMAP = new nsHtml5ElementName(
+ nsGkAtoms::fedisplacementmap, nsGkAtoms::feDisplacementMap,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEDisplacementMapElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_HGROUP = new nsHtml5ElementName(
+ nsGkAtoms::hgroup, nsGkAtoms::hgroup, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_RP = new nsHtml5ElementName(
+ nsGkAtoms::rp, nsGkAtoms::rp, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RT_OR_RP | OPTIONAL_END_TAG);
+ ELT_OPTGROUP = new nsHtml5ElementName(
+ nsGkAtoms::optgroup, nsGkAtoms::optgroup, NS_NewHTMLOptGroupElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OPTGROUP | OPTIONAL_END_TAG);
+ ELT_SAMP = new nsHtml5ElementName(nsGkAtoms::samp, nsGkAtoms::samp,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_STOP = new nsHtml5ElementName(
+ nsGkAtoms::stop, nsGkAtoms::stop, NS_NewHTMLUnknownElement,
+ NS_NewSVGStopElement, nsHtml5TreeBuilder::OTHER);
+ ELT_BR = new nsHtml5ElementName(nsGkAtoms::br, nsGkAtoms::br,
+ NS_NewHTMLBRElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::BR | SPECIAL);
+ ELT_ABBR = new nsHtml5ElementName(nsGkAtoms::abbr, nsGkAtoms::abbr,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_ANIMATECOLOR =
+ new nsHtml5ElementName(nsGkAtoms::animatecolor, nsGkAtoms::animateColor,
+ NS_NewHTMLUnknownElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_CENTER = new nsHtml5ElementName(
+ nsGkAtoms::center, nsGkAtoms::center, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+ ELT_HR = new nsHtml5ElementName(nsGkAtoms::hr, nsGkAtoms::hr,
+ NS_NewHTMLHRElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::HR | SPECIAL);
+ ELT_FEFUNCR = new nsHtml5ElementName(
+ nsGkAtoms::fefuncr, nsGkAtoms::feFuncR, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEFuncRElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FECOMPONENTTRANSFER = new nsHtml5ElementName(
+ nsGkAtoms::fecomponenttransfer, nsGkAtoms::feComponentTransfer,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEComponentTransferElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_FILTER = new nsHtml5ElementName(
+ nsGkAtoms::filter, nsGkAtoms::filter, NS_NewHTMLUnknownElement,
+ NS_NewSVGFilterElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FOOTER = new nsHtml5ElementName(
+ nsGkAtoms::footer, nsGkAtoms::footer, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_FEGAUSSIANBLUR = new nsHtml5ElementName(
+ nsGkAtoms::fegaussianblur, nsGkAtoms::feGaussianBlur,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEGaussianBlurElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_HEADER = new nsHtml5ElementName(
+ nsGkAtoms::header, nsGkAtoms::header, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_MARKER = new nsHtml5ElementName(
+ nsGkAtoms::marker, nsGkAtoms::marker, NS_NewHTMLUnknownElement,
+ NS_NewSVGMarkerElement, nsHtml5TreeBuilder::OTHER);
+ ELT_METER = new nsHtml5ElementName(
+ nsGkAtoms::meter, nsGkAtoms::meter, NS_NewHTMLMeterElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_NOBR = new nsHtml5ElementName(nsGkAtoms::nobr, nsGkAtoms::nobr,
+ NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::NOBR);
+ ELT_TR = new nsHtml5ElementName(
+ nsGkAtoms::tr, nsGkAtoms::tr, NS_NewHTMLTableRowElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TR | SPECIAL | FOSTER_PARENTING | OPTIONAL_END_TAG);
+ ELT_ADDRESS = new nsHtml5ElementName(
+ nsGkAtoms::address, nsGkAtoms::address, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_CANVAS = new nsHtml5ElementName(
+ nsGkAtoms::canvas, nsGkAtoms::canvas, NS_NewHTMLCanvasElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_DEFS = new nsHtml5ElementName(
+ nsGkAtoms::defs, nsGkAtoms::defs, NS_NewHTMLUnknownElement,
+ NS_NewSVGDefsElement, nsHtml5TreeBuilder::OTHER);
+ ELT_DETAILS = new nsHtml5ElementName(
+ nsGkAtoms::details, nsGkAtoms::details, NS_NewHTMLDetailsElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_MS = new nsHtml5ElementName(
+ nsGkAtoms::ms_, nsGkAtoms::ms_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+ ELT_NOFRAMES = new nsHtml5ElementName(
+ nsGkAtoms::noframes, nsGkAtoms::noframes, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::NOFRAMES | SPECIAL);
+ ELT_PROGRESS = new nsHtml5ElementName(
+ nsGkAtoms::progress, nsGkAtoms::progress, NS_NewHTMLProgressElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_DT = new nsHtml5ElementName(
+ nsGkAtoms::dt, nsGkAtoms::dt, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::DD_OR_DT | SPECIAL | OPTIONAL_END_TAG);
+ ELT_APPLET = new nsHtml5ElementName(
+ nsGkAtoms::applet, nsGkAtoms::applet, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MARQUEE_OR_APPLET | SPECIAL | SCOPING);
+ ELT_BASEFONT = new nsHtml5ElementName(
+ nsGkAtoms::basefont, nsGkAtoms::basefont, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::LINK_OR_BASEFONT_OR_BGSOUND | SPECIAL);
+ ELT_DATALIST = new nsHtml5ElementName(
+ nsGkAtoms::datalist, nsGkAtoms::datalist, NS_NewHTMLDataListElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FOREIGNOBJECT = new nsHtml5ElementName(
+ nsGkAtoms::foreignobject, nsGkAtoms::foreignObject,
+ NS_NewHTMLUnknownElement, NS_NewSVGForeignObjectElement,
+ nsHtml5TreeBuilder::FOREIGNOBJECT_OR_DESC | SCOPING_AS_SVG);
+ ELT_FIELDSET = new nsHtml5ElementName(
+ nsGkAtoms::fieldset, nsGkAtoms::fieldset, NS_NewHTMLFieldSetElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FIELDSET | SPECIAL);
+ ELT_FRAMESET = new nsHtml5ElementName(
+ nsGkAtoms::frameset, nsGkAtoms::frameset, NS_NewHTMLFrameSetElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FRAMESET | SPECIAL);
+ ELT_FEOFFSET = new nsHtml5ElementName(
+ nsGkAtoms::feoffset, nsGkAtoms::feOffset, NS_NewHTMLUnknownElement,
+ NS_NewSVGFEOffsetElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FESPOTLIGHT = new nsHtml5ElementName(
+ nsGkAtoms::fespotlight, nsGkAtoms::feSpotLight, NS_NewHTMLUnknownElement,
+ NS_NewSVGFESpotLightElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FEPOINTLIGHT = new nsHtml5ElementName(
+ nsGkAtoms::fepointlight, nsGkAtoms::fePointLight,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEPointLightElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_FEDISTANTLIGHT = new nsHtml5ElementName(
+ nsGkAtoms::fedistantlight, nsGkAtoms::feDistantLight,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEDistantLightElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_FONT = new nsHtml5ElementName(
+ nsGkAtoms::font, nsGkAtoms::font, NS_NewHTMLFontElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::FONT);
+ ELT_INPUT = new nsHtml5ElementName(
+ nsGkAtoms::input, nsGkAtoms::input, NS_NewHTMLInputElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::INPUT | SPECIAL);
+ ELT_LINEARGRADIENT = new nsHtml5ElementName(
+ nsGkAtoms::lineargradient, nsGkAtoms::linearGradient,
+ NS_NewHTMLUnknownElement, NS_NewSVGLinearGradientElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_MTEXT = new nsHtml5ElementName(
+ nsGkAtoms::mtext_, nsGkAtoms::mtext_, NS_NewHTMLUnknownElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::MI_MO_MN_MS_MTEXT | SCOPING_AS_MATHML);
+ ELT_NOSCRIPT = new nsHtml5ElementName(
+ nsGkAtoms::noscript, nsGkAtoms::noscript, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::NOSCRIPT | SPECIAL);
+ ELT_RT = new nsHtml5ElementName(
+ nsGkAtoms::rt, nsGkAtoms::rt, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RT_OR_RP | OPTIONAL_END_TAG);
+ ELT_OBJECT = new nsHtml5ElementName(
+ nsGkAtoms::object, nsGkAtoms::object, NS_NewHTMLObjectElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OBJECT | SPECIAL | SCOPING);
+ ELT_OUTPUT = new nsHtml5ElementName(
+ nsGkAtoms::output, nsGkAtoms::output, NS_NewHTMLOutputElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OUTPUT);
+ ELT_PLAINTEXT = new nsHtml5ElementName(
+ nsGkAtoms::plaintext, nsGkAtoms::plaintext, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::PLAINTEXT | SPECIAL);
+ ELT_TT = new nsHtml5ElementName(
+ nsGkAtoms::tt, nsGkAtoms::tt, NS_NewHTMLElement, NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
+ ELT_RECT = new nsHtml5ElementName(
+ nsGkAtoms::rect, nsGkAtoms::rect, NS_NewHTMLUnknownElement,
+ NS_NewSVGRectElement, nsHtml5TreeBuilder::OTHER);
+ ELT_RADIALGRADIENT = new nsHtml5ElementName(
+ nsGkAtoms::radialgradient, nsGkAtoms::radialGradient,
+ NS_NewHTMLUnknownElement, NS_NewSVGRadialGradientElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_SELECT = new nsHtml5ElementName(
+ nsGkAtoms::select, nsGkAtoms::select, NS_NewHTMLSelectElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::SELECT | SPECIAL);
+ ELT_SLOT = new nsHtml5ElementName(
+ nsGkAtoms::slot, nsGkAtoms::slot, NS_NewHTMLSlotElement,
+ NS_NewSVGUnknownElement, nsHtml5TreeBuilder::OTHER);
+ ELT_SCRIPT = new nsHtml5ElementName(
+ nsGkAtoms::script, nsGkAtoms::script, NS_NewHTMLScriptElement,
+ NS_NewSVGScriptElement, nsHtml5TreeBuilder::SCRIPT | SPECIAL);
+ ELT_TFOOT = new nsHtml5ElementName(
+ nsGkAtoms::tfoot, nsGkAtoms::tfoot, NS_NewHTMLTableSectionElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING |
+ OPTIONAL_END_TAG);
+ ELT_TEXT = new nsHtml5ElementName(
+ nsGkAtoms::text, nsGkAtoms::text, NS_NewHTMLUnknownElement,
+ NS_NewSVGTextElement, nsHtml5TreeBuilder::OTHER);
+ ELT_MENU = new nsHtml5ElementName(
+ nsGkAtoms::menu, nsGkAtoms::menu, NS_NewHTMLMenuElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU | SPECIAL);
+ ELT_FEDROPSHADOW = new nsHtml5ElementName(
+ nsGkAtoms::fedropshadow, nsGkAtoms::feDropShadow,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEDropShadowElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_VIEW = new nsHtml5ElementName(
+ nsGkAtoms::view, nsGkAtoms::view, NS_NewHTMLUnknownElement,
+ NS_NewSVGViewElement, nsHtml5TreeBuilder::OTHER);
+ ELT_FECOLORMATRIX = new nsHtml5ElementName(
+ nsGkAtoms::fecolormatrix, nsGkAtoms::feColorMatrix,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEColorMatrixElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_FECONVOLVEMATRIX = new nsHtml5ElementName(
+ nsGkAtoms::feconvolvematrix, nsGkAtoms::feConvolveMatrix,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEConvolveMatrixElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_BODY = new nsHtml5ElementName(
+ nsGkAtoms::body, nsGkAtoms::body, NS_NewHTMLBodyElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::BODY | SPECIAL | OPTIONAL_END_TAG);
+ ELT_FEMORPHOLOGY = new nsHtml5ElementName(
+ nsGkAtoms::femorphology, nsGkAtoms::feMorphology,
+ NS_NewHTMLUnknownElement, NS_NewSVGFEMorphologyElement,
+ nsHtml5TreeBuilder::OTHER);
+ ELT_RUBY = new nsHtml5ElementName(
+ nsGkAtoms::ruby, nsGkAtoms::ruby, NS_NewHTMLElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR);
+ ELT_SUMMARY = new nsHtml5ElementName(
+ nsGkAtoms::summary, nsGkAtoms::summary, NS_NewHTMLSummaryElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY |
+ SPECIAL);
+ ELT_TBODY = new nsHtml5ElementName(
+ nsGkAtoms::tbody, nsGkAtoms::tbody, NS_NewHTMLTableSectionElement,
+ NS_NewSVGUnknownElement,
+ nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT | SPECIAL | FOSTER_PARENTING |
+ OPTIONAL_END_TAG);
+ ELEMENT_NAMES = new nsHtml5ElementName*[206];
+ ELEMENT_NAMES[0] = ELT_MN;
+ ELEMENT_NAMES[1] = ELT_CITE;
+ ELEMENT_NAMES[2] = ELT_FRAMESET;
+ ELEMENT_NAMES[3] = ELT_H1;
+ ELEMENT_NAMES[4] = ELT_CLIPPATH;
+ ELEMENT_NAMES[5] = ELT_METER;
+ ELEMENT_NAMES[6] = ELT_RADIALGRADIENT;
+ ELEMENT_NAMES[7] = ELT_B;
+ ELEMENT_NAMES[8] = ELT_BGSOUND;
+ ELEMENT_NAMES[9] = ELT_SOURCE;
+ ELEMENT_NAMES[10] = ELT_HTML;
+ ELEMENT_NAMES[11] = ELT_OPTGROUP;
+ ELEMENT_NAMES[12] = ELT_NOFRAMES;
+ ELEMENT_NAMES[13] = ELT_MTEXT;
+ ELEMENT_NAMES[14] = ELT_VIEW;
+ ELEMENT_NAMES[15] = ELT_DIV;
+ ELEMENT_NAMES[16] = ELT_G;
+ ELEMENT_NAMES[17] = ELT_FEFUNCA;
+ ELEMENT_NAMES[18] = ELT_THEAD;
+ ELEMENT_NAMES[19] = ELT_FIGURE;
+ ELEMENT_NAMES[20] = ELT_GLYPHREF;
+ ELEMENT_NAMES[21] = ELT_LI;
+ ELEMENT_NAMES[22] = ELT_ACRONYM;
+ ELEMENT_NAMES[23] = ELT_TSPAN;
+ ELEMENT_NAMES[24] = ELT_FEFUNCR;
+ ELEMENT_NAMES[25] = ELT_CANVAS;
+ ELEMENT_NAMES[26] = ELT_BASEFONT;
+ ELEMENT_NAMES[27] = ELT_FEDISTANTLIGHT;
+ ELEMENT_NAMES[28] = ELT_OUTPUT;
+ ELEMENT_NAMES[29] = ELT_TFOOT;
+ ELEMENT_NAMES[30] = ELT_FEMORPHOLOGY;
+ ELEMENT_NAMES[31] = ELT_COL;
+ ELEMENT_NAMES[32] = ELT_MAP;
+ ELEMENT_NAMES[33] = ELT_SUP;
+ ELEMENT_NAMES[34] = ELT_P;
+ ELEMENT_NAMES[35] = ELT_H5;
+ ELEMENT_NAMES[36] = ELT_FEFUNCB;
+ ELEMENT_NAMES[37] = ELT_HEAD;
+ ELEMENT_NAMES[38] = ELT_BASE;
+ ELEMENT_NAMES[39] = ELT_FEIMAGE;
+ ELEMENT_NAMES[40] = ELT_LINE;
+ ELEMENT_NAMES[41] = ELT_TITLE;
+ ELEMENT_NAMES[42] = ELT_FESPECULARLIGHTING;
+ ELEMENT_NAMES[43] = ELT_PATH;
+ ELEMENT_NAMES[44] = ELT_MALIGNMARK;
+ ELEMENT_NAMES[45] = ELT_SMALL;
+ ELEMENT_NAMES[46] = ELT_ANIMATEMOTION;
+ ELEMENT_NAMES[47] = ELT_POLYGON;
+ ELEMENT_NAMES[48] = ELT_COLGROUP;
+ ELEMENT_NAMES[49] = ELT_ABBR;
+ ELEMENT_NAMES[50] = ELT_FEGAUSSIANBLUR;
+ ELEMENT_NAMES[51] = ELT_TR;
+ ELEMENT_NAMES[52] = ELT_DETAILS;
+ ELEMENT_NAMES[53] = ELT_DT;
+ ELEMENT_NAMES[54] = ELT_FOREIGNOBJECT;
+ ELEMENT_NAMES[55] = ELT_FESPOTLIGHT;
+ ELEMENT_NAMES[56] = ELT_INPUT;
+ ELEMENT_NAMES[57] = ELT_RT;
+ ELEMENT_NAMES[58] = ELT_TT;
+ ELEMENT_NAMES[59] = ELT_SLOT;
+ ELEMENT_NAMES[60] = ELT_MENU;
+ ELEMENT_NAMES[61] = ELT_FECONVOLVEMATRIX;
+ ELEMENT_NAMES[62] = ELT_SUMMARY;
+ ELEMENT_NAMES[63] = ELT_BDI;
+ ELEMENT_NAMES[64] = ELT_DFN;
+ ELEMENT_NAMES[65] = ELT_INS;
+ ELEMENT_NAMES[66] = ELT_PRE;
+ ELEMENT_NAMES[67] = ELT_SUB;
+ ELEMENT_NAMES[68] = ELT_USE;
+ ELEMENT_NAMES[69] = ELT_XMP;
+ ELEMENT_NAMES[70] = ELT_S;
+ ELEMENT_NAMES[71] = ELT_H3;
+ ELEMENT_NAMES[72] = ELT_AREA;
+ ELEMENT_NAMES[73] = ELT_META;
+ ELEMENT_NAMES[74] = ELT_DESC;
+ ELEMENT_NAMES[75] = ELT_FEBLEND;
+ ELEMENT_NAMES[76] = ELT_NOEMBED;
+ ELEMENT_NAMES[77] = ELT_ARTICLE;
+ ELEMENT_NAMES[78] = ELT_CODE;
+ ELEMENT_NAMES[79] = ELT_FETURBULENCE;
+ ELEMENT_NAMES[80] = ELT_FETILE;
+ ELEMENT_NAMES[81] = ELT_IMAGE;
+ ELEMENT_NAMES[82] = ELT_POLYLINE;
+ ELEMENT_NAMES[83] = ELT_STYLE;
+ ELEMENT_NAMES[84] = ELT_TEMPLATE;
+ ELEMENT_NAMES[85] = ELT_FEFUNCG;
+ ELEMENT_NAMES[86] = ELT_STRONG;
+ ELEMENT_NAMES[87] = ELT_MATH;
+ ELEMENT_NAMES[88] = ELT_SWITCH;
+ ELEMENT_NAMES[89] = ELT_LINK;
+ ELEMENT_NAMES[90] = ELT_TRACK;
+ ELEMENT_NAMES[91] = ELT_LABEL;
+ ELEMENT_NAMES[92] = ELT_ALTGLYPHITEM;
+ ELEMENT_NAMES[93] = ELT_FORM;
+ ELEMENT_NAMES[94] = ELT_CAPTION;
+ ELEMENT_NAMES[95] = ELT_MAIN;
+ ELEMENT_NAMES[96] = ELT_SPAN;
+ ELEMENT_NAMES[97] = ELT_MO;
+ ELEMENT_NAMES[98] = ELT_HGROUP;
+ ELEMENT_NAMES[99] = ELT_STOP;
+ ELEMENT_NAMES[100] = ELT_CENTER;
+ ELEMENT_NAMES[101] = ELT_FILTER;
+ ELEMENT_NAMES[102] = ELT_MARKER;
+ ELEMENT_NAMES[103] = ELT_NOBR;
+ ELEMENT_NAMES[104] = ELT_ADDRESS;
+ ELEMENT_NAMES[105] = ELT_DEFS;
+ ELEMENT_NAMES[106] = ELT_MS;
+ ELEMENT_NAMES[107] = ELT_PROGRESS;
+ ELEMENT_NAMES[108] = ELT_APPLET;
+ ELEMENT_NAMES[109] = ELT_DATALIST;
+ ELEMENT_NAMES[110] = ELT_FIELDSET;
+ ELEMENT_NAMES[111] = ELT_FEOFFSET;
+ ELEMENT_NAMES[112] = ELT_FEPOINTLIGHT;
+ ELEMENT_NAMES[113] = ELT_FONT;
+ ELEMENT_NAMES[114] = ELT_LINEARGRADIENT;
+ ELEMENT_NAMES[115] = ELT_NOSCRIPT;
+ ELEMENT_NAMES[116] = ELT_OBJECT;
+ ELEMENT_NAMES[117] = ELT_PLAINTEXT;
+ ELEMENT_NAMES[118] = ELT_RECT;
+ ELEMENT_NAMES[119] = ELT_SELECT;
+ ELEMENT_NAMES[120] = ELT_SCRIPT;
+ ELEMENT_NAMES[121] = ELT_TEXT;
+ ELEMENT_NAMES[122] = ELT_FEDROPSHADOW;
+ ELEMENT_NAMES[123] = ELT_FECOLORMATRIX;
+ ELEMENT_NAMES[124] = ELT_BODY;
+ ELEMENT_NAMES[125] = ELT_RUBY;
+ ELEMENT_NAMES[126] = ELT_TBODY;
+ ELEMENT_NAMES[127] = ELT_BIG;
+ ELEMENT_NAMES[128] = ELT_BDO;
+ ELEMENT_NAMES[129] = ELT_DEL;
+ ELEMENT_NAMES[130] = ELT_DIR;
+ ELEMENT_NAMES[131] = ELT_IMG;
+ ELEMENT_NAMES[132] = ELT_KBD;
+ ELEMENT_NAMES[133] = ELT_NAV;
+ ELEMENT_NAMES[134] = ELT_A;
+ ELEMENT_NAMES[135] = ELT_RTC;
+ ELEMENT_NAMES[136] = ELT_SVG;
+ ELEMENT_NAMES[137] = ELT_SET;
+ ELEMENT_NAMES[138] = ELT_VAR;
+ ELEMENT_NAMES[139] = ELT_WBR;
+ ELEMENT_NAMES[140] = ELT_I;
+ ELEMENT_NAMES[141] = ELT_Q;
+ ELEMENT_NAMES[142] = ELT_U;
+ ELEMENT_NAMES[143] = ELT_H2;
+ ELEMENT_NAMES[144] = ELT_H4;
+ ELEMENT_NAMES[145] = ELT_H6;
+ ELEMENT_NAMES[146] = ELT_DATA;
+ ELEMENT_NAMES[147] = ELT_METADATA;
+ ELEMENT_NAMES[148] = ELT_TEXTAREA;
+ ELEMENT_NAMES[149] = ELT_RB;
+ ELEMENT_NAMES[150] = ELT_DD;
+ ELEMENT_NAMES[151] = ELT_EMBED;
+ ELEMENT_NAMES[152] = ELT_FEFLOOD;
+ ELEMENT_NAMES[153] = ELT_LEGEND;
+ ELEMENT_NAMES[154] = ELT_TD;
+ ELEMENT_NAMES[155] = ELT_ASIDE;
+ ELEMENT_NAMES[156] = ELT_ANIMATE;
+ ELEMENT_NAMES[157] = ELT_BLOCKQUOTE;
+ ELEMENT_NAMES[158] = ELT_CIRCLE;
+ ELEMENT_NAMES[159] = ELT_ELLIPSE;
+ ELEMENT_NAMES[160] = ELT_FEMERGENODE;
+ ELEMENT_NAMES[161] = ELT_FEMERGE;
+ ELEMENT_NAMES[162] = ELT_FRAME;
+ ELEMENT_NAMES[163] = ELT_FECOMPOSITE;
+ ELEMENT_NAMES[164] = ELT_IFRAME;
+ ELEMENT_NAMES[165] = ELT_MARQUEE;
+ ELEMENT_NAMES[166] = ELT_PICTURE;
+ ELEMENT_NAMES[167] = ELT_STRIKE;
+ ELEMENT_NAMES[168] = ELT_TABLE;
+ ELEMENT_NAMES[169] = ELT_TIME;
+ ELEMENT_NAMES[170] = ELT_ALTGLYPHDEF;
+ ELEMENT_NAMES[171] = ELT_DIALOG;
+ ELEMENT_NAMES[172] = ELT_FEDIFFUSELIGHTING;
+ ELEMENT_NAMES[173] = ELT_LISTING;
+ ELEMENT_NAMES[174] = ELT_ALTGLYPH;
+ ELEMENT_NAMES[175] = ELT_MGLYPH;
+ ELEMENT_NAMES[176] = ELT_MPATH;
+ ELEMENT_NAMES[177] = ELT_TH;
+ ELEMENT_NAMES[178] = ELT_TEXTPATH;
+ ELEMENT_NAMES[179] = ELT_MI;
+ ELEMENT_NAMES[180] = ELT_MARK;
+ ELEMENT_NAMES[181] = ELT_MASK;
+ ELEMENT_NAMES[182] = ELT_DL;
+ ELEMENT_NAMES[183] = ELT_OL;
+ ELEMENT_NAMES[184] = ELT_UL;
+ ELEMENT_NAMES[185] = ELT_SYMBOL;
+ ELEMENT_NAMES[186] = ELT_ANIMATETRANSFORM;
+ ELEMENT_NAMES[187] = ELT_EM;
+ ELEMENT_NAMES[188] = ELT_PARAM;
+ ELEMENT_NAMES[189] = ELT_BUTTON;
+ ELEMENT_NAMES[190] = ELT_FIGCAPTION;
+ ELEMENT_NAMES[191] = ELT_KEYGEN;
+ ELEMENT_NAMES[192] = ELT_OPTION;
+ ELEMENT_NAMES[193] = ELT_PATTERN;
+ ELEMENT_NAMES[194] = ELT_SECTION;
+ ELEMENT_NAMES[195] = ELT_AUDIO;
+ ELEMENT_NAMES[196] = ELT_VIDEO;
+ ELEMENT_NAMES[197] = ELT_FEDISPLACEMENTMAP;
+ ELEMENT_NAMES[198] = ELT_RP;
+ ELEMENT_NAMES[199] = ELT_SAMP;
+ ELEMENT_NAMES[200] = ELT_BR;
+ ELEMENT_NAMES[201] = ELT_ANIMATECOLOR;
+ ELEMENT_NAMES[202] = ELT_HR;
+ ELEMENT_NAMES[203] = ELT_FECOMPONENTTRANSFER;
+ ELEMENT_NAMES[204] = ELT_FOOTER;
+ ELEMENT_NAMES[205] = ELT_HEADER;
+}
+
+void nsHtml5ElementName::releaseStatics() {
+ delete ELT_ANNOTATION_XML;
+ delete ELT_BIG;
+ delete ELT_BDI;
+ delete ELT_BDO;
+ delete ELT_COL;
+ delete ELT_DEL;
+ delete ELT_DFN;
+ delete ELT_DIR;
+ delete ELT_DIV;
+ delete ELT_IMG;
+ delete ELT_INS;
+ delete ELT_KBD;
+ delete ELT_MAP;
+ delete ELT_NAV;
+ delete ELT_PRE;
+ delete ELT_A;
+ delete ELT_B;
+ delete ELT_RTC;
+ delete ELT_SUB;
+ delete ELT_SVG;
+ delete ELT_SUP;
+ delete ELT_SET;
+ delete ELT_USE;
+ delete ELT_VAR;
+ delete ELT_G;
+ delete ELT_WBR;
+ delete ELT_XMP;
+ delete ELT_I;
+ delete ELT_P;
+ delete ELT_Q;
+ delete ELT_S;
+ delete ELT_U;
+ delete ELT_H1;
+ delete ELT_H2;
+ delete ELT_H3;
+ delete ELT_H4;
+ delete ELT_H5;
+ delete ELT_H6;
+ delete ELT_AREA;
+ delete ELT_DATA;
+ delete ELT_FEFUNCA;
+ delete ELT_METADATA;
+ delete ELT_META;
+ delete ELT_TEXTAREA;
+ delete ELT_FEFUNCB;
+ delete ELT_RB;
+ delete ELT_DESC;
+ delete ELT_DD;
+ delete ELT_BGSOUND;
+ delete ELT_EMBED;
+ delete ELT_FEBLEND;
+ delete ELT_FEFLOOD;
+ delete ELT_HEAD;
+ delete ELT_LEGEND;
+ delete ELT_NOEMBED;
+ delete ELT_TD;
+ delete ELT_THEAD;
+ delete ELT_ASIDE;
+ delete ELT_ARTICLE;
+ delete ELT_ANIMATE;
+ delete ELT_BASE;
+ delete ELT_BLOCKQUOTE;
+ delete ELT_CODE;
+ delete ELT_CIRCLE;
+ delete ELT_CITE;
+ delete ELT_ELLIPSE;
+ delete ELT_FETURBULENCE;
+ delete ELT_FEMERGENODE;
+ delete ELT_FEIMAGE;
+ delete ELT_FEMERGE;
+ delete ELT_FETILE;
+ delete ELT_FRAME;
+ delete ELT_FIGURE;
+ delete ELT_FECOMPOSITE;
+ delete ELT_IMAGE;
+ delete ELT_IFRAME;
+ delete ELT_LINE;
+ delete ELT_MARQUEE;
+ delete ELT_POLYLINE;
+ delete ELT_PICTURE;
+ delete ELT_SOURCE;
+ delete ELT_STRIKE;
+ delete ELT_STYLE;
+ delete ELT_TABLE;
+ delete ELT_TITLE;
+ delete ELT_TIME;
+ delete ELT_TEMPLATE;
+ delete ELT_ALTGLYPHDEF;
+ delete ELT_GLYPHREF;
+ delete ELT_DIALOG;
+ delete ELT_FEFUNCG;
+ delete ELT_FEDIFFUSELIGHTING;
+ delete ELT_FESPECULARLIGHTING;
+ delete ELT_LISTING;
+ delete ELT_STRONG;
+ delete ELT_ALTGLYPH;
+ delete ELT_CLIPPATH;
+ delete ELT_MGLYPH;
+ delete ELT_MATH;
+ delete ELT_MPATH;
+ delete ELT_PATH;
+ delete ELT_TH;
+ delete ELT_SWITCH;
+ delete ELT_TEXTPATH;
+ delete ELT_LI;
+ delete ELT_MI;
+ delete ELT_LINK;
+ delete ELT_MARK;
+ delete ELT_MALIGNMARK;
+ delete ELT_MASK;
+ delete ELT_TRACK;
+ delete ELT_DL;
+ delete ELT_HTML;
+ delete ELT_OL;
+ delete ELT_LABEL;
+ delete ELT_UL;
+ delete ELT_SMALL;
+ delete ELT_SYMBOL;
+ delete ELT_ALTGLYPHITEM;
+ delete ELT_ANIMATETRANSFORM;
+ delete ELT_ACRONYM;
+ delete ELT_EM;
+ delete ELT_FORM;
+ delete ELT_PARAM;
+ delete ELT_ANIMATEMOTION;
+ delete ELT_BUTTON;
+ delete ELT_CAPTION;
+ delete ELT_FIGCAPTION;
+ delete ELT_MN;
+ delete ELT_KEYGEN;
+ delete ELT_MAIN;
+ delete ELT_OPTION;
+ delete ELT_POLYGON;
+ delete ELT_PATTERN;
+ delete ELT_SPAN;
+ delete ELT_SECTION;
+ delete ELT_TSPAN;
+ delete ELT_AUDIO;
+ delete ELT_MO;
+ delete ELT_VIDEO;
+ delete ELT_COLGROUP;
+ delete ELT_FEDISPLACEMENTMAP;
+ delete ELT_HGROUP;
+ delete ELT_RP;
+ delete ELT_OPTGROUP;
+ delete ELT_SAMP;
+ delete ELT_STOP;
+ delete ELT_BR;
+ delete ELT_ABBR;
+ delete ELT_ANIMATECOLOR;
+ delete ELT_CENTER;
+ delete ELT_HR;
+ delete ELT_FEFUNCR;
+ delete ELT_FECOMPONENTTRANSFER;
+ delete ELT_FILTER;
+ delete ELT_FOOTER;
+ delete ELT_FEGAUSSIANBLUR;
+ delete ELT_HEADER;
+ delete ELT_MARKER;
+ delete ELT_METER;
+ delete ELT_NOBR;
+ delete ELT_TR;
+ delete ELT_ADDRESS;
+ delete ELT_CANVAS;
+ delete ELT_DEFS;
+ delete ELT_DETAILS;
+ delete ELT_MS;
+ delete ELT_NOFRAMES;
+ delete ELT_PROGRESS;
+ delete ELT_DT;
+ delete ELT_APPLET;
+ delete ELT_BASEFONT;
+ delete ELT_DATALIST;
+ delete ELT_FOREIGNOBJECT;
+ delete ELT_FIELDSET;
+ delete ELT_FRAMESET;
+ delete ELT_FEOFFSET;
+ delete ELT_FESPOTLIGHT;
+ delete ELT_FEPOINTLIGHT;
+ delete ELT_FEDISTANTLIGHT;
+ delete ELT_FONT;
+ delete ELT_INPUT;
+ delete ELT_LINEARGRADIENT;
+ delete ELT_MTEXT;
+ delete ELT_NOSCRIPT;
+ delete ELT_RT;
+ delete ELT_OBJECT;
+ delete ELT_OUTPUT;
+ delete ELT_PLAINTEXT;
+ delete ELT_TT;
+ delete ELT_RECT;
+ delete ELT_RADIALGRADIENT;
+ delete ELT_SELECT;
+ delete ELT_SLOT;
+ delete ELT_SCRIPT;
+ delete ELT_TFOOT;
+ delete ELT_TEXT;
+ delete ELT_MENU;
+ delete ELT_FEDROPSHADOW;
+ delete ELT_VIEW;
+ delete ELT_FECOLORMATRIX;
+ delete ELT_FECONVOLVEMATRIX;
+ delete ELT_BODY;
+ delete ELT_FEMORPHOLOGY;
+ delete ELT_RUBY;
+ delete ELT_SUMMARY;
+ delete ELT_TBODY;
+ delete[] ELEMENT_NAMES;
+}
diff --git a/parser/html/nsHtml5ElementName.h b/parser/html/nsHtml5ElementName.h
new file mode 100644
index 0000000000..fc064a2655
--- /dev/null
+++ b/parser/html/nsHtml5ElementName.h
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit ElementName.java instead and regenerate.
+ */
+
+#ifndef nsHtml5ElementName_h
+#define nsHtml5ElementName_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5ElementName {
+ public:
+ static const int32_t GROUP_MASK = 127;
+
+ static const int32_t NOT_INTERNED = (1 << 30);
+
+ static const int32_t SPECIAL = (1 << 29);
+
+ static const int32_t FOSTER_PARENTING = (1 << 28);
+
+ static const int32_t SCOPING = (1 << 27);
+
+ static const int32_t SCOPING_AS_SVG = (1 << 26);
+
+ static const int32_t SCOPING_AS_MATHML = (1 << 25);
+
+ static const int32_t HTML_INTEGRATION_POINT = (1 << 24);
+
+ static const int32_t OPTIONAL_END_TAG = (1 << 23);
+
+ private:
+ RefPtr<nsAtom> name;
+ RefPtr<nsAtom> camelCaseName;
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator;
+ mozilla::dom::SVGContentCreatorFunction svgCreator;
+
+ public:
+ int32_t flags;
+ inline nsAtom* getName() { return name; }
+
+ inline nsAtom* getCamelCaseName() { return camelCaseName; }
+
+ inline mozilla::dom::HTMLContentCreatorFunction getHtmlCreator() {
+ return htmlCreator;
+ }
+
+ inline mozilla::dom::SVGContentCreatorFunction getSvgCreator() {
+ return svgCreator;
+ }
+
+ inline int32_t getFlags() { return flags; }
+
+ inline int32_t getGroup() { return flags & nsHtml5ElementName::GROUP_MASK; }
+
+ inline bool isInterned() {
+ return !(flags & nsHtml5ElementName::NOT_INTERNED);
+ }
+
+ inline static int32_t levelOrderBinarySearch(jArray<int32_t, int32_t> data,
+ int32_t key) {
+ int32_t n = data.length;
+ int32_t i = 0;
+ while (i < n) {
+ int32_t val = data[i];
+ if (val < key) {
+ i = 2 * i + 2;
+ } else if (val > key) {
+ i = 2 * i + 1;
+ } else {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ inline static nsHtml5ElementName* elementNameByBuffer(
+ char16_t* buf, int32_t length, nsHtml5AtomTable* interner) {
+ uint32_t hash = nsHtml5ElementName::bufToHash(buf, length);
+ jArray<int32_t, int32_t> hashes;
+ hashes = nsHtml5ElementName::ELEMENT_HASHES;
+ int32_t index = levelOrderBinarySearch(hashes, hash);
+ if (index < 0) {
+ return nullptr;
+ } else {
+ nsHtml5ElementName* elementName =
+ nsHtml5ElementName::ELEMENT_NAMES[index];
+ nsAtom* name = elementName->name;
+ if (!nsHtml5Portability::localEqualsBuffer(name, buf, length)) {
+ return nullptr;
+ }
+ return elementName;
+ }
+ }
+
+ private:
+ inline static uint32_t bufToHash(char16_t* buf, int32_t length) {
+ uint32_t len = length;
+ uint32_t first = buf[0];
+ first <<= 19;
+ uint32_t second = 1 << 23;
+ uint32_t third = 0;
+ uint32_t fourth = 0;
+ uint32_t fifth = 0;
+ if (length >= 4) {
+ second = buf[length - 4];
+ second <<= 4;
+ third = buf[length - 3];
+ third <<= 9;
+ fourth = buf[length - 2];
+ fourth <<= 14;
+ fifth = buf[length - 1];
+ fifth <<= 24;
+ } else if (length == 3) {
+ second = buf[1];
+ second <<= 4;
+ third = buf[2];
+ third <<= 9;
+ } else if (length == 2) {
+ second = buf[1];
+ second <<= 24;
+ }
+ return len + first + second + third + fourth + fifth;
+ }
+
+ nsHtml5ElementName(nsAtom* name, nsAtom* camelCaseName,
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator,
+ mozilla::dom::SVGContentCreatorFunction svgCreator,
+ int32_t flags);
+
+ public:
+ nsHtml5ElementName();
+ ~nsHtml5ElementName();
+ inline void setNameForNonInterned(nsAtom* name, bool custom) {
+ this->name = name;
+ this->camelCaseName = name;
+ if (custom) {
+ this->htmlCreator = NS_NewCustomElement;
+ } else {
+ this->htmlCreator = NS_NewHTMLUnknownElement;
+ }
+ MOZ_ASSERT(this->flags == nsHtml5ElementName::NOT_INTERNED);
+ }
+
+ inline bool isCustom() { return this->htmlCreator == NS_NewCustomElement; }
+
+ static nsHtml5ElementName* ELT_ANNOTATION_XML;
+ static nsHtml5ElementName* ELT_BIG;
+ static nsHtml5ElementName* ELT_BDI;
+ static nsHtml5ElementName* ELT_BDO;
+ static nsHtml5ElementName* ELT_COL;
+ static nsHtml5ElementName* ELT_DEL;
+ static nsHtml5ElementName* ELT_DFN;
+ static nsHtml5ElementName* ELT_DIR;
+ static nsHtml5ElementName* ELT_DIV;
+ static nsHtml5ElementName* ELT_IMG;
+ static nsHtml5ElementName* ELT_INS;
+ static nsHtml5ElementName* ELT_KBD;
+ static nsHtml5ElementName* ELT_MAP;
+ static nsHtml5ElementName* ELT_NAV;
+ static nsHtml5ElementName* ELT_PRE;
+ static nsHtml5ElementName* ELT_A;
+ static nsHtml5ElementName* ELT_B;
+ static nsHtml5ElementName* ELT_RTC;
+ static nsHtml5ElementName* ELT_SUB;
+ static nsHtml5ElementName* ELT_SVG;
+ static nsHtml5ElementName* ELT_SUP;
+ static nsHtml5ElementName* ELT_SET;
+ static nsHtml5ElementName* ELT_USE;
+ static nsHtml5ElementName* ELT_VAR;
+ static nsHtml5ElementName* ELT_G;
+ static nsHtml5ElementName* ELT_WBR;
+ static nsHtml5ElementName* ELT_XMP;
+ static nsHtml5ElementName* ELT_I;
+ static nsHtml5ElementName* ELT_P;
+ static nsHtml5ElementName* ELT_Q;
+ static nsHtml5ElementName* ELT_S;
+ static nsHtml5ElementName* ELT_U;
+ static nsHtml5ElementName* ELT_H1;
+ static nsHtml5ElementName* ELT_H2;
+ static nsHtml5ElementName* ELT_H3;
+ static nsHtml5ElementName* ELT_H4;
+ static nsHtml5ElementName* ELT_H5;
+ static nsHtml5ElementName* ELT_H6;
+ static nsHtml5ElementName* ELT_AREA;
+ static nsHtml5ElementName* ELT_DATA;
+ static nsHtml5ElementName* ELT_FEFUNCA;
+ static nsHtml5ElementName* ELT_METADATA;
+ static nsHtml5ElementName* ELT_META;
+ static nsHtml5ElementName* ELT_TEXTAREA;
+ static nsHtml5ElementName* ELT_FEFUNCB;
+ static nsHtml5ElementName* ELT_RB;
+ static nsHtml5ElementName* ELT_DESC;
+ static nsHtml5ElementName* ELT_DD;
+ static nsHtml5ElementName* ELT_BGSOUND;
+ static nsHtml5ElementName* ELT_EMBED;
+ static nsHtml5ElementName* ELT_FEBLEND;
+ static nsHtml5ElementName* ELT_FEFLOOD;
+ static nsHtml5ElementName* ELT_HEAD;
+ static nsHtml5ElementName* ELT_LEGEND;
+ static nsHtml5ElementName* ELT_NOEMBED;
+ static nsHtml5ElementName* ELT_TD;
+ static nsHtml5ElementName* ELT_THEAD;
+ static nsHtml5ElementName* ELT_ASIDE;
+ static nsHtml5ElementName* ELT_ARTICLE;
+ static nsHtml5ElementName* ELT_ANIMATE;
+ static nsHtml5ElementName* ELT_BASE;
+ static nsHtml5ElementName* ELT_BLOCKQUOTE;
+ static nsHtml5ElementName* ELT_CODE;
+ static nsHtml5ElementName* ELT_CIRCLE;
+ static nsHtml5ElementName* ELT_CITE;
+ static nsHtml5ElementName* ELT_ELLIPSE;
+ static nsHtml5ElementName* ELT_FETURBULENCE;
+ static nsHtml5ElementName* ELT_FEMERGENODE;
+ static nsHtml5ElementName* ELT_FEIMAGE;
+ static nsHtml5ElementName* ELT_FEMERGE;
+ static nsHtml5ElementName* ELT_FETILE;
+ static nsHtml5ElementName* ELT_FRAME;
+ static nsHtml5ElementName* ELT_FIGURE;
+ static nsHtml5ElementName* ELT_FECOMPOSITE;
+ static nsHtml5ElementName* ELT_IMAGE;
+ static nsHtml5ElementName* ELT_IFRAME;
+ static nsHtml5ElementName* ELT_LINE;
+ static nsHtml5ElementName* ELT_MARQUEE;
+ static nsHtml5ElementName* ELT_POLYLINE;
+ static nsHtml5ElementName* ELT_PICTURE;
+ static nsHtml5ElementName* ELT_SOURCE;
+ static nsHtml5ElementName* ELT_STRIKE;
+ static nsHtml5ElementName* ELT_STYLE;
+ static nsHtml5ElementName* ELT_TABLE;
+ static nsHtml5ElementName* ELT_TITLE;
+ static nsHtml5ElementName* ELT_TIME;
+ static nsHtml5ElementName* ELT_TEMPLATE;
+ static nsHtml5ElementName* ELT_ALTGLYPHDEF;
+ static nsHtml5ElementName* ELT_GLYPHREF;
+ static nsHtml5ElementName* ELT_DIALOG;
+ static nsHtml5ElementName* ELT_FEFUNCG;
+ static nsHtml5ElementName* ELT_FEDIFFUSELIGHTING;
+ static nsHtml5ElementName* ELT_FESPECULARLIGHTING;
+ static nsHtml5ElementName* ELT_LISTING;
+ static nsHtml5ElementName* ELT_STRONG;
+ static nsHtml5ElementName* ELT_ALTGLYPH;
+ static nsHtml5ElementName* ELT_CLIPPATH;
+ static nsHtml5ElementName* ELT_MGLYPH;
+ static nsHtml5ElementName* ELT_MATH;
+ static nsHtml5ElementName* ELT_MPATH;
+ static nsHtml5ElementName* ELT_PATH;
+ static nsHtml5ElementName* ELT_TH;
+ static nsHtml5ElementName* ELT_SWITCH;
+ static nsHtml5ElementName* ELT_TEXTPATH;
+ static nsHtml5ElementName* ELT_LI;
+ static nsHtml5ElementName* ELT_MI;
+ static nsHtml5ElementName* ELT_LINK;
+ static nsHtml5ElementName* ELT_MARK;
+ static nsHtml5ElementName* ELT_MALIGNMARK;
+ static nsHtml5ElementName* ELT_MASK;
+ static nsHtml5ElementName* ELT_TRACK;
+ static nsHtml5ElementName* ELT_DL;
+ static nsHtml5ElementName* ELT_HTML;
+ static nsHtml5ElementName* ELT_OL;
+ static nsHtml5ElementName* ELT_LABEL;
+ static nsHtml5ElementName* ELT_UL;
+ static nsHtml5ElementName* ELT_SMALL;
+ static nsHtml5ElementName* ELT_SYMBOL;
+ static nsHtml5ElementName* ELT_ALTGLYPHITEM;
+ static nsHtml5ElementName* ELT_ANIMATETRANSFORM;
+ static nsHtml5ElementName* ELT_ACRONYM;
+ static nsHtml5ElementName* ELT_EM;
+ static nsHtml5ElementName* ELT_FORM;
+ static nsHtml5ElementName* ELT_PARAM;
+ static nsHtml5ElementName* ELT_ANIMATEMOTION;
+ static nsHtml5ElementName* ELT_BUTTON;
+ static nsHtml5ElementName* ELT_CAPTION;
+ static nsHtml5ElementName* ELT_FIGCAPTION;
+ static nsHtml5ElementName* ELT_MN;
+ static nsHtml5ElementName* ELT_KEYGEN;
+ static nsHtml5ElementName* ELT_MAIN;
+ static nsHtml5ElementName* ELT_OPTION;
+ static nsHtml5ElementName* ELT_POLYGON;
+ static nsHtml5ElementName* ELT_PATTERN;
+ static nsHtml5ElementName* ELT_SPAN;
+ static nsHtml5ElementName* ELT_SECTION;
+ static nsHtml5ElementName* ELT_TSPAN;
+ static nsHtml5ElementName* ELT_AUDIO;
+ static nsHtml5ElementName* ELT_MO;
+ static nsHtml5ElementName* ELT_VIDEO;
+ static nsHtml5ElementName* ELT_COLGROUP;
+ static nsHtml5ElementName* ELT_FEDISPLACEMENTMAP;
+ static nsHtml5ElementName* ELT_HGROUP;
+ static nsHtml5ElementName* ELT_RP;
+ static nsHtml5ElementName* ELT_OPTGROUP;
+ static nsHtml5ElementName* ELT_SAMP;
+ static nsHtml5ElementName* ELT_STOP;
+ static nsHtml5ElementName* ELT_BR;
+ static nsHtml5ElementName* ELT_ABBR;
+ static nsHtml5ElementName* ELT_ANIMATECOLOR;
+ static nsHtml5ElementName* ELT_CENTER;
+ static nsHtml5ElementName* ELT_HR;
+ static nsHtml5ElementName* ELT_FEFUNCR;
+ static nsHtml5ElementName* ELT_FECOMPONENTTRANSFER;
+ static nsHtml5ElementName* ELT_FILTER;
+ static nsHtml5ElementName* ELT_FOOTER;
+ static nsHtml5ElementName* ELT_FEGAUSSIANBLUR;
+ static nsHtml5ElementName* ELT_HEADER;
+ static nsHtml5ElementName* ELT_MARKER;
+ static nsHtml5ElementName* ELT_METER;
+ static nsHtml5ElementName* ELT_NOBR;
+ static nsHtml5ElementName* ELT_TR;
+ static nsHtml5ElementName* ELT_ADDRESS;
+ static nsHtml5ElementName* ELT_CANVAS;
+ static nsHtml5ElementName* ELT_DEFS;
+ static nsHtml5ElementName* ELT_DETAILS;
+ static nsHtml5ElementName* ELT_MS;
+ static nsHtml5ElementName* ELT_NOFRAMES;
+ static nsHtml5ElementName* ELT_PROGRESS;
+ static nsHtml5ElementName* ELT_DT;
+ static nsHtml5ElementName* ELT_APPLET;
+ static nsHtml5ElementName* ELT_BASEFONT;
+ static nsHtml5ElementName* ELT_DATALIST;
+ static nsHtml5ElementName* ELT_FOREIGNOBJECT;
+ static nsHtml5ElementName* ELT_FIELDSET;
+ static nsHtml5ElementName* ELT_FRAMESET;
+ static nsHtml5ElementName* ELT_FEOFFSET;
+ static nsHtml5ElementName* ELT_FESPOTLIGHT;
+ static nsHtml5ElementName* ELT_FEPOINTLIGHT;
+ static nsHtml5ElementName* ELT_FEDISTANTLIGHT;
+ static nsHtml5ElementName* ELT_FONT;
+ static nsHtml5ElementName* ELT_INPUT;
+ static nsHtml5ElementName* ELT_LINEARGRADIENT;
+ static nsHtml5ElementName* ELT_MTEXT;
+ static nsHtml5ElementName* ELT_NOSCRIPT;
+ static nsHtml5ElementName* ELT_RT;
+ static nsHtml5ElementName* ELT_OBJECT;
+ static nsHtml5ElementName* ELT_OUTPUT;
+ static nsHtml5ElementName* ELT_PLAINTEXT;
+ static nsHtml5ElementName* ELT_TT;
+ static nsHtml5ElementName* ELT_RECT;
+ static nsHtml5ElementName* ELT_RADIALGRADIENT;
+ static nsHtml5ElementName* ELT_SELECT;
+ static nsHtml5ElementName* ELT_SLOT;
+ static nsHtml5ElementName* ELT_SCRIPT;
+ static nsHtml5ElementName* ELT_TFOOT;
+ static nsHtml5ElementName* ELT_TEXT;
+ static nsHtml5ElementName* ELT_MENU;
+ static nsHtml5ElementName* ELT_FEDROPSHADOW;
+ static nsHtml5ElementName* ELT_VIEW;
+ static nsHtml5ElementName* ELT_FECOLORMATRIX;
+ static nsHtml5ElementName* ELT_FECONVOLVEMATRIX;
+ static nsHtml5ElementName* ELT_BODY;
+ static nsHtml5ElementName* ELT_FEMORPHOLOGY;
+ static nsHtml5ElementName* ELT_RUBY;
+ static nsHtml5ElementName* ELT_SUMMARY;
+ static nsHtml5ElementName* ELT_TBODY;
+
+ private:
+ static nsHtml5ElementName** ELEMENT_NAMES;
+ static staticJArray<int32_t, int32_t> ELEMENT_HASHES;
+
+ public:
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif
diff --git a/parser/html/nsHtml5Highlighter.cpp b/parser/html/nsHtml5Highlighter.cpp
new file mode 100644
index 0000000000..45c84b743a
--- /dev/null
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -0,0 +1,790 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5Highlighter.h"
+#include "ErrorList.h"
+#include "nsDebug.h"
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5ViewSourceUtils.h"
+#include "nsString.h"
+#include "nsThreadUtils.h"
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
+
+// The old code had a limit of 16 tokens. 1300 is a number picked my measuring
+// the size of 16 tokens on cnn.com.
+#define NS_HTML5_HIGHLIGHTER_PRE_BREAK_THRESHOLD 1300
+
+char16_t nsHtml5Highlighter::sComment[] = {'c', 'o', 'm', 'm',
+ 'e', 'n', 't', 0};
+
+char16_t nsHtml5Highlighter::sCdata[] = {'c', 'd', 'a', 't', 'a', 0};
+
+char16_t nsHtml5Highlighter::sEntity[] = {'e', 'n', 't', 'i', 't', 'y', 0};
+
+char16_t nsHtml5Highlighter::sEndTag[] = {'e', 'n', 'd', '-', 't', 'a', 'g', 0};
+
+char16_t nsHtml5Highlighter::sStartTag[] = {'s', 't', 'a', 'r', 't',
+ '-', 't', 'a', 'g', 0};
+
+char16_t nsHtml5Highlighter::sAttributeName[] = {
+ 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', '-', 'n', 'a', 'm', 'e', 0};
+
+char16_t nsHtml5Highlighter::sAttributeValue[] = {'a', 't', 't', 'r', 'i', 'b',
+ 'u', 't', 'e', '-', 'v', 'a',
+ 'l', 'u', 'e', 0};
+
+char16_t nsHtml5Highlighter::sDoctype[] = {'d', 'o', 'c', 't',
+ 'y', 'p', 'e', 0};
+
+char16_t nsHtml5Highlighter::sPi[] = {'p', 'i', 0};
+
+nsHtml5Highlighter::nsHtml5Highlighter(nsAHtml5TreeOpSink* aOpSink)
+ : mState(nsHtml5Tokenizer::DATA),
+ mCStart(INT32_MAX),
+ mPos(0),
+ mLineNumber(1),
+ mInlinesOpen(0),
+ mInCharacters(false),
+ mBuffer(nullptr),
+ mOpSink(aOpSink),
+ mCurrentRun(nullptr),
+ mAmpersand(nullptr),
+ mSlash(nullptr),
+ mHandles(
+ MakeUnique<nsIContent*[]>(NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH)),
+ mHandlesUsed(0),
+ mSeenBase(false) {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+}
+
+nsHtml5Highlighter::~nsHtml5Highlighter() {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+}
+
+void nsHtml5Highlighter::SetOpSink(nsAHtml5TreeOpSink* aOpSink) {
+ mOpSink = aOpSink;
+}
+
+void nsHtml5Highlighter::Rewind() {
+ mState = 0;
+ mCStart = INT32_MAX;
+ mPos = 0;
+ mLineNumber = 1;
+ mInlinesOpen = 0;
+ mInCharacters = false;
+ mBuffer = nullptr;
+ mOpQueue.Clear();
+ mCurrentRun = nullptr;
+ mAmpersand = nullptr;
+ mSlash = nullptr;
+ // Pop until we have three elements on the stack:
+ // html, body, and pre.
+ while (mStack.Length() > 3) {
+ Pop();
+ }
+ mSeenBase = false;
+}
+
+void nsHtml5Highlighter::Start(const nsAutoString& aTitle) {
+ // Doctype
+ opAppendDoctypeToDocument operation(nsGkAtoms::html, u""_ns, u""_ns);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(STANDARDS_MODE));
+
+ // <html> uses NS_NewHTMLSharedElement creator
+ nsIContent** root =
+ CreateElement(nsGkAtoms::html, nullptr, nullptr, NS_NewHTMLSharedElement);
+ opAppendToDocument appendOp(root);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(appendOp));
+ mStack.AppendElement(root);
+
+ // <head> uses NS_NewHTMLSharedElement creator
+ Push(nsGkAtoms::head, nullptr, NS_NewHTMLSharedElement);
+
+ Push(nsGkAtoms::meta, nsHtml5ViewSourceUtils::NewMetaViewportAttributes(),
+ NS_NewHTMLMetaElement);
+ Pop(); // meta
+
+ Push(nsGkAtoms::title, nullptr, NS_NewHTMLTitleElement);
+ // XUL will add the "Source of: " prefix.
+ uint32_t length = aTitle.Length();
+ if (length > INT32_MAX) {
+ length = INT32_MAX;
+ }
+ AppendCharacters(aTitle.BeginReading(), 0, (int32_t)length);
+ Pop(); // title
+
+ Push(nsGkAtoms::link, nsHtml5ViewSourceUtils::NewLinkAttributes(),
+ NS_NewHTMLLinkElement);
+
+ opUpdateStyleSheet updateOp(CurrentNode());
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(updateOp));
+
+ Pop(); // link
+
+ Pop(); // head
+
+ Push(nsGkAtoms::body, nsHtml5ViewSourceUtils::NewBodyAttributes(),
+ NS_NewHTMLBodyElement);
+
+ nsHtml5HtmlAttributes* preAttrs = new nsHtml5HtmlAttributes(0);
+ nsHtml5String preId = nsHtml5Portability::newStringFromLiteral("line1");
+ preAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, preId, -1);
+ Push(nsGkAtoms::pre, preAttrs, NS_NewHTMLPreElement);
+
+ // Don't call StartCharacters here in order to be able to put it in
+ // a speculation.
+
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(opStartLayout()));
+}
+
+void nsHtml5Highlighter::UpdateCharsetSource(nsCharsetSource aCharsetSource) {
+ opUpdateCharsetSource operation(aCharsetSource);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+int32_t nsHtml5Highlighter::Transition(int32_t aState, bool aReconsume,
+ int32_t aPos) {
+ mPos = aPos;
+ switch (mState) {
+ case nsHtml5Tokenizer::SCRIPT_DATA:
+ case nsHtml5Tokenizer::RAWTEXT:
+ case nsHtml5Tokenizer::RCDATA:
+ case nsHtml5Tokenizer::DATA:
+ // We can transition on < and on &. Either way, we don't yet know the
+ // role of the token, so open a span without class.
+ if (aState == nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE) {
+ StartSpan();
+ // Start another span for highlighting the ampersand
+ StartSpan();
+ mAmpersand = CurrentNode();
+ } else {
+ EndCharactersAndStartMarkupRun();
+ }
+ break;
+ case nsHtml5Tokenizer::TAG_OPEN:
+ switch (aState) {
+ case nsHtml5Tokenizer::TAG_NAME:
+ StartSpan(sStartTag);
+ break;
+ case nsHtml5Tokenizer::DATA:
+ FinishTag(); // DATA
+ break;
+ case nsHtml5Tokenizer::PROCESSING_INSTRUCTION:
+ AddClass(sPi);
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::TAG_NAME:
+ switch (aState) {
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME:
+ EndSpanOrA(); // nsHtml5Tokenizer::TAG_NAME
+ break;
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ EndSpanOrA(); // nsHtml5Tokenizer::TAG_NAME
+ StartSpan(); // for highlighting the slash
+ mSlash = CurrentNode();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME:
+ switch (aState) {
+ case nsHtml5Tokenizer::ATTRIBUTE_NAME:
+ StartSpan(sAttributeName);
+ break;
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ StartSpan(); // for highlighting the slash
+ mSlash = CurrentNode();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::ATTRIBUTE_NAME:
+ switch (aState) {
+ case nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME:
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE:
+ EndSpanOrA(); // nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME
+ break;
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ EndSpanOrA(); // nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME
+ StartSpan(); // for highlighting the slash
+ mSlash = CurrentNode();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE:
+ switch (aState) {
+ case nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ case nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ FlushCurrent();
+ StartA();
+ break;
+ case nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED:
+ StartA();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ case nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ switch (aState) {
+ case nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED:
+ EndSpanOrA();
+ break;
+ case nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE:
+ StartSpan();
+ StartSpan(); // for ampersand itself
+ mAmpersand = CurrentNode();
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Impossible transition.");
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED:
+ switch (aState) {
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME:
+ break;
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ StartSpan(); // for highlighting the slash
+ mSlash = CurrentNode();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ EndSpanOrA(); // end the slash highlight
+ switch (aState) {
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME:
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED:
+ switch (aState) {
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME:
+ EndSpanOrA();
+ break;
+ case nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE:
+ StartSpan();
+ StartSpan(); // for ampersand itself
+ mAmpersand = CurrentNode();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME:
+ switch (aState) {
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ StartSpan(); // for highlighting the slash
+ mSlash = CurrentNode();
+ break;
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE:
+ break;
+ case nsHtml5Tokenizer::ATTRIBUTE_NAME:
+ StartSpan(sAttributeName);
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ // most comment states are omitted, because they don't matter to
+ // highlighting
+ case nsHtml5Tokenizer::COMMENT_START:
+ case nsHtml5Tokenizer::COMMENT_END:
+ case nsHtml5Tokenizer::COMMENT_END_BANG:
+ case nsHtml5Tokenizer::COMMENT_START_DASH:
+ case nsHtml5Tokenizer::BOGUS_COMMENT:
+ case nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN:
+ case nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG_DASH_DASH:
+ if (aState == nsHtml5Tokenizer::DATA) {
+ AddClass(sComment);
+ FinishTag();
+ }
+ break;
+ // most cdata states are omitted, because they don't matter to
+ // highlighting
+ case nsHtml5Tokenizer::CDATA_RSQB_RSQB:
+ if (aState == nsHtml5Tokenizer::DATA) {
+ AddClass(sCdata);
+ FinishTag();
+ }
+ break;
+ case nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE:
+ EndSpanOrA(); // the span for the ampersand
+ switch (aState) {
+ case nsHtml5Tokenizer::CONSUME_NCR:
+ case nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP:
+ break;
+ default:
+ // not actually a character reference
+ EndSpanOrA();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP:
+ if (aState == nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL) {
+ break;
+ }
+ // not actually a character reference
+ EndSpanOrA();
+ break;
+ case nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL:
+ if (!aReconsume) {
+ FlushCurrent();
+ }
+ EndSpanOrA();
+ break;
+ case nsHtml5Tokenizer::DECIMAL_NRC_LOOP:
+ case nsHtml5Tokenizer::HEX_NCR_LOOP:
+ switch (aState) {
+ case nsHtml5Tokenizer::HANDLE_NCR_VALUE:
+ AddClass(sEntity);
+ FlushCurrent();
+ break;
+ case nsHtml5Tokenizer::HANDLE_NCR_VALUE_RECONSUME:
+ AddClass(sEntity);
+ break;
+ }
+ EndSpanOrA();
+ break;
+ case nsHtml5Tokenizer::CLOSE_TAG_OPEN:
+ switch (aState) {
+ case nsHtml5Tokenizer::DATA:
+ FinishTag();
+ break;
+ case nsHtml5Tokenizer::TAG_NAME:
+ StartSpan(sEndTag);
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN:
+ if (aState == nsHtml5Tokenizer::NON_DATA_END_TAG_NAME) {
+ FlushCurrent();
+ StartSpan(); // don't know if it is "end-tag" yet :-(
+ break;
+ }
+ EndSpanOrA();
+ StartCharacters();
+ break;
+ case nsHtml5Tokenizer::NON_DATA_END_TAG_NAME:
+ switch (aState) {
+ case nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME:
+ AddClass(sEndTag);
+ EndSpanOrA();
+ break;
+ case nsHtml5Tokenizer::SELF_CLOSING_START_TAG:
+ AddClass(sEndTag);
+ EndSpanOrA();
+ StartSpan(); // for highlighting the slash
+ mSlash = CurrentNode();
+ break;
+ case nsHtml5Tokenizer::DATA: // yes, as a result of emitting the token
+ AddClass(sEndTag);
+ FinishTag();
+ break;
+ default:
+ FinishTag();
+ break;
+ }
+ break;
+ case nsHtml5Tokenizer::SCRIPT_DATA_LESS_THAN_SIGN:
+ case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
+ if (aState == nsHtml5Tokenizer::NON_DATA_END_TAG_NAME) {
+ FlushCurrent();
+ StartSpan(); // don't know if it is "end-tag" yet :-(
+ break;
+ }
+ FinishTag();
+ break;
+ case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH:
+ case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED:
+ case nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH:
+ if (aState == nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN) {
+ EndCharactersAndStartMarkupRun();
+ }
+ break;
+ // Lots of double escape states omitted, because they don't highlight.
+ // Likewise, only doctype states that can emit the doctype are of
+ // interest. Otherwise, the transition out of bogus comment deals.
+ case nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME:
+ case nsHtml5Tokenizer::DOCTYPE_NAME:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_NAME:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ case nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
+ case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ case nsHtml5Tokenizer::BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
+ case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
+ case nsHtml5Tokenizer::BOGUS_DOCTYPE:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ case nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
+ case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
+ if (aState == nsHtml5Tokenizer::DATA) {
+ AddClass(sDoctype);
+ FinishTag();
+ }
+ break;
+ case nsHtml5Tokenizer::PROCESSING_INSTRUCTION_QUESTION_MARK:
+ if (aState == nsHtml5Tokenizer::DATA) {
+ FinishTag();
+ }
+ break;
+ default:
+ break;
+ }
+ mState = aState;
+ return aState;
+}
+
+[[nodiscard]] bool nsHtml5Highlighter::End() {
+ switch (mState) {
+ case nsHtml5Tokenizer::COMMENT_END:
+ case nsHtml5Tokenizer::COMMENT_END_BANG:
+ case nsHtml5Tokenizer::COMMENT_START_DASH:
+ case nsHtml5Tokenizer::BOGUS_COMMENT:
+ case nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN:
+ AddClass(sComment);
+ break;
+ case nsHtml5Tokenizer::CDATA_RSQB_RSQB:
+ AddClass(sCdata);
+ break;
+ case nsHtml5Tokenizer::DECIMAL_NRC_LOOP:
+ case nsHtml5Tokenizer::HEX_NCR_LOOP:
+ // XXX need tokenizer help here
+ break;
+ case nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME:
+ case nsHtml5Tokenizer::DOCTYPE_NAME:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_NAME:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ case nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
+ case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ case nsHtml5Tokenizer::BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
+ case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
+ case nsHtml5Tokenizer::BOGUS_DOCTYPE:
+ case nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ case nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ case nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
+ case nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
+ AddClass(sDoctype);
+ break;
+ default:
+ break;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ treeOp->Init(mozilla::AsVariant(opStreamEnded()));
+ return FlushOps().isOk();
+}
+
+void nsHtml5Highlighter::SetBuffer(nsHtml5UTF16Buffer* aBuffer) {
+ MOZ_ASSERT(!mBuffer, "Old buffer still here!");
+ mBuffer = aBuffer;
+ mCStart = aBuffer->getStart();
+}
+
+void nsHtml5Highlighter::DropBuffer(int32_t aPos) {
+ MOZ_ASSERT(mBuffer, "No buffer to drop!");
+ mPos = aPos;
+ FlushChars();
+ mBuffer = nullptr;
+}
+
+void nsHtml5Highlighter::StartSpan() {
+ FlushChars();
+ Push(nsGkAtoms::span, nullptr, NS_NewHTMLSpanElement);
+ ++mInlinesOpen;
+}
+
+void nsHtml5Highlighter::StartSpan(const char16_t* aClass) {
+ StartSpan();
+ AddClass(aClass);
+}
+
+void nsHtml5Highlighter::EndSpanOrA() {
+ FlushChars();
+ Pop();
+ --mInlinesOpen;
+}
+
+void nsHtml5Highlighter::StartCharacters() {
+ MOZ_ASSERT(!mInCharacters, "Already in characters!");
+ FlushChars();
+ Push(nsGkAtoms::span, nullptr, NS_NewHTMLSpanElement);
+ mCurrentRun = CurrentNode();
+ mInCharacters = true;
+}
+
+void nsHtml5Highlighter::EndCharactersAndStartMarkupRun() {
+ MOZ_ASSERT(mInCharacters, "Not in characters!");
+ FlushChars();
+ Pop();
+ mInCharacters = false;
+ // Now start markup run
+ StartSpan();
+ mCurrentRun = CurrentNode();
+}
+
+void nsHtml5Highlighter::StartA() {
+ FlushChars();
+ Push(nsGkAtoms::a, nullptr, NS_NewHTMLAnchorElement);
+ AddClass(sAttributeValue);
+ ++mInlinesOpen;
+}
+
+void nsHtml5Highlighter::FinishTag() {
+ while (mInlinesOpen > 1) {
+ EndSpanOrA();
+ }
+ FlushCurrent(); // >
+ EndSpanOrA(); // DATA
+ NS_ASSERTION(!mInlinesOpen, "mInlinesOpen got out of sync!");
+ StartCharacters();
+}
+
+void nsHtml5Highlighter::FlushChars() {
+ if (mCStart < mPos) {
+ char16_t* buf = mBuffer->getBuffer();
+ int32_t i = mCStart;
+ while (i < mPos) {
+ char16_t c = buf[i];
+ switch (c) {
+ case '\r':
+ // The input this code sees has been normalized so that there are
+ // CR breaks and LF breaks but no CRLF breaks. Overwrite CR with LF
+ // to show consistent LF line breaks to layout. It is OK to mutate
+ // the input data, because there are no reparses in the View Source
+ // case, so we won't need the original data in the buffer anymore.
+ buf[i] = '\n';
+ [[fallthrough]];
+ case '\n': {
+ ++i;
+ if (mCStart < i) {
+ int32_t len = i - mCStart;
+ AppendCharacters(buf, mCStart, len);
+ mCStart = i;
+ }
+ ++mLineNumber;
+ Push(nsGkAtoms::span, nullptr, NS_NewHTMLSpanElement);
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddLineNumberId operation(CurrentNode(), mLineNumber);
+ treeOp->Init(mozilla::AsVariant(operation));
+ Pop();
+ break;
+ }
+ default:
+ ++i;
+ break;
+ }
+ }
+ if (mCStart < mPos) {
+ int32_t len = mPos - mCStart;
+ AppendCharacters(buf, mCStart, len);
+ mCStart = mPos;
+ }
+ }
+}
+
+void nsHtml5Highlighter::FlushCurrent() {
+ mPos++;
+ FlushChars();
+}
+
+bool nsHtml5Highlighter::ShouldFlushOps() {
+ // Arbitrary threshold that doesn't have an exact justification.
+ // The general idea is to flush much, much sooner than reaching
+ // the maximum size of `nsTArray`.
+ return mOpQueue.Length() > 100000;
+}
+
+mozilla::Result<bool, nsresult> nsHtml5Highlighter::FlushOps() {
+ bool hasOps = !mOpQueue.IsEmpty();
+ if (hasOps) {
+ if (!mOpSink->MoveOpsFrom(mOpQueue)) {
+ return Err(NS_ERROR_OUT_OF_MEMORY);
+ }
+ }
+ return hasOps;
+}
+
+void nsHtml5Highlighter::MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName,
+ nsHtml5String aValue) {
+ if (!(nsHtml5AttributeName::ATTR_HREF == aName ||
+ nsHtml5AttributeName::ATTR_SRC == aName ||
+ nsHtml5AttributeName::ATTR_ACTION == aName ||
+ nsHtml5AttributeName::ATTR_CITE == aName ||
+ nsHtml5AttributeName::ATTR_BACKGROUND == aName ||
+ nsHtml5AttributeName::ATTR_LONGDESC == aName ||
+ nsHtml5AttributeName::ATTR_XLINK_HREF == aName ||
+ nsHtml5AttributeName::ATTR_DEFINITIONURL == aName)) {
+ return;
+ }
+ AddViewSourceHref(aValue);
+}
+
+void nsHtml5Highlighter::CompletedNamedCharacterReference() {
+ AddClass(sEntity);
+}
+
+nsIContent** nsHtml5Highlighter::AllocateContentHandle() {
+ if (mHandlesUsed == NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH) {
+ mOldHandles.AppendElement(std::move(mHandles));
+ mHandles =
+ MakeUnique<nsIContent*[]>(NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH);
+ mHandlesUsed = 0;
+ }
+#ifdef DEBUG
+ mHandles[mHandlesUsed] = reinterpret_cast<nsIContent*>(uintptr_t(0xC0DEDBAD));
+#endif
+ return &mHandles[mHandlesUsed++];
+}
+
+nsIContent** nsHtml5Highlighter::CreateElement(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ nsIContent** aIntendedParent,
+ mozilla::dom::HTMLContentCreatorFunction aCreator) {
+ MOZ_ASSERT(aName, "Got null name.");
+ nsIContent** content = AllocateContentHandle();
+ opCreateHTMLElement opeation(content, aName, aAttributes, aCreator,
+ aIntendedParent,
+ mozilla::dom::FROM_PARSER_NETWORK);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(opeation));
+ return content;
+}
+
+nsIContent** nsHtml5Highlighter::CurrentNode() {
+ MOZ_ASSERT(mStack.Length() >= 1, "Must have something on stack.");
+ return mStack[mStack.Length() - 1];
+}
+
+void nsHtml5Highlighter::Push(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::HTMLContentCreatorFunction aCreator) {
+ MOZ_ASSERT(mStack.Length() >= 1, "Pushing without root.");
+ nsIContent** elt = CreateElement(aName, aAttributes, CurrentNode(),
+ aCreator); // Don't inline below!
+ opAppend operation(elt, CurrentNode(), mozilla::dom::FROM_PARSER_NETWORK);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+ mStack.AppendElement(elt);
+}
+
+void nsHtml5Highlighter::Pop() {
+ MOZ_ASSERT(mStack.Length() >= 2, "Popping when stack too short.");
+ mStack.RemoveLastElement();
+}
+
+void nsHtml5Highlighter::AppendCharacters(const char16_t* aBuffer,
+ int32_t aStart, int32_t aLength) {
+ MOZ_ASSERT(aBuffer, "Null buffer");
+
+ char16_t* bufferCopy = new char16_t[aLength];
+ memcpy(bufferCopy, aBuffer + aStart, aLength * sizeof(char16_t));
+
+ opAppendText operation(CurrentNode(), bufferCopy, aLength);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddClass(const char16_t* aClass) {
+ opAddClass operation(CurrentNode(), (char16_t*)aClass);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddViewSourceHref(nsHtml5String aValue) {
+ char16_t* bufferCopy = new char16_t[aValue.Length() + 1];
+ aValue.CopyToBuffer(bufferCopy);
+ bufferCopy[aValue.Length()] = 0;
+
+ opAddViewSourceHref operation(CurrentNode(), bufferCopy, aValue.Length());
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddBase(nsHtml5String aValue) {
+ if (mSeenBase) {
+ return;
+ }
+ mSeenBase = true;
+ char16_t* bufferCopy = new char16_t[aValue.Length() + 1];
+ aValue.CopyToBuffer(bufferCopy);
+ bufferCopy[aValue.Length()] = 0;
+
+ opAddViewSourceBase operation(bufferCopy, aValue.Length());
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddErrorToCurrentNode(const char* aMsgId) {
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddErrorType operation(CurrentNode(), (char*)aMsgId);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId) {
+ MOZ_ASSERT(mCurrentRun, "Adding error to run without one!");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddErrorType operation(mCurrentRun, (char*)aMsgId);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId,
+ nsAtom* aName) {
+ MOZ_ASSERT(mCurrentRun, "Adding error to run without one!");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddErrorType operation(mCurrentRun, (char*)aMsgId, aName);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddErrorToCurrentRun(const char* aMsgId, nsAtom* aName,
+ nsAtom* aOther) {
+ MOZ_ASSERT(mCurrentRun, "Adding error to run without one!");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddErrorType operation(mCurrentRun, (char*)aMsgId, aName, aOther);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddErrorToCurrentAmpersand(const char* aMsgId) {
+ MOZ_ASSERT(mAmpersand, "Adding error to ampersand without one!");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddErrorType operation(mAmpersand, (char*)aMsgId);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5Highlighter::AddErrorToCurrentSlash(const char* aMsgId) {
+ MOZ_ASSERT(mSlash, "Adding error to slash without one!");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ opAddErrorType operation(mSlash, (char*)aMsgId);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
diff --git a/parser/html/nsHtml5Highlighter.h b/parser/html/nsHtml5Highlighter.h
new file mode 100644
index 0000000000..4966b21608
--- /dev/null
+++ b/parser/html/nsHtml5Highlighter.h
@@ -0,0 +1,444 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsHtml5Highlighter_h
+#define nsHtml5Highlighter_h
+
+#include "nsCOMPtr.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsAHtml5TreeOpSink.h"
+
+#define NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH 512
+
+/**
+ * A state machine for generating HTML for display in View Source based on
+ * the transitions the tokenizer makes on the source being viewed.
+ */
+class nsHtml5Highlighter {
+ public:
+ /**
+ * The constructor.
+ *
+ * @param aOpSink the sink for the tree ops generated by this highlighter
+ */
+ explicit nsHtml5Highlighter(nsAHtml5TreeOpSink* aOpSink);
+
+ /**
+ * The destructor.
+ */
+ ~nsHtml5Highlighter();
+
+ /**
+ * Set the op sink (for speculation).
+ */
+ void SetOpSink(nsAHtml5TreeOpSink* aOpSink);
+
+ /**
+ * Reset state to after generated head but before processing any of the input
+ * stream.
+ */
+ void Rewind();
+
+ /**
+ * Starts the generated document.
+ */
+ void Start(const nsAutoString& aTitle);
+
+ /**
+ * Updates the charset source via the op queue.
+ */
+ void UpdateCharsetSource(nsCharsetSource aCharsetSource);
+
+ /**
+ * Report a tokenizer state transition.
+ *
+ * @param aState the state being transitioned to
+ * @param aReconsume whether this is a reconsuming transition
+ * @param aPos the tokenizer's current position into the buffer
+ */
+ int32_t Transition(int32_t aState, bool aReconsume, int32_t aPos);
+
+ /**
+ * Report end of file.
+ *
+ * Returns `true` normally and `false` on OOM.
+ */
+ [[nodiscard]] bool End();
+
+ /**
+ * Set the current buffer being tokenized
+ */
+ void SetBuffer(nsHtml5UTF16Buffer* aBuffer);
+
+ /**
+ * Let go of the buffer being tokenized but first, flush text from it.
+ *
+ * @param aPos the first UTF-16 code unit not to flush
+ */
+ void DropBuffer(int32_t aPos);
+
+ /**
+ * Query whether there are some many ops in the queue
+ * that they should be flushed now.
+ *
+ * @return true if FlushOps() should be called now
+ */
+ bool ShouldFlushOps();
+
+ /**
+ * Flush the tree ops into the sink.
+ *
+ * @return Ok(true) if there were ops to flush, Ok(false)
+ * if there were no ops to flush and Err() on OOM.
+ */
+ mozilla::Result<bool, nsresult> FlushOps();
+
+ /**
+ * Linkify the current attribute value if the attribute name is one of
+ * known URL attributes. (When executing tree ops, javascript: URLs will
+ * not be linkified, though.)
+ *
+ * @param aName the name of the attribute
+ * @param aValue the value of the attribute
+ */
+ void MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName,
+ nsHtml5String aValue);
+
+ /**
+ * Inform the highlighter that the tokenizer successfully completed a
+ * named character reference.
+ */
+ void CompletedNamedCharacterReference();
+
+ /**
+ * Adds an error annotation to the node that's currently on top of
+ * mStack.
+ *
+ * @param aMsgId the id of the message in the property file
+ */
+ void AddErrorToCurrentNode(const char* aMsgId);
+
+ /**
+ * Adds an error annotation to the node that corresponds to the most
+ * recently opened markup declaration/tag span, character reference or
+ * run of text.
+ *
+ * @param aMsgId the id of the message in the property file
+ */
+ void AddErrorToCurrentRun(const char* aMsgId);
+
+ /**
+ * Adds an error annotation to the node that corresponds to the most
+ * recently opened markup declaration/tag span, character reference or
+ * run of text with one atom to use when formatting the message.
+ *
+ * @param aMsgId the id of the message in the property file
+ * @param aName the atom
+ */
+ void AddErrorToCurrentRun(const char* aMsgId, nsAtom* aName);
+
+ /**
+ * Adds an error annotation to the node that corresponds to the most
+ * recently opened markup declaration/tag span, character reference or
+ * run of text with two atoms to use when formatting the message.
+ *
+ * @param aMsgId the id of the message in the property file
+ * @param aName the first atom
+ * @param aOther the second atom
+ */
+ void AddErrorToCurrentRun(const char* aMsgId, nsAtom* aName, nsAtom* aOther);
+
+ /**
+ * Adds an error annotation to the node that corresponds to the most
+ * recent potentially character reference-starting ampersand.
+ *
+ * @param aMsgId the id of the message in the property file
+ */
+ void AddErrorToCurrentAmpersand(const char* aMsgId);
+
+ /**
+ * Adds an error annotation to the node that corresponds to the most
+ * recent potentially self-closing slash.
+ *
+ * @param aMsgId the id of the message in the property file
+ */
+ void AddErrorToCurrentSlash(const char* aMsgId);
+
+ /**
+ * Enqueues a tree op for adding base to the urls with the view-source:
+ *
+ * @param aValue the base URL to add
+ */
+ void AddBase(nsHtml5String aValue);
+
+ /**
+ * Starts a wrapper around a run of characters.
+ */
+ void StartCharacters();
+
+ private:
+ /**
+ * Starts a span with no class.
+ */
+ void StartSpan();
+
+ /**
+ * Starts a <span> and sets the class attribute on it.
+ *
+ * @param aClass the class to set (MUST be a static string that does not
+ * need to be released!)
+ */
+ void StartSpan(const char16_t* aClass);
+
+ /**
+ * End the current <span> or <a> in the highlighter output.
+ */
+ void EndSpanOrA();
+
+ /**
+ * Ends a wrapper around a run of characters.
+ */
+ void EndCharactersAndStartMarkupRun();
+
+ /**
+ * Starts an <a>.
+ */
+ void StartA();
+
+ /**
+ * Flushes characters up to but not including the current one.
+ */
+ void FlushChars();
+
+ /**
+ * Flushes characters up to and including the current one.
+ */
+ void FlushCurrent();
+
+ /**
+ * Finishes highlighting a tag in the input data by closing the open
+ * <span> and <a> elements in the highlighter output and then starts
+ * another <span> for potentially highlighting characters potentially
+ * appearing next.
+ */
+ void FinishTag();
+
+ /**
+ * Adds a class attribute to the current node.
+ *
+ * @param aClass the class to set (MUST be a static string that does not
+ * need to be released!)
+ */
+ void AddClass(const char16_t* aClass);
+
+ /**
+ * Allocates a handle for an element.
+ *
+ * See the documentation for nsHtml5TreeBuilder::AllocateContentHandle()
+ * in nsHtml5TreeBuilderHSupplement.h.
+ *
+ * @return the handle
+ */
+ nsIContent** AllocateContentHandle();
+
+ /**
+ * Enqueues an element creation tree operation.
+ *
+ * @param aName the name of the element
+ * @param aAttributes the attribute holder (ownership will be taken) or
+ * nullptr for no attributes
+ * @param aIntendedParent the intended parent node for the created element
+ * @param aCreator the content creator function
+ * @return the handle for the element that will be created
+ */
+ nsIContent** CreateElement(nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ nsIContent** aIntendedParent,
+ mozilla::dom::HTMLContentCreatorFunction aCreator);
+
+ /**
+ * Gets the handle for the current node. May be called only after the
+ * root element has been set.
+ *
+ * @return the handle for the current node
+ */
+ nsIContent** CurrentNode();
+
+ /**
+ * Create an element and push it (its handle) on the stack.
+ *
+ * @param aName the name of the element
+ * @param aAttributes the attribute holder (ownership will be taken) or
+ * nullptr for no attributes
+ * @param aCreator the content creator function
+ */
+ void Push(nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::HTMLContentCreatorFunction aCreator);
+
+ /**
+ * Pops the current node off the stack.
+ */
+ void Pop();
+
+ /**
+ * Appends text content to the current node.
+ *
+ * @param aBuffer the buffer to copy from
+ * @param aStart the index of the first code unit to copy
+ * @param aLength the number of code units to copy
+ */
+ void AppendCharacters(const char16_t* aBuffer, int32_t aStart,
+ int32_t aLength);
+
+ /**
+ * Enqueues a tree op for adding an href attribute with the view-source:
+ * URL scheme to the current node.
+ *
+ * @param aValue the (potentially relative) URL to link to
+ */
+ void AddViewSourceHref(nsHtml5String aValue);
+
+ /**
+ * The state we are transitioning away from.
+ */
+ int32_t mState;
+
+ /**
+ * The index of the first UTF-16 code unit in mBuffer that hasn't been
+ * flushed yet.
+ */
+ int32_t mCStart;
+
+ /**
+ * The position of the code unit in mBuffer that caused the current
+ * transition.
+ */
+ int32_t mPos;
+
+ /**
+ * The current line number.
+ */
+ int32_t mLineNumber;
+
+ /**
+ * The number of inline elements open inside the <pre> excluding the
+ * span potentially wrapping a run of characters.
+ */
+ int32_t mInlinesOpen;
+
+ /**
+ * Whether there's a span wrapping a run of characters (excluding CDATA
+ * section) open.
+ */
+ bool mInCharacters;
+
+ /**
+ * The current buffer being tokenized.
+ */
+ nsHtml5UTF16Buffer* mBuffer;
+
+ /**
+ * The outgoing tree op queue.
+ */
+ nsTArray<nsHtml5TreeOperation> mOpQueue;
+
+ /**
+ * The tree op stage for the tree op executor or a speculation when looking
+ * for meta charset.
+ *
+ * The op sink is owned by the nsHtml5TreeOpExecutor, which outlives this
+ * object, because this object is owned by the nsHtml5Tokenizer instance that
+ * is owned by the nsHtml5StreamParser, which keeps the executor alive via
+ * nsHtml5Streamparser::mExecutorFlusher.
+ */
+ nsAHtml5TreeOpSink* mOpSink;
+
+ /**
+ * The most recently opened markup declaration/tag or run of characters.
+ */
+ nsIContent** mCurrentRun;
+
+ /**
+ * The most recent ampersand in a place where character references were
+ * allowed.
+ */
+ nsIContent** mAmpersand;
+
+ /**
+ * The most recent slash that might become a self-closing slash.
+ */
+ nsIContent** mSlash;
+
+ /**
+ * Memory for element handles.
+ */
+ mozilla::UniquePtr<nsIContent*[]> mHandles;
+
+ /**
+ * Number of handles used in mHandles
+ */
+ int32_t mHandlesUsed;
+
+ /**
+ * A holder for old contents of mHandles
+ */
+ nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles;
+
+ /**
+ * The element stack.
+ */
+ nsTArray<nsIContent**> mStack;
+
+ /**
+ * The string "comment"
+ */
+ static char16_t sComment[];
+
+ /**
+ * The string "cdata"
+ */
+ static char16_t sCdata[];
+
+ /**
+ * The string "start-tag"
+ */
+ static char16_t sStartTag[];
+
+ /**
+ * The string "attribute-name"
+ */
+ static char16_t sAttributeName[];
+
+ /**
+ * The string "attribute-value"
+ */
+ static char16_t sAttributeValue[];
+
+ /**
+ * The string "end-tag"
+ */
+ static char16_t sEndTag[];
+
+ /**
+ * The string "doctype"
+ */
+ static char16_t sDoctype[];
+
+ /**
+ * The string "entity"
+ */
+ static char16_t sEntity[];
+
+ /**
+ * The string "pi"
+ */
+ static char16_t sPi[];
+
+ /**
+ * Whether base is already visited once.
+ */
+ bool mSeenBase;
+};
+
+#endif // nsHtml5Highlighter_h
diff --git a/parser/html/nsHtml5HtmlAttributes.cpp b/parser/html/nsHtml5HtmlAttributes.cpp
new file mode 100644
index 0000000000..c2cd97de50
--- /dev/null
+++ b/parser/html/nsHtml5HtmlAttributes.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define nsHtml5HtmlAttributes_cpp__
+
+#include "jArray.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsAtom.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsHtml5String.h"
+#include "nsIContent.h"
+#include "nsIContentHandle.h"
+#include "nsNameSpaceManager.h"
+#include "nsTraceRefcnt.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5UTF16Buffer.h"
+
+#include "nsHtml5HtmlAttributes.h"
+
+nsHtml5HtmlAttributes* nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES = nullptr;
+
+nsHtml5HtmlAttributes::nsHtml5HtmlAttributes(int32_t aMode) : mMode(aMode) {
+ MOZ_COUNT_CTOR(nsHtml5HtmlAttributes);
+}
+
+nsHtml5HtmlAttributes::~nsHtml5HtmlAttributes() {
+ MOZ_COUNT_DTOR(nsHtml5HtmlAttributes);
+ clear(0);
+}
+
+int32_t nsHtml5HtmlAttributes::getIndex(nsHtml5AttributeName* aName) {
+ for (size_t i = 0; i < mStorage.Length(); i++) {
+ if (mStorage[i].GetLocal(nsHtml5AttributeName::HTML) ==
+ aName->getLocal(nsHtml5AttributeName::HTML)) {
+ // It's release asserted elsewhere that i can't be too large.
+ return i;
+ }
+ }
+ return -1;
+}
+
+nsHtml5String nsHtml5HtmlAttributes::getValue(nsHtml5AttributeName* aName) {
+ int32_t index = getIndex(aName);
+ if (index == -1) {
+ return nullptr;
+ } else {
+ return getValueNoBoundsCheck(index);
+ }
+}
+
+int32_t nsHtml5HtmlAttributes::getLength() { return mStorage.Length(); }
+
+nsAtom* nsHtml5HtmlAttributes::getLocalNameNoBoundsCheck(int32_t aIndex) {
+ MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0,
+ "Index out of bounds");
+ return mStorage[aIndex].GetLocal(mMode);
+}
+
+int32_t nsHtml5HtmlAttributes::getURINoBoundsCheck(int32_t aIndex) {
+ MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0,
+ "Index out of bounds");
+ return mStorage[aIndex].GetUri(mMode);
+}
+
+nsAtom* nsHtml5HtmlAttributes::getPrefixNoBoundsCheck(int32_t aIndex) {
+ MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0,
+ "Index out of bounds");
+ return mStorage[aIndex].GetPrefix(mMode);
+}
+
+nsHtml5String nsHtml5HtmlAttributes::getValueNoBoundsCheck(int32_t aIndex) {
+ MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0,
+ "Index out of bounds");
+ return mStorage[aIndex].GetValue();
+}
+
+int32_t nsHtml5HtmlAttributes::getLineNoBoundsCheck(int32_t aIndex) {
+ MOZ_ASSERT(aIndex < int32_t(mStorage.Length()) && aIndex >= 0,
+ "Index out of bounds");
+ return mStorage[aIndex].GetLine();
+}
+
+void nsHtml5HtmlAttributes::addAttribute(nsHtml5AttributeName* aName,
+ nsHtml5String aValue, int32_t aLine) {
+ mStorage.AppendElement(nsHtml5AttributeEntry(aName, aValue, aLine));
+ MOZ_RELEASE_ASSERT(mStorage.Length() <= INT32_MAX,
+ "Can't handle this many attributes.");
+}
+
+// Isindex-only, so doesn't need to deal with SVG and MathML
+void nsHtml5HtmlAttributes::AddAttributeWithLocal(nsAtom* aName,
+ nsHtml5String aValue,
+ int32_t aLine) {
+ mStorage.AppendElement(nsHtml5AttributeEntry(aName, aValue, aLine));
+ MOZ_RELEASE_ASSERT(mStorage.Length() <= INT32_MAX,
+ "Can't handle this many attributes.");
+}
+
+void nsHtml5HtmlAttributes::clear(int32_t aMode) {
+ for (nsHtml5AttributeEntry& entry : mStorage) {
+ entry.ReleaseValue();
+ }
+ mStorage.TruncateLength(0);
+ mMode = aMode;
+}
+
+void nsHtml5HtmlAttributes::releaseValue(int32_t aIndex) {
+ mStorage[aIndex].ReleaseValue();
+}
+
+void nsHtml5HtmlAttributes::clearWithoutReleasingContents() {
+ mStorage.TruncateLength(0);
+}
+
+bool nsHtml5HtmlAttributes::contains(nsHtml5AttributeName* aName) {
+ for (size_t i = 0; i < mStorage.Length(); i++) {
+ if (mStorage[i].GetLocal(nsHtml5AttributeName::HTML) ==
+ aName->getLocal(nsHtml5AttributeName::HTML)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void nsHtml5HtmlAttributes::adjustForMath() {
+ mMode = nsHtml5AttributeName::MATHML;
+}
+
+void nsHtml5HtmlAttributes::adjustForSvg() {
+ mMode = nsHtml5AttributeName::SVG;
+}
+
+nsHtml5HtmlAttributes* nsHtml5HtmlAttributes::cloneAttributes() {
+ MOZ_ASSERT(mStorage.IsEmpty() || !mMode);
+ nsHtml5HtmlAttributes* clone =
+ new nsHtml5HtmlAttributes(nsHtml5AttributeName::HTML);
+ for (nsHtml5AttributeEntry& entry : mStorage) {
+ clone->AddEntry(entry.Clone());
+ }
+ return clone;
+}
+
+bool nsHtml5HtmlAttributes::equalsAnother(nsHtml5HtmlAttributes* aOther) {
+ MOZ_ASSERT(!mMode, "Trying to compare attributes in foreign content.");
+ if (mStorage.Length() != aOther->mStorage.Length()) {
+ return false;
+ }
+ for (nsHtml5AttributeEntry& entry : mStorage) {
+ bool found = false;
+ nsAtom* ownLocal = entry.GetLocal(nsHtml5AttributeName::HTML);
+ for (nsHtml5AttributeEntry& otherEntry : aOther->mStorage) {
+ if (ownLocal == otherEntry.GetLocal(nsHtml5AttributeName::HTML)) {
+ found = true;
+ if (!entry.GetValue().Equals(otherEntry.GetValue())) {
+ return false;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void nsHtml5HtmlAttributes::AddEntry(nsHtml5AttributeEntry&& aEntry) {
+ mStorage.AppendElement(aEntry);
+}
+
+void nsHtml5HtmlAttributes::initializeStatics() {
+ EMPTY_ATTRIBUTES = new nsHtml5HtmlAttributes(nsHtml5AttributeName::HTML);
+}
+
+void nsHtml5HtmlAttributes::releaseStatics() { delete EMPTY_ATTRIBUTES; }
diff --git a/parser/html/nsHtml5HtmlAttributes.h b/parser/html/nsHtml5HtmlAttributes.h
new file mode 100644
index 0000000000..f840f0cc3e
--- /dev/null
+++ b/parser/html/nsHtml5HtmlAttributes.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2008-2017 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef nsHtml5HtmlAttributes_h
+#define nsHtml5HtmlAttributes_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsTArray.h"
+#include "nsHtml5AttributeEntry.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5HtmlAttributes {
+ public:
+ static nsHtml5HtmlAttributes* EMPTY_ATTRIBUTES;
+
+ private:
+ AutoTArray<nsHtml5AttributeEntry, 5> mStorage;
+ int32_t mMode;
+ void AddEntry(nsHtml5AttributeEntry&& aEntry);
+
+ public:
+ explicit nsHtml5HtmlAttributes(int32_t aMode);
+ ~nsHtml5HtmlAttributes();
+
+ // Remove getIndex when removing isindex support
+ int32_t getIndex(nsHtml5AttributeName* aName);
+
+ nsHtml5String getValue(nsHtml5AttributeName* aName);
+ int32_t getLength();
+ nsAtom* getLocalNameNoBoundsCheck(int32_t aIndex);
+ int32_t getURINoBoundsCheck(int32_t aIndex);
+ nsAtom* getPrefixNoBoundsCheck(int32_t aIndex);
+ nsHtml5String getValueNoBoundsCheck(int32_t aIndex);
+ nsHtml5AttributeName* getAttributeNameNoBoundsCheck(int32_t aIndex);
+ int32_t getLineNoBoundsCheck(int32_t aIndex);
+ void addAttribute(nsHtml5AttributeName* aName, nsHtml5String aValue,
+ int32_t aLine);
+ void AddAttributeWithLocal(nsAtom* aName, nsHtml5String aValue,
+ int32_t aLine);
+ void clear(int32_t aMode);
+ void releaseValue(int32_t aIndex);
+ void clearWithoutReleasingContents();
+ bool contains(nsHtml5AttributeName* aName);
+ void adjustForMath();
+ void adjustForSvg();
+ nsHtml5HtmlAttributes* cloneAttributes();
+ bool equalsAnother(nsHtml5HtmlAttributes* aOther);
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif
diff --git a/parser/html/nsHtml5Macros.h b/parser/html/nsHtml5Macros.h
new file mode 100644
index 0000000000..751d4dc04e
--- /dev/null
+++ b/parser/html/nsHtml5Macros.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef nsHtml5Macros_h
+#define nsHtml5Macros_h
+
+#define NS_HTML5_CONTINUE(target) goto target
+
+#define NS_HTML5_BREAK(target) goto target##_end
+
+#endif /* nsHtml5Macros_h */
diff --git a/parser/html/nsHtml5Module.cpp b/parser/html/nsHtml5Module.cpp
new file mode 100644
index 0000000000..366a63e54f
--- /dev/null
+++ b/parser/html/nsHtml5Module.cpp
@@ -0,0 +1,123 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5Module.h"
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPrefs_html5.h"
+#include "nsCOMPtr.h"
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5HtmlAttributes.h"
+#include "nsHtml5NamedCharacters.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsIObserverService.h"
+
+using namespace mozilla;
+
+// static
+nsIThread* nsHtml5Module::sStreamParserThread = nullptr;
+
+class nsHtml5ParserThreadTerminator final : public nsIObserver {
+ public:
+ NS_DECL_ISUPPORTS
+ explicit nsHtml5ParserThreadTerminator(nsIThread* aThread)
+ : mThread(aThread) {}
+ NS_IMETHOD Observe(nsISupports*, const char* topic,
+ const char16_t*) override {
+ NS_ASSERTION(!strcmp(topic, "xpcom-shutdown-threads"), "Unexpected topic");
+ mThread->Shutdown();
+ mThread = nullptr;
+ NS_IF_RELEASE(nsHtml5Module::sStreamParserThread);
+ nsHtml5Module::sStreamParserThread = nullptr;
+ return NS_OK;
+ }
+
+ private:
+ ~nsHtml5ParserThreadTerminator() = default;
+
+ nsCOMPtr<nsIThread> mThread;
+};
+
+NS_IMPL_ISUPPORTS(nsHtml5ParserThreadTerminator, nsIObserver)
+
+// static
+void nsHtml5Module::InitializeStatics() {
+ nsHtml5AttributeName::initializeStatics();
+ nsHtml5ElementName::initializeStatics();
+ nsHtml5HtmlAttributes::initializeStatics();
+ nsHtml5NamedCharacters::initializeStatics();
+ nsHtml5Portability::initializeStatics();
+ nsHtml5StackNode::initializeStatics();
+ nsHtml5Tokenizer::initializeStatics();
+ nsHtml5TreeBuilder::initializeStatics();
+ nsHtml5UTF16Buffer::initializeStatics();
+
+ NS_NewNamedThread("HTML5 Parser", &sStreamParserThread);
+ if (sStreamParserThread) {
+ nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+ if (os) {
+ os->AddObserver(new nsHtml5ParserThreadTerminator(sStreamParserThread),
+ "xpcom-shutdown-threads", false);
+ } else {
+ MOZ_ASSERT(false,
+ "How come we failed to create get the observer service?");
+ }
+ } else {
+ MOZ_ASSERT(false, "How come we failed to create the parser thread?");
+ }
+
+#ifdef DEBUG
+ sNsHtml5ModuleInitialized = true;
+#endif
+}
+
+// static
+void nsHtml5Module::ReleaseStatics() {
+#ifdef DEBUG
+ sNsHtml5ModuleInitialized = false;
+#endif
+ nsHtml5AttributeName::releaseStatics();
+ nsHtml5ElementName::releaseStatics();
+ nsHtml5HtmlAttributes::releaseStatics();
+ nsHtml5NamedCharacters::releaseStatics();
+ nsHtml5Portability::releaseStatics();
+ nsHtml5StackNode::releaseStatics();
+ nsHtml5Tokenizer::releaseStatics();
+ nsHtml5TreeBuilder::releaseStatics();
+ nsHtml5UTF16Buffer::releaseStatics();
+ NS_IF_RELEASE(sStreamParserThread);
+}
+
+// static
+already_AddRefed<nsHtml5Parser> nsHtml5Module::NewHtml5Parser() {
+ MOZ_ASSERT(sNsHtml5ModuleInitialized, "nsHtml5Module not initialized.");
+ RefPtr<nsHtml5Parser> rv = new nsHtml5Parser();
+ return rv.forget();
+}
+
+// static
+already_AddRefed<nsISerialEventTarget>
+nsHtml5Module::GetStreamParserEventTarget() {
+ MOZ_ASSERT(sNsHtml5ModuleInitialized, "nsHtml5Module not initialized.");
+ if (sStreamParserThread) {
+ nsCOMPtr<nsISerialEventTarget> target = sStreamParserThread;
+ return target.forget();
+ }
+ nsCOMPtr<nsIThread> mainThread;
+ NS_GetMainThread(getter_AddRefs(mainThread));
+ MOZ_RELEASE_ASSERT(mainThread); // Unrecoverable situation
+ nsCOMPtr<nsISerialEventTarget> target = mainThread;
+ return target.forget();
+}
+
+#ifdef DEBUG
+bool nsHtml5Module::sNsHtml5ModuleInitialized = false;
+#endif
diff --git a/parser/html/nsHtml5Module.h b/parser/html/nsHtml5Module.h
new file mode 100644
index 0000000000..950de37e53
--- /dev/null
+++ b/parser/html/nsHtml5Module.h
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5Module_h
+#define nsHtml5Module_h
+
+#include "nsIThread.h"
+
+class nsHtml5Parser;
+
+class nsHtml5Module {
+ friend class nsHtml5ParserThreadTerminator;
+
+ public:
+ static void InitializeStatics();
+ static void ReleaseStatics();
+ static already_AddRefed<nsHtml5Parser> NewHtml5Parser();
+ static already_AddRefed<nsISerialEventTarget> GetStreamParserEventTarget();
+
+ private:
+#ifdef DEBUG
+ static bool sNsHtml5ModuleInitialized;
+#endif
+ static nsIThread* sStreamParserThread;
+};
+
+#endif // nsHtml5Module_h
diff --git a/parser/html/nsHtml5NamedCharacters.cpp b/parser/html/nsHtml5NamedCharacters.cpp
new file mode 100644
index 0000000000..5181d7538e
--- /dev/null
+++ b/parser/html/nsHtml5NamedCharacters.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2008-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define nsHtml5NamedCharacters_cpp_
+#include "jArray.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Logging.h"
+#include "nsDebug.h"
+#include "nscore.h"
+
+#include "nsHtml5NamedCharacters.h"
+
+const char16_t nsHtml5NamedCharacters::VALUES[][2] = {
+#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) {VALUE},
+#include "nsHtml5NamedCharactersInclude.h"
+#undef NAMED_CHARACTER_REFERENCE
+ {0, 0}};
+
+char16_t** nsHtml5NamedCharacters::WINDOWS_1252;
+static char16_t const WINDOWS_1252_DATA[] = {
+ 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
+ 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F,
+ 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
+ 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178};
+
+/**
+ * To avoid having lots of pointers in the |charData| array, below,
+ * which would cause us to have to do lots of relocations at library
+ * load time, store all the string data for the names in one big array.
+ * Then use tricks with enums to help us build an array that contains
+ * the positions of each within the big arrays.
+ */
+
+static const int8_t ALL_NAMES[] = {
+#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) CHARS,
+#include "nsHtml5NamedCharactersInclude.h"
+#undef NAMED_CHARACTER_REFERENCE
+};
+
+enum NamePositions {
+ DUMMY_INITIAL_NAME_POSITION = 0,
+/* enums don't take up space, so generate _START and _END */
+#define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \
+ NAME_##N##_DUMMY, /* automatically one higher than previous */ \
+ NAME_##N##_START = NAME_##N##_DUMMY - 1, \
+ NAME_##N##_END = NAME_##N##_START + LEN + FLAG,
+#include "nsHtml5NamedCharactersInclude.h"
+#undef NAMED_CHARACTER_REFERENCE
+ DUMMY_FINAL_NAME_VALUE
+};
+
+static_assert(MOZ_ARRAY_LENGTH(ALL_NAMES) < 0x10000,
+ "Start positions should fit in 16 bits");
+
+const nsHtml5CharacterName nsHtml5NamedCharacters::NAMES[] = {
+#ifdef DEBUG
+# define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \
+ {NAME_##N##_START, LEN, N},
+#else
+# define NAMED_CHARACTER_REFERENCE(N, CHARS, LEN, FLAG, VALUE) \
+ { \
+ NAME_##N##_START, \
+ LEN, \
+ },
+#endif
+#include "nsHtml5NamedCharactersInclude.h"
+#undef NAMED_CHARACTER_REFERENCE
+};
+
+int32_t nsHtml5CharacterName::length() const { return nameLen; }
+
+char16_t nsHtml5CharacterName::charAt(int32_t index) const {
+ return static_cast<char16_t>(ALL_NAMES[nameStart + index]);
+}
+
+void nsHtml5NamedCharacters::initializeStatics() {
+ WINDOWS_1252 = new char16_t*[32];
+ for (int32_t i = 0; i < 32; ++i) {
+ WINDOWS_1252[i] = (char16_t*)&(WINDOWS_1252_DATA[i]);
+ }
+}
+
+void nsHtml5NamedCharacters::releaseStatics() { delete[] WINDOWS_1252; }
diff --git a/parser/html/nsHtml5NamedCharacters.h b/parser/html/nsHtml5NamedCharacters.h
new file mode 100644
index 0000000000..379c2c17b9
--- /dev/null
+++ b/parser/html/nsHtml5NamedCharacters.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef nsHtml5NamedCharacters_h
+#define nsHtml5NamedCharacters_h
+
+#include "jArray.h"
+#include "nscore.h"
+#include "nsDebug.h"
+#include "mozilla/Logging.h"
+
+struct nsHtml5CharacterName {
+ uint16_t nameStart;
+ uint16_t nameLen;
+#ifdef DEBUG
+ int32_t n;
+#endif
+ int32_t length() const;
+ char16_t charAt(int32_t index) const;
+};
+
+class nsHtml5NamedCharacters {
+ public:
+ static const nsHtml5CharacterName NAMES[];
+ static const char16_t VALUES[][2];
+ static char16_t** WINDOWS_1252;
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif // nsHtml5NamedCharacters_h
diff --git a/parser/html/nsHtml5NamedCharactersAccel.cpp b/parser/html/nsHtml5NamedCharactersAccel.cpp
new file mode 100644
index 0000000000..a486c102d2
--- /dev/null
+++ b/parser/html/nsHtml5NamedCharactersAccel.cpp
@@ -0,0 +1,463 @@
+/*
+ * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera
+ * Software ASA.
+ *
+ * You are granted a license to use, reproduce and create derivative works of
+ * this document.
+ */
+
+#include "nsHtml5NamedCharactersAccel.h"
+
+static int32_t const HILO_ACCEL_65[] = {
+ 0, 0, 0, 0, 0, 0, 0, 12386493, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 40174181, 0, 0,
+ 0, 0, 60162966, 0, 0, 0, 75367550, 0, 0,
+ 0, 82183396, 0, 0, 0, 0, 0, 115148507, 0,
+ 0, 135989275, 139397199, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_66[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 28770743, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82248935, 0,
+ 0, 0, 0, 0, 115214046, 0, 0, 0, 139528272, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_68[] = {
+ 0, 0, 0, 4980811, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 38470219, 0, 0, 0, 0,
+ 0, 0, 0, 0, 64553944, 0, 0, 0, 0, 0, 0, 0, 92145022,
+ 0, 0, 0, 0, 0, 0, 0, 0, 139593810, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_69[] = {
+ 65536, 0, 0, 0, 0, 0, 0, 0, 13172937, 0, 0, 0, 0, 0,
+ 25297282, 0, 0, 28901816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 71500866, 0, 0, 0, 0, 82380008, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_71[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 94897574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_72[] = {
+ 0, 0, 2555943, 0, 0, 0, 0, 0, 0, 0, 15532269,
+ 0, 0, 0, 0, 0, 0, 0, 31785444, 34406924, 0, 0,
+ 0, 0, 0, 40895088, 0, 0, 0, 60228503, 0, 0, 0,
+ 0, 0, 0, 0, 82445546, 0, 0, 0, 0, 0, 115279583,
+ 0, 0, 136054812, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_73[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 40239718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_74[] = {
+ 0, 0, 0, 5046349, 0, 0, 10944679, 0, 13238474, 0, 15597806,
+ 16056565, 0, 20578618, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_76[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 95225257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_77[] = {
+ 196610, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_78[] = {
+ 0, 0, 0, 0, 8454273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 46072511, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_79[] = {
+ 0, 0, 2687016, 0, 0, 0, 0, 0, 13304011, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 31850982, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_82[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 34472462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 95290798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_83[] = {
+ 0, 0, 0, 5111886, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 34603535, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 105776718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_84[] = {
+ 0, 0, 0, 0, 8585346, 0, 11075752, 0, 0, 0, 0, 16187638, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_85[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28508594, 0,
+ 0, 0, 0, 0, 0, 0, 40305255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_86[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 95421871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_90[] = {
+ 0, 0, 0, 5177423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_97[] = {
+ 327684, 1900571, 2949162, 5374032, 8716420, 0, 11206826,
+ 12517566, 13435084, 0, 15663343, 16515320, 19988785, 20644155,
+ 25428355, 27197855, 0, 29163962, 31916519, 34734609, 36045347,
+ 0, 0, 0, 40436328, 40960625, 41615994, 46596800,
+ 54264627, 60556184, 64750554, 68879387, 71763012, 75826303, 77268122,
+ 0, 81462490, 83952875, 92865919, 96142769, 105973327, 110167691,
+ 0, 116917984, 121833283, 132253665, 136251421, 140707923, 0,
+ 0, 144574620, 145361066};
+
+static int32_t const HILO_ACCEL_98[] = {
+ 393222, 0, 0, 0, 0, 0, 11272364,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 36176423,
+ 38535756, 0, 0, 0, 0, 41681532, 46727880,
+ 0, 60687261, 0, 0, 71828552, 75891846, 0,
+ 0, 0, 84411650, 0, 96404924, 0, 0,
+ 0, 117376761, 121898820, 132319203, 136382496, 0, 0,
+ 0, 0, 0};
+
+static int32_t const HILO_ACCEL_99[] = {
+ 589831, 1966110, 3276846, 5505107, 8978566, 10420383, 11468973,
+ 12583104, 13631694, 15139046, 15794416, 16711933, 20054322, 20840764,
+ 25624965, 27263392, 0, 29360574, 32244200, 34931219, 36373033,
+ 38601293, 39584348, 0, 40567402, 41091698, 42205821, 46858954,
+ 54723389, 60818335, 65143773, 68944924, 71959625, 75957383, 77530268,
+ 80938194, 81593564, 84739337, 92997002, 96863680, 106235474, 110233234,
+ 0, 117704448, 122816325, 132515812, 136579106, 140773476, 142149753,
+ 143001732, 144705695, 145492139};
+
+static int32_t const HILO_ACCEL_100[] = {
+ 0, 0, 3342387, 0, 9044106, 0, 11534512,
+ 0, 13697233, 0, 0, 0, 0, 0,
+ 25690504, 0, 0, 0, 0, 0, 36438572,
+ 38732366, 0, 0, 0, 41157236, 0, 46924492,
+ 54788932, 61080481, 65209315, 0, 72025163, 0, 0,
+ 0, 0, 85132558, 93062540, 96929223, 106563158, 0,
+ 0, 118032133, 123012947, 132581351, 136775717, 140839013, 0,
+ 143067271, 0, 145557677};
+
+static int32_t const HILO_ACCEL_101[] = {
+ 0, 2162719, 3473460, 5636181, 0, 0, 0,
+ 0, 0, 0, 0, 18809088, 20185395, 21299519,
+ 0, 0, 0, 29622721, 0, 0, 0,
+ 39256656, 39649885, 0, 0, 41288309, 42336901, 47448781,
+ 55182149, 61342629, 65274852, 69010461, 72811596, 76219528, 77726880,
+ 0, 0, 86967572, 93128077, 97650120, 106628699, 110560915,
+ 0, 118490890, 123733846, 132646888, 0, 141232230, 142411898,
+ 0, 144836769, 145688750};
+
+static int32_t const HILO_ACCEL_102[] = {
+ 655370, 2228258, 3538998, 5701719, 9109643, 10485920, 11600049,
+ 12648641, 13762770, 15204584, 15859954, 18874656, 20250933, 21365062,
+ 25756041, 27328929, 28574132, 29688261, 32309741, 34996758, 36504109,
+ 39322200, 39715422, 39912033, 40632940, 41353847, 42467975, 47514325,
+ 55247691, 61473705, 65405925, 69272606, 72877144, 76285068, 77857955,
+ 81003732, 81659102, 87164208, 93193614, 97715667, 106759772, 110626456,
+ 114296528, 118687505, 123864929, 132712425, 136906792, 141297772, 142477438,
+ 143132808, 144902307, 145754288};
+
+static int32_t const HILO_ACCEL_103[] = {
+ 786443, 0, 0, 0, 9240716, 0, 11665586, 0,
+ 13893843, 0, 0, 0, 0, 0, 25887114, 0,
+ 0, 0, 0, 0, 36635182, 0, 0, 0,
+ 0, 0, 42599049, 0, 0, 0, 65733607, 0,
+ 73008217, 0, 77989029, 0, 81724639, 87295283, 0, 98305492,
+ 107021918, 0, 0, 0, 0, 0, 137037866, 0,
+ 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_104[] = {
+ 0, 0, 3604535, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 27394466, 0, 29753798, 32571886, 35258903, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 55509836, 61604779, 0, 0, 0, 0, 0,
+ 0, 81790176, 87557429, 93259151, 98502109, 107152994, 110888601,
+ 0, 119015188, 124323683, 133498858, 137234476, 0, 0,
+ 143263881, 0, 145819825};
+
+static int32_t const HILO_ACCEL_105[] = {
+ 0, 0, 3866680, 6160472, 0, 10616993, 0,
+ 12714178, 0, 0, 0, 0, 20316470, 0,
+ 0, 27460003, 0, 31261127, 32637426, 35521051, 0,
+ 0, 0, 39977570, 0, 0, 0, 48366294,
+ 56492880, 62391213, 0, 69338146, 73073755, 0, 78316711,
+ 0, 0, 0, 93980048, 98764256, 107218532, 111085213,
+ 114362065, 119736089, 125241194, 133957622, 0, 0, 0,
+ 143329419, 144967844, 145885362};
+
+static int32_t const HILO_ACCEL_106[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 62456761, 0, 69403683, 73139292, 0, 78382252, 0,
+ 81855713, 87622969, 0, 98829796, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_107[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 48431843, 0, 0, 0, 0, 0, 76416141, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_108[] = {
+ 851981, 0, 4063292, 0, 9306254, 0, 0,
+ 0, 0, 0, 0, 19005729, 0, 0,
+ 0, 27525540, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 42795659, 49152740,
+ 56623967, 62587834, 66061292, 69600292, 73401437, 0, 0,
+ 0, 0, 87950650, 94111131, 99878373, 107546213, 112002720,
+ 0, 119932708, 125306744, 0, 137496623, 141363309, 0,
+ 143460492, 0, 0};
+
+static int32_t const HILO_ACCEL_109[] = {
+ 917518, 0, 0, 0, 9502863, 0, 0,
+ 0, 14155989, 0, 0, 19071267, 0, 0,
+ 26083724, 0, 0, 0, 32702963, 0, 36700720,
+ 0, 0, 0, 0, 0, 43057806, 0,
+ 0, 0, 66520049, 0, 0, 0, 78841005,
+ 81069269, 0, 88147263, 0, 99943925, 107873898, 112068270,
+ 0, 120063783, 125831033, 0, 137693235, 0, 0,
+ 143526030, 0, 0};
+
+static int32_t const HILO_ACCEL_110[] = {
+ 983055, 0, 0, 0, 0, 0, 0,
+ 0, 14483673, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 37093937,
+ 0, 0, 0, 0, 0, 44565138, 49349359,
+ 0, 0, 66651128, 69665831, 73860193, 0, 79561908,
+ 0, 0, 88606018, 94176669, 0, 0, 0,
+ 0, 120129321, 0, 0, 0, 141494382, 0,
+ 143591567, 0, 0};
+
+static int32_t const HILO_ACCEL_111[] = {
+ 1114128, 2293795, 4587583, 8257631, 9633938, 10813603, 11731123,
+ 12845251, 14680286, 15270121, 15925491, 19661092, 20382007, 24969543,
+ 26149263, 27656613, 28639669, 31392222, 32768500, 35586591, 37225015,
+ 39387737, 39780959, 40043107, 40698477, 41419384, 44696233, 52495090,
+ 57738081, 63439804, 66782202, 69927976, 73925736, 76809359, 79824063,
+ 81134806, 81921250, 89785673, 94307742, 100795894, 107939439, 112330415,
+ 114427602, 120588074, 126158721, 134416381, 137824310, 141559920, 142542975,
+ 143853712, 145033381, 145950899};
+
+static int32_t const HILO_ACCEL_112[] = {
+ 1179666, 0, 0, 0, 9699476, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 26280336, 0, 0, 0, 0, 0, 38076985,
+ 0, 0, 0, 0, 0, 45220523, 52560674,
+ 0, 0, 67175420, 69993516, 0, 0, 79889603,
+ 0, 0, 89916763, 94373280, 101451267, 108136048, 0,
+ 114493139, 120784689, 126355334, 134481924, 138414136, 141625457, 142608512,
+ 0, 0, 0};
+
+static int32_t const HILO_ACCEL_113[] = {
+ 0, 0, 0, 0, 9896085, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 33292789, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 67830786, 0, 0, 0, 80020676, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 127403913, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_114[] = {
+ 1310739, 2359332, 4653127, 0, 0, 0, 12189876,
+ 0, 0, 0, 0, 0, 0, 0,
+ 26345874, 28246439, 0, 31457760, 0, 35652128, 38142534,
+ 0, 0, 0, 0, 0, 45351603, 52757283,
+ 57869170, 63636425, 67961868, 71304237, 73991273, 0, 0,
+ 0, 0, 90309981, 0, 101910029, 108988019, 114034355,
+ 0, 120850228, 127469465, 135464965, 138741825, 141690994, 142739585,
+ 143984788, 0, 0};
+
+static int32_t const HILO_ACCEL_115[] = {
+ 1441813, 2424869, 4718664, 8388735, 10027160, 10879142, 12255419,
+ 12976325, 14745825, 15401194, 15991028, 19857709, 20447544, 25035134,
+ 26542483, 28377520, 28705206, 31588833, 33358333, 35783201, 38208071,
+ 39453274, 39846496, 40108644, 40764014, 41484921, 45613749, 53216038,
+ 58196852, 63898572, 68158478, 71369793, 74253418, 77005973, 80479430,
+ 81265879, 81986787, 90965347, 94504353, 103679508, 109250176, 114165453,
+ 114558676, 121243445, 127731610, 135727124, 138807366, 142018675, 142805123,
+ 144115862, 145098918, 146016436};
+
+static int32_t const HILO_ACCEL_116[] = {
+ 1572887, 0, 0, 0, 10092698, 0, 12320956,
+ 0, 14811362, 0, 0, 19923248, 0, 25166207,
+ 26739094, 0, 0, 0, 33423870, 0, 38273608,
+ 0, 0, 0, 0, 0, 45744825, 0,
+ 58262393, 64095184, 68355089, 0, 75170926, 0, 80610509,
+ 0, 0, 91817325, 0, 104203823, 109512324, 0,
+ 0, 121636667, 128059294, 0, 139069511, 0, 0,
+ 0, 0, 0};
+
+static int32_t const HILO_ACCEL_117[] = {
+ 1703961, 2490406, 4849737, 0, 10223771, 0, 0,
+ 13107399, 15007971, 15466732, 0, 0, 20513081, 25231745,
+ 26870169, 0, 0, 31654371, 34275839, 0, 38404681,
+ 0, 0, 0, 40829551, 0, 45875899, 53609261,
+ 59900794, 64226259, 68551700, 0, 0, 0, 80807119,
+ 81331417, 0, 91948410, 94700963, 104465975, 109643400, 114230991,
+ 114951893, 121702209, 131663779, 0, 139266123, 0, 0,
+ 144246936, 145295527, 0};
+
+static int32_t const HILO_ACCEL_118[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 27132315, 0, 0, 0,
+ 0, 0, 0, 39518811, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 75302012, 0, 0, 0,
+ 0, 92079484, 0, 105383483, 109708938, 0, 0, 0, 0,
+ 0, 0, 0, 0, 144312474, 0, 0};
+
+static int32_t const HILO_ACCEL_119[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 46006973, 0, 60031891, 64291797,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 105711177,
+ 0, 0, 0, 0, 131991514, 135923736, 139331662, 0, 0, 144378011,
+ 0, 146147509};
+
+static int32_t const HILO_ACCEL_120[] = {
+ 0, 0, 0, 0, 10354845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68813847, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 121767746, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_121[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60097429, 0, 0, 0, 0, 77137048, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static int32_t const HILO_ACCEL_122[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64422870, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 132122591, 0, 0, 142084216, 0, 0, 0, 0};
+
+const int32_t* const nsHtml5NamedCharactersAccel::HILO_ACCEL[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ HILO_ACCEL_65,
+ HILO_ACCEL_66,
+ 0,
+ HILO_ACCEL_68,
+ HILO_ACCEL_69,
+ 0,
+ HILO_ACCEL_71,
+ HILO_ACCEL_72,
+ HILO_ACCEL_73,
+ HILO_ACCEL_74,
+ 0,
+ HILO_ACCEL_76,
+ HILO_ACCEL_77,
+ HILO_ACCEL_78,
+ HILO_ACCEL_79,
+ 0,
+ 0,
+ HILO_ACCEL_82,
+ HILO_ACCEL_83,
+ HILO_ACCEL_84,
+ HILO_ACCEL_85,
+ HILO_ACCEL_86,
+ 0,
+ 0,
+ 0,
+ HILO_ACCEL_90,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ HILO_ACCEL_97,
+ HILO_ACCEL_98,
+ HILO_ACCEL_99,
+ HILO_ACCEL_100,
+ HILO_ACCEL_101,
+ HILO_ACCEL_102,
+ HILO_ACCEL_103,
+ HILO_ACCEL_104,
+ HILO_ACCEL_105,
+ HILO_ACCEL_106,
+ HILO_ACCEL_107,
+ HILO_ACCEL_108,
+ HILO_ACCEL_109,
+ HILO_ACCEL_110,
+ HILO_ACCEL_111,
+ HILO_ACCEL_112,
+ HILO_ACCEL_113,
+ HILO_ACCEL_114,
+ HILO_ACCEL_115,
+ HILO_ACCEL_116,
+ HILO_ACCEL_117,
+ HILO_ACCEL_118,
+ HILO_ACCEL_119,
+ HILO_ACCEL_120,
+ HILO_ACCEL_121,
+ HILO_ACCEL_122};
diff --git a/parser/html/nsHtml5NamedCharactersAccel.h b/parser/html/nsHtml5NamedCharactersAccel.h
new file mode 100644
index 0000000000..de21f67c45
--- /dev/null
+++ b/parser/html/nsHtml5NamedCharactersAccel.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera
+ * Software ASA.
+ *
+ * You are granted a license to use, reproduce and create derivative works of
+ * this document.
+ */
+
+#ifndef nsHtml5NamedCharactersAccel_h
+#define nsHtml5NamedCharactersAccel_h
+
+#include "jArray.h"
+#include "nscore.h"
+#include "nsDebug.h"
+#include "mozilla/Logging.h"
+
+class nsHtml5NamedCharactersAccel {
+ public:
+ static const int32_t* const HILO_ACCEL[];
+};
+
+#endif // nsHtml5NamedCharactersAccel_h
diff --git a/parser/html/nsHtml5NamedCharactersInclude.h b/parser/html/nsHtml5NamedCharactersInclude.h
new file mode 100644
index 0000000000..1d178937a4
--- /dev/null
+++ b/parser/html/nsHtml5NamedCharactersInclude.h
@@ -0,0 +1,5467 @@
+/*
+ * Copyright 2004-2010 Apple Computer, Inc., Mozilla Foundation, and Opera
+ * Software ASA.
+ *
+ * You are granted a license to use, reproduce and create derivative works of
+ * this document.
+ */
+
+/* Data generated from the table of named character references found at
+ *
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html#named-character-references
+ *
+ * Files that #include this file must #define NAMED_CHARACTER_REFERENCE as a
+ * macro of four parameters:
+ *
+ * 1. a unique integer N identifying the Nth [0,1,..] macro expansion in this
+ * file,
+ * 2. a comma-separated sequence of characters comprising the character name,
+ * without the first two letters or 0 if the sequence would be empty.
+ * See Tokenizer.java.
+ * 3. the length of this sequence of characters,
+ * 4. placeholder flag (0 if argument #is not a placeholder and 1 if it is),
+ * 5. a comma-separated sequence of char16_t literals corresponding
+ * to the code-point(s) of the named character.
+ *
+ * The macro expansion doesn't have to refer to all or any of these parameters,
+ * but common sense dictates that it should involve at least one of them.
+ */
+
+// This #define allows the NAMED_CHARACTER_REFERENCE macro to accept comma-
+// separated sequences as single macro arguments. Using commas directly would
+// split the sequence into multiple macro arguments.
+#define _ ,
+
+NAMED_CHARACTER_REFERENCE(0, /* A E */ 'l' _ 'i' _ 'g', 3, 0, 0x00c6 _ 0)
+NAMED_CHARACTER_REFERENCE(1, /* A E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00c6 _ 0)
+NAMED_CHARACTER_REFERENCE(2, /* A M */ 'P', 1, 0, 0x0026 _ 0)
+NAMED_CHARACTER_REFERENCE(3, /* A M */ 'P' _ ';', 2, 0, 0x0026 _ 0)
+NAMED_CHARACTER_REFERENCE(4, /* A a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c1 _ 0)
+NAMED_CHARACTER_REFERENCE(5,
+ /* A a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00c1 _ 0)
+NAMED_CHARACTER_REFERENCE(6,
+ /* A b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x0102 _ 0)
+NAMED_CHARACTER_REFERENCE(7, /* A c */ 'i' _ 'r' _ 'c', 3, 0, 0x00c2 _ 0)
+NAMED_CHARACTER_REFERENCE(8, /* A c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00c2 _ 0)
+NAMED_CHARACTER_REFERENCE(9, /* A c */ 'y' _ ';', 2, 0, 0x0410 _ 0)
+NAMED_CHARACTER_REFERENCE(10, /* A f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd04)
+NAMED_CHARACTER_REFERENCE(11, /* A g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c0 _ 0)
+NAMED_CHARACTER_REFERENCE(12,
+ /* A g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00c0 _ 0)
+NAMED_CHARACTER_REFERENCE(13, /* A l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x0391 _ 0)
+NAMED_CHARACTER_REFERENCE(14, /* A m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0100 _ 0)
+NAMED_CHARACTER_REFERENCE(15, /* A n */ 'd' _ ';', 2, 0, 0x2a53 _ 0)
+NAMED_CHARACTER_REFERENCE(16, /* A o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0104 _ 0)
+NAMED_CHARACTER_REFERENCE(17, /* A o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd38)
+NAMED_CHARACTER_REFERENCE(
+ 18,
+ /* A p */
+ 'p' _ 'l' _ 'y' _ 'F' _ 'u' _ 'n' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 12,
+ 0, 0x2061 _ 0)
+NAMED_CHARACTER_REFERENCE(19, /* A r */ 'i' _ 'n' _ 'g', 3, 0, 0x00c5 _ 0)
+NAMED_CHARACTER_REFERENCE(20, /* A r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00c5 _ 0)
+NAMED_CHARACTER_REFERENCE(21, /* A s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9c)
+NAMED_CHARACTER_REFERENCE(22,
+ /* A s */ 's' _ 'i' _ 'g' _ 'n' _ ';', 5, 0,
+ 0x2254 _ 0)
+NAMED_CHARACTER_REFERENCE(23, /* A t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00c3 _ 0)
+NAMED_CHARACTER_REFERENCE(24,
+ /* A t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00c3 _ 0)
+NAMED_CHARACTER_REFERENCE(25, /* A u */ 'm' _ 'l', 2, 0, 0x00c4 _ 0)
+NAMED_CHARACTER_REFERENCE(26, /* A u */ 'm' _ 'l' _ ';', 3, 0, 0x00c4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 27,
+ /* B a */ 'c' _ 'k' _ 's' _ 'l' _ 'a' _ 's' _ 'h' _ ';', 8, 0, 0x2216 _ 0)
+NAMED_CHARACTER_REFERENCE(28, /* B a */ 'r' _ 'v' _ ';', 3, 0, 0x2ae7 _ 0)
+NAMED_CHARACTER_REFERENCE(29,
+ /* B a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0,
+ 0x2306 _ 0)
+NAMED_CHARACTER_REFERENCE(30, /* B c */ 'y' _ ';', 2, 0, 0x0411 _ 0)
+NAMED_CHARACTER_REFERENCE(31,
+ /* B e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0,
+ 0x2235 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 32,
+ /* B e */ 'r' _ 'n' _ 'o' _ 'u' _ 'l' _ 'l' _ 'i' _ 's' _ ';', 9, 0,
+ 0x212c _ 0)
+NAMED_CHARACTER_REFERENCE(33, /* B e */ 't' _ 'a' _ ';', 3, 0, 0x0392 _ 0)
+NAMED_CHARACTER_REFERENCE(34, /* B f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd05)
+NAMED_CHARACTER_REFERENCE(35, /* B o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd39)
+NAMED_CHARACTER_REFERENCE(36, /* B r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0)
+NAMED_CHARACTER_REFERENCE(37, /* B s */ 'c' _ 'r' _ ';', 3, 0, 0x212c _ 0)
+NAMED_CHARACTER_REFERENCE(38,
+ /* B u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x224e _ 0)
+NAMED_CHARACTER_REFERENCE(39, /* C H */ 'c' _ 'y' _ ';', 3, 0, 0x0427 _ 0)
+NAMED_CHARACTER_REFERENCE(40, /* C O */ 'P' _ 'Y', 2, 0, 0x00a9 _ 0)
+NAMED_CHARACTER_REFERENCE(41, /* C O */ 'P' _ 'Y' _ ';', 3, 0, 0x00a9 _ 0)
+NAMED_CHARACTER_REFERENCE(42,
+ /* C a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0106 _ 0)
+NAMED_CHARACTER_REFERENCE(43, /* C a */ 'p' _ ';', 2, 0, 0x22d2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 44,
+ /* C a */
+ 'p' _ 'i' _ 't' _ 'a' _ 'l' _ 'D' _ 'i' _ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';',
+ 19, 0, 0x2145 _ 0)
+NAMED_CHARACTER_REFERENCE(45,
+ /* C a */ 'y' _ 'l' _ 'e' _ 'y' _ 's' _ ';', 6, 0,
+ 0x212d _ 0)
+NAMED_CHARACTER_REFERENCE(46,
+ /* C c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x010c _ 0)
+NAMED_CHARACTER_REFERENCE(47, /* C c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00c7 _ 0)
+NAMED_CHARACTER_REFERENCE(48,
+ /* C c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x00c7 _ 0)
+NAMED_CHARACTER_REFERENCE(49, /* C c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0108 _ 0)
+NAMED_CHARACTER_REFERENCE(50,
+ /* C c */ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 6, 0,
+ 0x2230 _ 0)
+NAMED_CHARACTER_REFERENCE(51, /* C d */ 'o' _ 't' _ ';', 3, 0, 0x010a _ 0)
+NAMED_CHARACTER_REFERENCE(52,
+ /* C e */ 'd' _ 'i' _ 'l' _ 'l' _ 'a' _ ';', 6, 0,
+ 0x00b8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 53,
+ /* C e */ 'n' _ 't' _ 'e' _ 'r' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0)
+NAMED_CHARACTER_REFERENCE(54, /* C f */ 'r' _ ';', 2, 0, 0x212d _ 0)
+NAMED_CHARACTER_REFERENCE(55, /* C h */ 'i' _ ';', 2, 0, 0x03a7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 56,
+ /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x2299 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 57,
+ /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 10, 0,
+ 0x2296 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 58,
+ /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 9, 0,
+ 0x2295 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 59,
+ /* C i */ 'r' _ 'c' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 10, 0,
+ 0x2297 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 60,
+ /* C l */
+ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';',
+ 23, 0, 0x2232 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 61,
+ /* C l */
+ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';',
+ 20, 0, 0x201d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 62,
+ /* C l */
+ 'o' _ 's' _ 'e' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';',
+ 14, 0, 0x2019 _ 0)
+NAMED_CHARACTER_REFERENCE(63, /* C o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x2237 _ 0)
+NAMED_CHARACTER_REFERENCE(64,
+ /* C o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0,
+ 0x2a74 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 65,
+ /* C o */ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';', 8, 0, 0x2261 _ 0)
+NAMED_CHARACTER_REFERENCE(66,
+ /* C o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0,
+ 0x222f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 67,
+ /* C o */
+ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';',
+ 14, 0, 0x222e _ 0)
+NAMED_CHARACTER_REFERENCE(68, /* C o */ 'p' _ 'f' _ ';', 3, 0, 0x2102 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 69,
+ /* C o */ 'p' _ 'r' _ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 8, 0, 0x2210 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 70,
+ /* C o */
+ 'u' _ 'n' _ 't' _ 'e' _ 'r' _ 'C' _ 'l' _ 'o' _ 'c' _ 'k' _ 'w' _ 'i' _ 's' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';',
+ 30, 0, 0x2233 _ 0)
+NAMED_CHARACTER_REFERENCE(71, /* C r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2a2f _ 0)
+NAMED_CHARACTER_REFERENCE(72, /* C s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9e)
+NAMED_CHARACTER_REFERENCE(73, /* C u */ 'p' _ ';', 2, 0, 0x22d3 _ 0)
+NAMED_CHARACTER_REFERENCE(74,
+ /* C u */ 'p' _ 'C' _ 'a' _ 'p' _ ';', 5, 0,
+ 0x224d _ 0)
+NAMED_CHARACTER_REFERENCE(75, /* D D */ ';', 1, 0, 0x2145 _ 0)
+NAMED_CHARACTER_REFERENCE(76,
+ /* D D */ 'o' _ 't' _ 'r' _ 'a' _ 'h' _ 'd' _ ';', 7,
+ 0, 0x2911 _ 0)
+NAMED_CHARACTER_REFERENCE(77, /* D J */ 'c' _ 'y' _ ';', 3, 0, 0x0402 _ 0)
+NAMED_CHARACTER_REFERENCE(78, /* D S */ 'c' _ 'y' _ ';', 3, 0, 0x0405 _ 0)
+NAMED_CHARACTER_REFERENCE(79, /* D Z */ 'c' _ 'y' _ ';', 3, 0, 0x040f _ 0)
+NAMED_CHARACTER_REFERENCE(80,
+ /* D a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0,
+ 0x2021 _ 0)
+NAMED_CHARACTER_REFERENCE(81, /* D a */ 'r' _ 'r' _ ';', 3, 0, 0x21a1 _ 0)
+NAMED_CHARACTER_REFERENCE(82, /* D a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x2ae4 _ 0)
+NAMED_CHARACTER_REFERENCE(83,
+ /* D c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x010e _ 0)
+NAMED_CHARACTER_REFERENCE(84, /* D c */ 'y' _ ';', 2, 0, 0x0414 _ 0)
+NAMED_CHARACTER_REFERENCE(85, /* D e */ 'l' _ ';', 2, 0, 0x2207 _ 0)
+NAMED_CHARACTER_REFERENCE(86, /* D e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x0394 _ 0)
+NAMED_CHARACTER_REFERENCE(87, /* D f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd07)
+NAMED_CHARACTER_REFERENCE(
+ 88,
+ /* D i */
+ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';',
+ 15, 0, 0x00b4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 89,
+ /* D i */
+ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 't' _ ';',
+ 13, 0, 0x02d9 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 90,
+ /* D i */
+ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'A' _ 'c' _ 'u' _ 't' _ 'e' _ ';',
+ 21, 0, 0x02dd _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 91,
+ /* D i */
+ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'G' _ 'r' _ 'a' _ 'v' _ 'e' _ ';',
+ 15, 0, 0x0060 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 92,
+ /* D i */
+ 'a' _ 'c' _ 'r' _ 'i' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';',
+ 15, 0, 0x02dc _ 0)
+NAMED_CHARACTER_REFERENCE(93,
+ /* D i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0,
+ 0x22c4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 94,
+ /* D i */
+ 'f' _ 'f' _ 'e' _ 'r' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 12,
+ 0, 0x2146 _ 0)
+NAMED_CHARACTER_REFERENCE(95, /* D o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3b)
+NAMED_CHARACTER_REFERENCE(96, /* D o */ 't' _ ';', 2, 0, 0x00a8 _ 0)
+NAMED_CHARACTER_REFERENCE(97,
+ /* D o */ 't' _ 'D' _ 'o' _ 't' _ ';', 5, 0,
+ 0x20dc _ 0)
+NAMED_CHARACTER_REFERENCE(98,
+ /* D o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7,
+ 0, 0x2250 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 99,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'n' _ 't' _ 'o' _ 'u' _ 'r' _ 'I' _ 'n' _ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';',
+ 20, 0, 0x222f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 100,
+ /* D o */ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x00a8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 101,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x21d3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 102,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x21d0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 103,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 19, 0, 0x21d4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 104,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 12,
+ 0, 0x2ae4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 105,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 18, 0, 0x27f8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 106,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 23, 0, 0x27fa _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 107,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'L' _ 'o' _ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 19, 0, 0x27f9 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 108,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 15, 0, 0x21d2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 109,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';',
+ 13, 0, 0x22a8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 110,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12,
+ 0, 0x21d1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 111,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 16, 0, 0x21d5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 112,
+ /* D o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';',
+ 16, 0, 0x2225 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 113,
+ /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 114,
+ /* D o */ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';',
+ 11, 0, 0x2913 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 115,
+ /* D o */
+ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 15, 0, 0x21f5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 116,
+ /* D o */ 'w' _ 'n' _ 'B' _ 'r' _ 'e' _ 'v' _ 'e' _ ';', 8, 0, 0x0311 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 117,
+ /* D o */
+ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 18, 0, 0x2950 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 118,
+ /* D o */
+ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 16, 0, 0x295e _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 119,
+ /* D o */
+ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 13, 0, 0x21bd _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 120,
+ /* D o */
+ 'w' _ 'n' _ 'L' _ 'e' _ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 16, 0, 0x2956 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 121,
+ /* D o */
+ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 17, 0, 0x295f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 122,
+ /* D o */
+ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 14, 0, 0x21c1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 123,
+ /* D o */
+ 'w' _ 'n' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 17, 0, 0x2957 _ 0)
+NAMED_CHARACTER_REFERENCE(124,
+ /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ ';', 6, 0,
+ 0x22a4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 125,
+ /* D o */ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 11, 0, 0x21a7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 126,
+ /* D o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d3 _ 0)
+NAMED_CHARACTER_REFERENCE(127, /* D s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdc9f)
+NAMED_CHARACTER_REFERENCE(128,
+ /* D s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0110 _ 0)
+NAMED_CHARACTER_REFERENCE(129, /* E N */ 'G' _ ';', 2, 0, 0x014a _ 0)
+NAMED_CHARACTER_REFERENCE(130, /* E T */ 'H', 1, 0, 0x00d0 _ 0)
+NAMED_CHARACTER_REFERENCE(131, /* E T */ 'H' _ ';', 2, 0, 0x00d0 _ 0)
+NAMED_CHARACTER_REFERENCE(132,
+ /* E a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00c9 _ 0)
+NAMED_CHARACTER_REFERENCE(133,
+ /* E a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00c9 _ 0)
+NAMED_CHARACTER_REFERENCE(134,
+ /* E c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x011a _ 0)
+NAMED_CHARACTER_REFERENCE(135, /* E c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ca _ 0)
+NAMED_CHARACTER_REFERENCE(136,
+ /* E c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ca _ 0)
+NAMED_CHARACTER_REFERENCE(137, /* E c */ 'y' _ ';', 2, 0, 0x042d _ 0)
+NAMED_CHARACTER_REFERENCE(138, /* E d */ 'o' _ 't' _ ';', 3, 0, 0x0116 _ 0)
+NAMED_CHARACTER_REFERENCE(139, /* E f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd08)
+NAMED_CHARACTER_REFERENCE(140,
+ /* E g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00c8 _ 0)
+NAMED_CHARACTER_REFERENCE(141,
+ /* E g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00c8 _ 0)
+NAMED_CHARACTER_REFERENCE(142,
+ /* E l */ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 6, 0,
+ 0x2208 _ 0)
+NAMED_CHARACTER_REFERENCE(143,
+ /* E m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0112 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 144,
+ /* E m */
+ 'p' _ 't' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';',
+ 15, 0, 0x25fb _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 145,
+ /* E m */
+ 'p' _ 't' _ 'y' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';',
+ 19, 0, 0x25ab _ 0)
+NAMED_CHARACTER_REFERENCE(146,
+ /* E o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0118 _ 0)
+NAMED_CHARACTER_REFERENCE(147, /* E o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3c)
+NAMED_CHARACTER_REFERENCE(148,
+ /* E p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x0395 _ 0)
+NAMED_CHARACTER_REFERENCE(149,
+ /* E q */ 'u' _ 'a' _ 'l' _ ';', 4, 0, 0x2a75 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 150,
+ /* E q */ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0,
+ 0x2242 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 151,
+ /* E q */ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 10, 0,
+ 0x21cc _ 0)
+NAMED_CHARACTER_REFERENCE(152, /* E s */ 'c' _ 'r' _ ';', 3, 0, 0x2130 _ 0)
+NAMED_CHARACTER_REFERENCE(153, /* E s */ 'i' _ 'm' _ ';', 3, 0, 0x2a73 _ 0)
+NAMED_CHARACTER_REFERENCE(154, /* E t */ 'a' _ ';', 2, 0, 0x0397 _ 0)
+NAMED_CHARACTER_REFERENCE(155, /* E u */ 'm' _ 'l', 2, 0, 0x00cb _ 0)
+NAMED_CHARACTER_REFERENCE(156, /* E u */ 'm' _ 'l' _ ';', 3, 0, 0x00cb _ 0)
+NAMED_CHARACTER_REFERENCE(157,
+ /* E x */ 'i' _ 's' _ 't' _ 's' _ ';', 5, 0,
+ 0x2203 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 158,
+ /* E x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'E' _ ';',
+ 11, 0, 0x2147 _ 0)
+NAMED_CHARACTER_REFERENCE(159, /* F c */ 'y' _ ';', 2, 0, 0x0424 _ 0)
+NAMED_CHARACTER_REFERENCE(160, /* F f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd09)
+NAMED_CHARACTER_REFERENCE(
+ 161,
+ /* F i */
+ 'l' _ 'l' _ 'e' _ 'd' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';',
+ 16, 0, 0x25fc _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 162,
+ /* F i */
+ 'l' _ 'l' _ 'e' _ 'd' _ 'V' _ 'e' _ 'r' _ 'y' _ 'S' _ 'm' _ 'a' _ 'l' _ 'l' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';',
+ 20, 0, 0x25aa _ 0)
+NAMED_CHARACTER_REFERENCE(163, /* F o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3d)
+NAMED_CHARACTER_REFERENCE(164,
+ /* F o */ 'r' _ 'A' _ 'l' _ 'l' _ ';', 5, 0,
+ 0x2200 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 165,
+ /* F o */ 'u' _ 'r' _ 'i' _ 'e' _ 'r' _ 't' _ 'r' _ 'f' _ ';', 9, 0,
+ 0x2131 _ 0)
+NAMED_CHARACTER_REFERENCE(166, /* F s */ 'c' _ 'r' _ ';', 3, 0, 0x2131 _ 0)
+NAMED_CHARACTER_REFERENCE(167, /* G J */ 'c' _ 'y' _ ';', 3, 0, 0x0403 _ 0)
+NAMED_CHARACTER_REFERENCE(168, /* G T */ 0, 0, 1, 0x003e _ 0)
+NAMED_CHARACTER_REFERENCE(169, /* G T */ ';', 1, 0, 0x003e _ 0)
+NAMED_CHARACTER_REFERENCE(170,
+ /* G a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x0393 _ 0)
+NAMED_CHARACTER_REFERENCE(171,
+ /* G a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0,
+ 0x03dc _ 0)
+NAMED_CHARACTER_REFERENCE(172,
+ /* G b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x011e _ 0)
+NAMED_CHARACTER_REFERENCE(173,
+ /* G c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0122 _ 0)
+NAMED_CHARACTER_REFERENCE(174,
+ /* G c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011c _ 0)
+NAMED_CHARACTER_REFERENCE(175, /* G c */ 'y' _ ';', 2, 0, 0x0413 _ 0)
+NAMED_CHARACTER_REFERENCE(176, /* G d */ 'o' _ 't' _ ';', 3, 0, 0x0120 _ 0)
+NAMED_CHARACTER_REFERENCE(177, /* G f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0a)
+NAMED_CHARACTER_REFERENCE(178, /* G g */ ';', 1, 0, 0x22d9 _ 0)
+NAMED_CHARACTER_REFERENCE(179, /* G o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd3e)
+NAMED_CHARACTER_REFERENCE(
+ 180,
+ /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 11, 0, 0x2265 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 181,
+ /* G r */
+ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'L' _ 'e' _ 's' _ 's' _ ';',
+ 15, 0, 0x22db _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 182,
+ /* G r */
+ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 15, 0, 0x2267 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 183,
+ /* G r */
+ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';',
+ 13, 0, 0x2aa2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 184,
+ /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0,
+ 0x2277 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 185,
+ /* G r */
+ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 16, 0, 0x2a7e _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 186,
+ /* G r */ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';',
+ 11, 0, 0x2273 _ 0)
+NAMED_CHARACTER_REFERENCE(187, /* G s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca2)
+NAMED_CHARACTER_REFERENCE(188, /* G t */ ';', 1, 0, 0x226b _ 0)
+NAMED_CHARACTER_REFERENCE(189,
+ /* H A */ 'R' _ 'D' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x042a _ 0)
+NAMED_CHARACTER_REFERENCE(190,
+ /* H a */ 'c' _ 'e' _ 'k' _ ';', 4, 0, 0x02c7 _ 0)
+NAMED_CHARACTER_REFERENCE(191, /* H a */ 't' _ ';', 2, 0, 0x005e _ 0)
+NAMED_CHARACTER_REFERENCE(192,
+ /* H c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0124 _ 0)
+NAMED_CHARACTER_REFERENCE(193, /* H f */ 'r' _ ';', 2, 0, 0x210c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 194,
+ /* H i */ 'l' _ 'b' _ 'e' _ 'r' _ 't' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 11, 0, 0x210b _ 0)
+NAMED_CHARACTER_REFERENCE(195, /* H o */ 'p' _ 'f' _ ';', 3, 0, 0x210d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 196,
+ /* H o */
+ 'r' _ 'i' _ 'z' _ 'o' _ 'n' _ 't' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';',
+ 13, 0, 0x2500 _ 0)
+NAMED_CHARACTER_REFERENCE(197, /* H s */ 'c' _ 'r' _ ';', 3, 0, 0x210b _ 0)
+NAMED_CHARACTER_REFERENCE(198,
+ /* H s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0126 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 199,
+ /* H u */ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';',
+ 11, 0, 0x224e _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 200,
+ /* H u */ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 8, 0, 0x224f _ 0)
+NAMED_CHARACTER_REFERENCE(201, /* I E */ 'c' _ 'y' _ ';', 3, 0, 0x0415 _ 0)
+NAMED_CHARACTER_REFERENCE(202,
+ /* I J */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0132 _ 0)
+NAMED_CHARACTER_REFERENCE(203, /* I O */ 'c' _ 'y' _ ';', 3, 0, 0x0401 _ 0)
+NAMED_CHARACTER_REFERENCE(204,
+ /* I a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00cd _ 0)
+NAMED_CHARACTER_REFERENCE(205,
+ /* I a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00cd _ 0)
+NAMED_CHARACTER_REFERENCE(206, /* I c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ce _ 0)
+NAMED_CHARACTER_REFERENCE(207,
+ /* I c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ce _ 0)
+NAMED_CHARACTER_REFERENCE(208, /* I c */ 'y' _ ';', 2, 0, 0x0418 _ 0)
+NAMED_CHARACTER_REFERENCE(209, /* I d */ 'o' _ 't' _ ';', 3, 0, 0x0130 _ 0)
+NAMED_CHARACTER_REFERENCE(210, /* I f */ 'r' _ ';', 2, 0, 0x2111 _ 0)
+NAMED_CHARACTER_REFERENCE(211,
+ /* I g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00cc _ 0)
+NAMED_CHARACTER_REFERENCE(212,
+ /* I g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00cc _ 0)
+NAMED_CHARACTER_REFERENCE(213, /* I m */ ';', 1, 0, 0x2111 _ 0)
+NAMED_CHARACTER_REFERENCE(214,
+ /* I m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 215,
+ /* I m */ 'a' _ 'g' _ 'i' _ 'n' _ 'a' _ 'r' _ 'y' _ 'I' _ ';', 9, 0,
+ 0x2148 _ 0)
+NAMED_CHARACTER_REFERENCE(216,
+ /* I m */ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';', 6, 0,
+ 0x21d2 _ 0)
+NAMED_CHARACTER_REFERENCE(217, /* I n */ 't' _ ';', 2, 0, 0x222c _ 0)
+NAMED_CHARACTER_REFERENCE(218,
+ /* I n */ 't' _ 'e' _ 'g' _ 'r' _ 'a' _ 'l' _ ';', 7,
+ 0, 0x222b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 219,
+ /* I n */ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';',
+ 11, 0, 0x22c2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 220,
+ /* I n */
+ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'C' _ 'o' _ 'm' _ 'm' _ 'a' _ ';',
+ 13, 0, 0x2063 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 221,
+ /* I n */
+ 'v' _ 'i' _ 's' _ 'i' _ 'b' _ 'l' _ 'e' _ 'T' _ 'i' _ 'm' _ 'e' _ 's' _ ';',
+ 13, 0, 0x2062 _ 0)
+NAMED_CHARACTER_REFERENCE(222,
+ /* I o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012e _ 0)
+NAMED_CHARACTER_REFERENCE(223, /* I o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd40)
+NAMED_CHARACTER_REFERENCE(224, /* I o */ 't' _ 'a' _ ';', 3, 0, 0x0399 _ 0)
+NAMED_CHARACTER_REFERENCE(225, /* I s */ 'c' _ 'r' _ ';', 3, 0, 0x2110 _ 0)
+NAMED_CHARACTER_REFERENCE(226,
+ /* I t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x0128 _ 0)
+NAMED_CHARACTER_REFERENCE(227,
+ /* I u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0406 _ 0)
+NAMED_CHARACTER_REFERENCE(228, /* I u */ 'm' _ 'l', 2, 0, 0x00cf _ 0)
+NAMED_CHARACTER_REFERENCE(229, /* I u */ 'm' _ 'l' _ ';', 3, 0, 0x00cf _ 0)
+NAMED_CHARACTER_REFERENCE(230,
+ /* J c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0134 _ 0)
+NAMED_CHARACTER_REFERENCE(231, /* J c */ 'y' _ ';', 2, 0, 0x0419 _ 0)
+NAMED_CHARACTER_REFERENCE(232, /* J f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0d)
+NAMED_CHARACTER_REFERENCE(233, /* J o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd41)
+NAMED_CHARACTER_REFERENCE(234, /* J s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca5)
+NAMED_CHARACTER_REFERENCE(235,
+ /* J s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x0408 _ 0)
+NAMED_CHARACTER_REFERENCE(236,
+ /* J u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0404 _ 0)
+NAMED_CHARACTER_REFERENCE(237, /* K H */ 'c' _ 'y' _ ';', 3, 0, 0x0425 _ 0)
+NAMED_CHARACTER_REFERENCE(238, /* K J */ 'c' _ 'y' _ ';', 3, 0, 0x040c _ 0)
+NAMED_CHARACTER_REFERENCE(239,
+ /* K a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x039a _ 0)
+NAMED_CHARACTER_REFERENCE(240,
+ /* K c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0136 _ 0)
+NAMED_CHARACTER_REFERENCE(241, /* K c */ 'y' _ ';', 2, 0, 0x041a _ 0)
+NAMED_CHARACTER_REFERENCE(242, /* K f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0e)
+NAMED_CHARACTER_REFERENCE(243, /* K o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd42)
+NAMED_CHARACTER_REFERENCE(244, /* K s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca6)
+NAMED_CHARACTER_REFERENCE(245, /* L J */ 'c' _ 'y' _ ';', 3, 0, 0x0409 _ 0)
+NAMED_CHARACTER_REFERENCE(246, /* L T */ 0, 0, 1, 0x003c _ 0)
+NAMED_CHARACTER_REFERENCE(247, /* L T */ ';', 1, 0, 0x003c _ 0)
+NAMED_CHARACTER_REFERENCE(248,
+ /* L a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0139 _ 0)
+NAMED_CHARACTER_REFERENCE(249,
+ /* L a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0,
+ 0x039b _ 0)
+NAMED_CHARACTER_REFERENCE(250, /* L a */ 'n' _ 'g' _ ';', 3, 0, 0x27ea _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 251,
+ /* L a */ 'p' _ 'l' _ 'a' _ 'c' _ 'e' _ 't' _ 'r' _ 'f' _ ';', 9, 0,
+ 0x2112 _ 0)
+NAMED_CHARACTER_REFERENCE(252, /* L a */ 'r' _ 'r' _ ';', 3, 0, 0x219e _ 0)
+NAMED_CHARACTER_REFERENCE(253,
+ /* L c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x013d _ 0)
+NAMED_CHARACTER_REFERENCE(254,
+ /* L c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x013b _ 0)
+NAMED_CHARACTER_REFERENCE(255, /* L c */ 'y' _ ';', 2, 0, 0x041b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 256,
+ /* L e */
+ 'f' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';',
+ 15, 0, 0x27e8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 257,
+ /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 258,
+ /* L e */ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';',
+ 11, 0, 0x21e4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 259,
+ /* L e */
+ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 18, 0, 0x21c6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 260,
+ /* L e */ 'f' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';', 10, 0,
+ 0x2308 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 261,
+ /* L e */
+ 'f' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';',
+ 16, 0, 0x27e6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 262,
+ /* L e */
+ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 16, 0, 0x2961 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 263,
+ /* L e */
+ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 13, 0, 0x21c3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 264,
+ /* L e */
+ 'f' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 16, 0, 0x2959 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 265,
+ /* L e */ 'f' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 8, 0, 0x230a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 266,
+ /* L e */
+ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x2194 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 267,
+ /* L e */
+ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 14, 0, 0x294e _ 0)
+NAMED_CHARACTER_REFERENCE(268,
+ /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 6, 0,
+ 0x22a3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 269,
+ /* L e */ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 11, 0, 0x21a4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 270,
+ /* L e */
+ 'f' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12,
+ 0, 0x295a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 271,
+ /* L e */ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';',
+ 11, 0, 0x22b2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 272,
+ /* L e */
+ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';',
+ 14, 0, 0x29cf _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 273,
+ /* L e */
+ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 16, 0, 0x22b4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 274,
+ /* L e */
+ 'f' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 15, 0, 0x2951 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 275,
+ /* L e */
+ 'f' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 14, 0, 0x2960 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 276,
+ /* L e */ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 11, 0, 0x21bf _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 277,
+ /* L e */
+ 'f' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 14, 0, 0x2958 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 278,
+ /* L e */ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 9, 0,
+ 0x21bc _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 279,
+ /* L e */
+ 'f' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 12,
+ 0, 0x2952 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 280,
+ /* L e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x21d0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 281,
+ /* L e */
+ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x21d4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 282,
+ /* L e */
+ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';',
+ 15, 0, 0x22da _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 283,
+ /* L e */
+ 's' _ 's' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12,
+ 0, 0x2266 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 284,
+ /* L e */ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 10, 0,
+ 0x2276 _ 0)
+NAMED_CHARACTER_REFERENCE(285,
+ /* L e */ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 7,
+ 0, 0x2aa1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 286,
+ /* L e */
+ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 13, 0, 0x2a7d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 287,
+ /* L e */ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 8, 0, 0x2272 _ 0)
+NAMED_CHARACTER_REFERENCE(288, /* L f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd0f)
+NAMED_CHARACTER_REFERENCE(289, /* L l */ ';', 1, 0, 0x22d8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 290,
+ /* L l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x21da _ 0)
+NAMED_CHARACTER_REFERENCE(291,
+ /* L m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x013f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 292,
+ /* L o */
+ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12,
+ 0, 0x27f5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 293,
+ /* L o */
+ 'n' _ 'g' _ 'L' _ 'e' _ 'f' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 17, 0, 0x27f7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 294,
+ /* L o */
+ 'n' _ 'g' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x27f6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 295,
+ /* L o */
+ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12,
+ 0, 0x27f8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 296,
+ /* L o */
+ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 17, 0, 0x27fa _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 297,
+ /* L o */
+ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x27f9 _ 0)
+NAMED_CHARACTER_REFERENCE(298, /* L o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd43)
+NAMED_CHARACTER_REFERENCE(
+ 299,
+ /* L o */
+ 'w' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x2199 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 300,
+ /* L o */
+ 'w' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x2198 _ 0)
+NAMED_CHARACTER_REFERENCE(301, /* L s */ 'c' _ 'r' _ ';', 3, 0, 0x2112 _ 0)
+NAMED_CHARACTER_REFERENCE(302, /* L s */ 'h' _ ';', 2, 0, 0x21b0 _ 0)
+NAMED_CHARACTER_REFERENCE(303,
+ /* L s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0141 _ 0)
+NAMED_CHARACTER_REFERENCE(304, /* L t */ ';', 1, 0, 0x226a _ 0)
+NAMED_CHARACTER_REFERENCE(305, /* M a */ 'p' _ ';', 2, 0, 0x2905 _ 0)
+NAMED_CHARACTER_REFERENCE(306, /* M c */ 'y' _ ';', 2, 0, 0x041c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 307,
+ /* M e */ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 10, 0,
+ 0x205f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 308,
+ /* M e */ 'l' _ 'l' _ 'i' _ 'n' _ 't' _ 'r' _ 'f' _ ';', 8, 0, 0x2133 _ 0)
+NAMED_CHARACTER_REFERENCE(309, /* M f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd10)
+NAMED_CHARACTER_REFERENCE(
+ 310,
+ /* M i */ 'n' _ 'u' _ 's' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x2213 _ 0)
+NAMED_CHARACTER_REFERENCE(311, /* M o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd44)
+NAMED_CHARACTER_REFERENCE(312, /* M s */ 'c' _ 'r' _ ';', 3, 0, 0x2133 _ 0)
+NAMED_CHARACTER_REFERENCE(313, /* M u */ ';', 1, 0, 0x039c _ 0)
+NAMED_CHARACTER_REFERENCE(314, /* N J */ 'c' _ 'y' _ ';', 3, 0, 0x040a _ 0)
+NAMED_CHARACTER_REFERENCE(315,
+ /* N a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0143 _ 0)
+NAMED_CHARACTER_REFERENCE(316,
+ /* N c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0147 _ 0)
+NAMED_CHARACTER_REFERENCE(317,
+ /* N c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0145 _ 0)
+NAMED_CHARACTER_REFERENCE(318, /* N c */ 'y' _ ';', 2, 0, 0x041d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 319,
+ /* N e */
+ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'M' _ 'e' _ 'd' _ 'i' _ 'u' _ 'm' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 18, 0, 0x200b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 320,
+ /* N e */
+ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 17, 0, 0x200b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 321,
+ /* N e */
+ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 16, 0, 0x200b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 322,
+ /* N e */
+ 'g' _ 'a' _ 't' _ 'i' _ 'v' _ 'e' _ 'V' _ 'e' _ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 20, 0, 0x200b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 323,
+ /* N e */
+ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';',
+ 19, 0, 0x226b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 324,
+ /* N e */
+ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';',
+ 13, 0, 0x226a _ 0)
+NAMED_CHARACTER_REFERENCE(325,
+ /* N e */ 'w' _ 'L' _ 'i' _ 'n' _ 'e' _ ';', 6, 0,
+ 0x000a _ 0)
+NAMED_CHARACTER_REFERENCE(326, /* N f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd11)
+NAMED_CHARACTER_REFERENCE(327,
+ /* N o */ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ ';', 6, 0,
+ 0x2060 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 328,
+ /* N o */
+ 'n' _ 'B' _ 'r' _ 'e' _ 'a' _ 'k' _ 'i' _ 'n' _ 'g' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 15, 0, 0x00a0 _ 0)
+NAMED_CHARACTER_REFERENCE(329, /* N o */ 'p' _ 'f' _ ';', 3, 0, 0x2115 _ 0)
+NAMED_CHARACTER_REFERENCE(330, /* N o */ 't' _ ';', 2, 0, 0x2aec _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 331,
+ /* N o */ 't' _ 'C' _ 'o' _ 'n' _ 'g' _ 'r' _ 'u' _ 'e' _ 'n' _ 't' _ ';',
+ 11, 0, 0x2262 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 332,
+ /* N o */ 't' _ 'C' _ 'u' _ 'p' _ 'C' _ 'a' _ 'p' _ ';', 8, 0, 0x226d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 333,
+ /* N o */
+ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';',
+ 19, 0, 0x2226 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 334,
+ /* N o */ 't' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0,
+ 0x2209 _ 0)
+NAMED_CHARACTER_REFERENCE(335,
+ /* N o */ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 7,
+ 0, 0x2260 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 336,
+ /* N o */
+ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12,
+ 0, 0x2242 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 337,
+ /* N o */ 't' _ 'E' _ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 8, 0, 0x2204 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 338,
+ /* N o */ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';', 9, 0,
+ 0x226f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 339,
+ /* N o */
+ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 14, 0, 0x2271 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 340,
+ /* N o */
+ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 18, 0, 0x2267 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 341,
+ /* N o */
+ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';',
+ 16, 0, 0x226b _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 342,
+ /* N o */
+ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'L' _ 'e' _ 's' _ 's' _ ';',
+ 13, 0, 0x2279 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 343,
+ /* N o */
+ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 19, 0, 0x2a7e _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 344,
+ /* N o */
+ 't' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';',
+ 14, 0, 0x2275 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 345,
+ /* N o */
+ 't' _ 'H' _ 'u' _ 'm' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'H' _ 'u' _ 'm' _ 'p' _ ';',
+ 14, 0, 0x224e _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 346,
+ /* N o */ 't' _ 'H' _ 'u' _ 'm' _ 'p' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 11, 0, 0x224f _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 347,
+ /* N o */
+ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';',
+ 14, 0, 0x22ea _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 348,
+ /* N o */
+ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';',
+ 17, 0, 0x29cf _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 349,
+ /* N o */
+ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 19, 0, 0x22ec _ 0)
+NAMED_CHARACTER_REFERENCE(350,
+ /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ ';', 6, 0,
+ 0x226e _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 351,
+ /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 11, 0, 0x2270 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 352,
+ /* N o */
+ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';',
+ 13, 0, 0x2278 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 353,
+ /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';', 10, 0,
+ 0x226a _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 354,
+ /* N o */
+ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 16, 0, 0x2a7d _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 355,
+ /* N o */ 't' _ 'L' _ 'e' _ 's' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';',
+ 11, 0, 0x2274 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 356,
+ /* N o */
+ 't' _ 'N' _ 'e' _ 's' _ 't' _ 'e' _ 'd' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ 'G' _ 'r' _ 'e' _ 'a' _ 't' _ 'e' _ 'r' _ ';',
+ 22, 0, 0x2aa2 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 357,
+ /* N o */
+ 't' _ 'N' _ 'e' _ 's' _ 't' _ 'e' _ 'd' _ 'L' _ 'e' _ 's' _ 's' _ 'L' _ 'e' _ 's' _ 's' _ ';',
+ 16, 0, 0x2aa1 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 358,
+ /* N o */ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 10, 0,
+ 0x2280 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 359,
+ /* N o */
+ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 15, 0, 0x2aaf _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 360,
+ /* N o */
+ 't' _ 'P' _ 'r' _ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 20, 0, 0x22e0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 361,
+ /* N o */
+ 't' _ 'R' _ 'e' _ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';',
+ 16, 0, 0x220c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 362,
+ /* N o */
+ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';',
+ 15, 0, 0x22eb _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 363,
+ /* N o */
+ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';',
+ 18, 0, 0x29d0 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 364,
+ /* N o */
+ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 20, 0, 0x22ed _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 365,
+ /* N o */
+ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';',
+ 14, 0, 0x228f _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 366,
+ /* N o */
+ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 19, 0, 0x22e2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 367,
+ /* N o */
+ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';',
+ 16, 0, 0x2290 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 368,
+ /* N o */
+ 't' _ 'S' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 21, 0, 0x22e3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 369,
+ /* N o */ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 8, 0,
+ 0x2282 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(
+ 370,
+ /* N o */
+ 't' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 13, 0, 0x2288 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 371,
+ /* N o */ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 10, 0,
+ 0x2281 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 372,
+ /* N o */
+ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 15, 0, 0x2ab0 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 373,
+ /* N o */
+ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 20, 0, 0x22e1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 374,
+ /* N o */
+ 't' _ 'S' _ 'u' _ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';',
+ 15, 0, 0x227f _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 375,
+ /* N o */ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 10, 0,
+ 0x2283 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(
+ 376,
+ /* N o */
+ 't' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 15, 0, 0x2289 _ 0)
+NAMED_CHARACTER_REFERENCE(377,
+ /* N o */ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 7,
+ 0, 0x2241 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 378,
+ /* N o */
+ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12,
+ 0, 0x2244 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 379,
+ /* N o */
+ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 16, 0, 0x2247 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 380,
+ /* N o */
+ 't' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12,
+ 0, 0x2249 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 381,
+ /* N o */
+ 't' _ 'V' _ 'e' _ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';',
+ 13, 0, 0x2224 _ 0)
+NAMED_CHARACTER_REFERENCE(382, /* N s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdca9)
+NAMED_CHARACTER_REFERENCE(383,
+ /* N t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d1 _ 0)
+NAMED_CHARACTER_REFERENCE(384,
+ /* N t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00d1 _ 0)
+NAMED_CHARACTER_REFERENCE(385, /* N u */ ';', 1, 0, 0x039d _ 0)
+NAMED_CHARACTER_REFERENCE(386,
+ /* O E */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0152 _ 0)
+NAMED_CHARACTER_REFERENCE(387,
+ /* O a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00d3 _ 0)
+NAMED_CHARACTER_REFERENCE(388,
+ /* O a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00d3 _ 0)
+NAMED_CHARACTER_REFERENCE(389, /* O c */ 'i' _ 'r' _ 'c', 3, 0, 0x00d4 _ 0)
+NAMED_CHARACTER_REFERENCE(390,
+ /* O c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00d4 _ 0)
+NAMED_CHARACTER_REFERENCE(391, /* O c */ 'y' _ ';', 2, 0, 0x041e _ 0)
+NAMED_CHARACTER_REFERENCE(392,
+ /* O d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0,
+ 0x0150 _ 0)
+NAMED_CHARACTER_REFERENCE(393, /* O f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd12)
+NAMED_CHARACTER_REFERENCE(394,
+ /* O g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d2 _ 0)
+NAMED_CHARACTER_REFERENCE(395,
+ /* O g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00d2 _ 0)
+NAMED_CHARACTER_REFERENCE(396,
+ /* O m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014c _ 0)
+NAMED_CHARACTER_REFERENCE(397,
+ /* O m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03a9 _ 0)
+NAMED_CHARACTER_REFERENCE(398,
+ /* O m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x039f _ 0)
+NAMED_CHARACTER_REFERENCE(399, /* O o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd46)
+NAMED_CHARACTER_REFERENCE(
+ 400,
+ /* O p */
+ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';',
+ 19, 0, 0x201c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 401,
+ /* O p */
+ 'e' _ 'n' _ 'C' _ 'u' _ 'r' _ 'l' _ 'y' _ 'Q' _ 'u' _ 'o' _ 't' _ 'e' _ ';',
+ 13, 0, 0x2018 _ 0)
+NAMED_CHARACTER_REFERENCE(402, /* O r */ ';', 1, 0, 0x2a54 _ 0)
+NAMED_CHARACTER_REFERENCE(403, /* O s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaa)
+NAMED_CHARACTER_REFERENCE(404,
+ /* O s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00d8 _ 0)
+NAMED_CHARACTER_REFERENCE(405,
+ /* O s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x00d8 _ 0)
+NAMED_CHARACTER_REFERENCE(406,
+ /* O t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00d5 _ 0)
+NAMED_CHARACTER_REFERENCE(407,
+ /* O t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00d5 _ 0)
+NAMED_CHARACTER_REFERENCE(408,
+ /* O t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0,
+ 0x2a37 _ 0)
+NAMED_CHARACTER_REFERENCE(409, /* O u */ 'm' _ 'l', 2, 0, 0x00d6 _ 0)
+NAMED_CHARACTER_REFERENCE(410, /* O u */ 'm' _ 'l' _ ';', 3, 0, 0x00d6 _ 0)
+NAMED_CHARACTER_REFERENCE(411,
+ /* O v */ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 6, 0,
+ 0x203e _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 412,
+ /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x23de _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 413,
+ /* O v */ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';', 10, 0,
+ 0x23b4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 414,
+ /* O v */
+ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';',
+ 14, 0, 0x23dc _ 0)
+NAMED_CHARACTER_REFERENCE(415,
+ /* P a */ 'r' _ 't' _ 'i' _ 'a' _ 'l' _ 'D' _ ';', 7,
+ 0, 0x2202 _ 0)
+NAMED_CHARACTER_REFERENCE(416, /* P c */ 'y' _ ';', 2, 0, 0x041f _ 0)
+NAMED_CHARACTER_REFERENCE(417, /* P f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd13)
+NAMED_CHARACTER_REFERENCE(418, /* P h */ 'i' _ ';', 2, 0, 0x03a6 _ 0)
+NAMED_CHARACTER_REFERENCE(419, /* P i */ ';', 1, 0, 0x03a0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 420,
+ /* P l */ 'u' _ 's' _ 'M' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 8, 0, 0x00b1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 421,
+ /* P o */
+ 'i' _ 'n' _ 'c' _ 'a' _ 'r' _ 'e' _ 'p' _ 'l' _ 'a' _ 'n' _ 'e' _ ';', 12,
+ 0, 0x210c _ 0)
+NAMED_CHARACTER_REFERENCE(422, /* P o */ 'p' _ 'f' _ ';', 3, 0, 0x2119 _ 0)
+NAMED_CHARACTER_REFERENCE(423, /* P r */ ';', 1, 0, 0x2abb _ 0)
+NAMED_CHARACTER_REFERENCE(424,
+ /* P r */ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ ';', 7,
+ 0, 0x227a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 425,
+ /* P r */
+ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12,
+ 0, 0x2aaf _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 426,
+ /* P r */
+ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 17, 0, 0x227c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 427,
+ /* P r */
+ 'e' _ 'c' _ 'e' _ 'd' _ 'e' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12,
+ 0, 0x227e _ 0)
+NAMED_CHARACTER_REFERENCE(428,
+ /* P r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2033 _ 0)
+NAMED_CHARACTER_REFERENCE(429,
+ /* P r */ 'o' _ 'd' _ 'u' _ 'c' _ 't' _ ';', 6, 0,
+ 0x220f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 430,
+ /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 9, 0,
+ 0x2237 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 431,
+ /* P r */ 'o' _ 'p' _ 'o' _ 'r' _ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ ';',
+ 11, 0, 0x221d _ 0)
+NAMED_CHARACTER_REFERENCE(432, /* P s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcab)
+NAMED_CHARACTER_REFERENCE(433, /* P s */ 'i' _ ';', 2, 0, 0x03a8 _ 0)
+NAMED_CHARACTER_REFERENCE(434, /* Q U */ 'O' _ 'T', 2, 0, 0x0022 _ 0)
+NAMED_CHARACTER_REFERENCE(435, /* Q U */ 'O' _ 'T' _ ';', 3, 0, 0x0022 _ 0)
+NAMED_CHARACTER_REFERENCE(436, /* Q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd14)
+NAMED_CHARACTER_REFERENCE(437, /* Q o */ 'p' _ 'f' _ ';', 3, 0, 0x211a _ 0)
+NAMED_CHARACTER_REFERENCE(438, /* Q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcac)
+NAMED_CHARACTER_REFERENCE(439,
+ /* R B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2910 _ 0)
+NAMED_CHARACTER_REFERENCE(440, /* R E */ 'G', 1, 0, 0x00ae _ 0)
+NAMED_CHARACTER_REFERENCE(441, /* R E */ 'G' _ ';', 2, 0, 0x00ae _ 0)
+NAMED_CHARACTER_REFERENCE(442,
+ /* R a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0154 _ 0)
+NAMED_CHARACTER_REFERENCE(443, /* R a */ 'n' _ 'g' _ ';', 3, 0, 0x27eb _ 0)
+NAMED_CHARACTER_REFERENCE(444, /* R a */ 'r' _ 'r' _ ';', 3, 0, 0x21a0 _ 0)
+NAMED_CHARACTER_REFERENCE(445,
+ /* R a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0,
+ 0x2916 _ 0)
+NAMED_CHARACTER_REFERENCE(446,
+ /* R c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0158 _ 0)
+NAMED_CHARACTER_REFERENCE(447,
+ /* R c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0156 _ 0)
+NAMED_CHARACTER_REFERENCE(448, /* R c */ 'y' _ ';', 2, 0, 0x0420 _ 0)
+NAMED_CHARACTER_REFERENCE(449, /* R e */ ';', 1, 0, 0x211c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 450,
+ /* R e */
+ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';',
+ 13, 0, 0x220b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 451,
+ /* R e */
+ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';',
+ 17, 0, 0x21cb _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 452,
+ /* R e */
+ 'v' _ 'e' _ 'r' _ 's' _ 'e' _ 'U' _ 'p' _ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';',
+ 19, 0, 0x296f _ 0)
+NAMED_CHARACTER_REFERENCE(453, /* R f */ 'r' _ ';', 2, 0, 0x211c _ 0)
+NAMED_CHARACTER_REFERENCE(454, /* R h */ 'o' _ ';', 2, 0, 0x03a1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 455,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'A' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';',
+ 16, 0, 0x27e9 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 456,
+ /* R i */ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x2192 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 457,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 12,
+ 0, 0x21e5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 458,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 18, 0, 0x21c4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 459,
+ /* R i */ 'g' _ 'h' _ 't' _ 'C' _ 'e' _ 'i' _ 'l' _ 'i' _ 'n' _ 'g' _ ';',
+ 11, 0, 0x2309 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 460,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'u' _ 'b' _ 'l' _ 'e' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';',
+ 17, 0, 0x27e7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 461,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 17, 0, 0x295d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 462,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 14, 0, 0x21c2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 463,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 17, 0, 0x2955 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 464,
+ /* R i */ 'g' _ 'h' _ 't' _ 'F' _ 'l' _ 'o' _ 'o' _ 'r' _ ';', 9, 0,
+ 0x230b _ 0)
+NAMED_CHARACTER_REFERENCE(465,
+ /* R i */ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ ';', 7,
+ 0, 0x22a2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 466,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12,
+ 0, 0x21a6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 467,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 13, 0, 0x295b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 468,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12,
+ 0, 0x22b3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 469,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'B' _ 'a' _ 'r' _ ';',
+ 15, 0, 0x29d0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 470,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'T' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 17, 0, 0x22b5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 471,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'D' _ 'o' _ 'w' _ 'n' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 16, 0, 0x294f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 472,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'T' _ 'e' _ 'e' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';',
+ 15, 0, 0x295c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 473,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 12,
+ 0, 0x21be _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 474,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'U' _ 'p' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 15, 0, 0x2954 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 475,
+ /* R i */ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ ';', 10, 0,
+ 0x21c0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 476,
+ /* R i */
+ 'g' _ 'h' _ 't' _ 'V' _ 'e' _ 'c' _ 't' _ 'o' _ 'r' _ 'B' _ 'a' _ 'r' _ ';',
+ 13, 0, 0x2953 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 477,
+ /* R i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x21d2 _ 0)
+NAMED_CHARACTER_REFERENCE(478, /* R o */ 'p' _ 'f' _ ';', 3, 0, 0x211d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 479,
+ /* R o */ 'u' _ 'n' _ 'd' _ 'I' _ 'm' _ 'p' _ 'l' _ 'i' _ 'e' _ 's' _ ';',
+ 11, 0, 0x2970 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 480,
+ /* R r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0,
+ 0x21db _ 0)
+NAMED_CHARACTER_REFERENCE(481, /* R s */ 'c' _ 'r' _ ';', 3, 0, 0x211b _ 0)
+NAMED_CHARACTER_REFERENCE(482, /* R s */ 'h' _ ';', 2, 0, 0x21b1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 483,
+ /* R u */ 'l' _ 'e' _ 'D' _ 'e' _ 'l' _ 'a' _ 'y' _ 'e' _ 'd' _ ';', 10, 0,
+ 0x29f4 _ 0)
+NAMED_CHARACTER_REFERENCE(484,
+ /* S H */ 'C' _ 'H' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x0429 _ 0)
+NAMED_CHARACTER_REFERENCE(485, /* S H */ 'c' _ 'y' _ ';', 3, 0, 0x0428 _ 0)
+NAMED_CHARACTER_REFERENCE(486,
+ /* S O */ 'F' _ 'T' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x042c _ 0)
+NAMED_CHARACTER_REFERENCE(487,
+ /* S a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x015a _ 0)
+NAMED_CHARACTER_REFERENCE(488, /* S c */ ';', 1, 0, 0x2abc _ 0)
+NAMED_CHARACTER_REFERENCE(489,
+ /* S c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0160 _ 0)
+NAMED_CHARACTER_REFERENCE(490,
+ /* S c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x015e _ 0)
+NAMED_CHARACTER_REFERENCE(491,
+ /* S c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015c _ 0)
+NAMED_CHARACTER_REFERENCE(492, /* S c */ 'y' _ ';', 2, 0, 0x0421 _ 0)
+NAMED_CHARACTER_REFERENCE(493, /* S f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd16)
+NAMED_CHARACTER_REFERENCE(
+ 494,
+ /* S h */
+ 'o' _ 'r' _ 't' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x2193 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 495,
+ /* S h */
+ 'o' _ 'r' _ 't' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x2190 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 496,
+ /* S h */
+ 'o' _ 'r' _ 't' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x2192 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 497,
+ /* S h */ 'o' _ 'r' _ 't' _ 'U' _ 'p' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 11, 0, 0x2191 _ 0)
+NAMED_CHARACTER_REFERENCE(498,
+ /* S i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03a3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 499,
+ /* S m */ 'a' _ 'l' _ 'l' _ 'C' _ 'i' _ 'r' _ 'c' _ 'l' _ 'e' _ ';', 10, 0,
+ 0x2218 _ 0)
+NAMED_CHARACTER_REFERENCE(500, /* S o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4a)
+NAMED_CHARACTER_REFERENCE(501, /* S q */ 'r' _ 't' _ ';', 3, 0, 0x221a _ 0)
+NAMED_CHARACTER_REFERENCE(502,
+ /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0,
+ 0x25a1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 503,
+ /* S q */
+ 'u' _ 'a' _ 'r' _ 'e' _ 'I' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ 'e' _ 'c' _ 't' _ 'i' _ 'o' _ 'n' _ ';',
+ 17, 0, 0x2293 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 504,
+ /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';',
+ 11, 0, 0x228f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 505,
+ /* S q */
+ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 16, 0, 0x2291 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 506,
+ /* S q */
+ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';',
+ 13, 0, 0x2290 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 507,
+ /* S q */
+ 'u' _ 'a' _ 'r' _ 'e' _ 'S' _ 'u' _ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 18, 0, 0x2292 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 508,
+ /* S q */ 'u' _ 'a' _ 'r' _ 'e' _ 'U' _ 'n' _ 'i' _ 'o' _ 'n' _ ';', 10, 0,
+ 0x2294 _ 0)
+NAMED_CHARACTER_REFERENCE(509, /* S s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcae)
+NAMED_CHARACTER_REFERENCE(510, /* S t */ 'a' _ 'r' _ ';', 3, 0, 0x22c6 _ 0)
+NAMED_CHARACTER_REFERENCE(511, /* S u */ 'b' _ ';', 2, 0, 0x22d0 _ 0)
+NAMED_CHARACTER_REFERENCE(512,
+ /* S u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0,
+ 0x22d0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 513,
+ /* S u */ 'b' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 10, 0,
+ 0x2286 _ 0)
+NAMED_CHARACTER_REFERENCE(514,
+ /* S u */ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ ';', 7,
+ 0, 0x227b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 515,
+ /* S u */
+ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12,
+ 0, 0x2ab0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 516,
+ /* S u */
+ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'S' _ 'l' _ 'a' _ 'n' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 17, 0, 0x227d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 517,
+ /* S u */
+ 'c' _ 'c' _ 'e' _ 'e' _ 'd' _ 's' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12,
+ 0, 0x227f _ 0)
+NAMED_CHARACTER_REFERENCE(518,
+ /* S u */ 'c' _ 'h' _ 'T' _ 'h' _ 'a' _ 't' _ ';', 7,
+ 0, 0x220b _ 0)
+NAMED_CHARACTER_REFERENCE(519, /* S u */ 'm' _ ';', 2, 0, 0x2211 _ 0)
+NAMED_CHARACTER_REFERENCE(520, /* S u */ 'p' _ ';', 2, 0, 0x22d1 _ 0)
+NAMED_CHARACTER_REFERENCE(521,
+ /* S u */ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ ';', 7,
+ 0, 0x2283 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 522,
+ /* S u */
+ 'p' _ 'e' _ 'r' _ 's' _ 'e' _ 't' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 12,
+ 0, 0x2287 _ 0)
+NAMED_CHARACTER_REFERENCE(523,
+ /* S u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0,
+ 0x22d1 _ 0)
+NAMED_CHARACTER_REFERENCE(524, /* T H */ 'O' _ 'R' _ 'N', 3, 0, 0x00de _ 0)
+NAMED_CHARACTER_REFERENCE(525,
+ /* T H */ 'O' _ 'R' _ 'N' _ ';', 4, 0, 0x00de _ 0)
+NAMED_CHARACTER_REFERENCE(526,
+ /* T R */ 'A' _ 'D' _ 'E' _ ';', 4, 0, 0x2122 _ 0)
+NAMED_CHARACTER_REFERENCE(527,
+ /* T S */ 'H' _ 'c' _ 'y' _ ';', 4, 0, 0x040b _ 0)
+NAMED_CHARACTER_REFERENCE(528, /* T S */ 'c' _ 'y' _ ';', 3, 0, 0x0426 _ 0)
+NAMED_CHARACTER_REFERENCE(529, /* T a */ 'b' _ ';', 2, 0, 0x0009 _ 0)
+NAMED_CHARACTER_REFERENCE(530, /* T a */ 'u' _ ';', 2, 0, 0x03a4 _ 0)
+NAMED_CHARACTER_REFERENCE(531,
+ /* T c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0164 _ 0)
+NAMED_CHARACTER_REFERENCE(532,
+ /* T c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0162 _ 0)
+NAMED_CHARACTER_REFERENCE(533, /* T c */ 'y' _ ';', 2, 0, 0x0422 _ 0)
+NAMED_CHARACTER_REFERENCE(534, /* T f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd17)
+NAMED_CHARACTER_REFERENCE(
+ 535,
+ /* T h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0)
+NAMED_CHARACTER_REFERENCE(536,
+ /* T h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x0398 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 537,
+ /* T h */ 'i' _ 'c' _ 'k' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 9, 0,
+ 0x205f _ 0x200a)
+NAMED_CHARACTER_REFERENCE(
+ 538,
+ /* T h */ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 8, 0, 0x2009 _ 0)
+NAMED_CHARACTER_REFERENCE(539,
+ /* T i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x223c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 540,
+ /* T i */ 'l' _ 'd' _ 'e' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';', 9, 0,
+ 0x2243 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 541,
+ /* T i */
+ 'l' _ 'd' _ 'e' _ 'F' _ 'u' _ 'l' _ 'l' _ 'E' _ 'q' _ 'u' _ 'a' _ 'l' _ ';',
+ 13, 0, 0x2245 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 542,
+ /* T i */ 'l' _ 'd' _ 'e' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 9, 0,
+ 0x2248 _ 0)
+NAMED_CHARACTER_REFERENCE(543, /* T o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4b)
+NAMED_CHARACTER_REFERENCE(
+ 544,
+ /* T r */ 'i' _ 'p' _ 'l' _ 'e' _ 'D' _ 'o' _ 't' _ ';', 8, 0, 0x20db _ 0)
+NAMED_CHARACTER_REFERENCE(545, /* T s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcaf)
+NAMED_CHARACTER_REFERENCE(546,
+ /* T s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0166 _ 0)
+NAMED_CHARACTER_REFERENCE(547,
+ /* U a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00da _ 0)
+NAMED_CHARACTER_REFERENCE(548,
+ /* U a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00da _ 0)
+NAMED_CHARACTER_REFERENCE(549, /* U a */ 'r' _ 'r' _ ';', 3, 0, 0x219f _ 0)
+NAMED_CHARACTER_REFERENCE(550,
+ /* U a */ 'r' _ 'r' _ 'o' _ 'c' _ 'i' _ 'r' _ ';', 7,
+ 0, 0x2949 _ 0)
+NAMED_CHARACTER_REFERENCE(551,
+ /* U b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x040e _ 0)
+NAMED_CHARACTER_REFERENCE(552,
+ /* U b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x016c _ 0)
+NAMED_CHARACTER_REFERENCE(553, /* U c */ 'i' _ 'r' _ 'c', 3, 0, 0x00db _ 0)
+NAMED_CHARACTER_REFERENCE(554,
+ /* U c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00db _ 0)
+NAMED_CHARACTER_REFERENCE(555, /* U c */ 'y' _ ';', 2, 0, 0x0423 _ 0)
+NAMED_CHARACTER_REFERENCE(556,
+ /* U d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0,
+ 0x0170 _ 0)
+NAMED_CHARACTER_REFERENCE(557, /* U f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd18)
+NAMED_CHARACTER_REFERENCE(558,
+ /* U g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00d9 _ 0)
+NAMED_CHARACTER_REFERENCE(559,
+ /* U g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00d9 _ 0)
+NAMED_CHARACTER_REFERENCE(560,
+ /* U m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016a _ 0)
+NAMED_CHARACTER_REFERENCE(561,
+ /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'a' _ 'r' _ ';', 7,
+ 0, 0x005f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 562,
+ /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'e' _ ';', 9, 0,
+ 0x23df _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 563,
+ /* U n */ 'd' _ 'e' _ 'r' _ 'B' _ 'r' _ 'a' _ 'c' _ 'k' _ 'e' _ 't' _ ';',
+ 11, 0, 0x23b5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 564,
+ /* U n */
+ 'd' _ 'e' _ 'r' _ 'P' _ 'a' _ 'r' _ 'e' _ 'n' _ 't' _ 'h' _ 'e' _ 's' _ 'i' _ 's' _ ';',
+ 15, 0, 0x23dd _ 0)
+NAMED_CHARACTER_REFERENCE(565,
+ /* U n */ 'i' _ 'o' _ 'n' _ ';', 4, 0, 0x22c3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 566,
+ /* U n */ 'i' _ 'o' _ 'n' _ 'P' _ 'l' _ 'u' _ 's' _ ';', 8, 0, 0x228e _ 0)
+NAMED_CHARACTER_REFERENCE(567,
+ /* U o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0172 _ 0)
+NAMED_CHARACTER_REFERENCE(568, /* U o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4c)
+NAMED_CHARACTER_REFERENCE(569,
+ /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x2191 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 570,
+ /* U p */ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'B' _ 'a' _ 'r' _ ';', 9, 0,
+ 0x2912 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 571,
+ /* U p */
+ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 15, 0, 0x21c5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 572,
+ /* U p */ 'D' _ 'o' _ 'w' _ 'n' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0,
+ 0x2195 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 573,
+ /* U p */
+ 'E' _ 'q' _ 'u' _ 'i' _ 'l' _ 'i' _ 'b' _ 'r' _ 'i' _ 'u' _ 'm' _ ';', 12,
+ 0, 0x296e _ 0)
+NAMED_CHARACTER_REFERENCE(574,
+ /* U p */ 'T' _ 'e' _ 'e' _ ';', 4, 0, 0x22a5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 575,
+ /* U p */ 'T' _ 'e' _ 'e' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x21a5 _ 0)
+NAMED_CHARACTER_REFERENCE(576,
+ /* U p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x21d1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 577,
+ /* U p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0,
+ 0x21d5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 578,
+ /* U p */
+ 'p' _ 'e' _ 'r' _ 'L' _ 'e' _ 'f' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x2196 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 579,
+ /* U p */
+ 'p' _ 'e' _ 'r' _ 'R' _ 'i' _ 'g' _ 'h' _ 't' _ 'A' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x2197 _ 0)
+NAMED_CHARACTER_REFERENCE(580, /* U p */ 's' _ 'i' _ ';', 3, 0, 0x03d2 _ 0)
+NAMED_CHARACTER_REFERENCE(581,
+ /* U p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x03a5 _ 0)
+NAMED_CHARACTER_REFERENCE(582,
+ /* U r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016e _ 0)
+NAMED_CHARACTER_REFERENCE(583, /* U s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb0)
+NAMED_CHARACTER_REFERENCE(584,
+ /* U t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x0168 _ 0)
+NAMED_CHARACTER_REFERENCE(585, /* U u */ 'm' _ 'l', 2, 0, 0x00dc _ 0)
+NAMED_CHARACTER_REFERENCE(586, /* U u */ 'm' _ 'l' _ ';', 3, 0, 0x00dc _ 0)
+NAMED_CHARACTER_REFERENCE(587,
+ /* V D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22ab _ 0)
+NAMED_CHARACTER_REFERENCE(588, /* V b */ 'a' _ 'r' _ ';', 3, 0, 0x2aeb _ 0)
+NAMED_CHARACTER_REFERENCE(589, /* V c */ 'y' _ ';', 2, 0, 0x0412 _ 0)
+NAMED_CHARACTER_REFERENCE(590,
+ /* V d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a9 _ 0)
+NAMED_CHARACTER_REFERENCE(591,
+ /* V d */ 'a' _ 's' _ 'h' _ 'l' _ ';', 5, 0,
+ 0x2ae6 _ 0)
+NAMED_CHARACTER_REFERENCE(592, /* V e */ 'e' _ ';', 2, 0, 0x22c1 _ 0)
+NAMED_CHARACTER_REFERENCE(593,
+ /* V e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2016 _ 0)
+NAMED_CHARACTER_REFERENCE(594, /* V e */ 'r' _ 't' _ ';', 3, 0, 0x2016 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 595,
+ /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'B' _ 'a' _ 'r' _ ';', 10, 0,
+ 0x2223 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 596,
+ /* V e */ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'L' _ 'i' _ 'n' _ 'e' _ ';',
+ 11, 0, 0x007c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 597,
+ /* V e */
+ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'S' _ 'e' _ 'p' _ 'a' _ 'r' _ 'a' _ 't' _ 'o' _ 'r' _ ';',
+ 16, 0, 0x2758 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 598,
+ /* V e */
+ 'r' _ 't' _ 'i' _ 'c' _ 'a' _ 'l' _ 'T' _ 'i' _ 'l' _ 'd' _ 'e' _ ';', 12,
+ 0, 0x2240 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 599,
+ /* V e */
+ 'r' _ 'y' _ 'T' _ 'h' _ 'i' _ 'n' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';', 12,
+ 0, 0x200a _ 0)
+NAMED_CHARACTER_REFERENCE(600, /* V f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd19)
+NAMED_CHARACTER_REFERENCE(601, /* V o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4d)
+NAMED_CHARACTER_REFERENCE(602, /* V s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb1)
+NAMED_CHARACTER_REFERENCE(603,
+ /* V v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x22aa _ 0)
+NAMED_CHARACTER_REFERENCE(604,
+ /* W c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0174 _ 0)
+NAMED_CHARACTER_REFERENCE(605,
+ /* W e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x22c0 _ 0)
+NAMED_CHARACTER_REFERENCE(606, /* W f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1a)
+NAMED_CHARACTER_REFERENCE(607, /* W o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4e)
+NAMED_CHARACTER_REFERENCE(608, /* W s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb2)
+NAMED_CHARACTER_REFERENCE(609, /* X f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1b)
+NAMED_CHARACTER_REFERENCE(610, /* X i */ ';', 1, 0, 0x039e _ 0)
+NAMED_CHARACTER_REFERENCE(611, /* X o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd4f)
+NAMED_CHARACTER_REFERENCE(612, /* X s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb3)
+NAMED_CHARACTER_REFERENCE(613, /* Y A */ 'c' _ 'y' _ ';', 3, 0, 0x042f _ 0)
+NAMED_CHARACTER_REFERENCE(614, /* Y I */ 'c' _ 'y' _ ';', 3, 0, 0x0407 _ 0)
+NAMED_CHARACTER_REFERENCE(615, /* Y U */ 'c' _ 'y' _ ';', 3, 0, 0x042e _ 0)
+NAMED_CHARACTER_REFERENCE(616,
+ /* Y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00dd _ 0)
+NAMED_CHARACTER_REFERENCE(617,
+ /* Y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00dd _ 0)
+NAMED_CHARACTER_REFERENCE(618,
+ /* Y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0176 _ 0)
+NAMED_CHARACTER_REFERENCE(619, /* Y c */ 'y' _ ';', 2, 0, 0x042b _ 0)
+NAMED_CHARACTER_REFERENCE(620, /* Y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1c)
+NAMED_CHARACTER_REFERENCE(621, /* Y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd50)
+NAMED_CHARACTER_REFERENCE(622, /* Y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb4)
+NAMED_CHARACTER_REFERENCE(623, /* Y u */ 'm' _ 'l' _ ';', 3, 0, 0x0178 _ 0)
+NAMED_CHARACTER_REFERENCE(624, /* Z H */ 'c' _ 'y' _ ';', 3, 0, 0x0416 _ 0)
+NAMED_CHARACTER_REFERENCE(625,
+ /* Z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0179 _ 0)
+NAMED_CHARACTER_REFERENCE(626,
+ /* Z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x017d _ 0)
+NAMED_CHARACTER_REFERENCE(627, /* Z c */ 'y' _ ';', 2, 0, 0x0417 _ 0)
+NAMED_CHARACTER_REFERENCE(628, /* Z d */ 'o' _ 't' _ ';', 3, 0, 0x017b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 629,
+ /* Z e */
+ 'r' _ 'o' _ 'W' _ 'i' _ 'd' _ 't' _ 'h' _ 'S' _ 'p' _ 'a' _ 'c' _ 'e' _ ';',
+ 13, 0, 0x200b _ 0)
+NAMED_CHARACTER_REFERENCE(630, /* Z e */ 't' _ 'a' _ ';', 3, 0, 0x0396 _ 0)
+NAMED_CHARACTER_REFERENCE(631, /* Z f */ 'r' _ ';', 2, 0, 0x2128 _ 0)
+NAMED_CHARACTER_REFERENCE(632, /* Z o */ 'p' _ 'f' _ ';', 3, 0, 0x2124 _ 0)
+NAMED_CHARACTER_REFERENCE(633, /* Z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb5)
+NAMED_CHARACTER_REFERENCE(634,
+ /* a a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e1 _ 0)
+NAMED_CHARACTER_REFERENCE(635,
+ /* a a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00e1 _ 0)
+NAMED_CHARACTER_REFERENCE(636,
+ /* a b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x0103 _ 0)
+NAMED_CHARACTER_REFERENCE(637, /* a c */ ';', 1, 0, 0x223e _ 0)
+NAMED_CHARACTER_REFERENCE(638, /* a c */ 'E' _ ';', 2, 0, 0x223e _ 0x0333)
+NAMED_CHARACTER_REFERENCE(639, /* a c */ 'd' _ ';', 2, 0, 0x223f _ 0)
+NAMED_CHARACTER_REFERENCE(640, /* a c */ 'i' _ 'r' _ 'c', 3, 0, 0x00e2 _ 0)
+NAMED_CHARACTER_REFERENCE(641,
+ /* a c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00e2 _ 0)
+NAMED_CHARACTER_REFERENCE(642, /* a c */ 'u' _ 't' _ 'e', 3, 0, 0x00b4 _ 0)
+NAMED_CHARACTER_REFERENCE(643,
+ /* a c */ 'u' _ 't' _ 'e' _ ';', 4, 0, 0x00b4 _ 0)
+NAMED_CHARACTER_REFERENCE(644, /* a c */ 'y' _ ';', 2, 0, 0x0430 _ 0)
+NAMED_CHARACTER_REFERENCE(645, /* a e */ 'l' _ 'i' _ 'g', 3, 0, 0x00e6 _ 0)
+NAMED_CHARACTER_REFERENCE(646,
+ /* a e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00e6 _ 0)
+NAMED_CHARACTER_REFERENCE(647, /* a f */ ';', 1, 0, 0x2061 _ 0)
+NAMED_CHARACTER_REFERENCE(648, /* a f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1e)
+NAMED_CHARACTER_REFERENCE(649,
+ /* a g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e0 _ 0)
+NAMED_CHARACTER_REFERENCE(650,
+ /* a g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00e0 _ 0)
+NAMED_CHARACTER_REFERENCE(651,
+ /* a l */ 'e' _ 'f' _ 's' _ 'y' _ 'm' _ ';', 6, 0,
+ 0x2135 _ 0)
+NAMED_CHARACTER_REFERENCE(652,
+ /* a l */ 'e' _ 'p' _ 'h' _ ';', 4, 0, 0x2135 _ 0)
+NAMED_CHARACTER_REFERENCE(653,
+ /* a l */ 'p' _ 'h' _ 'a' _ ';', 4, 0, 0x03b1 _ 0)
+NAMED_CHARACTER_REFERENCE(654,
+ /* a m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0101 _ 0)
+NAMED_CHARACTER_REFERENCE(655,
+ /* a m */ 'a' _ 'l' _ 'g' _ ';', 4, 0, 0x2a3f _ 0)
+NAMED_CHARACTER_REFERENCE(656, /* a m */ 'p', 1, 0, 0x0026 _ 0)
+NAMED_CHARACTER_REFERENCE(657, /* a m */ 'p' _ ';', 2, 0, 0x0026 _ 0)
+NAMED_CHARACTER_REFERENCE(658, /* a n */ 'd' _ ';', 2, 0, 0x2227 _ 0)
+NAMED_CHARACTER_REFERENCE(659,
+ /* a n */ 'd' _ 'a' _ 'n' _ 'd' _ ';', 5, 0,
+ 0x2a55 _ 0)
+NAMED_CHARACTER_REFERENCE(660, /* a n */ 'd' _ 'd' _ ';', 3, 0, 0x2a5c _ 0)
+NAMED_CHARACTER_REFERENCE(661,
+ /* a n */ 'd' _ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 7,
+ 0, 0x2a58 _ 0)
+NAMED_CHARACTER_REFERENCE(662, /* a n */ 'd' _ 'v' _ ';', 3, 0, 0x2a5a _ 0)
+NAMED_CHARACTER_REFERENCE(663, /* a n */ 'g' _ ';', 2, 0, 0x2220 _ 0)
+NAMED_CHARACTER_REFERENCE(664, /* a n */ 'g' _ 'e' _ ';', 3, 0, 0x29a4 _ 0)
+NAMED_CHARACTER_REFERENCE(665,
+ /* a n */ 'g' _ 'l' _ 'e' _ ';', 4, 0, 0x2220 _ 0)
+NAMED_CHARACTER_REFERENCE(666,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ ';', 5, 0,
+ 0x2221 _ 0)
+NAMED_CHARACTER_REFERENCE(667,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'a' _ ';', 7,
+ 0, 0x29a8 _ 0)
+NAMED_CHARACTER_REFERENCE(668,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'b' _ ';', 7,
+ 0, 0x29a9 _ 0)
+NAMED_CHARACTER_REFERENCE(669,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'c' _ ';', 7,
+ 0, 0x29aa _ 0)
+NAMED_CHARACTER_REFERENCE(670,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'd' _ ';', 7,
+ 0, 0x29ab _ 0)
+NAMED_CHARACTER_REFERENCE(671,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'e' _ ';', 7,
+ 0, 0x29ac _ 0)
+NAMED_CHARACTER_REFERENCE(672,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'f' _ ';', 7,
+ 0, 0x29ad _ 0)
+NAMED_CHARACTER_REFERENCE(673,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'g' _ ';', 7,
+ 0, 0x29ae _ 0)
+NAMED_CHARACTER_REFERENCE(674,
+ /* a n */ 'g' _ 'm' _ 's' _ 'd' _ 'a' _ 'h' _ ';', 7,
+ 0, 0x29af _ 0)
+NAMED_CHARACTER_REFERENCE(675,
+ /* a n */ 'g' _ 'r' _ 't' _ ';', 4, 0, 0x221f _ 0)
+NAMED_CHARACTER_REFERENCE(676,
+ /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ ';', 6, 0,
+ 0x22be _ 0)
+NAMED_CHARACTER_REFERENCE(677,
+ /* a n */ 'g' _ 'r' _ 't' _ 'v' _ 'b' _ 'd' _ ';', 7,
+ 0, 0x299d _ 0)
+NAMED_CHARACTER_REFERENCE(678,
+ /* a n */ 'g' _ 's' _ 'p' _ 'h' _ ';', 5, 0,
+ 0x2222 _ 0)
+NAMED_CHARACTER_REFERENCE(679,
+ /* a n */ 'g' _ 's' _ 't' _ ';', 4, 0, 0x00c5 _ 0)
+NAMED_CHARACTER_REFERENCE(680,
+ /* a n */ 'g' _ 'z' _ 'a' _ 'r' _ 'r' _ ';', 6, 0,
+ 0x237c _ 0)
+NAMED_CHARACTER_REFERENCE(681,
+ /* a o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0105 _ 0)
+NAMED_CHARACTER_REFERENCE(682, /* a o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd52)
+NAMED_CHARACTER_REFERENCE(683, /* a p */ ';', 1, 0, 0x2248 _ 0)
+NAMED_CHARACTER_REFERENCE(684, /* a p */ 'E' _ ';', 2, 0, 0x2a70 _ 0)
+NAMED_CHARACTER_REFERENCE(685,
+ /* a p */ 'a' _ 'c' _ 'i' _ 'r' _ ';', 5, 0,
+ 0x2a6f _ 0)
+NAMED_CHARACTER_REFERENCE(686, /* a p */ 'e' _ ';', 2, 0, 0x224a _ 0)
+NAMED_CHARACTER_REFERENCE(687, /* a p */ 'i' _ 'd' _ ';', 3, 0, 0x224b _ 0)
+NAMED_CHARACTER_REFERENCE(688, /* a p */ 'o' _ 's' _ ';', 3, 0, 0x0027 _ 0)
+NAMED_CHARACTER_REFERENCE(689,
+ /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ ';', 5, 0,
+ 0x2248 _ 0)
+NAMED_CHARACTER_REFERENCE(690,
+ /* a p */ 'p' _ 'r' _ 'o' _ 'x' _ 'e' _ 'q' _ ';', 7,
+ 0, 0x224a _ 0)
+NAMED_CHARACTER_REFERENCE(691, /* a r */ 'i' _ 'n' _ 'g', 3, 0, 0x00e5 _ 0)
+NAMED_CHARACTER_REFERENCE(692,
+ /* a r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x00e5 _ 0)
+NAMED_CHARACTER_REFERENCE(693, /* a s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb6)
+NAMED_CHARACTER_REFERENCE(694, /* a s */ 't' _ ';', 2, 0, 0x002a _ 0)
+NAMED_CHARACTER_REFERENCE(695,
+ /* a s */ 'y' _ 'm' _ 'p' _ ';', 4, 0, 0x2248 _ 0)
+NAMED_CHARACTER_REFERENCE(696,
+ /* a s */ 'y' _ 'm' _ 'p' _ 'e' _ 'q' _ ';', 6, 0,
+ 0x224d _ 0)
+NAMED_CHARACTER_REFERENCE(697,
+ /* a t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00e3 _ 0)
+NAMED_CHARACTER_REFERENCE(698,
+ /* a t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00e3 _ 0)
+NAMED_CHARACTER_REFERENCE(699, /* a u */ 'm' _ 'l', 2, 0, 0x00e4 _ 0)
+NAMED_CHARACTER_REFERENCE(700, /* a u */ 'm' _ 'l' _ ';', 3, 0, 0x00e4 _ 0)
+NAMED_CHARACTER_REFERENCE(701,
+ /* a w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2233 _ 0)
+NAMED_CHARACTER_REFERENCE(702,
+ /* a w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2a11 _ 0)
+NAMED_CHARACTER_REFERENCE(703, /* b N */ 'o' _ 't' _ ';', 3, 0, 0x2aed _ 0)
+NAMED_CHARACTER_REFERENCE(704,
+ /* b a */ 'c' _ 'k' _ 'c' _ 'o' _ 'n' _ 'g' _ ';', 7,
+ 0, 0x224c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 705,
+ /* b a */ 'c' _ 'k' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 10, 0,
+ 0x03f6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 706,
+ /* b a */ 'c' _ 'k' _ 'p' _ 'r' _ 'i' _ 'm' _ 'e' _ ';', 8, 0, 0x2035 _ 0)
+NAMED_CHARACTER_REFERENCE(707,
+ /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x223d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 708,
+ /* b a */ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ 'e' _ 'q' _ ';', 8, 0, 0x22cd _ 0)
+NAMED_CHARACTER_REFERENCE(709,
+ /* b a */ 'r' _ 'v' _ 'e' _ 'e' _ ';', 5, 0,
+ 0x22bd _ 0)
+NAMED_CHARACTER_REFERENCE(710,
+ /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ ';', 5, 0,
+ 0x2305 _ 0)
+NAMED_CHARACTER_REFERENCE(711,
+ /* b a */ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7,
+ 0, 0x2305 _ 0)
+NAMED_CHARACTER_REFERENCE(712, /* b b */ 'r' _ 'k' _ ';', 3, 0, 0x23b5 _ 0)
+NAMED_CHARACTER_REFERENCE(713,
+ /* b b */ 'r' _ 'k' _ 't' _ 'b' _ 'r' _ 'k' _ ';', 7,
+ 0, 0x23b6 _ 0)
+NAMED_CHARACTER_REFERENCE(714,
+ /* b c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x224c _ 0)
+NAMED_CHARACTER_REFERENCE(715, /* b c */ 'y' _ ';', 2, 0, 0x0431 _ 0)
+NAMED_CHARACTER_REFERENCE(716,
+ /* b d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201e _ 0)
+NAMED_CHARACTER_REFERENCE(717,
+ /* b e */ 'c' _ 'a' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2235 _ 0)
+NAMED_CHARACTER_REFERENCE(718,
+ /* b e */ 'c' _ 'a' _ 'u' _ 's' _ 'e' _ ';', 6, 0,
+ 0x2235 _ 0)
+NAMED_CHARACTER_REFERENCE(719,
+ /* b e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0,
+ 0x29b0 _ 0)
+NAMED_CHARACTER_REFERENCE(720,
+ /* b e */ 'p' _ 's' _ 'i' _ ';', 4, 0, 0x03f6 _ 0)
+NAMED_CHARACTER_REFERENCE(721,
+ /* b e */ 'r' _ 'n' _ 'o' _ 'u' _ ';', 5, 0,
+ 0x212c _ 0)
+NAMED_CHARACTER_REFERENCE(722, /* b e */ 't' _ 'a' _ ';', 3, 0, 0x03b2 _ 0)
+NAMED_CHARACTER_REFERENCE(723, /* b e */ 't' _ 'h' _ ';', 3, 0, 0x2136 _ 0)
+NAMED_CHARACTER_REFERENCE(724,
+ /* b e */ 't' _ 'w' _ 'e' _ 'e' _ 'n' _ ';', 6, 0,
+ 0x226c _ 0)
+NAMED_CHARACTER_REFERENCE(725, /* b f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd1f)
+NAMED_CHARACTER_REFERENCE(726,
+ /* b i */ 'g' _ 'c' _ 'a' _ 'p' _ ';', 5, 0,
+ 0x22c2 _ 0)
+NAMED_CHARACTER_REFERENCE(727,
+ /* b i */ 'g' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 6, 0,
+ 0x25ef _ 0)
+NAMED_CHARACTER_REFERENCE(728,
+ /* b i */ 'g' _ 'c' _ 'u' _ 'p' _ ';', 5, 0,
+ 0x22c3 _ 0)
+NAMED_CHARACTER_REFERENCE(729,
+ /* b i */ 'g' _ 'o' _ 'd' _ 'o' _ 't' _ ';', 6, 0,
+ 0x2a00 _ 0)
+NAMED_CHARACTER_REFERENCE(730,
+ /* b i */ 'g' _ 'o' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7,
+ 0, 0x2a01 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 731,
+ /* b i */ 'g' _ 'o' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 8, 0, 0x2a02 _ 0)
+NAMED_CHARACTER_REFERENCE(732,
+ /* b i */ 'g' _ 's' _ 'q' _ 'c' _ 'u' _ 'p' _ ';', 7,
+ 0, 0x2a06 _ 0)
+NAMED_CHARACTER_REFERENCE(733,
+ /* b i */ 'g' _ 's' _ 't' _ 'a' _ 'r' _ ';', 6, 0,
+ 0x2605 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 734,
+ /* b i */
+ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';',
+ 14, 0, 0x25bd _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 735,
+ /* b i */
+ 'g' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'u' _ 'p' _ ';', 12,
+ 0, 0x25b3 _ 0)
+NAMED_CHARACTER_REFERENCE(736,
+ /* b i */ 'g' _ 'u' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 7,
+ 0, 0x2a04 _ 0)
+NAMED_CHARACTER_REFERENCE(737,
+ /* b i */ 'g' _ 'v' _ 'e' _ 'e' _ ';', 5, 0,
+ 0x22c1 _ 0)
+NAMED_CHARACTER_REFERENCE(738,
+ /* b i */ 'g' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 7,
+ 0, 0x22c0 _ 0)
+NAMED_CHARACTER_REFERENCE(739,
+ /* b k */ 'a' _ 'r' _ 'o' _ 'w' _ ';', 5, 0,
+ 0x290d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 740,
+ /* b l */ 'a' _ 'c' _ 'k' _ 'l' _ 'o' _ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';',
+ 11, 0, 0x29eb _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 741,
+ /* b l */ 'a' _ 'c' _ 'k' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 10, 0,
+ 0x25aa _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 742,
+ /* b l */
+ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12,
+ 0, 0x25b4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 743,
+ /* b l */
+ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';',
+ 16, 0, 0x25be _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 744,
+ /* b l */
+ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';',
+ 16, 0, 0x25c2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 745,
+ /* b l */
+ 'a' _ 'c' _ 'k' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 17, 0, 0x25b8 _ 0)
+NAMED_CHARACTER_REFERENCE(746,
+ /* b l */ 'a' _ 'n' _ 'k' _ ';', 4, 0, 0x2423 _ 0)
+NAMED_CHARACTER_REFERENCE(747,
+ /* b l */ 'k' _ '1' _ '2' _ ';', 4, 0, 0x2592 _ 0)
+NAMED_CHARACTER_REFERENCE(748,
+ /* b l */ 'k' _ '1' _ '4' _ ';', 4, 0, 0x2591 _ 0)
+NAMED_CHARACTER_REFERENCE(749,
+ /* b l */ 'k' _ '3' _ '4' _ ';', 4, 0, 0x2593 _ 0)
+NAMED_CHARACTER_REFERENCE(750,
+ /* b l */ 'o' _ 'c' _ 'k' _ ';', 4, 0, 0x2588 _ 0)
+NAMED_CHARACTER_REFERENCE(751, /* b n */ 'e' _ ';', 2, 0, 0x003d _ 0x20e5)
+NAMED_CHARACTER_REFERENCE(752,
+ /* b n */ 'e' _ 'q' _ 'u' _ 'i' _ 'v' _ ';', 6, 0,
+ 0x2261 _ 0x20e5)
+NAMED_CHARACTER_REFERENCE(753, /* b n */ 'o' _ 't' _ ';', 3, 0, 0x2310 _ 0)
+NAMED_CHARACTER_REFERENCE(754, /* b o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd53)
+NAMED_CHARACTER_REFERENCE(755, /* b o */ 't' _ ';', 2, 0, 0x22a5 _ 0)
+NAMED_CHARACTER_REFERENCE(756,
+ /* b o */ 't' _ 't' _ 'o' _ 'm' _ ';', 5, 0,
+ 0x22a5 _ 0)
+NAMED_CHARACTER_REFERENCE(757,
+ /* b o */ 'w' _ 't' _ 'i' _ 'e' _ ';', 5, 0,
+ 0x22c8 _ 0)
+NAMED_CHARACTER_REFERENCE(758,
+ /* b o */ 'x' _ 'D' _ 'L' _ ';', 4, 0, 0x2557 _ 0)
+NAMED_CHARACTER_REFERENCE(759,
+ /* b o */ 'x' _ 'D' _ 'R' _ ';', 4, 0, 0x2554 _ 0)
+NAMED_CHARACTER_REFERENCE(760,
+ /* b o */ 'x' _ 'D' _ 'l' _ ';', 4, 0, 0x2556 _ 0)
+NAMED_CHARACTER_REFERENCE(761,
+ /* b o */ 'x' _ 'D' _ 'r' _ ';', 4, 0, 0x2553 _ 0)
+NAMED_CHARACTER_REFERENCE(762, /* b o */ 'x' _ 'H' _ ';', 3, 0, 0x2550 _ 0)
+NAMED_CHARACTER_REFERENCE(763,
+ /* b o */ 'x' _ 'H' _ 'D' _ ';', 4, 0, 0x2566 _ 0)
+NAMED_CHARACTER_REFERENCE(764,
+ /* b o */ 'x' _ 'H' _ 'U' _ ';', 4, 0, 0x2569 _ 0)
+NAMED_CHARACTER_REFERENCE(765,
+ /* b o */ 'x' _ 'H' _ 'd' _ ';', 4, 0, 0x2564 _ 0)
+NAMED_CHARACTER_REFERENCE(766,
+ /* b o */ 'x' _ 'H' _ 'u' _ ';', 4, 0, 0x2567 _ 0)
+NAMED_CHARACTER_REFERENCE(767,
+ /* b o */ 'x' _ 'U' _ 'L' _ ';', 4, 0, 0x255d _ 0)
+NAMED_CHARACTER_REFERENCE(768,
+ /* b o */ 'x' _ 'U' _ 'R' _ ';', 4, 0, 0x255a _ 0)
+NAMED_CHARACTER_REFERENCE(769,
+ /* b o */ 'x' _ 'U' _ 'l' _ ';', 4, 0, 0x255c _ 0)
+NAMED_CHARACTER_REFERENCE(770,
+ /* b o */ 'x' _ 'U' _ 'r' _ ';', 4, 0, 0x2559 _ 0)
+NAMED_CHARACTER_REFERENCE(771, /* b o */ 'x' _ 'V' _ ';', 3, 0, 0x2551 _ 0)
+NAMED_CHARACTER_REFERENCE(772,
+ /* b o */ 'x' _ 'V' _ 'H' _ ';', 4, 0, 0x256c _ 0)
+NAMED_CHARACTER_REFERENCE(773,
+ /* b o */ 'x' _ 'V' _ 'L' _ ';', 4, 0, 0x2563 _ 0)
+NAMED_CHARACTER_REFERENCE(774,
+ /* b o */ 'x' _ 'V' _ 'R' _ ';', 4, 0, 0x2560 _ 0)
+NAMED_CHARACTER_REFERENCE(775,
+ /* b o */ 'x' _ 'V' _ 'h' _ ';', 4, 0, 0x256b _ 0)
+NAMED_CHARACTER_REFERENCE(776,
+ /* b o */ 'x' _ 'V' _ 'l' _ ';', 4, 0, 0x2562 _ 0)
+NAMED_CHARACTER_REFERENCE(777,
+ /* b o */ 'x' _ 'V' _ 'r' _ ';', 4, 0, 0x255f _ 0)
+NAMED_CHARACTER_REFERENCE(778,
+ /* b o */ 'x' _ 'b' _ 'o' _ 'x' _ ';', 5, 0,
+ 0x29c9 _ 0)
+NAMED_CHARACTER_REFERENCE(779,
+ /* b o */ 'x' _ 'd' _ 'L' _ ';', 4, 0, 0x2555 _ 0)
+NAMED_CHARACTER_REFERENCE(780,
+ /* b o */ 'x' _ 'd' _ 'R' _ ';', 4, 0, 0x2552 _ 0)
+NAMED_CHARACTER_REFERENCE(781,
+ /* b o */ 'x' _ 'd' _ 'l' _ ';', 4, 0, 0x2510 _ 0)
+NAMED_CHARACTER_REFERENCE(782,
+ /* b o */ 'x' _ 'd' _ 'r' _ ';', 4, 0, 0x250c _ 0)
+NAMED_CHARACTER_REFERENCE(783, /* b o */ 'x' _ 'h' _ ';', 3, 0, 0x2500 _ 0)
+NAMED_CHARACTER_REFERENCE(784,
+ /* b o */ 'x' _ 'h' _ 'D' _ ';', 4, 0, 0x2565 _ 0)
+NAMED_CHARACTER_REFERENCE(785,
+ /* b o */ 'x' _ 'h' _ 'U' _ ';', 4, 0, 0x2568 _ 0)
+NAMED_CHARACTER_REFERENCE(786,
+ /* b o */ 'x' _ 'h' _ 'd' _ ';', 4, 0, 0x252c _ 0)
+NAMED_CHARACTER_REFERENCE(787,
+ /* b o */ 'x' _ 'h' _ 'u' _ ';', 4, 0, 0x2534 _ 0)
+NAMED_CHARACTER_REFERENCE(788,
+ /* b o */ 'x' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7,
+ 0, 0x229f _ 0)
+NAMED_CHARACTER_REFERENCE(789,
+ /* b o */ 'x' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0,
+ 0x229e _ 0)
+NAMED_CHARACTER_REFERENCE(790,
+ /* b o */ 'x' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 7,
+ 0, 0x22a0 _ 0)
+NAMED_CHARACTER_REFERENCE(791,
+ /* b o */ 'x' _ 'u' _ 'L' _ ';', 4, 0, 0x255b _ 0)
+NAMED_CHARACTER_REFERENCE(792,
+ /* b o */ 'x' _ 'u' _ 'R' _ ';', 4, 0, 0x2558 _ 0)
+NAMED_CHARACTER_REFERENCE(793,
+ /* b o */ 'x' _ 'u' _ 'l' _ ';', 4, 0, 0x2518 _ 0)
+NAMED_CHARACTER_REFERENCE(794,
+ /* b o */ 'x' _ 'u' _ 'r' _ ';', 4, 0, 0x2514 _ 0)
+NAMED_CHARACTER_REFERENCE(795, /* b o */ 'x' _ 'v' _ ';', 3, 0, 0x2502 _ 0)
+NAMED_CHARACTER_REFERENCE(796,
+ /* b o */ 'x' _ 'v' _ 'H' _ ';', 4, 0, 0x256a _ 0)
+NAMED_CHARACTER_REFERENCE(797,
+ /* b o */ 'x' _ 'v' _ 'L' _ ';', 4, 0, 0x2561 _ 0)
+NAMED_CHARACTER_REFERENCE(798,
+ /* b o */ 'x' _ 'v' _ 'R' _ ';', 4, 0, 0x255e _ 0)
+NAMED_CHARACTER_REFERENCE(799,
+ /* b o */ 'x' _ 'v' _ 'h' _ ';', 4, 0, 0x253c _ 0)
+NAMED_CHARACTER_REFERENCE(800,
+ /* b o */ 'x' _ 'v' _ 'l' _ ';', 4, 0, 0x2524 _ 0)
+NAMED_CHARACTER_REFERENCE(801,
+ /* b o */ 'x' _ 'v' _ 'r' _ ';', 4, 0, 0x251c _ 0)
+NAMED_CHARACTER_REFERENCE(802,
+ /* b p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0,
+ 0x2035 _ 0)
+NAMED_CHARACTER_REFERENCE(803,
+ /* b r */ 'e' _ 'v' _ 'e' _ ';', 4, 0, 0x02d8 _ 0)
+NAMED_CHARACTER_REFERENCE(804,
+ /* b r */ 'v' _ 'b' _ 'a' _ 'r', 4, 0, 0x00a6 _ 0)
+NAMED_CHARACTER_REFERENCE(805,
+ /* b r */ 'v' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x00a6 _ 0)
+NAMED_CHARACTER_REFERENCE(806, /* b s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb7)
+NAMED_CHARACTER_REFERENCE(807,
+ /* b s */ 'e' _ 'm' _ 'i' _ ';', 4, 0, 0x204f _ 0)
+NAMED_CHARACTER_REFERENCE(808, /* b s */ 'i' _ 'm' _ ';', 3, 0, 0x223d _ 0)
+NAMED_CHARACTER_REFERENCE(809,
+ /* b s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x22cd _ 0)
+NAMED_CHARACTER_REFERENCE(810, /* b s */ 'o' _ 'l' _ ';', 3, 0, 0x005c _ 0)
+NAMED_CHARACTER_REFERENCE(811,
+ /* b s */ 'o' _ 'l' _ 'b' _ ';', 4, 0, 0x29c5 _ 0)
+NAMED_CHARACTER_REFERENCE(812,
+ /* b s */ 'o' _ 'l' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 7,
+ 0, 0x27c8 _ 0)
+NAMED_CHARACTER_REFERENCE(813, /* b u */ 'l' _ 'l' _ ';', 3, 0, 0x2022 _ 0)
+NAMED_CHARACTER_REFERENCE(814,
+ /* b u */ 'l' _ 'l' _ 'e' _ 't' _ ';', 5, 0,
+ 0x2022 _ 0)
+NAMED_CHARACTER_REFERENCE(815, /* b u */ 'm' _ 'p' _ ';', 3, 0, 0x224e _ 0)
+NAMED_CHARACTER_REFERENCE(816,
+ /* b u */ 'm' _ 'p' _ 'E' _ ';', 4, 0, 0x2aae _ 0)
+NAMED_CHARACTER_REFERENCE(817,
+ /* b u */ 'm' _ 'p' _ 'e' _ ';', 4, 0, 0x224f _ 0)
+NAMED_CHARACTER_REFERENCE(818,
+ /* b u */ 'm' _ 'p' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x224f _ 0)
+NAMED_CHARACTER_REFERENCE(819,
+ /* c a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0107 _ 0)
+NAMED_CHARACTER_REFERENCE(820, /* c a */ 'p' _ ';', 2, 0, 0x2229 _ 0)
+NAMED_CHARACTER_REFERENCE(821,
+ /* c a */ 'p' _ 'a' _ 'n' _ 'd' _ ';', 5, 0,
+ 0x2a44 _ 0)
+NAMED_CHARACTER_REFERENCE(822,
+ /* c a */ 'p' _ 'b' _ 'r' _ 'c' _ 'u' _ 'p' _ ';', 7,
+ 0, 0x2a49 _ 0)
+NAMED_CHARACTER_REFERENCE(823,
+ /* c a */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0,
+ 0x2a4b _ 0)
+NAMED_CHARACTER_REFERENCE(824,
+ /* c a */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0,
+ 0x2a47 _ 0)
+NAMED_CHARACTER_REFERENCE(825,
+ /* c a */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2a40 _ 0)
+NAMED_CHARACTER_REFERENCE(826, /* c a */ 'p' _ 's' _ ';', 3, 0, 0x2229 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(827,
+ /* c a */ 'r' _ 'e' _ 't' _ ';', 4, 0, 0x2041 _ 0)
+NAMED_CHARACTER_REFERENCE(828,
+ /* c a */ 'r' _ 'o' _ 'n' _ ';', 4, 0, 0x02c7 _ 0)
+NAMED_CHARACTER_REFERENCE(829,
+ /* c c */ 'a' _ 'p' _ 's' _ ';', 4, 0, 0x2a4d _ 0)
+NAMED_CHARACTER_REFERENCE(830,
+ /* c c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x010d _ 0)
+NAMED_CHARACTER_REFERENCE(831,
+ /* c c */ 'e' _ 'd' _ 'i' _ 'l', 4, 0, 0x00e7 _ 0)
+NAMED_CHARACTER_REFERENCE(832,
+ /* c c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x00e7 _ 0)
+NAMED_CHARACTER_REFERENCE(833,
+ /* c c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0109 _ 0)
+NAMED_CHARACTER_REFERENCE(834,
+ /* c c */ 'u' _ 'p' _ 's' _ ';', 4, 0, 0x2a4c _ 0)
+NAMED_CHARACTER_REFERENCE(835,
+ /* c c */ 'u' _ 'p' _ 's' _ 's' _ 'm' _ ';', 6, 0,
+ 0x2a50 _ 0)
+NAMED_CHARACTER_REFERENCE(836, /* c d */ 'o' _ 't' _ ';', 3, 0, 0x010b _ 0)
+NAMED_CHARACTER_REFERENCE(837, /* c e */ 'd' _ 'i' _ 'l', 3, 0, 0x00b8 _ 0)
+NAMED_CHARACTER_REFERENCE(838,
+ /* c e */ 'd' _ 'i' _ 'l' _ ';', 4, 0, 0x00b8 _ 0)
+NAMED_CHARACTER_REFERENCE(839,
+ /* c e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0,
+ 0x29b2 _ 0)
+NAMED_CHARACTER_REFERENCE(840, /* c e */ 'n' _ 't', 2, 0, 0x00a2 _ 0)
+NAMED_CHARACTER_REFERENCE(841, /* c e */ 'n' _ 't' _ ';', 3, 0, 0x00a2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 842,
+ /* c e */ 'n' _ 't' _ 'e' _ 'r' _ 'd' _ 'o' _ 't' _ ';', 8, 0, 0x00b7 _ 0)
+NAMED_CHARACTER_REFERENCE(843, /* c f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd20)
+NAMED_CHARACTER_REFERENCE(844, /* c h */ 'c' _ 'y' _ ';', 3, 0, 0x0447 _ 0)
+NAMED_CHARACTER_REFERENCE(845,
+ /* c h */ 'e' _ 'c' _ 'k' _ ';', 4, 0, 0x2713 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 846,
+ /* c h */ 'e' _ 'c' _ 'k' _ 'm' _ 'a' _ 'r' _ 'k' _ ';', 8, 0, 0x2713 _ 0)
+NAMED_CHARACTER_REFERENCE(847, /* c h */ 'i' _ ';', 2, 0, 0x03c7 _ 0)
+NAMED_CHARACTER_REFERENCE(848, /* c i */ 'r' _ ';', 2, 0, 0x25cb _ 0)
+NAMED_CHARACTER_REFERENCE(849, /* c i */ 'r' _ 'E' _ ';', 3, 0, 0x29c3 _ 0)
+NAMED_CHARACTER_REFERENCE(850, /* c i */ 'r' _ 'c' _ ';', 3, 0, 0x02c6 _ 0)
+NAMED_CHARACTER_REFERENCE(851,
+ /* c i */ 'r' _ 'c' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x2257 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 852,
+ /* c i */
+ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';',
+ 14, 0, 0x21ba _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 853,
+ /* c i */
+ 'r' _ 'c' _ 'l' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 15, 0, 0x21bb _ 0)
+NAMED_CHARACTER_REFERENCE(854,
+ /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'R' _ ';', 7,
+ 0, 0x00ae _ 0)
+NAMED_CHARACTER_REFERENCE(855,
+ /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'S' _ ';', 7,
+ 0, 0x24c8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 856,
+ /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'a' _ 's' _ 't' _ ';', 9, 0,
+ 0x229b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 857,
+ /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'c' _ 'i' _ 'r' _ 'c' _ ';', 10, 0,
+ 0x229a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 858,
+ /* c i */ 'r' _ 'c' _ 'l' _ 'e' _ 'd' _ 'd' _ 'a' _ 's' _ 'h' _ ';', 10, 0,
+ 0x229d _ 0)
+NAMED_CHARACTER_REFERENCE(859, /* c i */ 'r' _ 'e' _ ';', 3, 0, 0x2257 _ 0)
+NAMED_CHARACTER_REFERENCE(860,
+ /* c i */ 'r' _ 'f' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a10 _ 0)
+NAMED_CHARACTER_REFERENCE(861,
+ /* c i */ 'r' _ 'm' _ 'i' _ 'd' _ ';', 5, 0,
+ 0x2aef _ 0)
+NAMED_CHARACTER_REFERENCE(862,
+ /* c i */ 'r' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0,
+ 0x29c2 _ 0)
+NAMED_CHARACTER_REFERENCE(863,
+ /* c l */ 'u' _ 'b' _ 's' _ ';', 4, 0, 0x2663 _ 0)
+NAMED_CHARACTER_REFERENCE(864,
+ /* c l */ 'u' _ 'b' _ 's' _ 'u' _ 'i' _ 't' _ ';', 7,
+ 0, 0x2663 _ 0)
+NAMED_CHARACTER_REFERENCE(865,
+ /* c o */ 'l' _ 'o' _ 'n' _ ';', 4, 0, 0x003a _ 0)
+NAMED_CHARACTER_REFERENCE(866,
+ /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ ';', 5, 0,
+ 0x2254 _ 0)
+NAMED_CHARACTER_REFERENCE(867,
+ /* c o */ 'l' _ 'o' _ 'n' _ 'e' _ 'q' _ ';', 6, 0,
+ 0x2254 _ 0)
+NAMED_CHARACTER_REFERENCE(868,
+ /* c o */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x002c _ 0)
+NAMED_CHARACTER_REFERENCE(869,
+ /* c o */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0,
+ 0x0040 _ 0)
+NAMED_CHARACTER_REFERENCE(870, /* c o */ 'm' _ 'p' _ ';', 3, 0, 0x2201 _ 0)
+NAMED_CHARACTER_REFERENCE(871,
+ /* c o */ 'm' _ 'p' _ 'f' _ 'n' _ ';', 5, 0,
+ 0x2218 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 872,
+ /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'm' _ 'e' _ 'n' _ 't' _ ';', 9, 0,
+ 0x2201 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 873,
+ /* c o */ 'm' _ 'p' _ 'l' _ 'e' _ 'x' _ 'e' _ 's' _ ';', 8, 0, 0x2102 _ 0)
+NAMED_CHARACTER_REFERENCE(874, /* c o */ 'n' _ 'g' _ ';', 3, 0, 0x2245 _ 0)
+NAMED_CHARACTER_REFERENCE(875,
+ /* c o */ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 6, 0,
+ 0x2a6d _ 0)
+NAMED_CHARACTER_REFERENCE(876,
+ /* c o */ 'n' _ 'i' _ 'n' _ 't' _ ';', 5, 0,
+ 0x222e _ 0)
+NAMED_CHARACTER_REFERENCE(877, /* c o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd54)
+NAMED_CHARACTER_REFERENCE(878,
+ /* c o */ 'p' _ 'r' _ 'o' _ 'd' _ ';', 5, 0,
+ 0x2210 _ 0)
+NAMED_CHARACTER_REFERENCE(879, /* c o */ 'p' _ 'y', 2, 0, 0x00a9 _ 0)
+NAMED_CHARACTER_REFERENCE(880, /* c o */ 'p' _ 'y' _ ';', 3, 0, 0x00a9 _ 0)
+NAMED_CHARACTER_REFERENCE(881,
+ /* c o */ 'p' _ 'y' _ 's' _ 'r' _ ';', 5, 0,
+ 0x2117 _ 0)
+NAMED_CHARACTER_REFERENCE(882,
+ /* c r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21b5 _ 0)
+NAMED_CHARACTER_REFERENCE(883,
+ /* c r */ 'o' _ 's' _ 's' _ ';', 4, 0, 0x2717 _ 0)
+NAMED_CHARACTER_REFERENCE(884, /* c s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb8)
+NAMED_CHARACTER_REFERENCE(885, /* c s */ 'u' _ 'b' _ ';', 3, 0, 0x2acf _ 0)
+NAMED_CHARACTER_REFERENCE(886,
+ /* c s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2ad1 _ 0)
+NAMED_CHARACTER_REFERENCE(887, /* c s */ 'u' _ 'p' _ ';', 3, 0, 0x2ad0 _ 0)
+NAMED_CHARACTER_REFERENCE(888,
+ /* c s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2ad2 _ 0)
+NAMED_CHARACTER_REFERENCE(889,
+ /* c t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22ef _ 0)
+NAMED_CHARACTER_REFERENCE(890,
+ /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'l' _ ';', 6, 0,
+ 0x2938 _ 0)
+NAMED_CHARACTER_REFERENCE(891,
+ /* c u */ 'd' _ 'a' _ 'r' _ 'r' _ 'r' _ ';', 6, 0,
+ 0x2935 _ 0)
+NAMED_CHARACTER_REFERENCE(892,
+ /* c u */ 'e' _ 'p' _ 'r' _ ';', 4, 0, 0x22de _ 0)
+NAMED_CHARACTER_REFERENCE(893,
+ /* c u */ 'e' _ 's' _ 'c' _ ';', 4, 0, 0x22df _ 0)
+NAMED_CHARACTER_REFERENCE(894,
+ /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x21b6 _ 0)
+NAMED_CHARACTER_REFERENCE(895,
+ /* c u */ 'l' _ 'a' _ 'r' _ 'r' _ 'p' _ ';', 6, 0,
+ 0x293d _ 0)
+NAMED_CHARACTER_REFERENCE(896, /* c u */ 'p' _ ';', 2, 0, 0x222a _ 0)
+NAMED_CHARACTER_REFERENCE(897,
+ /* c u */ 'p' _ 'b' _ 'r' _ 'c' _ 'a' _ 'p' _ ';', 7,
+ 0, 0x2a48 _ 0)
+NAMED_CHARACTER_REFERENCE(898,
+ /* c u */ 'p' _ 'c' _ 'a' _ 'p' _ ';', 5, 0,
+ 0x2a46 _ 0)
+NAMED_CHARACTER_REFERENCE(899,
+ /* c u */ 'p' _ 'c' _ 'u' _ 'p' _ ';', 5, 0,
+ 0x2a4a _ 0)
+NAMED_CHARACTER_REFERENCE(900,
+ /* c u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x228d _ 0)
+NAMED_CHARACTER_REFERENCE(901,
+ /* c u */ 'p' _ 'o' _ 'r' _ ';', 4, 0, 0x2a45 _ 0)
+NAMED_CHARACTER_REFERENCE(902, /* c u */ 'p' _ 's' _ ';', 3, 0, 0x222a _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(903,
+ /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x21b7 _ 0)
+NAMED_CHARACTER_REFERENCE(904,
+ /* c u */ 'r' _ 'a' _ 'r' _ 'r' _ 'm' _ ';', 6, 0,
+ 0x293c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 905,
+ /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 'p' _ 'r' _ 'e' _ 'c' _ ';', 10, 0,
+ 0x22de _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 906,
+ /* c u */ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ 's' _ 'u' _ 'c' _ 'c' _ ';', 10, 0,
+ 0x22df _ 0)
+NAMED_CHARACTER_REFERENCE(907,
+ /* c u */ 'r' _ 'l' _ 'y' _ 'v' _ 'e' _ 'e' _ ';', 7,
+ 0, 0x22ce _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 908,
+ /* c u */ 'r' _ 'l' _ 'y' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';', 9, 0,
+ 0x22cf _ 0)
+NAMED_CHARACTER_REFERENCE(909,
+ /* c u */ 'r' _ 'r' _ 'e' _ 'n', 4, 0, 0x00a4 _ 0)
+NAMED_CHARACTER_REFERENCE(910,
+ /* c u */ 'r' _ 'r' _ 'e' _ 'n' _ ';', 5, 0,
+ 0x00a4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 911,
+ /* c u */
+ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';',
+ 13, 0, 0x21b6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 912,
+ /* c u */
+ 'r' _ 'v' _ 'e' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 14, 0, 0x21b7 _ 0)
+NAMED_CHARACTER_REFERENCE(913,
+ /* c u */ 'v' _ 'e' _ 'e' _ ';', 4, 0, 0x22ce _ 0)
+NAMED_CHARACTER_REFERENCE(914,
+ /* c u */ 'w' _ 'e' _ 'd' _ ';', 4, 0, 0x22cf _ 0)
+NAMED_CHARACTER_REFERENCE(915,
+ /* c w */ 'c' _ 'o' _ 'n' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2232 _ 0)
+NAMED_CHARACTER_REFERENCE(916,
+ /* c w */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x2231 _ 0)
+NAMED_CHARACTER_REFERENCE(917,
+ /* c y */ 'l' _ 'c' _ 't' _ 'y' _ ';', 5, 0,
+ 0x232d _ 0)
+NAMED_CHARACTER_REFERENCE(918, /* d A */ 'r' _ 'r' _ ';', 3, 0, 0x21d3 _ 0)
+NAMED_CHARACTER_REFERENCE(919, /* d H */ 'a' _ 'r' _ ';', 3, 0, 0x2965 _ 0)
+NAMED_CHARACTER_REFERENCE(920,
+ /* d a */ 'g' _ 'g' _ 'e' _ 'r' _ ';', 5, 0,
+ 0x2020 _ 0)
+NAMED_CHARACTER_REFERENCE(921,
+ /* d a */ 'l' _ 'e' _ 't' _ 'h' _ ';', 5, 0,
+ 0x2138 _ 0)
+NAMED_CHARACTER_REFERENCE(922, /* d a */ 'r' _ 'r' _ ';', 3, 0, 0x2193 _ 0)
+NAMED_CHARACTER_REFERENCE(923, /* d a */ 's' _ 'h' _ ';', 3, 0, 0x2010 _ 0)
+NAMED_CHARACTER_REFERENCE(924,
+ /* d a */ 's' _ 'h' _ 'v' _ ';', 4, 0, 0x22a3 _ 0)
+NAMED_CHARACTER_REFERENCE(925,
+ /* d b */ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x290f _ 0)
+NAMED_CHARACTER_REFERENCE(926,
+ /* d b */ 'l' _ 'a' _ 'c' _ ';', 4, 0, 0x02dd _ 0)
+NAMED_CHARACTER_REFERENCE(927,
+ /* d c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x010f _ 0)
+NAMED_CHARACTER_REFERENCE(928, /* d c */ 'y' _ ';', 2, 0, 0x0434 _ 0)
+NAMED_CHARACTER_REFERENCE(929, /* d d */ ';', 1, 0, 0x2146 _ 0)
+NAMED_CHARACTER_REFERENCE(930,
+ /* d d */ 'a' _ 'g' _ 'g' _ 'e' _ 'r' _ ';', 6, 0,
+ 0x2021 _ 0)
+NAMED_CHARACTER_REFERENCE(931,
+ /* d d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ca _ 0)
+NAMED_CHARACTER_REFERENCE(932,
+ /* d d */ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 6, 0,
+ 0x2a77 _ 0)
+NAMED_CHARACTER_REFERENCE(933, /* d e */ 'g', 1, 0, 0x00b0 _ 0)
+NAMED_CHARACTER_REFERENCE(934, /* d e */ 'g' _ ';', 2, 0, 0x00b0 _ 0)
+NAMED_CHARACTER_REFERENCE(935,
+ /* d e */ 'l' _ 't' _ 'a' _ ';', 4, 0, 0x03b4 _ 0)
+NAMED_CHARACTER_REFERENCE(936,
+ /* d e */ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 6, 0,
+ 0x29b1 _ 0)
+NAMED_CHARACTER_REFERENCE(937,
+ /* d f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0,
+ 0x297f _ 0)
+NAMED_CHARACTER_REFERENCE(938, /* d f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd21)
+NAMED_CHARACTER_REFERENCE(939,
+ /* d h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21c3 _ 0)
+NAMED_CHARACTER_REFERENCE(940,
+ /* d h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c2 _ 0)
+NAMED_CHARACTER_REFERENCE(941, /* d i */ 'a' _ 'm' _ ';', 3, 0, 0x22c4 _ 0)
+NAMED_CHARACTER_REFERENCE(942,
+ /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ ';', 6, 0,
+ 0x22c4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 943,
+ /* d i */ 'a' _ 'm' _ 'o' _ 'n' _ 'd' _ 's' _ 'u' _ 'i' _ 't' _ ';', 10, 0,
+ 0x2666 _ 0)
+NAMED_CHARACTER_REFERENCE(944,
+ /* d i */ 'a' _ 'm' _ 's' _ ';', 4, 0, 0x2666 _ 0)
+NAMED_CHARACTER_REFERENCE(945, /* d i */ 'e' _ ';', 2, 0, 0x00a8 _ 0)
+NAMED_CHARACTER_REFERENCE(946,
+ /* d i */ 'g' _ 'a' _ 'm' _ 'm' _ 'a' _ ';', 6, 0,
+ 0x03dd _ 0)
+NAMED_CHARACTER_REFERENCE(947,
+ /* d i */ 's' _ 'i' _ 'n' _ ';', 4, 0, 0x22f2 _ 0)
+NAMED_CHARACTER_REFERENCE(948, /* d i */ 'v' _ ';', 2, 0, 0x00f7 _ 0)
+NAMED_CHARACTER_REFERENCE(949,
+ /* d i */ 'v' _ 'i' _ 'd' _ 'e', 4, 0, 0x00f7 _ 0)
+NAMED_CHARACTER_REFERENCE(950,
+ /* d i */ 'v' _ 'i' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00f7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 951,
+ /* d i */
+ 'v' _ 'i' _ 'd' _ 'e' _ 'o' _ 'n' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 12,
+ 0, 0x22c7 _ 0)
+NAMED_CHARACTER_REFERENCE(952,
+ /* d i */ 'v' _ 'o' _ 'n' _ 'x' _ ';', 5, 0,
+ 0x22c7 _ 0)
+NAMED_CHARACTER_REFERENCE(953, /* d j */ 'c' _ 'y' _ ';', 3, 0, 0x0452 _ 0)
+NAMED_CHARACTER_REFERENCE(954,
+ /* d l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0,
+ 0x231e _ 0)
+NAMED_CHARACTER_REFERENCE(955,
+ /* d l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0,
+ 0x230d _ 0)
+NAMED_CHARACTER_REFERENCE(956,
+ /* d o */ 'l' _ 'l' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x0024 _ 0)
+NAMED_CHARACTER_REFERENCE(957, /* d o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd55)
+NAMED_CHARACTER_REFERENCE(958, /* d o */ 't' _ ';', 2, 0, 0x02d9 _ 0)
+NAMED_CHARACTER_REFERENCE(959,
+ /* d o */ 't' _ 'e' _ 'q' _ ';', 4, 0, 0x2250 _ 0)
+NAMED_CHARACTER_REFERENCE(960,
+ /* d o */ 't' _ 'e' _ 'q' _ 'd' _ 'o' _ 't' _ ';', 7,
+ 0, 0x2251 _ 0)
+NAMED_CHARACTER_REFERENCE(961,
+ /* d o */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7,
+ 0, 0x2238 _ 0)
+NAMED_CHARACTER_REFERENCE(962,
+ /* d o */ 't' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0,
+ 0x2214 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 963,
+ /* d o */ 't' _ 's' _ 'q' _ 'u' _ 'a' _ 'r' _ 'e' _ ';', 8, 0, 0x22a1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 964,
+ /* d o */
+ 'u' _ 'b' _ 'l' _ 'e' _ 'b' _ 'a' _ 'r' _ 'w' _ 'e' _ 'd' _ 'g' _ 'e' _ ';',
+ 13, 0, 0x2306 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 965,
+ /* d o */ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2193 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 966,
+ /* d o */
+ 'w' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';',
+ 13, 0, 0x21ca _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 967,
+ /* d o */
+ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';',
+ 14, 0, 0x21c3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 968,
+ /* d o */
+ 'w' _ 'n' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 15, 0, 0x21c2 _ 0)
+NAMED_CHARACTER_REFERENCE(969,
+ /* d r */ 'b' _ 'k' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7,
+ 0, 0x2910 _ 0)
+NAMED_CHARACTER_REFERENCE(970,
+ /* d r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0,
+ 0x231f _ 0)
+NAMED_CHARACTER_REFERENCE(971,
+ /* d r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0,
+ 0x230c _ 0)
+NAMED_CHARACTER_REFERENCE(972, /* d s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcb9)
+NAMED_CHARACTER_REFERENCE(973, /* d s */ 'c' _ 'y' _ ';', 3, 0, 0x0455 _ 0)
+NAMED_CHARACTER_REFERENCE(974, /* d s */ 'o' _ 'l' _ ';', 3, 0, 0x29f6 _ 0)
+NAMED_CHARACTER_REFERENCE(975,
+ /* d s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0111 _ 0)
+NAMED_CHARACTER_REFERENCE(976,
+ /* d t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f1 _ 0)
+NAMED_CHARACTER_REFERENCE(977, /* d t */ 'r' _ 'i' _ ';', 3, 0, 0x25bf _ 0)
+NAMED_CHARACTER_REFERENCE(978,
+ /* d t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25be _ 0)
+NAMED_CHARACTER_REFERENCE(979,
+ /* d u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21f5 _ 0)
+NAMED_CHARACTER_REFERENCE(980,
+ /* d u */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296f _ 0)
+NAMED_CHARACTER_REFERENCE(981,
+ /* d w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0,
+ 0x29a6 _ 0)
+NAMED_CHARACTER_REFERENCE(982, /* d z */ 'c' _ 'y' _ ';', 3, 0, 0x045f _ 0)
+NAMED_CHARACTER_REFERENCE(983,
+ /* d z */ 'i' _ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 7,
+ 0, 0x27ff _ 0)
+NAMED_CHARACTER_REFERENCE(984,
+ /* e D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2a77 _ 0)
+NAMED_CHARACTER_REFERENCE(985, /* e D */ 'o' _ 't' _ ';', 3, 0, 0x2251 _ 0)
+NAMED_CHARACTER_REFERENCE(986,
+ /* e a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00e9 _ 0)
+NAMED_CHARACTER_REFERENCE(987,
+ /* e a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00e9 _ 0)
+NAMED_CHARACTER_REFERENCE(988,
+ /* e a */ 's' _ 't' _ 'e' _ 'r' _ ';', 5, 0,
+ 0x2a6e _ 0)
+NAMED_CHARACTER_REFERENCE(989,
+ /* e c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x011b _ 0)
+NAMED_CHARACTER_REFERENCE(990, /* e c */ 'i' _ 'r' _ ';', 3, 0, 0x2256 _ 0)
+NAMED_CHARACTER_REFERENCE(991, /* e c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ea _ 0)
+NAMED_CHARACTER_REFERENCE(992,
+ /* e c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ea _ 0)
+NAMED_CHARACTER_REFERENCE(993,
+ /* e c */ 'o' _ 'l' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x2255 _ 0)
+NAMED_CHARACTER_REFERENCE(994, /* e c */ 'y' _ ';', 2, 0, 0x044d _ 0)
+NAMED_CHARACTER_REFERENCE(995, /* e d */ 'o' _ 't' _ ';', 3, 0, 0x0117 _ 0)
+NAMED_CHARACTER_REFERENCE(996, /* e e */ ';', 1, 0, 0x2147 _ 0)
+NAMED_CHARACTER_REFERENCE(997,
+ /* e f */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2252 _ 0)
+NAMED_CHARACTER_REFERENCE(998, /* e f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd22)
+NAMED_CHARACTER_REFERENCE(999, /* e g */ ';', 1, 0, 0x2a9a _ 0)
+NAMED_CHARACTER_REFERENCE(1000,
+ /* e g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00e8 _ 0)
+NAMED_CHARACTER_REFERENCE(1001,
+ /* e g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00e8 _ 0)
+NAMED_CHARACTER_REFERENCE(1002, /* e g */ 's' _ ';', 2, 0, 0x2a96 _ 0)
+NAMED_CHARACTER_REFERENCE(1003,
+ /* e g */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2a98 _ 0)
+NAMED_CHARACTER_REFERENCE(1004, /* e l */ ';', 1, 0, 0x2a99 _ 0)
+NAMED_CHARACTER_REFERENCE(1005,
+ /* e l */ 'i' _ 'n' _ 't' _ 'e' _ 'r' _ 's' _ ';', 7,
+ 0, 0x23e7 _ 0)
+NAMED_CHARACTER_REFERENCE(1006, /* e l */ 'l' _ ';', 2, 0, 0x2113 _ 0)
+NAMED_CHARACTER_REFERENCE(1007, /* e l */ 's' _ ';', 2, 0, 0x2a95 _ 0)
+NAMED_CHARACTER_REFERENCE(1008,
+ /* e l */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2a97 _ 0)
+NAMED_CHARACTER_REFERENCE(1009,
+ /* e m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x0113 _ 0)
+NAMED_CHARACTER_REFERENCE(1010,
+ /* e m */ 'p' _ 't' _ 'y' _ ';', 4, 0, 0x2205 _ 0)
+NAMED_CHARACTER_REFERENCE(1011,
+ /* e m */ 'p' _ 't' _ 'y' _ 's' _ 'e' _ 't' _ ';', 7,
+ 0, 0x2205 _ 0)
+NAMED_CHARACTER_REFERENCE(1012,
+ /* e m */ 'p' _ 't' _ 'y' _ 'v' _ ';', 5, 0,
+ 0x2205 _ 0)
+NAMED_CHARACTER_REFERENCE(1013,
+ /* e m */ 's' _ 'p' _ '1' _ '3' _ ';', 5, 0,
+ 0x2004 _ 0)
+NAMED_CHARACTER_REFERENCE(1014,
+ /* e m */ 's' _ 'p' _ '1' _ '4' _ ';', 5, 0,
+ 0x2005 _ 0)
+NAMED_CHARACTER_REFERENCE(1015, /* e m */ 's' _ 'p' _ ';', 3, 0, 0x2003 _ 0)
+NAMED_CHARACTER_REFERENCE(1016, /* e n */ 'g' _ ';', 2, 0, 0x014b _ 0)
+NAMED_CHARACTER_REFERENCE(1017, /* e n */ 's' _ 'p' _ ';', 3, 0, 0x2002 _ 0)
+NAMED_CHARACTER_REFERENCE(1018,
+ /* e o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0119 _ 0)
+NAMED_CHARACTER_REFERENCE(1019,
+ /* e o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd56)
+NAMED_CHARACTER_REFERENCE(1020, /* e p */ 'a' _ 'r' _ ';', 3, 0, 0x22d5 _ 0)
+NAMED_CHARACTER_REFERENCE(1021,
+ /* e p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0,
+ 0x29e3 _ 0)
+NAMED_CHARACTER_REFERENCE(1022,
+ /* e p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2a71 _ 0)
+NAMED_CHARACTER_REFERENCE(1023, /* e p */ 's' _ 'i' _ ';', 3, 0, 0x03b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1024,
+ /* e p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x03b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1025,
+ /* e p */ 's' _ 'i' _ 'v' _ ';', 4, 0, 0x03f5 _ 0)
+NAMED_CHARACTER_REFERENCE(1026,
+ /* e q */ 'c' _ 'i' _ 'r' _ 'c' _ ';', 5, 0,
+ 0x2256 _ 0)
+NAMED_CHARACTER_REFERENCE(1027,
+ /* e q */ 'c' _ 'o' _ 'l' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x2255 _ 0)
+NAMED_CHARACTER_REFERENCE(1028,
+ /* e q */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2242 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1029,
+ /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'g' _ 't' _ 'r' _ ';', 9, 0,
+ 0x2a96 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1030,
+ /* e q */ 's' _ 'l' _ 'a' _ 'n' _ 't' _ 'l' _ 'e' _ 's' _ 's' _ ';', 10, 0,
+ 0x2a95 _ 0)
+NAMED_CHARACTER_REFERENCE(1031,
+ /* e q */ 'u' _ 'a' _ 'l' _ 's' _ ';', 5, 0,
+ 0x003d _ 0)
+NAMED_CHARACTER_REFERENCE(1032,
+ /* e q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0,
+ 0x225f _ 0)
+NAMED_CHARACTER_REFERENCE(1033,
+ /* e q */ 'u' _ 'i' _ 'v' _ ';', 4, 0, 0x2261 _ 0)
+NAMED_CHARACTER_REFERENCE(1034,
+ /* e q */ 'u' _ 'i' _ 'v' _ 'D' _ 'D' _ ';', 6, 0,
+ 0x2a78 _ 0)
+NAMED_CHARACTER_REFERENCE(1035,
+ /* e q */ 'v' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7,
+ 0, 0x29e5 _ 0)
+NAMED_CHARACTER_REFERENCE(1036,
+ /* e r */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x2253 _ 0)
+NAMED_CHARACTER_REFERENCE(1037,
+ /* e r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2971 _ 0)
+NAMED_CHARACTER_REFERENCE(1038, /* e s */ 'c' _ 'r' _ ';', 3, 0, 0x212f _ 0)
+NAMED_CHARACTER_REFERENCE(1039,
+ /* e s */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2250 _ 0)
+NAMED_CHARACTER_REFERENCE(1040, /* e s */ 'i' _ 'm' _ ';', 3, 0, 0x2242 _ 0)
+NAMED_CHARACTER_REFERENCE(1041, /* e t */ 'a' _ ';', 2, 0, 0x03b7 _ 0)
+NAMED_CHARACTER_REFERENCE(1042, /* e t */ 'h', 1, 0, 0x00f0 _ 0)
+NAMED_CHARACTER_REFERENCE(1043, /* e t */ 'h' _ ';', 2, 0, 0x00f0 _ 0)
+NAMED_CHARACTER_REFERENCE(1044, /* e u */ 'm' _ 'l', 2, 0, 0x00eb _ 0)
+NAMED_CHARACTER_REFERENCE(1045, /* e u */ 'm' _ 'l' _ ';', 3, 0, 0x00eb _ 0)
+NAMED_CHARACTER_REFERENCE(1046, /* e u */ 'r' _ 'o' _ ';', 3, 0, 0x20ac _ 0)
+NAMED_CHARACTER_REFERENCE(1047, /* e x */ 'c' _ 'l' _ ';', 3, 0, 0x0021 _ 0)
+NAMED_CHARACTER_REFERENCE(1048,
+ /* e x */ 'i' _ 's' _ 't' _ ';', 4, 0, 0x2203 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1049,
+ /* e x */ 'p' _ 'e' _ 'c' _ 't' _ 'a' _ 't' _ 'i' _ 'o' _ 'n' _ ';', 10, 0,
+ 0x2130 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1050,
+ /* e x */ 'p' _ 'o' _ 'n' _ 'e' _ 'n' _ 't' _ 'i' _ 'a' _ 'l' _ 'e' _ ';',
+ 11, 0, 0x2147 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1051,
+ /* f a */
+ 'l' _ 'l' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';', 12,
+ 0, 0x2252 _ 0)
+NAMED_CHARACTER_REFERENCE(1052, /* f c */ 'y' _ ';', 2, 0, 0x0444 _ 0)
+NAMED_CHARACTER_REFERENCE(1053,
+ /* f e */ 'm' _ 'a' _ 'l' _ 'e' _ ';', 5, 0,
+ 0x2640 _ 0)
+NAMED_CHARACTER_REFERENCE(1054,
+ /* f f */ 'i' _ 'l' _ 'i' _ 'g' _ ';', 5, 0,
+ 0xfb03 _ 0)
+NAMED_CHARACTER_REFERENCE(1055,
+ /* f f */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb00 _ 0)
+NAMED_CHARACTER_REFERENCE(1056,
+ /* f f */ 'l' _ 'l' _ 'i' _ 'g' _ ';', 5, 0,
+ 0xfb04 _ 0)
+NAMED_CHARACTER_REFERENCE(1057, /* f f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd23)
+NAMED_CHARACTER_REFERENCE(1058,
+ /* f i */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb01 _ 0)
+NAMED_CHARACTER_REFERENCE(1059,
+ /* f j */ 'l' _ 'i' _ 'g' _ ';', 4, 0,
+ 0x0066 _ 0x006a)
+NAMED_CHARACTER_REFERENCE(1060, /* f l */ 'a' _ 't' _ ';', 3, 0, 0x266d _ 0)
+NAMED_CHARACTER_REFERENCE(1061,
+ /* f l */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0xfb02 _ 0)
+NAMED_CHARACTER_REFERENCE(1062,
+ /* f l */ 't' _ 'n' _ 's' _ ';', 4, 0, 0x25b1 _ 0)
+NAMED_CHARACTER_REFERENCE(1063, /* f n */ 'o' _ 'f' _ ';', 3, 0, 0x0192 _ 0)
+NAMED_CHARACTER_REFERENCE(1064,
+ /* f o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd57)
+NAMED_CHARACTER_REFERENCE(1065,
+ /* f o */ 'r' _ 'a' _ 'l' _ 'l' _ ';', 5, 0,
+ 0x2200 _ 0)
+NAMED_CHARACTER_REFERENCE(1066, /* f o */ 'r' _ 'k' _ ';', 3, 0, 0x22d4 _ 0)
+NAMED_CHARACTER_REFERENCE(1067,
+ /* f o */ 'r' _ 'k' _ 'v' _ ';', 4, 0, 0x2ad9 _ 0)
+NAMED_CHARACTER_REFERENCE(1068,
+ /* f p */ 'a' _ 'r' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a0d _ 0)
+NAMED_CHARACTER_REFERENCE(1069,
+ /* f r */ 'a' _ 'c' _ '1' _ '2', 4, 0, 0x00bd _ 0)
+NAMED_CHARACTER_REFERENCE(1070,
+ /* f r */ 'a' _ 'c' _ '1' _ '2' _ ';', 5, 0,
+ 0x00bd _ 0)
+NAMED_CHARACTER_REFERENCE(1071,
+ /* f r */ 'a' _ 'c' _ '1' _ '3' _ ';', 5, 0,
+ 0x2153 _ 0)
+NAMED_CHARACTER_REFERENCE(1072,
+ /* f r */ 'a' _ 'c' _ '1' _ '4', 4, 0, 0x00bc _ 0)
+NAMED_CHARACTER_REFERENCE(1073,
+ /* f r */ 'a' _ 'c' _ '1' _ '4' _ ';', 5, 0,
+ 0x00bc _ 0)
+NAMED_CHARACTER_REFERENCE(1074,
+ /* f r */ 'a' _ 'c' _ '1' _ '5' _ ';', 5, 0,
+ 0x2155 _ 0)
+NAMED_CHARACTER_REFERENCE(1075,
+ /* f r */ 'a' _ 'c' _ '1' _ '6' _ ';', 5, 0,
+ 0x2159 _ 0)
+NAMED_CHARACTER_REFERENCE(1076,
+ /* f r */ 'a' _ 'c' _ '1' _ '8' _ ';', 5, 0,
+ 0x215b _ 0)
+NAMED_CHARACTER_REFERENCE(1077,
+ /* f r */ 'a' _ 'c' _ '2' _ '3' _ ';', 5, 0,
+ 0x2154 _ 0)
+NAMED_CHARACTER_REFERENCE(1078,
+ /* f r */ 'a' _ 'c' _ '2' _ '5' _ ';', 5, 0,
+ 0x2156 _ 0)
+NAMED_CHARACTER_REFERENCE(1079,
+ /* f r */ 'a' _ 'c' _ '3' _ '4', 4, 0, 0x00be _ 0)
+NAMED_CHARACTER_REFERENCE(1080,
+ /* f r */ 'a' _ 'c' _ '3' _ '4' _ ';', 5, 0,
+ 0x00be _ 0)
+NAMED_CHARACTER_REFERENCE(1081,
+ /* f r */ 'a' _ 'c' _ '3' _ '5' _ ';', 5, 0,
+ 0x2157 _ 0)
+NAMED_CHARACTER_REFERENCE(1082,
+ /* f r */ 'a' _ 'c' _ '3' _ '8' _ ';', 5, 0,
+ 0x215c _ 0)
+NAMED_CHARACTER_REFERENCE(1083,
+ /* f r */ 'a' _ 'c' _ '4' _ '5' _ ';', 5, 0,
+ 0x2158 _ 0)
+NAMED_CHARACTER_REFERENCE(1084,
+ /* f r */ 'a' _ 'c' _ '5' _ '6' _ ';', 5, 0,
+ 0x215a _ 0)
+NAMED_CHARACTER_REFERENCE(1085,
+ /* f r */ 'a' _ 'c' _ '5' _ '8' _ ';', 5, 0,
+ 0x215d _ 0)
+NAMED_CHARACTER_REFERENCE(1086,
+ /* f r */ 'a' _ 'c' _ '7' _ '8' _ ';', 5, 0,
+ 0x215e _ 0)
+NAMED_CHARACTER_REFERENCE(1087,
+ /* f r */ 'a' _ 's' _ 'l' _ ';', 4, 0, 0x2044 _ 0)
+NAMED_CHARACTER_REFERENCE(1088,
+ /* f r */ 'o' _ 'w' _ 'n' _ ';', 4, 0, 0x2322 _ 0)
+NAMED_CHARACTER_REFERENCE(1089,
+ /* f s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbb)
+NAMED_CHARACTER_REFERENCE(1090, /* g E */ ';', 1, 0, 0x2267 _ 0)
+NAMED_CHARACTER_REFERENCE(1091, /* g E */ 'l' _ ';', 2, 0, 0x2a8c _ 0)
+NAMED_CHARACTER_REFERENCE(1092,
+ /* g a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x01f5 _ 0)
+NAMED_CHARACTER_REFERENCE(1093,
+ /* g a */ 'm' _ 'm' _ 'a' _ ';', 4, 0, 0x03b3 _ 0)
+NAMED_CHARACTER_REFERENCE(1094,
+ /* g a */ 'm' _ 'm' _ 'a' _ 'd' _ ';', 5, 0,
+ 0x03dd _ 0)
+NAMED_CHARACTER_REFERENCE(1095, /* g a */ 'p' _ ';', 2, 0, 0x2a86 _ 0)
+NAMED_CHARACTER_REFERENCE(1096,
+ /* g b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x011f _ 0)
+NAMED_CHARACTER_REFERENCE(1097,
+ /* g c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x011d _ 0)
+NAMED_CHARACTER_REFERENCE(1098, /* g c */ 'y' _ ';', 2, 0, 0x0433 _ 0)
+NAMED_CHARACTER_REFERENCE(1099, /* g d */ 'o' _ 't' _ ';', 3, 0, 0x0121 _ 0)
+NAMED_CHARACTER_REFERENCE(1100, /* g e */ ';', 1, 0, 0x2265 _ 0)
+NAMED_CHARACTER_REFERENCE(1101, /* g e */ 'l' _ ';', 2, 0, 0x22db _ 0)
+NAMED_CHARACTER_REFERENCE(1102, /* g e */ 'q' _ ';', 2, 0, 0x2265 _ 0)
+NAMED_CHARACTER_REFERENCE(1103, /* g e */ 'q' _ 'q' _ ';', 3, 0, 0x2267 _ 0)
+NAMED_CHARACTER_REFERENCE(1104,
+ /* g e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a7e _ 0)
+NAMED_CHARACTER_REFERENCE(1105, /* g e */ 's' _ ';', 2, 0, 0x2a7e _ 0)
+NAMED_CHARACTER_REFERENCE(1106,
+ /* g e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa9 _ 0)
+NAMED_CHARACTER_REFERENCE(1107,
+ /* g e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2a80 _ 0)
+NAMED_CHARACTER_REFERENCE(1108,
+ /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0,
+ 0x2a82 _ 0)
+NAMED_CHARACTER_REFERENCE(1109,
+ /* g e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'l' _ ';', 7,
+ 0, 0x2a84 _ 0)
+NAMED_CHARACTER_REFERENCE(1110,
+ /* g e */ 's' _ 'l' _ ';', 3, 0, 0x22db _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1111,
+ /* g e */ 's' _ 'l' _ 'e' _ 's' _ ';', 5, 0,
+ 0x2a94 _ 0)
+NAMED_CHARACTER_REFERENCE(1112, /* g f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd24)
+NAMED_CHARACTER_REFERENCE(1113, /* g g */ ';', 1, 0, 0x226b _ 0)
+NAMED_CHARACTER_REFERENCE(1114, /* g g */ 'g' _ ';', 2, 0, 0x22d9 _ 0)
+NAMED_CHARACTER_REFERENCE(1115,
+ /* g i */ 'm' _ 'e' _ 'l' _ ';', 4, 0, 0x2137 _ 0)
+NAMED_CHARACTER_REFERENCE(1116, /* g j */ 'c' _ 'y' _ ';', 3, 0, 0x0453 _ 0)
+NAMED_CHARACTER_REFERENCE(1117, /* g l */ ';', 1, 0, 0x2277 _ 0)
+NAMED_CHARACTER_REFERENCE(1118, /* g l */ 'E' _ ';', 2, 0, 0x2a92 _ 0)
+NAMED_CHARACTER_REFERENCE(1119, /* g l */ 'a' _ ';', 2, 0, 0x2aa5 _ 0)
+NAMED_CHARACTER_REFERENCE(1120, /* g l */ 'j' _ ';', 2, 0, 0x2aa4 _ 0)
+NAMED_CHARACTER_REFERENCE(1121, /* g n */ 'E' _ ';', 2, 0, 0x2269 _ 0)
+NAMED_CHARACTER_REFERENCE(1122, /* g n */ 'a' _ 'p' _ ';', 3, 0, 0x2a8a _ 0)
+NAMED_CHARACTER_REFERENCE(1123,
+ /* g n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7,
+ 0, 0x2a8a _ 0)
+NAMED_CHARACTER_REFERENCE(1124, /* g n */ 'e' _ ';', 2, 0, 0x2a88 _ 0)
+NAMED_CHARACTER_REFERENCE(1125, /* g n */ 'e' _ 'q' _ ';', 3, 0, 0x2a88 _ 0)
+NAMED_CHARACTER_REFERENCE(1126,
+ /* g n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2269 _ 0)
+NAMED_CHARACTER_REFERENCE(1127,
+ /* g n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e7 _ 0)
+NAMED_CHARACTER_REFERENCE(1128,
+ /* g o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd58)
+NAMED_CHARACTER_REFERENCE(1129,
+ /* g r */ 'a' _ 'v' _ 'e' _ ';', 4, 0, 0x0060 _ 0)
+NAMED_CHARACTER_REFERENCE(1130, /* g s */ 'c' _ 'r' _ ';', 3, 0, 0x210a _ 0)
+NAMED_CHARACTER_REFERENCE(1131, /* g s */ 'i' _ 'm' _ ';', 3, 0, 0x2273 _ 0)
+NAMED_CHARACTER_REFERENCE(1132,
+ /* g s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8e _ 0)
+NAMED_CHARACTER_REFERENCE(1133,
+ /* g s */ 'i' _ 'm' _ 'l' _ ';', 4, 0, 0x2a90 _ 0)
+NAMED_CHARACTER_REFERENCE(1134, /* g t */ 0, 0, 1, 0x003e _ 0)
+NAMED_CHARACTER_REFERENCE(1135, /* g t */ ';', 1, 0, 0x003e _ 0)
+NAMED_CHARACTER_REFERENCE(1136, /* g t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa7 _ 0)
+NAMED_CHARACTER_REFERENCE(1137,
+ /* g t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a7a _ 0)
+NAMED_CHARACTER_REFERENCE(1138,
+ /* g t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d7 _ 0)
+NAMED_CHARACTER_REFERENCE(1139,
+ /* g t */ 'l' _ 'P' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2995 _ 0)
+NAMED_CHARACTER_REFERENCE(1140,
+ /* g t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0,
+ 0x2a7c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1141,
+ /* g t */ 'r' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 8, 0, 0x2a86 _ 0)
+NAMED_CHARACTER_REFERENCE(1142,
+ /* g t */ 'r' _ 'a' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x2978 _ 0)
+NAMED_CHARACTER_REFERENCE(1143,
+ /* g t */ 'r' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x22d7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1144,
+ /* g t */ 'r' _ 'e' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 8, 0, 0x22db _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1145,
+ /* g t */ 'r' _ 'e' _ 'q' _ 'q' _ 'l' _ 'e' _ 's' _ 's' _ ';', 9, 0,
+ 0x2a8c _ 0)
+NAMED_CHARACTER_REFERENCE(1146,
+ /* g t */ 'r' _ 'l' _ 'e' _ 's' _ 's' _ ';', 6, 0,
+ 0x2277 _ 0)
+NAMED_CHARACTER_REFERENCE(1147,
+ /* g t */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x2273 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1148,
+ /* g v */ 'e' _ 'r' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 8, 0,
+ 0x2269 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1149,
+ /* g v */ 'n' _ 'E' _ ';', 3, 0, 0x2269 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1150, /* h A */ 'r' _ 'r' _ ';', 3, 0, 0x21d4 _ 0)
+NAMED_CHARACTER_REFERENCE(1151,
+ /* h a */ 'i' _ 'r' _ 's' _ 'p' _ ';', 5, 0,
+ 0x200a _ 0)
+NAMED_CHARACTER_REFERENCE(1152, /* h a */ 'l' _ 'f' _ ';', 3, 0, 0x00bd _ 0)
+NAMED_CHARACTER_REFERENCE(1153,
+ /* h a */ 'm' _ 'i' _ 'l' _ 't' _ ';', 5, 0,
+ 0x210b _ 0)
+NAMED_CHARACTER_REFERENCE(1154,
+ /* h a */ 'r' _ 'd' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x044a _ 0)
+NAMED_CHARACTER_REFERENCE(1155, /* h a */ 'r' _ 'r' _ ';', 3, 0, 0x2194 _ 0)
+NAMED_CHARACTER_REFERENCE(1156,
+ /* h a */ 'r' _ 'r' _ 'c' _ 'i' _ 'r' _ ';', 6, 0,
+ 0x2948 _ 0)
+NAMED_CHARACTER_REFERENCE(1157,
+ /* h a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x21ad _ 0)
+NAMED_CHARACTER_REFERENCE(1158, /* h b */ 'a' _ 'r' _ ';', 3, 0, 0x210f _ 0)
+NAMED_CHARACTER_REFERENCE(1159,
+ /* h c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0125 _ 0)
+NAMED_CHARACTER_REFERENCE(1160,
+ /* h e */ 'a' _ 'r' _ 't' _ 's' _ ';', 5, 0,
+ 0x2665 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1161,
+ /* h e */ 'a' _ 'r' _ 't' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2665 _ 0)
+NAMED_CHARACTER_REFERENCE(1162,
+ /* h e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0,
+ 0x2026 _ 0)
+NAMED_CHARACTER_REFERENCE(1163,
+ /* h e */ 'r' _ 'c' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x22b9 _ 0)
+NAMED_CHARACTER_REFERENCE(1164, /* h f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd25)
+NAMED_CHARACTER_REFERENCE(1165,
+ /* h k */ 's' _ 'e' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7,
+ 0, 0x2925 _ 0)
+NAMED_CHARACTER_REFERENCE(1166,
+ /* h k */ 's' _ 'w' _ 'a' _ 'r' _ 'o' _ 'w' _ ';', 7,
+ 0, 0x2926 _ 0)
+NAMED_CHARACTER_REFERENCE(1167,
+ /* h o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ff _ 0)
+NAMED_CHARACTER_REFERENCE(1168,
+ /* h o */ 'm' _ 't' _ 'h' _ 't' _ ';', 5, 0,
+ 0x223b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1169,
+ /* h o */
+ 'o' _ 'k' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12,
+ 0, 0x21a9 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1170,
+ /* h o */
+ 'o' _ 'k' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x21aa _ 0)
+NAMED_CHARACTER_REFERENCE(1171,
+ /* h o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd59)
+NAMED_CHARACTER_REFERENCE(1172,
+ /* h o */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2015 _ 0)
+NAMED_CHARACTER_REFERENCE(1173,
+ /* h s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbd)
+NAMED_CHARACTER_REFERENCE(1174,
+ /* h s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x210f _ 0)
+NAMED_CHARACTER_REFERENCE(1175,
+ /* h s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0127 _ 0)
+NAMED_CHARACTER_REFERENCE(1176,
+ /* h y */ 'b' _ 'u' _ 'l' _ 'l' _ ';', 5, 0,
+ 0x2043 _ 0)
+NAMED_CHARACTER_REFERENCE(1177,
+ /* h y */ 'p' _ 'h' _ 'e' _ 'n' _ ';', 5, 0,
+ 0x2010 _ 0)
+NAMED_CHARACTER_REFERENCE(1178,
+ /* i a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00ed _ 0)
+NAMED_CHARACTER_REFERENCE(1179,
+ /* i a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00ed _ 0)
+NAMED_CHARACTER_REFERENCE(1180, /* i c */ ';', 1, 0, 0x2063 _ 0)
+NAMED_CHARACTER_REFERENCE(1181, /* i c */ 'i' _ 'r' _ 'c', 3, 0, 0x00ee _ 0)
+NAMED_CHARACTER_REFERENCE(1182,
+ /* i c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00ee _ 0)
+NAMED_CHARACTER_REFERENCE(1183, /* i c */ 'y' _ ';', 2, 0, 0x0438 _ 0)
+NAMED_CHARACTER_REFERENCE(1184, /* i e */ 'c' _ 'y' _ ';', 3, 0, 0x0435 _ 0)
+NAMED_CHARACTER_REFERENCE(1185, /* i e */ 'x' _ 'c' _ 'l', 3, 0, 0x00a1 _ 0)
+NAMED_CHARACTER_REFERENCE(1186,
+ /* i e */ 'x' _ 'c' _ 'l' _ ';', 4, 0, 0x00a1 _ 0)
+NAMED_CHARACTER_REFERENCE(1187, /* i f */ 'f' _ ';', 2, 0, 0x21d4 _ 0)
+NAMED_CHARACTER_REFERENCE(1188, /* i f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd26)
+NAMED_CHARACTER_REFERENCE(1189,
+ /* i g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00ec _ 0)
+NAMED_CHARACTER_REFERENCE(1190,
+ /* i g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00ec _ 0)
+NAMED_CHARACTER_REFERENCE(1191, /* i i */ ';', 1, 0, 0x2148 _ 0)
+NAMED_CHARACTER_REFERENCE(1192,
+ /* i i */ 'i' _ 'i' _ 'n' _ 't' _ ';', 5, 0,
+ 0x2a0c _ 0)
+NAMED_CHARACTER_REFERENCE(1193,
+ /* i i */ 'i' _ 'n' _ 't' _ ';', 4, 0, 0x222d _ 0)
+NAMED_CHARACTER_REFERENCE(1194,
+ /* i i */ 'n' _ 'f' _ 'i' _ 'n' _ ';', 5, 0,
+ 0x29dc _ 0)
+NAMED_CHARACTER_REFERENCE(1195,
+ /* i i */ 'o' _ 't' _ 'a' _ ';', 4, 0, 0x2129 _ 0)
+NAMED_CHARACTER_REFERENCE(1196,
+ /* i j */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0133 _ 0)
+NAMED_CHARACTER_REFERENCE(1197,
+ /* i m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x012b _ 0)
+NAMED_CHARACTER_REFERENCE(1198,
+ /* i m */ 'a' _ 'g' _ 'e' _ ';', 4, 0, 0x2111 _ 0)
+NAMED_CHARACTER_REFERENCE(1199,
+ /* i m */ 'a' _ 'g' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7,
+ 0, 0x2110 _ 0)
+NAMED_CHARACTER_REFERENCE(1200,
+ /* i m */ 'a' _ 'g' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7,
+ 0, 0x2111 _ 0)
+NAMED_CHARACTER_REFERENCE(1201,
+ /* i m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0131 _ 0)
+NAMED_CHARACTER_REFERENCE(1202, /* i m */ 'o' _ 'f' _ ';', 3, 0, 0x22b7 _ 0)
+NAMED_CHARACTER_REFERENCE(1203,
+ /* i m */ 'p' _ 'e' _ 'd' _ ';', 4, 0, 0x01b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1204, /* i n */ ';', 1, 0, 0x2208 _ 0)
+NAMED_CHARACTER_REFERENCE(1205,
+ /* i n */ 'c' _ 'a' _ 'r' _ 'e' _ ';', 5, 0,
+ 0x2105 _ 0)
+NAMED_CHARACTER_REFERENCE(1206,
+ /* i n */ 'f' _ 'i' _ 'n' _ ';', 4, 0, 0x221e _ 0)
+NAMED_CHARACTER_REFERENCE(1207,
+ /* i n */ 'f' _ 'i' _ 'n' _ 't' _ 'i' _ 'e' _ ';', 7,
+ 0, 0x29dd _ 0)
+NAMED_CHARACTER_REFERENCE(1208,
+ /* i n */ 'o' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x0131 _ 0)
+NAMED_CHARACTER_REFERENCE(1209, /* i n */ 't' _ ';', 2, 0, 0x222b _ 0)
+NAMED_CHARACTER_REFERENCE(1210,
+ /* i n */ 't' _ 'c' _ 'a' _ 'l' _ ';', 5, 0,
+ 0x22ba _ 0)
+NAMED_CHARACTER_REFERENCE(1211,
+ /* i n */ 't' _ 'e' _ 'g' _ 'e' _ 'r' _ 's' _ ';', 7,
+ 0, 0x2124 _ 0)
+NAMED_CHARACTER_REFERENCE(1212,
+ /* i n */ 't' _ 'e' _ 'r' _ 'c' _ 'a' _ 'l' _ ';', 7,
+ 0, 0x22ba _ 0)
+NAMED_CHARACTER_REFERENCE(1213,
+ /* i n */ 't' _ 'l' _ 'a' _ 'r' _ 'h' _ 'k' _ ';', 7,
+ 0, 0x2a17 _ 0)
+NAMED_CHARACTER_REFERENCE(1214,
+ /* i n */ 't' _ 'p' _ 'r' _ 'o' _ 'd' _ ';', 6, 0,
+ 0x2a3c _ 0)
+NAMED_CHARACTER_REFERENCE(1215, /* i o */ 'c' _ 'y' _ ';', 3, 0, 0x0451 _ 0)
+NAMED_CHARACTER_REFERENCE(1216,
+ /* i o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x012f _ 0)
+NAMED_CHARACTER_REFERENCE(1217,
+ /* i o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5a)
+NAMED_CHARACTER_REFERENCE(1218, /* i o */ 't' _ 'a' _ ';', 3, 0, 0x03b9 _ 0)
+NAMED_CHARACTER_REFERENCE(1219,
+ /* i p */ 'r' _ 'o' _ 'd' _ ';', 4, 0, 0x2a3c _ 0)
+NAMED_CHARACTER_REFERENCE(1220,
+ /* i q */ 'u' _ 'e' _ 's' _ 't', 4, 0, 0x00bf _ 0)
+NAMED_CHARACTER_REFERENCE(1221,
+ /* i q */ 'u' _ 'e' _ 's' _ 't' _ ';', 5, 0,
+ 0x00bf _ 0)
+NAMED_CHARACTER_REFERENCE(1222,
+ /* i s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbe)
+NAMED_CHARACTER_REFERENCE(1223, /* i s */ 'i' _ 'n' _ ';', 3, 0, 0x2208 _ 0)
+NAMED_CHARACTER_REFERENCE(1224,
+ /* i s */ 'i' _ 'n' _ 'E' _ ';', 4, 0, 0x22f9 _ 0)
+NAMED_CHARACTER_REFERENCE(1225,
+ /* i s */ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 6, 0,
+ 0x22f5 _ 0)
+NAMED_CHARACTER_REFERENCE(1226,
+ /* i s */ 'i' _ 'n' _ 's' _ ';', 4, 0, 0x22f4 _ 0)
+NAMED_CHARACTER_REFERENCE(1227,
+ /* i s */ 'i' _ 'n' _ 's' _ 'v' _ ';', 5, 0,
+ 0x22f3 _ 0)
+NAMED_CHARACTER_REFERENCE(1228,
+ /* i s */ 'i' _ 'n' _ 'v' _ ';', 4, 0, 0x2208 _ 0)
+NAMED_CHARACTER_REFERENCE(1229, /* i t */ ';', 1, 0, 0x2062 _ 0)
+NAMED_CHARACTER_REFERENCE(1230,
+ /* i t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x0129 _ 0)
+NAMED_CHARACTER_REFERENCE(1231,
+ /* i u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0456 _ 0)
+NAMED_CHARACTER_REFERENCE(1232, /* i u */ 'm' _ 'l', 2, 0, 0x00ef _ 0)
+NAMED_CHARACTER_REFERENCE(1233, /* i u */ 'm' _ 'l' _ ';', 3, 0, 0x00ef _ 0)
+NAMED_CHARACTER_REFERENCE(1234,
+ /* j c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0135 _ 0)
+NAMED_CHARACTER_REFERENCE(1235, /* j c */ 'y' _ ';', 2, 0, 0x0439 _ 0)
+NAMED_CHARACTER_REFERENCE(1236, /* j f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd27)
+NAMED_CHARACTER_REFERENCE(1237,
+ /* j m */ 'a' _ 't' _ 'h' _ ';', 4, 0, 0x0237 _ 0)
+NAMED_CHARACTER_REFERENCE(1238,
+ /* j o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5b)
+NAMED_CHARACTER_REFERENCE(1239,
+ /* j s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcbf)
+NAMED_CHARACTER_REFERENCE(1240,
+ /* j s */ 'e' _ 'r' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x0458 _ 0)
+NAMED_CHARACTER_REFERENCE(1241,
+ /* j u */ 'k' _ 'c' _ 'y' _ ';', 4, 0, 0x0454 _ 0)
+NAMED_CHARACTER_REFERENCE(1242,
+ /* k a */ 'p' _ 'p' _ 'a' _ ';', 4, 0, 0x03ba _ 0)
+NAMED_CHARACTER_REFERENCE(1243,
+ /* k a */ 'p' _ 'p' _ 'a' _ 'v' _ ';', 5, 0,
+ 0x03f0 _ 0)
+NAMED_CHARACTER_REFERENCE(1244,
+ /* k c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0137 _ 0)
+NAMED_CHARACTER_REFERENCE(1245, /* k c */ 'y' _ ';', 2, 0, 0x043a _ 0)
+NAMED_CHARACTER_REFERENCE(1246, /* k f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd28)
+NAMED_CHARACTER_REFERENCE(1247,
+ /* k g */ 'r' _ 'e' _ 'e' _ 'n' _ ';', 5, 0,
+ 0x0138 _ 0)
+NAMED_CHARACTER_REFERENCE(1248, /* k h */ 'c' _ 'y' _ ';', 3, 0, 0x0445 _ 0)
+NAMED_CHARACTER_REFERENCE(1249, /* k j */ 'c' _ 'y' _ ';', 3, 0, 0x045c _ 0)
+NAMED_CHARACTER_REFERENCE(1250,
+ /* k o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5c)
+NAMED_CHARACTER_REFERENCE(1251,
+ /* k s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc0)
+NAMED_CHARACTER_REFERENCE(1252,
+ /* l A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21da _ 0)
+NAMED_CHARACTER_REFERENCE(1253, /* l A */ 'r' _ 'r' _ ';', 3, 0, 0x21d0 _ 0)
+NAMED_CHARACTER_REFERENCE(1254,
+ /* l A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x291b _ 0)
+NAMED_CHARACTER_REFERENCE(1255,
+ /* l B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290e _ 0)
+NAMED_CHARACTER_REFERENCE(1256, /* l E */ ';', 1, 0, 0x2266 _ 0)
+NAMED_CHARACTER_REFERENCE(1257, /* l E */ 'g' _ ';', 2, 0, 0x2a8b _ 0)
+NAMED_CHARACTER_REFERENCE(1258, /* l H */ 'a' _ 'r' _ ';', 3, 0, 0x2962 _ 0)
+NAMED_CHARACTER_REFERENCE(1259,
+ /* l a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x013a _ 0)
+NAMED_CHARACTER_REFERENCE(1260,
+ /* l a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7,
+ 0, 0x29b4 _ 0)
+NAMED_CHARACTER_REFERENCE(1261,
+ /* l a */ 'g' _ 'r' _ 'a' _ 'n' _ ';', 5, 0,
+ 0x2112 _ 0)
+NAMED_CHARACTER_REFERENCE(1262,
+ /* l a */ 'm' _ 'b' _ 'd' _ 'a' _ ';', 5, 0,
+ 0x03bb _ 0)
+NAMED_CHARACTER_REFERENCE(1263, /* l a */ 'n' _ 'g' _ ';', 3, 0, 0x27e8 _ 0)
+NAMED_CHARACTER_REFERENCE(1264,
+ /* l a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2991 _ 0)
+NAMED_CHARACTER_REFERENCE(1265,
+ /* l a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0,
+ 0x27e8 _ 0)
+NAMED_CHARACTER_REFERENCE(1266, /* l a */ 'p' _ ';', 2, 0, 0x2a85 _ 0)
+NAMED_CHARACTER_REFERENCE(1267, /* l a */ 'q' _ 'u' _ 'o', 3, 0, 0x00ab _ 0)
+NAMED_CHARACTER_REFERENCE(1268,
+ /* l a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00ab _ 0)
+NAMED_CHARACTER_REFERENCE(1269, /* l a */ 'r' _ 'r' _ ';', 3, 0, 0x2190 _ 0)
+NAMED_CHARACTER_REFERENCE(1270,
+ /* l a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e4 _ 0)
+NAMED_CHARACTER_REFERENCE(1271,
+ /* l a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0,
+ 0x291f _ 0)
+NAMED_CHARACTER_REFERENCE(1272,
+ /* l a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0,
+ 0x291d _ 0)
+NAMED_CHARACTER_REFERENCE(1273,
+ /* l a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0,
+ 0x21a9 _ 0)
+NAMED_CHARACTER_REFERENCE(1274,
+ /* l a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0,
+ 0x21ab _ 0)
+NAMED_CHARACTER_REFERENCE(1275,
+ /* l a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0,
+ 0x2939 _ 0)
+NAMED_CHARACTER_REFERENCE(1276,
+ /* l a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x2973 _ 0)
+NAMED_CHARACTER_REFERENCE(1277,
+ /* l a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0,
+ 0x21a2 _ 0)
+NAMED_CHARACTER_REFERENCE(1278, /* l a */ 't' _ ';', 2, 0, 0x2aab _ 0)
+NAMED_CHARACTER_REFERENCE(1279,
+ /* l a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x2919 _ 0)
+NAMED_CHARACTER_REFERENCE(1280, /* l a */ 't' _ 'e' _ ';', 3, 0, 0x2aad _ 0)
+NAMED_CHARACTER_REFERENCE(1281,
+ /* l a */ 't' _ 'e' _ 's' _ ';', 4, 0,
+ 0x2aad _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1282,
+ /* l b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290c _ 0)
+NAMED_CHARACTER_REFERENCE(1283,
+ /* l b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2772 _ 0)
+NAMED_CHARACTER_REFERENCE(1284,
+ /* l b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0,
+ 0x007b _ 0)
+NAMED_CHARACTER_REFERENCE(1285,
+ /* l b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0,
+ 0x005b _ 0)
+NAMED_CHARACTER_REFERENCE(1286,
+ /* l b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298b _ 0)
+NAMED_CHARACTER_REFERENCE(1287,
+ /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0,
+ 0x298f _ 0)
+NAMED_CHARACTER_REFERENCE(1288,
+ /* l b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0,
+ 0x298d _ 0)
+NAMED_CHARACTER_REFERENCE(1289,
+ /* l c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x013e _ 0)
+NAMED_CHARACTER_REFERENCE(1290,
+ /* l c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x013c _ 0)
+NAMED_CHARACTER_REFERENCE(1291,
+ /* l c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2308 _ 0)
+NAMED_CHARACTER_REFERENCE(1292, /* l c */ 'u' _ 'b' _ ';', 3, 0, 0x007b _ 0)
+NAMED_CHARACTER_REFERENCE(1293, /* l c */ 'y' _ ';', 2, 0, 0x043b _ 0)
+NAMED_CHARACTER_REFERENCE(1294, /* l d */ 'c' _ 'a' _ ';', 3, 0, 0x2936 _ 0)
+NAMED_CHARACTER_REFERENCE(1295,
+ /* l d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201c _ 0)
+NAMED_CHARACTER_REFERENCE(1296,
+ /* l d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0,
+ 0x201e _ 0)
+NAMED_CHARACTER_REFERENCE(1297,
+ /* l d */ 'r' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0,
+ 0x2967 _ 0)
+NAMED_CHARACTER_REFERENCE(1298,
+ /* l d */ 'r' _ 'u' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7,
+ 0, 0x294b _ 0)
+NAMED_CHARACTER_REFERENCE(1299, /* l d */ 's' _ 'h' _ ';', 3, 0, 0x21b2 _ 0)
+NAMED_CHARACTER_REFERENCE(1300, /* l e */ ';', 1, 0, 0x2264 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1301,
+ /* l e */ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 8, 0, 0x2190 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1302,
+ /* l e */
+ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';', 12,
+ 0, 0x21a2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1303,
+ /* l e */
+ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';',
+ 14, 0, 0x21bd _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1304,
+ /* l e */
+ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';', 12,
+ 0, 0x21bc _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1305,
+ /* l e */
+ 'f' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';',
+ 13, 0, 0x21c7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1306,
+ /* l e */
+ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x2194 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1307,
+ /* l e */
+ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';',
+ 14, 0, 0x21c6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1308,
+ /* l e */
+ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';',
+ 16, 0, 0x21cb _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1309,
+ /* l e */
+ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 18, 0, 0x21ad _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1310,
+ /* l e */
+ 'f' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';',
+ 13, 0, 0x22cb _ 0)
+NAMED_CHARACTER_REFERENCE(1311, /* l e */ 'g' _ ';', 2, 0, 0x22da _ 0)
+NAMED_CHARACTER_REFERENCE(1312, /* l e */ 'q' _ ';', 2, 0, 0x2264 _ 0)
+NAMED_CHARACTER_REFERENCE(1313, /* l e */ 'q' _ 'q' _ ';', 3, 0, 0x2266 _ 0)
+NAMED_CHARACTER_REFERENCE(1314,
+ /* l e */ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a7d _ 0)
+NAMED_CHARACTER_REFERENCE(1315, /* l e */ 's' _ ';', 2, 0, 0x2a7d _ 0)
+NAMED_CHARACTER_REFERENCE(1316,
+ /* l e */ 's' _ 'c' _ 'c' _ ';', 4, 0, 0x2aa8 _ 0)
+NAMED_CHARACTER_REFERENCE(1317,
+ /* l e */ 's' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2a7f _ 0)
+NAMED_CHARACTER_REFERENCE(1318,
+ /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ ';', 6, 0,
+ 0x2a81 _ 0)
+NAMED_CHARACTER_REFERENCE(1319,
+ /* l e */ 's' _ 'd' _ 'o' _ 't' _ 'o' _ 'r' _ ';', 7,
+ 0, 0x2a83 _ 0)
+NAMED_CHARACTER_REFERENCE(1320,
+ /* l e */ 's' _ 'g' _ ';', 3, 0, 0x22da _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1321,
+ /* l e */ 's' _ 'g' _ 'e' _ 's' _ ';', 5, 0,
+ 0x2a93 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1322,
+ /* l e */ 's' _ 's' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0,
+ 0x2a85 _ 0)
+NAMED_CHARACTER_REFERENCE(1323,
+ /* l e */ 's' _ 's' _ 'd' _ 'o' _ 't' _ ';', 6, 0,
+ 0x22d6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1324,
+ /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 8, 0, 0x22da _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1325,
+ /* l e */ 's' _ 's' _ 'e' _ 'q' _ 'q' _ 'g' _ 't' _ 'r' _ ';', 9, 0,
+ 0x2a8b _ 0)
+NAMED_CHARACTER_REFERENCE(1326,
+ /* l e */ 's' _ 's' _ 'g' _ 't' _ 'r' _ ';', 6, 0,
+ 0x2276 _ 0)
+NAMED_CHARACTER_REFERENCE(1327,
+ /* l e */ 's' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x2272 _ 0)
+NAMED_CHARACTER_REFERENCE(1328,
+ /* l f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0,
+ 0x297c _ 0)
+NAMED_CHARACTER_REFERENCE(1329,
+ /* l f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0,
+ 0x230a _ 0)
+NAMED_CHARACTER_REFERENCE(1330, /* l f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd29)
+NAMED_CHARACTER_REFERENCE(1331, /* l g */ ';', 1, 0, 0x2276 _ 0)
+NAMED_CHARACTER_REFERENCE(1332, /* l g */ 'E' _ ';', 2, 0, 0x2a91 _ 0)
+NAMED_CHARACTER_REFERENCE(1333,
+ /* l h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21bd _ 0)
+NAMED_CHARACTER_REFERENCE(1334,
+ /* l h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21bc _ 0)
+NAMED_CHARACTER_REFERENCE(1335,
+ /* l h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0,
+ 0x296a _ 0)
+NAMED_CHARACTER_REFERENCE(1336,
+ /* l h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2584 _ 0)
+NAMED_CHARACTER_REFERENCE(1337, /* l j */ 'c' _ 'y' _ ';', 3, 0, 0x0459 _ 0)
+NAMED_CHARACTER_REFERENCE(1338, /* l l */ ';', 1, 0, 0x226a _ 0)
+NAMED_CHARACTER_REFERENCE(1339,
+ /* l l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c7 _ 0)
+NAMED_CHARACTER_REFERENCE(1340,
+ /* l l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7,
+ 0, 0x231e _ 0)
+NAMED_CHARACTER_REFERENCE(1341,
+ /* l l */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0,
+ 0x296b _ 0)
+NAMED_CHARACTER_REFERENCE(1342,
+ /* l l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25fa _ 0)
+NAMED_CHARACTER_REFERENCE(1343,
+ /* l m */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x0140 _ 0)
+NAMED_CHARACTER_REFERENCE(1344,
+ /* l m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0,
+ 0x23b0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1345,
+ /* l m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0,
+ 0x23b0 _ 0)
+NAMED_CHARACTER_REFERENCE(1346, /* l n */ 'E' _ ';', 2, 0, 0x2268 _ 0)
+NAMED_CHARACTER_REFERENCE(1347, /* l n */ 'a' _ 'p' _ ';', 3, 0, 0x2a89 _ 0)
+NAMED_CHARACTER_REFERENCE(1348,
+ /* l n */ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 7,
+ 0, 0x2a89 _ 0)
+NAMED_CHARACTER_REFERENCE(1349, /* l n */ 'e' _ ';', 2, 0, 0x2a87 _ 0)
+NAMED_CHARACTER_REFERENCE(1350, /* l n */ 'e' _ 'q' _ ';', 3, 0, 0x2a87 _ 0)
+NAMED_CHARACTER_REFERENCE(1351,
+ /* l n */ 'e' _ 'q' _ 'q' _ ';', 4, 0, 0x2268 _ 0)
+NAMED_CHARACTER_REFERENCE(1352,
+ /* l n */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x22e6 _ 0)
+NAMED_CHARACTER_REFERENCE(1353,
+ /* l o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ec _ 0)
+NAMED_CHARACTER_REFERENCE(1354,
+ /* l o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fd _ 0)
+NAMED_CHARACTER_REFERENCE(1355,
+ /* l o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1356,
+ /* l o */
+ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 12,
+ 0, 0x27f5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1357,
+ /* l o */
+ 'n' _ 'g' _ 'l' _ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 17, 0, 0x27f7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1358,
+ /* l o */ 'n' _ 'g' _ 'm' _ 'a' _ 'p' _ 's' _ 't' _ 'o' _ ';', 9, 0,
+ 0x27fc _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1359,
+ /* l o */
+ 'n' _ 'g' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 13, 0, 0x27f6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1360,
+ /* l o */
+ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12,
+ 0, 0x21ab _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1361,
+ /* l o */
+ 'o' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 13, 0, 0x21ac _ 0)
+NAMED_CHARACTER_REFERENCE(1362,
+ /* l o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2985 _ 0)
+NAMED_CHARACTER_REFERENCE(1363,
+ /* l o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5d)
+NAMED_CHARACTER_REFERENCE(1364,
+ /* l o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2a2d _ 0)
+NAMED_CHARACTER_REFERENCE(1365,
+ /* l o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0,
+ 0x2a34 _ 0)
+NAMED_CHARACTER_REFERENCE(1366,
+ /* l o */ 'w' _ 'a' _ 's' _ 't' _ ';', 5, 0,
+ 0x2217 _ 0)
+NAMED_CHARACTER_REFERENCE(1367,
+ /* l o */ 'w' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x005f _ 0)
+NAMED_CHARACTER_REFERENCE(1368, /* l o */ 'z' _ ';', 2, 0, 0x25ca _ 0)
+NAMED_CHARACTER_REFERENCE(1369,
+ /* l o */ 'z' _ 'e' _ 'n' _ 'g' _ 'e' _ ';', 6, 0,
+ 0x25ca _ 0)
+NAMED_CHARACTER_REFERENCE(1370, /* l o */ 'z' _ 'f' _ ';', 3, 0, 0x29eb _ 0)
+NAMED_CHARACTER_REFERENCE(1371, /* l p */ 'a' _ 'r' _ ';', 3, 0, 0x0028 _ 0)
+NAMED_CHARACTER_REFERENCE(1372,
+ /* l p */ 'a' _ 'r' _ 'l' _ 't' _ ';', 5, 0,
+ 0x2993 _ 0)
+NAMED_CHARACTER_REFERENCE(1373,
+ /* l r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c6 _ 0)
+NAMED_CHARACTER_REFERENCE(1374,
+ /* l r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7,
+ 0, 0x231f _ 0)
+NAMED_CHARACTER_REFERENCE(1375,
+ /* l r */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cb _ 0)
+NAMED_CHARACTER_REFERENCE(1376,
+ /* l r */ 'h' _ 'a' _ 'r' _ 'd' _ ';', 5, 0,
+ 0x296d _ 0)
+NAMED_CHARACTER_REFERENCE(1377, /* l r */ 'm' _ ';', 2, 0, 0x200e _ 0)
+NAMED_CHARACTER_REFERENCE(1378,
+ /* l r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22bf _ 0)
+NAMED_CHARACTER_REFERENCE(1379,
+ /* l s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0,
+ 0x2039 _ 0)
+NAMED_CHARACTER_REFERENCE(1380,
+ /* l s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc1)
+NAMED_CHARACTER_REFERENCE(1381, /* l s */ 'h' _ ';', 2, 0, 0x21b0 _ 0)
+NAMED_CHARACTER_REFERENCE(1382, /* l s */ 'i' _ 'm' _ ';', 3, 0, 0x2272 _ 0)
+NAMED_CHARACTER_REFERENCE(1383,
+ /* l s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2a8d _ 0)
+NAMED_CHARACTER_REFERENCE(1384,
+ /* l s */ 'i' _ 'm' _ 'g' _ ';', 4, 0, 0x2a8f _ 0)
+NAMED_CHARACTER_REFERENCE(1385, /* l s */ 'q' _ 'b' _ ';', 3, 0, 0x005b _ 0)
+NAMED_CHARACTER_REFERENCE(1386,
+ /* l s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2018 _ 0)
+NAMED_CHARACTER_REFERENCE(1387,
+ /* l s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0,
+ 0x201a _ 0)
+NAMED_CHARACTER_REFERENCE(1388,
+ /* l s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0142 _ 0)
+NAMED_CHARACTER_REFERENCE(1389, /* l t */ 0, 0, 1, 0x003c _ 0)
+NAMED_CHARACTER_REFERENCE(1390, /* l t */ ';', 1, 0, 0x003c _ 0)
+NAMED_CHARACTER_REFERENCE(1391, /* l t */ 'c' _ 'c' _ ';', 3, 0, 0x2aa6 _ 0)
+NAMED_CHARACTER_REFERENCE(1392,
+ /* l t */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x2a79 _ 0)
+NAMED_CHARACTER_REFERENCE(1393,
+ /* l t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22d6 _ 0)
+NAMED_CHARACTER_REFERENCE(1394,
+ /* l t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0,
+ 0x22cb _ 0)
+NAMED_CHARACTER_REFERENCE(1395,
+ /* l t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0,
+ 0x22c9 _ 0)
+NAMED_CHARACTER_REFERENCE(1396,
+ /* l t */ 'l' _ 'a' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x2976 _ 0)
+NAMED_CHARACTER_REFERENCE(1397,
+ /* l t */ 'q' _ 'u' _ 'e' _ 's' _ 't' _ ';', 6, 0,
+ 0x2a7b _ 0)
+NAMED_CHARACTER_REFERENCE(1398,
+ /* l t */ 'r' _ 'P' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2996 _ 0)
+NAMED_CHARACTER_REFERENCE(1399, /* l t */ 'r' _ 'i' _ ';', 3, 0, 0x25c3 _ 0)
+NAMED_CHARACTER_REFERENCE(1400,
+ /* l t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b4 _ 0)
+NAMED_CHARACTER_REFERENCE(1401,
+ /* l t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25c2 _ 0)
+NAMED_CHARACTER_REFERENCE(1402,
+ /* l u */ 'r' _ 'd' _ 's' _ 'h' _ 'a' _ 'r' _ ';', 7,
+ 0, 0x294a _ 0)
+NAMED_CHARACTER_REFERENCE(1403,
+ /* l u */ 'r' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0,
+ 0x2966 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1404,
+ /* l v */ 'e' _ 'r' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 8, 0,
+ 0x2268 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1405,
+ /* l v */ 'n' _ 'E' _ ';', 3, 0, 0x2268 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1406,
+ /* m D */ 'D' _ 'o' _ 't' _ ';', 4, 0, 0x223a _ 0)
+NAMED_CHARACTER_REFERENCE(1407, /* m a */ 'c' _ 'r', 2, 0, 0x00af _ 0)
+NAMED_CHARACTER_REFERENCE(1408, /* m a */ 'c' _ 'r' _ ';', 3, 0, 0x00af _ 0)
+NAMED_CHARACTER_REFERENCE(1409, /* m a */ 'l' _ 'e' _ ';', 3, 0, 0x2642 _ 0)
+NAMED_CHARACTER_REFERENCE(1410, /* m a */ 'l' _ 't' _ ';', 3, 0, 0x2720 _ 0)
+NAMED_CHARACTER_REFERENCE(1411,
+ /* m a */ 'l' _ 't' _ 'e' _ 's' _ 'e' _ ';', 6, 0,
+ 0x2720 _ 0)
+NAMED_CHARACTER_REFERENCE(1412, /* m a */ 'p' _ ';', 2, 0, 0x21a6 _ 0)
+NAMED_CHARACTER_REFERENCE(1413,
+ /* m a */ 'p' _ 's' _ 't' _ 'o' _ ';', 5, 0,
+ 0x21a6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1414,
+ /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'd' _ 'o' _ 'w' _ 'n' _ ';', 9, 0,
+ 0x21a7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1415,
+ /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 9, 0,
+ 0x21a4 _ 0)
+NAMED_CHARACTER_REFERENCE(1416,
+ /* m a */ 'p' _ 's' _ 't' _ 'o' _ 'u' _ 'p' _ ';', 7,
+ 0, 0x21a5 _ 0)
+NAMED_CHARACTER_REFERENCE(1417,
+ /* m a */ 'r' _ 'k' _ 'e' _ 'r' _ ';', 5, 0,
+ 0x25ae _ 0)
+NAMED_CHARACTER_REFERENCE(1418,
+ /* m c */ 'o' _ 'm' _ 'm' _ 'a' _ ';', 5, 0,
+ 0x2a29 _ 0)
+NAMED_CHARACTER_REFERENCE(1419, /* m c */ 'y' _ ';', 2, 0, 0x043c _ 0)
+NAMED_CHARACTER_REFERENCE(1420,
+ /* m d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2014 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1421,
+ /* m e */
+ 'a' _ 's' _ 'u' _ 'r' _ 'e' _ 'd' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 12,
+ 0, 0x2221 _ 0)
+NAMED_CHARACTER_REFERENCE(1422, /* m f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2a)
+NAMED_CHARACTER_REFERENCE(1423, /* m h */ 'o' _ ';', 2, 0, 0x2127 _ 0)
+NAMED_CHARACTER_REFERENCE(1424, /* m i */ 'c' _ 'r' _ 'o', 3, 0, 0x00b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1425,
+ /* m i */ 'c' _ 'r' _ 'o' _ ';', 4, 0, 0x00b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1426, /* m i */ 'd' _ ';', 2, 0, 0x2223 _ 0)
+NAMED_CHARACTER_REFERENCE(1427,
+ /* m i */ 'd' _ 'a' _ 's' _ 't' _ ';', 5, 0,
+ 0x002a _ 0)
+NAMED_CHARACTER_REFERENCE(1428,
+ /* m i */ 'd' _ 'c' _ 'i' _ 'r' _ ';', 5, 0,
+ 0x2af0 _ 0)
+NAMED_CHARACTER_REFERENCE(1429,
+ /* m i */ 'd' _ 'd' _ 'o' _ 't', 4, 0, 0x00b7 _ 0)
+NAMED_CHARACTER_REFERENCE(1430,
+ /* m i */ 'd' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x00b7 _ 0)
+NAMED_CHARACTER_REFERENCE(1431,
+ /* m i */ 'n' _ 'u' _ 's' _ ';', 4, 0, 0x2212 _ 0)
+NAMED_CHARACTER_REFERENCE(1432,
+ /* m i */ 'n' _ 'u' _ 's' _ 'b' _ ';', 5, 0,
+ 0x229f _ 0)
+NAMED_CHARACTER_REFERENCE(1433,
+ /* m i */ 'n' _ 'u' _ 's' _ 'd' _ ';', 5, 0,
+ 0x2238 _ 0)
+NAMED_CHARACTER_REFERENCE(1434,
+ /* m i */ 'n' _ 'u' _ 's' _ 'd' _ 'u' _ ';', 6, 0,
+ 0x2a2a _ 0)
+NAMED_CHARACTER_REFERENCE(1435, /* m l */ 'c' _ 'p' _ ';', 3, 0, 0x2adb _ 0)
+NAMED_CHARACTER_REFERENCE(1436, /* m l */ 'd' _ 'r' _ ';', 3, 0, 0x2026 _ 0)
+NAMED_CHARACTER_REFERENCE(1437,
+ /* m n */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2213 _ 0)
+NAMED_CHARACTER_REFERENCE(1438,
+ /* m o */ 'd' _ 'e' _ 'l' _ 's' _ ';', 5, 0,
+ 0x22a7 _ 0)
+NAMED_CHARACTER_REFERENCE(1439,
+ /* m o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5e)
+NAMED_CHARACTER_REFERENCE(1440, /* m p */ ';', 1, 0, 0x2213 _ 0)
+NAMED_CHARACTER_REFERENCE(1441,
+ /* m s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc2)
+NAMED_CHARACTER_REFERENCE(1442,
+ /* m s */ 't' _ 'p' _ 'o' _ 's' _ ';', 5, 0,
+ 0x223e _ 0)
+NAMED_CHARACTER_REFERENCE(1443, /* m u */ ';', 1, 0, 0x03bc _ 0)
+NAMED_CHARACTER_REFERENCE(1444,
+ /* m u */ 'l' _ 't' _ 'i' _ 'm' _ 'a' _ 'p' _ ';', 7,
+ 0, 0x22b8 _ 0)
+NAMED_CHARACTER_REFERENCE(1445,
+ /* m u */ 'm' _ 'a' _ 'p' _ ';', 4, 0, 0x22b8 _ 0)
+NAMED_CHARACTER_REFERENCE(1446, /* n G */ 'g' _ ';', 2, 0, 0x22d9 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1447, /* n G */ 't' _ ';', 2, 0, 0x226b _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1448,
+ /* n G */ 't' _ 'v' _ ';', 3, 0, 0x226b _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 1449,
+ /* n L */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x21cd _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1450,
+ /* n L */
+ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x21ce _ 0)
+NAMED_CHARACTER_REFERENCE(1451, /* n L */ 'l' _ ';', 2, 0, 0x22d8 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1452, /* n L */ 't' _ ';', 2, 0, 0x226a _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1453,
+ /* n L */ 't' _ 'v' _ ';', 3, 0, 0x226a _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 1454,
+ /* n R */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0,
+ 0x21cf _ 0)
+NAMED_CHARACTER_REFERENCE(1455,
+ /* n V */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x22af _ 0)
+NAMED_CHARACTER_REFERENCE(1456,
+ /* n V */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x22ae _ 0)
+NAMED_CHARACTER_REFERENCE(1457,
+ /* n a */ 'b' _ 'l' _ 'a' _ ';', 4, 0, 0x2207 _ 0)
+NAMED_CHARACTER_REFERENCE(1458,
+ /* n a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0144 _ 0)
+NAMED_CHARACTER_REFERENCE(1459,
+ /* n a */ 'n' _ 'g' _ ';', 3, 0, 0x2220 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1460, /* n a */ 'p' _ ';', 2, 0, 0x2249 _ 0)
+NAMED_CHARACTER_REFERENCE(1461,
+ /* n a */ 'p' _ 'E' _ ';', 3, 0, 0x2a70 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1462,
+ /* n a */ 'p' _ 'i' _ 'd' _ ';', 4, 0,
+ 0x224b _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1463,
+ /* n a */ 'p' _ 'o' _ 's' _ ';', 4, 0, 0x0149 _ 0)
+NAMED_CHARACTER_REFERENCE(1464,
+ /* n a */ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 6, 0,
+ 0x2249 _ 0)
+NAMED_CHARACTER_REFERENCE(1465,
+ /* n a */ 't' _ 'u' _ 'r' _ ';', 4, 0, 0x266e _ 0)
+NAMED_CHARACTER_REFERENCE(1466,
+ /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ ';', 6, 0,
+ 0x266e _ 0)
+NAMED_CHARACTER_REFERENCE(1467,
+ /* n a */ 't' _ 'u' _ 'r' _ 'a' _ 'l' _ 's' _ ';', 7,
+ 0, 0x2115 _ 0)
+NAMED_CHARACTER_REFERENCE(1468, /* n b */ 's' _ 'p', 2, 0, 0x00a0 _ 0)
+NAMED_CHARACTER_REFERENCE(1469, /* n b */ 's' _ 'p' _ ';', 3, 0, 0x00a0 _ 0)
+NAMED_CHARACTER_REFERENCE(1470,
+ /* n b */ 'u' _ 'm' _ 'p' _ ';', 4, 0,
+ 0x224e _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1471,
+ /* n b */ 'u' _ 'm' _ 'p' _ 'e' _ ';', 5, 0,
+ 0x224f _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1472, /* n c */ 'a' _ 'p' _ ';', 3, 0, 0x2a43 _ 0)
+NAMED_CHARACTER_REFERENCE(1473,
+ /* n c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0148 _ 0)
+NAMED_CHARACTER_REFERENCE(1474,
+ /* n c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0146 _ 0)
+NAMED_CHARACTER_REFERENCE(1475,
+ /* n c */ 'o' _ 'n' _ 'g' _ ';', 4, 0, 0x2247 _ 0)
+NAMED_CHARACTER_REFERENCE(1476,
+ /* n c */ 'o' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ ';', 7,
+ 0, 0x2a6d _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1477, /* n c */ 'u' _ 'p' _ ';', 3, 0, 0x2a42 _ 0)
+NAMED_CHARACTER_REFERENCE(1478, /* n c */ 'y' _ ';', 2, 0, 0x043d _ 0)
+NAMED_CHARACTER_REFERENCE(1479,
+ /* n d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x2013 _ 0)
+NAMED_CHARACTER_REFERENCE(1480, /* n e */ ';', 1, 0, 0x2260 _ 0)
+NAMED_CHARACTER_REFERENCE(1481,
+ /* n e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d7 _ 0)
+NAMED_CHARACTER_REFERENCE(1482,
+ /* n e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0,
+ 0x2924 _ 0)
+NAMED_CHARACTER_REFERENCE(1483,
+ /* n e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2197 _ 0)
+NAMED_CHARACTER_REFERENCE(1484,
+ /* n e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x2197 _ 0)
+NAMED_CHARACTER_REFERENCE(1485,
+ /* n e */ 'd' _ 'o' _ 't' _ ';', 4, 0,
+ 0x2250 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1486,
+ /* n e */ 'q' _ 'u' _ 'i' _ 'v' _ ';', 5, 0,
+ 0x2262 _ 0)
+NAMED_CHARACTER_REFERENCE(1487,
+ /* n e */ 's' _ 'e' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2928 _ 0)
+NAMED_CHARACTER_REFERENCE(1488,
+ /* n e */ 's' _ 'i' _ 'm' _ ';', 4, 0,
+ 0x2242 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1489,
+ /* n e */ 'x' _ 'i' _ 's' _ 't' _ ';', 5, 0,
+ 0x2204 _ 0)
+NAMED_CHARACTER_REFERENCE(1490,
+ /* n e */ 'x' _ 'i' _ 's' _ 't' _ 's' _ ';', 6, 0,
+ 0x2204 _ 0)
+NAMED_CHARACTER_REFERENCE(1491, /* n f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2b)
+NAMED_CHARACTER_REFERENCE(1492, /* n g */ 'E' _ ';', 2, 0, 0x2267 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1493, /* n g */ 'e' _ ';', 2, 0, 0x2271 _ 0)
+NAMED_CHARACTER_REFERENCE(1494, /* n g */ 'e' _ 'q' _ ';', 3, 0, 0x2271 _ 0)
+NAMED_CHARACTER_REFERENCE(1495,
+ /* n g */ 'e' _ 'q' _ 'q' _ ';', 4, 0,
+ 0x2267 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 1496,
+ /* n g */ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 8, 0,
+ 0x2a7e _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1497,
+ /* n g */ 'e' _ 's' _ ';', 3, 0, 0x2a7e _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1498,
+ /* n g */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2275 _ 0)
+NAMED_CHARACTER_REFERENCE(1499, /* n g */ 't' _ ';', 2, 0, 0x226f _ 0)
+NAMED_CHARACTER_REFERENCE(1500, /* n g */ 't' _ 'r' _ ';', 3, 0, 0x226f _ 0)
+NAMED_CHARACTER_REFERENCE(1501,
+ /* n h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21ce _ 0)
+NAMED_CHARACTER_REFERENCE(1502,
+ /* n h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ae _ 0)
+NAMED_CHARACTER_REFERENCE(1503,
+ /* n h */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2af2 _ 0)
+NAMED_CHARACTER_REFERENCE(1504, /* n i */ ';', 1, 0, 0x220b _ 0)
+NAMED_CHARACTER_REFERENCE(1505, /* n i */ 's' _ ';', 2, 0, 0x22fc _ 0)
+NAMED_CHARACTER_REFERENCE(1506, /* n i */ 's' _ 'd' _ ';', 3, 0, 0x22fa _ 0)
+NAMED_CHARACTER_REFERENCE(1507, /* n i */ 'v' _ ';', 2, 0, 0x220b _ 0)
+NAMED_CHARACTER_REFERENCE(1508, /* n j */ 'c' _ 'y' _ ';', 3, 0, 0x045a _ 0)
+NAMED_CHARACTER_REFERENCE(1509,
+ /* n l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cd _ 0)
+NAMED_CHARACTER_REFERENCE(1510, /* n l */ 'E' _ ';', 2, 0, 0x2266 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1511,
+ /* n l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219a _ 0)
+NAMED_CHARACTER_REFERENCE(1512, /* n l */ 'd' _ 'r' _ ';', 3, 0, 0x2025 _ 0)
+NAMED_CHARACTER_REFERENCE(1513, /* n l */ 'e' _ ';', 2, 0, 0x2270 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1514,
+ /* n l */ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x219a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1515,
+ /* n l */
+ 'e' _ 'f' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x21ae _ 0)
+NAMED_CHARACTER_REFERENCE(1516, /* n l */ 'e' _ 'q' _ ';', 3, 0, 0x2270 _ 0)
+NAMED_CHARACTER_REFERENCE(1517,
+ /* n l */ 'e' _ 'q' _ 'q' _ ';', 4, 0,
+ 0x2266 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 1518,
+ /* n l */ 'e' _ 'q' _ 's' _ 'l' _ 'a' _ 'n' _ 't' _ ';', 8, 0,
+ 0x2a7d _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1519,
+ /* n l */ 'e' _ 's' _ ';', 3, 0, 0x2a7d _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1520,
+ /* n l */ 'e' _ 's' _ 's' _ ';', 4, 0, 0x226e _ 0)
+NAMED_CHARACTER_REFERENCE(1521,
+ /* n l */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x2274 _ 0)
+NAMED_CHARACTER_REFERENCE(1522, /* n l */ 't' _ ';', 2, 0, 0x226e _ 0)
+NAMED_CHARACTER_REFERENCE(1523,
+ /* n l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22ea _ 0)
+NAMED_CHARACTER_REFERENCE(1524,
+ /* n l */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0,
+ 0x22ec _ 0)
+NAMED_CHARACTER_REFERENCE(1525, /* n m */ 'i' _ 'd' _ ';', 3, 0, 0x2224 _ 0)
+NAMED_CHARACTER_REFERENCE(1526,
+ /* n o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd5f)
+NAMED_CHARACTER_REFERENCE(1527, /* n o */ 't', 1, 0, 0x00ac _ 0)
+NAMED_CHARACTER_REFERENCE(1528, /* n o */ 't' _ ';', 2, 0, 0x00ac _ 0)
+NAMED_CHARACTER_REFERENCE(1529,
+ /* n o */ 't' _ 'i' _ 'n' _ ';', 4, 0, 0x2209 _ 0)
+NAMED_CHARACTER_REFERENCE(1530,
+ /* n o */ 't' _ 'i' _ 'n' _ 'E' _ ';', 5, 0,
+ 0x22f9 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1531,
+ /* n o */ 't' _ 'i' _ 'n' _ 'd' _ 'o' _ 't' _ ';', 7,
+ 0, 0x22f5 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1532,
+ /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'a' _ ';', 6, 0,
+ 0x2209 _ 0)
+NAMED_CHARACTER_REFERENCE(1533,
+ /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'b' _ ';', 6, 0,
+ 0x22f7 _ 0)
+NAMED_CHARACTER_REFERENCE(1534,
+ /* n o */ 't' _ 'i' _ 'n' _ 'v' _ 'c' _ ';', 6, 0,
+ 0x22f6 _ 0)
+NAMED_CHARACTER_REFERENCE(1535,
+ /* n o */ 't' _ 'n' _ 'i' _ ';', 4, 0, 0x220c _ 0)
+NAMED_CHARACTER_REFERENCE(1536,
+ /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'a' _ ';', 6, 0,
+ 0x220c _ 0)
+NAMED_CHARACTER_REFERENCE(1537,
+ /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'b' _ ';', 6, 0,
+ 0x22fe _ 0)
+NAMED_CHARACTER_REFERENCE(1538,
+ /* n o */ 't' _ 'n' _ 'i' _ 'v' _ 'c' _ ';', 6, 0,
+ 0x22fd _ 0)
+NAMED_CHARACTER_REFERENCE(1539, /* n p */ 'a' _ 'r' _ ';', 3, 0, 0x2226 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1540,
+ /* n p */ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 8, 0, 0x2226 _ 0)
+NAMED_CHARACTER_REFERENCE(1541,
+ /* n p */ 'a' _ 'r' _ 's' _ 'l' _ ';', 5, 0,
+ 0x2afd _ 0x20e5)
+NAMED_CHARACTER_REFERENCE(1542,
+ /* n p */ 'a' _ 'r' _ 't' _ ';', 4, 0,
+ 0x2202 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1543,
+ /* n p */ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 6, 0,
+ 0x2a14 _ 0)
+NAMED_CHARACTER_REFERENCE(1544, /* n p */ 'r' _ ';', 2, 0, 0x2280 _ 0)
+NAMED_CHARACTER_REFERENCE(1545,
+ /* n p */ 'r' _ 'c' _ 'u' _ 'e' _ ';', 5, 0,
+ 0x22e0 _ 0)
+NAMED_CHARACTER_REFERENCE(1546,
+ /* n p */ 'r' _ 'e' _ ';', 3, 0, 0x2aaf _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1547,
+ /* n p */ 'r' _ 'e' _ 'c' _ ';', 4, 0, 0x2280 _ 0)
+NAMED_CHARACTER_REFERENCE(1548,
+ /* n p */ 'r' _ 'e' _ 'c' _ 'e' _ 'q' _ ';', 6, 0,
+ 0x2aaf _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1549,
+ /* n r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21cf _ 0)
+NAMED_CHARACTER_REFERENCE(1550,
+ /* n r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x219b _ 0)
+NAMED_CHARACTER_REFERENCE(1551,
+ /* n r */ 'a' _ 'r' _ 'r' _ 'c' _ ';', 5, 0,
+ 0x2933 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1552,
+ /* n r */ 'a' _ 'r' _ 'r' _ 'w' _ ';', 5, 0,
+ 0x219d _ 0x0338)
+NAMED_CHARACTER_REFERENCE(
+ 1553,
+ /* n r */ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0,
+ 0x219b _ 0)
+NAMED_CHARACTER_REFERENCE(1554,
+ /* n r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22eb _ 0)
+NAMED_CHARACTER_REFERENCE(1555,
+ /* n r */ 't' _ 'r' _ 'i' _ 'e' _ ';', 5, 0,
+ 0x22ed _ 0)
+NAMED_CHARACTER_REFERENCE(1556, /* n s */ 'c' _ ';', 2, 0, 0x2281 _ 0)
+NAMED_CHARACTER_REFERENCE(1557,
+ /* n s */ 'c' _ 'c' _ 'u' _ 'e' _ ';', 5, 0,
+ 0x22e1 _ 0)
+NAMED_CHARACTER_REFERENCE(1558,
+ /* n s */ 'c' _ 'e' _ ';', 3, 0, 0x2ab0 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1559,
+ /* n s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc3)
+NAMED_CHARACTER_REFERENCE(
+ 1560,
+ /* n s */ 'h' _ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 8, 0, 0x2224 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1561,
+ /* n s */
+ 'h' _ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';',
+ 13, 0, 0x2226 _ 0)
+NAMED_CHARACTER_REFERENCE(1562, /* n s */ 'i' _ 'm' _ ';', 3, 0, 0x2241 _ 0)
+NAMED_CHARACTER_REFERENCE(1563,
+ /* n s */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2244 _ 0)
+NAMED_CHARACTER_REFERENCE(1564,
+ /* n s */ 'i' _ 'm' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x2244 _ 0)
+NAMED_CHARACTER_REFERENCE(1565,
+ /* n s */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2224 _ 0)
+NAMED_CHARACTER_REFERENCE(1566,
+ /* n s */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2226 _ 0)
+NAMED_CHARACTER_REFERENCE(1567,
+ /* n s */ 'q' _ 's' _ 'u' _ 'b' _ 'e' _ ';', 6, 0,
+ 0x22e2 _ 0)
+NAMED_CHARACTER_REFERENCE(1568,
+ /* n s */ 'q' _ 's' _ 'u' _ 'p' _ 'e' _ ';', 6, 0,
+ 0x22e3 _ 0)
+NAMED_CHARACTER_REFERENCE(1569, /* n s */ 'u' _ 'b' _ ';', 3, 0, 0x2284 _ 0)
+NAMED_CHARACTER_REFERENCE(1570,
+ /* n s */ 'u' _ 'b' _ 'E' _ ';', 4, 0,
+ 0x2ac5 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1571,
+ /* n s */ 'u' _ 'b' _ 'e' _ ';', 4, 0, 0x2288 _ 0)
+NAMED_CHARACTER_REFERENCE(1572,
+ /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 6, 0,
+ 0x2282 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(
+ 1573,
+ /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2288 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1574,
+ /* n s */ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 9, 0,
+ 0x2ac5 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1575,
+ /* n s */ 'u' _ 'c' _ 'c' _ ';', 4, 0, 0x2281 _ 0)
+NAMED_CHARACTER_REFERENCE(1576,
+ /* n s */ 'u' _ 'c' _ 'c' _ 'e' _ 'q' _ ';', 6, 0,
+ 0x2ab0 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1577, /* n s */ 'u' _ 'p' _ ';', 3, 0, 0x2285 _ 0)
+NAMED_CHARACTER_REFERENCE(1578,
+ /* n s */ 'u' _ 'p' _ 'E' _ ';', 4, 0,
+ 0x2ac6 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1579,
+ /* n s */ 'u' _ 'p' _ 'e' _ ';', 4, 0, 0x2289 _ 0)
+NAMED_CHARACTER_REFERENCE(1580,
+ /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 6, 0,
+ 0x2283 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(
+ 1581,
+ /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 8, 0, 0x2289 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1582,
+ /* n s */ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 9, 0,
+ 0x2ac6 _ 0x0338)
+NAMED_CHARACTER_REFERENCE(1583, /* n t */ 'g' _ 'l' _ ';', 3, 0, 0x2279 _ 0)
+NAMED_CHARACTER_REFERENCE(1584,
+ /* n t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f1 _ 0)
+NAMED_CHARACTER_REFERENCE(1585,
+ /* n t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00f1 _ 0)
+NAMED_CHARACTER_REFERENCE(1586, /* n t */ 'l' _ 'g' _ ';', 3, 0, 0x2278 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1587,
+ /* n t */
+ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12,
+ 0, 0x22ea _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1588,
+ /* n t */
+ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';',
+ 14, 0, 0x22ec _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1589,
+ /* n t */
+ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 13, 0, 0x22eb _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1590,
+ /* n t */
+ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';',
+ 15, 0, 0x22ed _ 0)
+NAMED_CHARACTER_REFERENCE(1591, /* n u */ ';', 1, 0, 0x03bd _ 0)
+NAMED_CHARACTER_REFERENCE(1592, /* n u */ 'm' _ ';', 2, 0, 0x0023 _ 0)
+NAMED_CHARACTER_REFERENCE(1593,
+ /* n u */ 'm' _ 'e' _ 'r' _ 'o' _ ';', 5, 0,
+ 0x2116 _ 0)
+NAMED_CHARACTER_REFERENCE(1594,
+ /* n u */ 'm' _ 's' _ 'p' _ ';', 4, 0, 0x2007 _ 0)
+NAMED_CHARACTER_REFERENCE(1595,
+ /* n v */ 'D' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x22ad _ 0)
+NAMED_CHARACTER_REFERENCE(1596,
+ /* n v */ 'H' _ 'a' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x2904 _ 0)
+NAMED_CHARACTER_REFERENCE(1597,
+ /* n v */ 'a' _ 'p' _ ';', 3, 0, 0x224d _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1598,
+ /* n v */ 'd' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x22ac _ 0)
+NAMED_CHARACTER_REFERENCE(1599,
+ /* n v */ 'g' _ 'e' _ ';', 3, 0, 0x2265 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1600,
+ /* n v */ 'g' _ 't' _ ';', 3, 0, 0x003e _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1601,
+ /* n v */ 'i' _ 'n' _ 'f' _ 'i' _ 'n' _ ';', 6, 0,
+ 0x29de _ 0)
+NAMED_CHARACTER_REFERENCE(1602,
+ /* n v */ 'l' _ 'A' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x2902 _ 0)
+NAMED_CHARACTER_REFERENCE(1603,
+ /* n v */ 'l' _ 'e' _ ';', 3, 0, 0x2264 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1604,
+ /* n v */ 'l' _ 't' _ ';', 3, 0, 0x003c _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1605,
+ /* n v */ 'l' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 6, 0,
+ 0x22b4 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1606,
+ /* n v */ 'r' _ 'A' _ 'r' _ 'r' _ ';', 5, 0,
+ 0x2903 _ 0)
+NAMED_CHARACTER_REFERENCE(1607,
+ /* n v */ 'r' _ 't' _ 'r' _ 'i' _ 'e' _ ';', 6, 0,
+ 0x22b5 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1608,
+ /* n v */ 's' _ 'i' _ 'm' _ ';', 4, 0,
+ 0x223c _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(1609,
+ /* n w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d6 _ 0)
+NAMED_CHARACTER_REFERENCE(1610,
+ /* n w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0,
+ 0x2923 _ 0)
+NAMED_CHARACTER_REFERENCE(1611,
+ /* n w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2196 _ 0)
+NAMED_CHARACTER_REFERENCE(1612,
+ /* n w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x2196 _ 0)
+NAMED_CHARACTER_REFERENCE(1613,
+ /* n w */ 'n' _ 'e' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2927 _ 0)
+NAMED_CHARACTER_REFERENCE(1614, /* o S */ ';', 1, 0, 0x24c8 _ 0)
+NAMED_CHARACTER_REFERENCE(1615,
+ /* o a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00f3 _ 0)
+NAMED_CHARACTER_REFERENCE(1616,
+ /* o a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00f3 _ 0)
+NAMED_CHARACTER_REFERENCE(1617, /* o a */ 's' _ 't' _ ';', 3, 0, 0x229b _ 0)
+NAMED_CHARACTER_REFERENCE(1618, /* o c */ 'i' _ 'r' _ ';', 3, 0, 0x229a _ 0)
+NAMED_CHARACTER_REFERENCE(1619, /* o c */ 'i' _ 'r' _ 'c', 3, 0, 0x00f4 _ 0)
+NAMED_CHARACTER_REFERENCE(1620,
+ /* o c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00f4 _ 0)
+NAMED_CHARACTER_REFERENCE(1621, /* o c */ 'y' _ ';', 2, 0, 0x043e _ 0)
+NAMED_CHARACTER_REFERENCE(1622,
+ /* o d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x229d _ 0)
+NAMED_CHARACTER_REFERENCE(1623,
+ /* o d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0,
+ 0x0151 _ 0)
+NAMED_CHARACTER_REFERENCE(1624, /* o d */ 'i' _ 'v' _ ';', 3, 0, 0x2a38 _ 0)
+NAMED_CHARACTER_REFERENCE(1625, /* o d */ 'o' _ 't' _ ';', 3, 0, 0x2299 _ 0)
+NAMED_CHARACTER_REFERENCE(1626,
+ /* o d */ 's' _ 'o' _ 'l' _ 'd' _ ';', 5, 0,
+ 0x29bc _ 0)
+NAMED_CHARACTER_REFERENCE(1627,
+ /* o e */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x0153 _ 0)
+NAMED_CHARACTER_REFERENCE(1628,
+ /* o f */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29bf _ 0)
+NAMED_CHARACTER_REFERENCE(1629, /* o f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2c)
+NAMED_CHARACTER_REFERENCE(1630, /* o g */ 'o' _ 'n' _ ';', 3, 0, 0x02db _ 0)
+NAMED_CHARACTER_REFERENCE(1631,
+ /* o g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f2 _ 0)
+NAMED_CHARACTER_REFERENCE(1632,
+ /* o g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00f2 _ 0)
+NAMED_CHARACTER_REFERENCE(1633, /* o g */ 't' _ ';', 2, 0, 0x29c1 _ 0)
+NAMED_CHARACTER_REFERENCE(1634,
+ /* o h */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x29b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1635, /* o h */ 'm' _ ';', 2, 0, 0x03a9 _ 0)
+NAMED_CHARACTER_REFERENCE(1636, /* o i */ 'n' _ 't' _ ';', 3, 0, 0x222e _ 0)
+NAMED_CHARACTER_REFERENCE(1637,
+ /* o l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21ba _ 0)
+NAMED_CHARACTER_REFERENCE(1638,
+ /* o l */ 'c' _ 'i' _ 'r' _ ';', 4, 0, 0x29be _ 0)
+NAMED_CHARACTER_REFERENCE(1639,
+ /* o l */ 'c' _ 'r' _ 'o' _ 's' _ 's' _ ';', 6, 0,
+ 0x29bb _ 0)
+NAMED_CHARACTER_REFERENCE(1640,
+ /* o l */ 'i' _ 'n' _ 'e' _ ';', 4, 0, 0x203e _ 0)
+NAMED_CHARACTER_REFERENCE(1641, /* o l */ 't' _ ';', 2, 0, 0x29c0 _ 0)
+NAMED_CHARACTER_REFERENCE(1642,
+ /* o m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x014d _ 0)
+NAMED_CHARACTER_REFERENCE(1643,
+ /* o m */ 'e' _ 'g' _ 'a' _ ';', 4, 0, 0x03c9 _ 0)
+NAMED_CHARACTER_REFERENCE(1644,
+ /* o m */ 'i' _ 'c' _ 'r' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x03bf _ 0)
+NAMED_CHARACTER_REFERENCE(1645, /* o m */ 'i' _ 'd' _ ';', 3, 0, 0x29b6 _ 0)
+NAMED_CHARACTER_REFERENCE(1646,
+ /* o m */ 'i' _ 'n' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2296 _ 0)
+NAMED_CHARACTER_REFERENCE(1647,
+ /* o o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd60)
+NAMED_CHARACTER_REFERENCE(1648, /* o p */ 'a' _ 'r' _ ';', 3, 0, 0x29b7 _ 0)
+NAMED_CHARACTER_REFERENCE(1649,
+ /* o p */ 'e' _ 'r' _ 'p' _ ';', 4, 0, 0x29b9 _ 0)
+NAMED_CHARACTER_REFERENCE(1650,
+ /* o p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x2295 _ 0)
+NAMED_CHARACTER_REFERENCE(1651, /* o r */ ';', 1, 0, 0x2228 _ 0)
+NAMED_CHARACTER_REFERENCE(1652,
+ /* o r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21bb _ 0)
+NAMED_CHARACTER_REFERENCE(1653, /* o r */ 'd' _ ';', 2, 0, 0x2a5d _ 0)
+NAMED_CHARACTER_REFERENCE(1654,
+ /* o r */ 'd' _ 'e' _ 'r' _ ';', 4, 0, 0x2134 _ 0)
+NAMED_CHARACTER_REFERENCE(1655,
+ /* o r */ 'd' _ 'e' _ 'r' _ 'o' _ 'f' _ ';', 6, 0,
+ 0x2134 _ 0)
+NAMED_CHARACTER_REFERENCE(1656, /* o r */ 'd' _ 'f', 2, 0, 0x00aa _ 0)
+NAMED_CHARACTER_REFERENCE(1657, /* o r */ 'd' _ 'f' _ ';', 3, 0, 0x00aa _ 0)
+NAMED_CHARACTER_REFERENCE(1658, /* o r */ 'd' _ 'm', 2, 0, 0x00ba _ 0)
+NAMED_CHARACTER_REFERENCE(1659, /* o r */ 'd' _ 'm' _ ';', 3, 0, 0x00ba _ 0)
+NAMED_CHARACTER_REFERENCE(1660,
+ /* o r */ 'i' _ 'g' _ 'o' _ 'f' _ ';', 5, 0,
+ 0x22b6 _ 0)
+NAMED_CHARACTER_REFERENCE(1661, /* o r */ 'o' _ 'r' _ ';', 3, 0, 0x2a56 _ 0)
+NAMED_CHARACTER_REFERENCE(1662,
+ /* o r */ 's' _ 'l' _ 'o' _ 'p' _ 'e' _ ';', 6, 0,
+ 0x2a57 _ 0)
+NAMED_CHARACTER_REFERENCE(1663, /* o r */ 'v' _ ';', 2, 0, 0x2a5b _ 0)
+NAMED_CHARACTER_REFERENCE(1664, /* o s */ 'c' _ 'r' _ ';', 3, 0, 0x2134 _ 0)
+NAMED_CHARACTER_REFERENCE(1665,
+ /* o s */ 'l' _ 'a' _ 's' _ 'h', 4, 0, 0x00f8 _ 0)
+NAMED_CHARACTER_REFERENCE(1666,
+ /* o s */ 'l' _ 'a' _ 's' _ 'h' _ ';', 5, 0,
+ 0x00f8 _ 0)
+NAMED_CHARACTER_REFERENCE(1667, /* o s */ 'o' _ 'l' _ ';', 3, 0, 0x2298 _ 0)
+NAMED_CHARACTER_REFERENCE(1668,
+ /* o t */ 'i' _ 'l' _ 'd' _ 'e', 4, 0, 0x00f5 _ 0)
+NAMED_CHARACTER_REFERENCE(1669,
+ /* o t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x00f5 _ 0)
+NAMED_CHARACTER_REFERENCE(1670,
+ /* o t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0,
+ 0x2297 _ 0)
+NAMED_CHARACTER_REFERENCE(1671,
+ /* o t */ 'i' _ 'm' _ 'e' _ 's' _ 'a' _ 's' _ ';', 7,
+ 0, 0x2a36 _ 0)
+NAMED_CHARACTER_REFERENCE(1672, /* o u */ 'm' _ 'l', 2, 0, 0x00f6 _ 0)
+NAMED_CHARACTER_REFERENCE(1673, /* o u */ 'm' _ 'l' _ ';', 3, 0, 0x00f6 _ 0)
+NAMED_CHARACTER_REFERENCE(1674,
+ /* o v */ 'b' _ 'a' _ 'r' _ ';', 4, 0, 0x233d _ 0)
+NAMED_CHARACTER_REFERENCE(1675, /* p a */ 'r' _ ';', 2, 0, 0x2225 _ 0)
+NAMED_CHARACTER_REFERENCE(1676, /* p a */ 'r' _ 'a', 2, 0, 0x00b6 _ 0)
+NAMED_CHARACTER_REFERENCE(1677, /* p a */ 'r' _ 'a' _ ';', 3, 0, 0x00b6 _ 0)
+NAMED_CHARACTER_REFERENCE(1678,
+ /* p a */ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 7,
+ 0, 0x2225 _ 0)
+NAMED_CHARACTER_REFERENCE(1679,
+ /* p a */ 'r' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x2af3 _ 0)
+NAMED_CHARACTER_REFERENCE(1680,
+ /* p a */ 'r' _ 's' _ 'l' _ ';', 4, 0, 0x2afd _ 0)
+NAMED_CHARACTER_REFERENCE(1681, /* p a */ 'r' _ 't' _ ';', 3, 0, 0x2202 _ 0)
+NAMED_CHARACTER_REFERENCE(1682, /* p c */ 'y' _ ';', 2, 0, 0x043f _ 0)
+NAMED_CHARACTER_REFERENCE(1683,
+ /* p e */ 'r' _ 'c' _ 'n' _ 't' _ ';', 5, 0,
+ 0x0025 _ 0)
+NAMED_CHARACTER_REFERENCE(1684,
+ /* p e */ 'r' _ 'i' _ 'o' _ 'd' _ ';', 5, 0,
+ 0x002e _ 0)
+NAMED_CHARACTER_REFERENCE(1685,
+ /* p e */ 'r' _ 'm' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x2030 _ 0)
+NAMED_CHARACTER_REFERENCE(1686, /* p e */ 'r' _ 'p' _ ';', 3, 0, 0x22a5 _ 0)
+NAMED_CHARACTER_REFERENCE(1687,
+ /* p e */ 'r' _ 't' _ 'e' _ 'n' _ 'k' _ ';', 6, 0,
+ 0x2031 _ 0)
+NAMED_CHARACTER_REFERENCE(1688, /* p f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2d)
+NAMED_CHARACTER_REFERENCE(1689, /* p h */ 'i' _ ';', 2, 0, 0x03c6 _ 0)
+NAMED_CHARACTER_REFERENCE(1690, /* p h */ 'i' _ 'v' _ ';', 3, 0, 0x03d5 _ 0)
+NAMED_CHARACTER_REFERENCE(1691,
+ /* p h */ 'm' _ 'm' _ 'a' _ 't' _ ';', 5, 0,
+ 0x2133 _ 0)
+NAMED_CHARACTER_REFERENCE(1692,
+ /* p h */ 'o' _ 'n' _ 'e' _ ';', 4, 0, 0x260e _ 0)
+NAMED_CHARACTER_REFERENCE(1693, /* p i */ ';', 1, 0, 0x03c0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1694,
+ /* p i */ 't' _ 'c' _ 'h' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 8, 0, 0x22d4 _ 0)
+NAMED_CHARACTER_REFERENCE(1695, /* p i */ 'v' _ ';', 2, 0, 0x03d6 _ 0)
+NAMED_CHARACTER_REFERENCE(1696,
+ /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ ';', 5, 0,
+ 0x210f _ 0)
+NAMED_CHARACTER_REFERENCE(1697,
+ /* p l */ 'a' _ 'n' _ 'c' _ 'k' _ 'h' _ ';', 6, 0,
+ 0x210e _ 0)
+NAMED_CHARACTER_REFERENCE(1698,
+ /* p l */ 'a' _ 'n' _ 'k' _ 'v' _ ';', 5, 0,
+ 0x210f _ 0)
+NAMED_CHARACTER_REFERENCE(1699, /* p l */ 'u' _ 's' _ ';', 3, 0, 0x002b _ 0)
+NAMED_CHARACTER_REFERENCE(1700,
+ /* p l */ 'u' _ 's' _ 'a' _ 'c' _ 'i' _ 'r' _ ';', 7,
+ 0, 0x2a23 _ 0)
+NAMED_CHARACTER_REFERENCE(1701,
+ /* p l */ 'u' _ 's' _ 'b' _ ';', 4, 0, 0x229e _ 0)
+NAMED_CHARACTER_REFERENCE(1702,
+ /* p l */ 'u' _ 's' _ 'c' _ 'i' _ 'r' _ ';', 6, 0,
+ 0x2a22 _ 0)
+NAMED_CHARACTER_REFERENCE(1703,
+ /* p l */ 'u' _ 's' _ 'd' _ 'o' _ ';', 5, 0,
+ 0x2214 _ 0)
+NAMED_CHARACTER_REFERENCE(1704,
+ /* p l */ 'u' _ 's' _ 'd' _ 'u' _ ';', 5, 0,
+ 0x2a25 _ 0)
+NAMED_CHARACTER_REFERENCE(1705,
+ /* p l */ 'u' _ 's' _ 'e' _ ';', 4, 0, 0x2a72 _ 0)
+NAMED_CHARACTER_REFERENCE(1706,
+ /* p l */ 'u' _ 's' _ 'm' _ 'n', 4, 0, 0x00b1 _ 0)
+NAMED_CHARACTER_REFERENCE(1707,
+ /* p l */ 'u' _ 's' _ 'm' _ 'n' _ ';', 5, 0,
+ 0x00b1 _ 0)
+NAMED_CHARACTER_REFERENCE(1708,
+ /* p l */ 'u' _ 's' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x2a26 _ 0)
+NAMED_CHARACTER_REFERENCE(1709,
+ /* p l */ 'u' _ 's' _ 't' _ 'w' _ 'o' _ ';', 6, 0,
+ 0x2a27 _ 0)
+NAMED_CHARACTER_REFERENCE(1710, /* p m */ ';', 1, 0, 0x00b1 _ 0)
+NAMED_CHARACTER_REFERENCE(1711,
+ /* p o */ 'i' _ 'n' _ 't' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a15 _ 0)
+NAMED_CHARACTER_REFERENCE(1712,
+ /* p o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd61)
+NAMED_CHARACTER_REFERENCE(1713, /* p o */ 'u' _ 'n' _ 'd', 3, 0, 0x00a3 _ 0)
+NAMED_CHARACTER_REFERENCE(1714,
+ /* p o */ 'u' _ 'n' _ 'd' _ ';', 4, 0, 0x00a3 _ 0)
+NAMED_CHARACTER_REFERENCE(1715, /* p r */ ';', 1, 0, 0x227a _ 0)
+NAMED_CHARACTER_REFERENCE(1716, /* p r */ 'E' _ ';', 2, 0, 0x2ab3 _ 0)
+NAMED_CHARACTER_REFERENCE(1717, /* p r */ 'a' _ 'p' _ ';', 3, 0, 0x2ab7 _ 0)
+NAMED_CHARACTER_REFERENCE(1718,
+ /* p r */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227c _ 0)
+NAMED_CHARACTER_REFERENCE(1719, /* p r */ 'e' _ ';', 2, 0, 0x2aaf _ 0)
+NAMED_CHARACTER_REFERENCE(1720, /* p r */ 'e' _ 'c' _ ';', 3, 0, 0x227a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1721,
+ /* p r */ 'e' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0,
+ 0x2ab7 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1722,
+ /* p r */ 'e' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0,
+ 0x227c _ 0)
+NAMED_CHARACTER_REFERENCE(1723,
+ /* p r */ 'e' _ 'c' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x2aaf _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1724,
+ /* p r */ 'e' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0,
+ 0x2ab9 _ 0)
+NAMED_CHARACTER_REFERENCE(1725,
+ /* p r */ 'e' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7,
+ 0, 0x2ab5 _ 0)
+NAMED_CHARACTER_REFERENCE(1726,
+ /* p r */ 'e' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7,
+ 0, 0x22e8 _ 0)
+NAMED_CHARACTER_REFERENCE(1727,
+ /* p r */ 'e' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x227e _ 0)
+NAMED_CHARACTER_REFERENCE(1728,
+ /* p r */ 'i' _ 'm' _ 'e' _ ';', 4, 0, 0x2032 _ 0)
+NAMED_CHARACTER_REFERENCE(1729,
+ /* p r */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0,
+ 0x2119 _ 0)
+NAMED_CHARACTER_REFERENCE(1730, /* p r */ 'n' _ 'E' _ ';', 3, 0, 0x2ab5 _ 0)
+NAMED_CHARACTER_REFERENCE(1731,
+ /* p r */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2ab9 _ 0)
+NAMED_CHARACTER_REFERENCE(1732,
+ /* p r */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x22e8 _ 0)
+NAMED_CHARACTER_REFERENCE(1733, /* p r */ 'o' _ 'd' _ ';', 3, 0, 0x220f _ 0)
+NAMED_CHARACTER_REFERENCE(1734,
+ /* p r */ 'o' _ 'f' _ 'a' _ 'l' _ 'a' _ 'r' _ ';', 7,
+ 0, 0x232e _ 0)
+NAMED_CHARACTER_REFERENCE(1735,
+ /* p r */ 'o' _ 'f' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 7,
+ 0, 0x2312 _ 0)
+NAMED_CHARACTER_REFERENCE(1736,
+ /* p r */ 'o' _ 'f' _ 's' _ 'u' _ 'r' _ 'f' _ ';', 7,
+ 0, 0x2313 _ 0)
+NAMED_CHARACTER_REFERENCE(1737, /* p r */ 'o' _ 'p' _ ';', 3, 0, 0x221d _ 0)
+NAMED_CHARACTER_REFERENCE(1738,
+ /* p r */ 'o' _ 'p' _ 't' _ 'o' _ ';', 5, 0,
+ 0x221d _ 0)
+NAMED_CHARACTER_REFERENCE(1739,
+ /* p r */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227e _ 0)
+NAMED_CHARACTER_REFERENCE(1740,
+ /* p r */ 'u' _ 'r' _ 'e' _ 'l' _ ';', 5, 0,
+ 0x22b0 _ 0)
+NAMED_CHARACTER_REFERENCE(1741,
+ /* p s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc5)
+NAMED_CHARACTER_REFERENCE(1742, /* p s */ 'i' _ ';', 2, 0, 0x03c8 _ 0)
+NAMED_CHARACTER_REFERENCE(1743,
+ /* p u */ 'n' _ 'c' _ 's' _ 'p' _ ';', 5, 0,
+ 0x2008 _ 0)
+NAMED_CHARACTER_REFERENCE(1744, /* q f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2e)
+NAMED_CHARACTER_REFERENCE(1745, /* q i */ 'n' _ 't' _ ';', 3, 0, 0x2a0c _ 0)
+NAMED_CHARACTER_REFERENCE(1746,
+ /* q o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd62)
+NAMED_CHARACTER_REFERENCE(1747,
+ /* q p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0,
+ 0x2057 _ 0)
+NAMED_CHARACTER_REFERENCE(1748,
+ /* q s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc6)
+NAMED_CHARACTER_REFERENCE(
+ 1749,
+ /* q u */ 'a' _ 't' _ 'e' _ 'r' _ 'n' _ 'i' _ 'o' _ 'n' _ 's' _ ';', 10, 0,
+ 0x210d _ 0)
+NAMED_CHARACTER_REFERENCE(1750,
+ /* q u */ 'a' _ 't' _ 'i' _ 'n' _ 't' _ ';', 6, 0,
+ 0x2a16 _ 0)
+NAMED_CHARACTER_REFERENCE(1751,
+ /* q u */ 'e' _ 's' _ 't' _ ';', 4, 0, 0x003f _ 0)
+NAMED_CHARACTER_REFERENCE(1752,
+ /* q u */ 'e' _ 's' _ 't' _ 'e' _ 'q' _ ';', 6, 0,
+ 0x225f _ 0)
+NAMED_CHARACTER_REFERENCE(1753, /* q u */ 'o' _ 't', 2, 0, 0x0022 _ 0)
+NAMED_CHARACTER_REFERENCE(1754, /* q u */ 'o' _ 't' _ ';', 3, 0, 0x0022 _ 0)
+NAMED_CHARACTER_REFERENCE(1755,
+ /* r A */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21db _ 0)
+NAMED_CHARACTER_REFERENCE(1756, /* r A */ 'r' _ 'r' _ ';', 3, 0, 0x21d2 _ 0)
+NAMED_CHARACTER_REFERENCE(1757,
+ /* r A */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x291c _ 0)
+NAMED_CHARACTER_REFERENCE(1758,
+ /* r B */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290f _ 0)
+NAMED_CHARACTER_REFERENCE(1759, /* r H */ 'a' _ 'r' _ ';', 3, 0, 0x2964 _ 0)
+NAMED_CHARACTER_REFERENCE(1760,
+ /* r a */ 'c' _ 'e' _ ';', 3, 0, 0x223d _ 0x0331)
+NAMED_CHARACTER_REFERENCE(1761,
+ /* r a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x0155 _ 0)
+NAMED_CHARACTER_REFERENCE(1762,
+ /* r a */ 'd' _ 'i' _ 'c' _ ';', 4, 0, 0x221a _ 0)
+NAMED_CHARACTER_REFERENCE(1763,
+ /* r a */ 'e' _ 'm' _ 'p' _ 't' _ 'y' _ 'v' _ ';', 7,
+ 0, 0x29b3 _ 0)
+NAMED_CHARACTER_REFERENCE(1764, /* r a */ 'n' _ 'g' _ ';', 3, 0, 0x27e9 _ 0)
+NAMED_CHARACTER_REFERENCE(1765,
+ /* r a */ 'n' _ 'g' _ 'd' _ ';', 4, 0, 0x2992 _ 0)
+NAMED_CHARACTER_REFERENCE(1766,
+ /* r a */ 'n' _ 'g' _ 'e' _ ';', 4, 0, 0x29a5 _ 0)
+NAMED_CHARACTER_REFERENCE(1767,
+ /* r a */ 'n' _ 'g' _ 'l' _ 'e' _ ';', 5, 0,
+ 0x27e9 _ 0)
+NAMED_CHARACTER_REFERENCE(1768, /* r a */ 'q' _ 'u' _ 'o', 3, 0, 0x00bb _ 0)
+NAMED_CHARACTER_REFERENCE(1769,
+ /* r a */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x00bb _ 0)
+NAMED_CHARACTER_REFERENCE(1770, /* r a */ 'r' _ 'r' _ ';', 3, 0, 0x2192 _ 0)
+NAMED_CHARACTER_REFERENCE(1771,
+ /* r a */ 'r' _ 'r' _ 'a' _ 'p' _ ';', 5, 0,
+ 0x2975 _ 0)
+NAMED_CHARACTER_REFERENCE(1772,
+ /* r a */ 'r' _ 'r' _ 'b' _ ';', 4, 0, 0x21e5 _ 0)
+NAMED_CHARACTER_REFERENCE(1773,
+ /* r a */ 'r' _ 'r' _ 'b' _ 'f' _ 's' _ ';', 6, 0,
+ 0x2920 _ 0)
+NAMED_CHARACTER_REFERENCE(1774,
+ /* r a */ 'r' _ 'r' _ 'c' _ ';', 4, 0, 0x2933 _ 0)
+NAMED_CHARACTER_REFERENCE(1775,
+ /* r a */ 'r' _ 'r' _ 'f' _ 's' _ ';', 5, 0,
+ 0x291e _ 0)
+NAMED_CHARACTER_REFERENCE(1776,
+ /* r a */ 'r' _ 'r' _ 'h' _ 'k' _ ';', 5, 0,
+ 0x21aa _ 0)
+NAMED_CHARACTER_REFERENCE(1777,
+ /* r a */ 'r' _ 'r' _ 'l' _ 'p' _ ';', 5, 0,
+ 0x21ac _ 0)
+NAMED_CHARACTER_REFERENCE(1778,
+ /* r a */ 'r' _ 'r' _ 'p' _ 'l' _ ';', 5, 0,
+ 0x2945 _ 0)
+NAMED_CHARACTER_REFERENCE(1779,
+ /* r a */ 'r' _ 'r' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x2974 _ 0)
+NAMED_CHARACTER_REFERENCE(1780,
+ /* r a */ 'r' _ 'r' _ 't' _ 'l' _ ';', 5, 0,
+ 0x21a3 _ 0)
+NAMED_CHARACTER_REFERENCE(1781,
+ /* r a */ 'r' _ 'r' _ 'w' _ ';', 4, 0, 0x219d _ 0)
+NAMED_CHARACTER_REFERENCE(1782,
+ /* r a */ 't' _ 'a' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x291a _ 0)
+NAMED_CHARACTER_REFERENCE(1783,
+ /* r a */ 't' _ 'i' _ 'o' _ ';', 4, 0, 0x2236 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1784,
+ /* r a */ 't' _ 'i' _ 'o' _ 'n' _ 'a' _ 'l' _ 's' _ ';', 8, 0, 0x211a _ 0)
+NAMED_CHARACTER_REFERENCE(1785,
+ /* r b */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x290d _ 0)
+NAMED_CHARACTER_REFERENCE(1786,
+ /* r b */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x2773 _ 0)
+NAMED_CHARACTER_REFERENCE(1787,
+ /* r b */ 'r' _ 'a' _ 'c' _ 'e' _ ';', 5, 0,
+ 0x007d _ 0)
+NAMED_CHARACTER_REFERENCE(1788,
+ /* r b */ 'r' _ 'a' _ 'c' _ 'k' _ ';', 5, 0,
+ 0x005d _ 0)
+NAMED_CHARACTER_REFERENCE(1789,
+ /* r b */ 'r' _ 'k' _ 'e' _ ';', 4, 0, 0x298c _ 0)
+NAMED_CHARACTER_REFERENCE(1790,
+ /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'd' _ ';', 6, 0,
+ 0x298e _ 0)
+NAMED_CHARACTER_REFERENCE(1791,
+ /* r b */ 'r' _ 'k' _ 's' _ 'l' _ 'u' _ ';', 6, 0,
+ 0x2990 _ 0)
+NAMED_CHARACTER_REFERENCE(1792,
+ /* r c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0159 _ 0)
+NAMED_CHARACTER_REFERENCE(1793,
+ /* r c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0157 _ 0)
+NAMED_CHARACTER_REFERENCE(1794,
+ /* r c */ 'e' _ 'i' _ 'l' _ ';', 4, 0, 0x2309 _ 0)
+NAMED_CHARACTER_REFERENCE(1795, /* r c */ 'u' _ 'b' _ ';', 3, 0, 0x007d _ 0)
+NAMED_CHARACTER_REFERENCE(1796, /* r c */ 'y' _ ';', 2, 0, 0x0440 _ 0)
+NAMED_CHARACTER_REFERENCE(1797, /* r d */ 'c' _ 'a' _ ';', 3, 0, 0x2937 _ 0)
+NAMED_CHARACTER_REFERENCE(1798,
+ /* r d */ 'l' _ 'd' _ 'h' _ 'a' _ 'r' _ ';', 6, 0,
+ 0x2969 _ 0)
+NAMED_CHARACTER_REFERENCE(1799,
+ /* r d */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201d _ 0)
+NAMED_CHARACTER_REFERENCE(1800,
+ /* r d */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0,
+ 0x201d _ 0)
+NAMED_CHARACTER_REFERENCE(1801, /* r d */ 's' _ 'h' _ ';', 3, 0, 0x21b3 _ 0)
+NAMED_CHARACTER_REFERENCE(1802, /* r e */ 'a' _ 'l' _ ';', 3, 0, 0x211c _ 0)
+NAMED_CHARACTER_REFERENCE(1803,
+ /* r e */ 'a' _ 'l' _ 'i' _ 'n' _ 'e' _ ';', 6, 0,
+ 0x211b _ 0)
+NAMED_CHARACTER_REFERENCE(1804,
+ /* r e */ 'a' _ 'l' _ 'p' _ 'a' _ 'r' _ 't' _ ';', 7,
+ 0, 0x211c _ 0)
+NAMED_CHARACTER_REFERENCE(1805,
+ /* r e */ 'a' _ 'l' _ 's' _ ';', 4, 0, 0x211d _ 0)
+NAMED_CHARACTER_REFERENCE(1806, /* r e */ 'c' _ 't' _ ';', 3, 0, 0x25ad _ 0)
+NAMED_CHARACTER_REFERENCE(1807, /* r e */ 'g', 1, 0, 0x00ae _ 0)
+NAMED_CHARACTER_REFERENCE(1808, /* r e */ 'g' _ ';', 2, 0, 0x00ae _ 0)
+NAMED_CHARACTER_REFERENCE(1809,
+ /* r f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0,
+ 0x297d _ 0)
+NAMED_CHARACTER_REFERENCE(1810,
+ /* r f */ 'l' _ 'o' _ 'o' _ 'r' _ ';', 5, 0,
+ 0x230b _ 0)
+NAMED_CHARACTER_REFERENCE(1811, /* r f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd2f)
+NAMED_CHARACTER_REFERENCE(1812,
+ /* r h */ 'a' _ 'r' _ 'd' _ ';', 4, 0, 0x21c1 _ 0)
+NAMED_CHARACTER_REFERENCE(1813,
+ /* r h */ 'a' _ 'r' _ 'u' _ ';', 4, 0, 0x21c0 _ 0)
+NAMED_CHARACTER_REFERENCE(1814,
+ /* r h */ 'a' _ 'r' _ 'u' _ 'l' _ ';', 5, 0,
+ 0x296c _ 0)
+NAMED_CHARACTER_REFERENCE(1815, /* r h */ 'o' _ ';', 2, 0, 0x03c1 _ 0)
+NAMED_CHARACTER_REFERENCE(1816, /* r h */ 'o' _ 'v' _ ';', 3, 0, 0x03f1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1817,
+ /* r i */ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 9, 0,
+ 0x2192 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1818,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 't' _ 'a' _ 'i' _ 'l' _ ';',
+ 13, 0, 0x21a3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1819,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'd' _ 'o' _ 'w' _ 'n' _ ';',
+ 15, 0, 0x21c1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1820,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'u' _ 'p' _ ';',
+ 13, 0, 0x21c0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1821,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';',
+ 14, 0, 0x21c4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1822,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 'l' _ 'e' _ 'f' _ 't' _ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 's' _ ';',
+ 16, 0, 0x21cc _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1823,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';',
+ 15, 0, 0x21c9 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1824,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 's' _ 'q' _ 'u' _ 'i' _ 'g' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 14, 0, 0x219d _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1825,
+ /* r i */
+ 'g' _ 'h' _ 't' _ 't' _ 'h' _ 'r' _ 'e' _ 'e' _ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';',
+ 14, 0, 0x22cc _ 0)
+NAMED_CHARACTER_REFERENCE(1826, /* r i */ 'n' _ 'g' _ ';', 3, 0, 0x02da _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1827,
+ /* r i */ 's' _ 'i' _ 'n' _ 'g' _ 'd' _ 'o' _ 't' _ 's' _ 'e' _ 'q' _ ';',
+ 11, 0, 0x2253 _ 0)
+NAMED_CHARACTER_REFERENCE(1828,
+ /* r l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c4 _ 0)
+NAMED_CHARACTER_REFERENCE(1829,
+ /* r l */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x21cc _ 0)
+NAMED_CHARACTER_REFERENCE(1830, /* r l */ 'm' _ ';', 2, 0, 0x200f _ 0)
+NAMED_CHARACTER_REFERENCE(1831,
+ /* r m */ 'o' _ 'u' _ 's' _ 't' _ ';', 5, 0,
+ 0x23b1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1832,
+ /* r m */ 'o' _ 'u' _ 's' _ 't' _ 'a' _ 'c' _ 'h' _ 'e' _ ';', 9, 0,
+ 0x23b1 _ 0)
+NAMED_CHARACTER_REFERENCE(1833,
+ /* r n */ 'm' _ 'i' _ 'd' _ ';', 4, 0, 0x2aee _ 0)
+NAMED_CHARACTER_REFERENCE(1834,
+ /* r o */ 'a' _ 'n' _ 'g' _ ';', 4, 0, 0x27ed _ 0)
+NAMED_CHARACTER_REFERENCE(1835,
+ /* r o */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21fe _ 0)
+NAMED_CHARACTER_REFERENCE(1836,
+ /* r o */ 'b' _ 'r' _ 'k' _ ';', 4, 0, 0x27e7 _ 0)
+NAMED_CHARACTER_REFERENCE(1837,
+ /* r o */ 'p' _ 'a' _ 'r' _ ';', 4, 0, 0x2986 _ 0)
+NAMED_CHARACTER_REFERENCE(1838,
+ /* r o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd63)
+NAMED_CHARACTER_REFERENCE(1839,
+ /* r o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2a2e _ 0)
+NAMED_CHARACTER_REFERENCE(1840,
+ /* r o */ 't' _ 'i' _ 'm' _ 'e' _ 's' _ ';', 6, 0,
+ 0x2a35 _ 0)
+NAMED_CHARACTER_REFERENCE(1841, /* r p */ 'a' _ 'r' _ ';', 3, 0, 0x0029 _ 0)
+NAMED_CHARACTER_REFERENCE(1842,
+ /* r p */ 'a' _ 'r' _ 'g' _ 't' _ ';', 5, 0,
+ 0x2994 _ 0)
+NAMED_CHARACTER_REFERENCE(1843,
+ /* r p */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a12 _ 0)
+NAMED_CHARACTER_REFERENCE(1844,
+ /* r r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c9 _ 0)
+NAMED_CHARACTER_REFERENCE(1845,
+ /* r s */ 'a' _ 'q' _ 'u' _ 'o' _ ';', 5, 0,
+ 0x203a _ 0)
+NAMED_CHARACTER_REFERENCE(1846,
+ /* r s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc7)
+NAMED_CHARACTER_REFERENCE(1847, /* r s */ 'h' _ ';', 2, 0, 0x21b1 _ 0)
+NAMED_CHARACTER_REFERENCE(1848, /* r s */ 'q' _ 'b' _ ';', 3, 0, 0x005d _ 0)
+NAMED_CHARACTER_REFERENCE(1849,
+ /* r s */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x2019 _ 0)
+NAMED_CHARACTER_REFERENCE(1850,
+ /* r s */ 'q' _ 'u' _ 'o' _ 'r' _ ';', 5, 0,
+ 0x2019 _ 0)
+NAMED_CHARACTER_REFERENCE(1851,
+ /* r t */ 'h' _ 'r' _ 'e' _ 'e' _ ';', 5, 0,
+ 0x22cc _ 0)
+NAMED_CHARACTER_REFERENCE(1852,
+ /* r t */ 'i' _ 'm' _ 'e' _ 's' _ ';', 5, 0,
+ 0x22ca _ 0)
+NAMED_CHARACTER_REFERENCE(1853, /* r t */ 'r' _ 'i' _ ';', 3, 0, 0x25b9 _ 0)
+NAMED_CHARACTER_REFERENCE(1854,
+ /* r t */ 'r' _ 'i' _ 'e' _ ';', 4, 0, 0x22b5 _ 0)
+NAMED_CHARACTER_REFERENCE(1855,
+ /* r t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b8 _ 0)
+NAMED_CHARACTER_REFERENCE(1856,
+ /* r t */ 'r' _ 'i' _ 'l' _ 't' _ 'r' _ 'i' _ ';', 7,
+ 0, 0x29ce _ 0)
+NAMED_CHARACTER_REFERENCE(1857,
+ /* r u */ 'l' _ 'u' _ 'h' _ 'a' _ 'r' _ ';', 6, 0,
+ 0x2968 _ 0)
+NAMED_CHARACTER_REFERENCE(1858, /* r x */ ';', 1, 0, 0x211e _ 0)
+NAMED_CHARACTER_REFERENCE(1859,
+ /* s a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x015b _ 0)
+NAMED_CHARACTER_REFERENCE(1860,
+ /* s b */ 'q' _ 'u' _ 'o' _ ';', 4, 0, 0x201a _ 0)
+NAMED_CHARACTER_REFERENCE(1861, /* s c */ ';', 1, 0, 0x227b _ 0)
+NAMED_CHARACTER_REFERENCE(1862, /* s c */ 'E' _ ';', 2, 0, 0x2ab4 _ 0)
+NAMED_CHARACTER_REFERENCE(1863, /* s c */ 'a' _ 'p' _ ';', 3, 0, 0x2ab8 _ 0)
+NAMED_CHARACTER_REFERENCE(1864,
+ /* s c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0161 _ 0)
+NAMED_CHARACTER_REFERENCE(1865,
+ /* s c */ 'c' _ 'u' _ 'e' _ ';', 4, 0, 0x227d _ 0)
+NAMED_CHARACTER_REFERENCE(1866, /* s c */ 'e' _ ';', 2, 0, 0x2ab0 _ 0)
+NAMED_CHARACTER_REFERENCE(1867,
+ /* s c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x015f _ 0)
+NAMED_CHARACTER_REFERENCE(1868,
+ /* s c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x015d _ 0)
+NAMED_CHARACTER_REFERENCE(1869, /* s c */ 'n' _ 'E' _ ';', 3, 0, 0x2ab6 _ 0)
+NAMED_CHARACTER_REFERENCE(1870,
+ /* s c */ 'n' _ 'a' _ 'p' _ ';', 4, 0, 0x2aba _ 0)
+NAMED_CHARACTER_REFERENCE(1871,
+ /* s c */ 'n' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x22e9 _ 0)
+NAMED_CHARACTER_REFERENCE(1872,
+ /* s c */ 'p' _ 'o' _ 'l' _ 'i' _ 'n' _ 't' _ ';', 7,
+ 0, 0x2a13 _ 0)
+NAMED_CHARACTER_REFERENCE(1873,
+ /* s c */ 's' _ 'i' _ 'm' _ ';', 4, 0, 0x227f _ 0)
+NAMED_CHARACTER_REFERENCE(1874, /* s c */ 'y' _ ';', 2, 0, 0x0441 _ 0)
+NAMED_CHARACTER_REFERENCE(1875, /* s d */ 'o' _ 't' _ ';', 3, 0, 0x22c5 _ 0)
+NAMED_CHARACTER_REFERENCE(1876,
+ /* s d */ 'o' _ 't' _ 'b' _ ';', 4, 0, 0x22a1 _ 0)
+NAMED_CHARACTER_REFERENCE(1877,
+ /* s d */ 'o' _ 't' _ 'e' _ ';', 4, 0, 0x2a66 _ 0)
+NAMED_CHARACTER_REFERENCE(1878,
+ /* s e */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d8 _ 0)
+NAMED_CHARACTER_REFERENCE(1879,
+ /* s e */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0,
+ 0x2925 _ 0)
+NAMED_CHARACTER_REFERENCE(1880,
+ /* s e */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2198 _ 0)
+NAMED_CHARACTER_REFERENCE(1881,
+ /* s e */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x2198 _ 0)
+NAMED_CHARACTER_REFERENCE(1882, /* s e */ 'c' _ 't', 2, 0, 0x00a7 _ 0)
+NAMED_CHARACTER_REFERENCE(1883, /* s e */ 'c' _ 't' _ ';', 3, 0, 0x00a7 _ 0)
+NAMED_CHARACTER_REFERENCE(1884, /* s e */ 'm' _ 'i' _ ';', 3, 0, 0x003b _ 0)
+NAMED_CHARACTER_REFERENCE(1885,
+ /* s e */ 's' _ 'w' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2929 _ 0)
+NAMED_CHARACTER_REFERENCE(1886,
+ /* s e */ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7,
+ 0, 0x2216 _ 0)
+NAMED_CHARACTER_REFERENCE(1887,
+ /* s e */ 't' _ 'm' _ 'n' _ ';', 4, 0, 0x2216 _ 0)
+NAMED_CHARACTER_REFERENCE(1888, /* s e */ 'x' _ 't' _ ';', 3, 0, 0x2736 _ 0)
+NAMED_CHARACTER_REFERENCE(1889, /* s f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd30)
+NAMED_CHARACTER_REFERENCE(1890,
+ /* s f */ 'r' _ 'o' _ 'w' _ 'n' _ ';', 5, 0,
+ 0x2322 _ 0)
+NAMED_CHARACTER_REFERENCE(1891,
+ /* s h */ 'a' _ 'r' _ 'p' _ ';', 4, 0, 0x266f _ 0)
+NAMED_CHARACTER_REFERENCE(1892,
+ /* s h */ 'c' _ 'h' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x0449 _ 0)
+NAMED_CHARACTER_REFERENCE(1893, /* s h */ 'c' _ 'y' _ ';', 3, 0, 0x0448 _ 0)
+NAMED_CHARACTER_REFERENCE(1894,
+ /* s h */ 'o' _ 'r' _ 't' _ 'm' _ 'i' _ 'd' _ ';', 7,
+ 0, 0x2223 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1895,
+ /* s h */
+ 'o' _ 'r' _ 't' _ 'p' _ 'a' _ 'r' _ 'a' _ 'l' _ 'l' _ 'e' _ 'l' _ ';', 12,
+ 0, 0x2225 _ 0)
+NAMED_CHARACTER_REFERENCE(1896, /* s h */ 'y', 1, 0, 0x00ad _ 0)
+NAMED_CHARACTER_REFERENCE(1897, /* s h */ 'y' _ ';', 2, 0, 0x00ad _ 0)
+NAMED_CHARACTER_REFERENCE(1898,
+ /* s i */ 'g' _ 'm' _ 'a' _ ';', 4, 0, 0x03c3 _ 0)
+NAMED_CHARACTER_REFERENCE(1899,
+ /* s i */ 'g' _ 'm' _ 'a' _ 'f' _ ';', 5, 0,
+ 0x03c2 _ 0)
+NAMED_CHARACTER_REFERENCE(1900,
+ /* s i */ 'g' _ 'm' _ 'a' _ 'v' _ ';', 5, 0,
+ 0x03c2 _ 0)
+NAMED_CHARACTER_REFERENCE(1901, /* s i */ 'm' _ ';', 2, 0, 0x223c _ 0)
+NAMED_CHARACTER_REFERENCE(1902,
+ /* s i */ 'm' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2a6a _ 0)
+NAMED_CHARACTER_REFERENCE(1903, /* s i */ 'm' _ 'e' _ ';', 3, 0, 0x2243 _ 0)
+NAMED_CHARACTER_REFERENCE(1904,
+ /* s i */ 'm' _ 'e' _ 'q' _ ';', 4, 0, 0x2243 _ 0)
+NAMED_CHARACTER_REFERENCE(1905, /* s i */ 'm' _ 'g' _ ';', 3, 0, 0x2a9e _ 0)
+NAMED_CHARACTER_REFERENCE(1906,
+ /* s i */ 'm' _ 'g' _ 'E' _ ';', 4, 0, 0x2aa0 _ 0)
+NAMED_CHARACTER_REFERENCE(1907, /* s i */ 'm' _ 'l' _ ';', 3, 0, 0x2a9d _ 0)
+NAMED_CHARACTER_REFERENCE(1908,
+ /* s i */ 'm' _ 'l' _ 'E' _ ';', 4, 0, 0x2a9f _ 0)
+NAMED_CHARACTER_REFERENCE(1909,
+ /* s i */ 'm' _ 'n' _ 'e' _ ';', 4, 0, 0x2246 _ 0)
+NAMED_CHARACTER_REFERENCE(1910,
+ /* s i */ 'm' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0,
+ 0x2a24 _ 0)
+NAMED_CHARACTER_REFERENCE(1911,
+ /* s i */ 'm' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0,
+ 0x2972 _ 0)
+NAMED_CHARACTER_REFERENCE(1912,
+ /* s l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2190 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1913,
+ /* s m */
+ 'a' _ 'l' _ 'l' _ 's' _ 'e' _ 't' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 12,
+ 0, 0x2216 _ 0)
+NAMED_CHARACTER_REFERENCE(1914,
+ /* s m */ 'a' _ 's' _ 'h' _ 'p' _ ';', 5, 0,
+ 0x2a33 _ 0)
+NAMED_CHARACTER_REFERENCE(1915,
+ /* s m */ 'e' _ 'p' _ 'a' _ 'r' _ 's' _ 'l' _ ';', 7,
+ 0, 0x29e4 _ 0)
+NAMED_CHARACTER_REFERENCE(1916, /* s m */ 'i' _ 'd' _ ';', 3, 0, 0x2223 _ 0)
+NAMED_CHARACTER_REFERENCE(1917,
+ /* s m */ 'i' _ 'l' _ 'e' _ ';', 4, 0, 0x2323 _ 0)
+NAMED_CHARACTER_REFERENCE(1918, /* s m */ 't' _ ';', 2, 0, 0x2aaa _ 0)
+NAMED_CHARACTER_REFERENCE(1919, /* s m */ 't' _ 'e' _ ';', 3, 0, 0x2aac _ 0)
+NAMED_CHARACTER_REFERENCE(1920,
+ /* s m */ 't' _ 'e' _ 's' _ ';', 4, 0,
+ 0x2aac _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1921,
+ /* s o */ 'f' _ 't' _ 'c' _ 'y' _ ';', 5, 0,
+ 0x044c _ 0)
+NAMED_CHARACTER_REFERENCE(1922, /* s o */ 'l' _ ';', 2, 0, 0x002f _ 0)
+NAMED_CHARACTER_REFERENCE(1923, /* s o */ 'l' _ 'b' _ ';', 3, 0, 0x29c4 _ 0)
+NAMED_CHARACTER_REFERENCE(1924,
+ /* s o */ 'l' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x233f _ 0)
+NAMED_CHARACTER_REFERENCE(1925,
+ /* s o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd64)
+NAMED_CHARACTER_REFERENCE(1926,
+ /* s p */ 'a' _ 'd' _ 'e' _ 's' _ ';', 5, 0,
+ 0x2660 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1927,
+ /* s p */ 'a' _ 'd' _ 'e' _ 's' _ 'u' _ 'i' _ 't' _ ';', 8, 0, 0x2660 _ 0)
+NAMED_CHARACTER_REFERENCE(1928, /* s p */ 'a' _ 'r' _ ';', 3, 0, 0x2225 _ 0)
+NAMED_CHARACTER_REFERENCE(1929,
+ /* s q */ 'c' _ 'a' _ 'p' _ ';', 4, 0, 0x2293 _ 0)
+NAMED_CHARACTER_REFERENCE(1930,
+ /* s q */ 'c' _ 'a' _ 'p' _ 's' _ ';', 5, 0,
+ 0x2293 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1931,
+ /* s q */ 'c' _ 'u' _ 'p' _ ';', 4, 0, 0x2294 _ 0)
+NAMED_CHARACTER_REFERENCE(1932,
+ /* s q */ 'c' _ 'u' _ 'p' _ 's' _ ';', 5, 0,
+ 0x2294 _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(1933,
+ /* s q */ 's' _ 'u' _ 'b' _ ';', 4, 0, 0x228f _ 0)
+NAMED_CHARACTER_REFERENCE(1934,
+ /* s q */ 's' _ 'u' _ 'b' _ 'e' _ ';', 5, 0,
+ 0x2291 _ 0)
+NAMED_CHARACTER_REFERENCE(1935,
+ /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ ';', 7,
+ 0, 0x228f _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1936,
+ /* s q */ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0,
+ 0x2291 _ 0)
+NAMED_CHARACTER_REFERENCE(1937,
+ /* s q */ 's' _ 'u' _ 'p' _ ';', 4, 0, 0x2290 _ 0)
+NAMED_CHARACTER_REFERENCE(1938,
+ /* s q */ 's' _ 'u' _ 'p' _ 'e' _ ';', 5, 0,
+ 0x2292 _ 0)
+NAMED_CHARACTER_REFERENCE(1939,
+ /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ ';', 7,
+ 0, 0x2290 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1940,
+ /* s q */ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 9, 0,
+ 0x2292 _ 0)
+NAMED_CHARACTER_REFERENCE(1941, /* s q */ 'u' _ ';', 2, 0, 0x25a1 _ 0)
+NAMED_CHARACTER_REFERENCE(1942,
+ /* s q */ 'u' _ 'a' _ 'r' _ 'e' _ ';', 5, 0,
+ 0x25a1 _ 0)
+NAMED_CHARACTER_REFERENCE(1943,
+ /* s q */ 'u' _ 'a' _ 'r' _ 'f' _ ';', 5, 0,
+ 0x25aa _ 0)
+NAMED_CHARACTER_REFERENCE(1944, /* s q */ 'u' _ 'f' _ ';', 3, 0, 0x25aa _ 0)
+NAMED_CHARACTER_REFERENCE(1945,
+ /* s r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2192 _ 0)
+NAMED_CHARACTER_REFERENCE(1946,
+ /* s s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc8)
+NAMED_CHARACTER_REFERENCE(1947,
+ /* s s */ 'e' _ 't' _ 'm' _ 'n' _ ';', 5, 0,
+ 0x2216 _ 0)
+NAMED_CHARACTER_REFERENCE(1948,
+ /* s s */ 'm' _ 'i' _ 'l' _ 'e' _ ';', 5, 0,
+ 0x2323 _ 0)
+NAMED_CHARACTER_REFERENCE(1949,
+ /* s s */ 't' _ 'a' _ 'r' _ 'f' _ ';', 5, 0,
+ 0x22c6 _ 0)
+NAMED_CHARACTER_REFERENCE(1950, /* s t */ 'a' _ 'r' _ ';', 3, 0, 0x2606 _ 0)
+NAMED_CHARACTER_REFERENCE(1951,
+ /* s t */ 'a' _ 'r' _ 'f' _ ';', 4, 0, 0x2605 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1952,
+ /* s t */
+ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';',
+ 14, 0, 0x03f5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1953,
+ /* s t */ 'r' _ 'a' _ 'i' _ 'g' _ 'h' _ 't' _ 'p' _ 'h' _ 'i' _ ';', 10, 0,
+ 0x03d5 _ 0)
+NAMED_CHARACTER_REFERENCE(1954,
+ /* s t */ 'r' _ 'n' _ 's' _ ';', 4, 0, 0x00af _ 0)
+NAMED_CHARACTER_REFERENCE(1955, /* s u */ 'b' _ ';', 2, 0, 0x2282 _ 0)
+NAMED_CHARACTER_REFERENCE(1956, /* s u */ 'b' _ 'E' _ ';', 3, 0, 0x2ac5 _ 0)
+NAMED_CHARACTER_REFERENCE(1957,
+ /* s u */ 'b' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2abd _ 0)
+NAMED_CHARACTER_REFERENCE(1958, /* s u */ 'b' _ 'e' _ ';', 3, 0, 0x2286 _ 0)
+NAMED_CHARACTER_REFERENCE(1959,
+ /* s u */ 'b' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0,
+ 0x2ac3 _ 0)
+NAMED_CHARACTER_REFERENCE(1960,
+ /* s u */ 'b' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0,
+ 0x2ac1 _ 0)
+NAMED_CHARACTER_REFERENCE(1961,
+ /* s u */ 'b' _ 'n' _ 'E' _ ';', 4, 0, 0x2acb _ 0)
+NAMED_CHARACTER_REFERENCE(1962,
+ /* s u */ 'b' _ 'n' _ 'e' _ ';', 4, 0, 0x228a _ 0)
+NAMED_CHARACTER_REFERENCE(1963,
+ /* s u */ 'b' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0,
+ 0x2abf _ 0)
+NAMED_CHARACTER_REFERENCE(1964,
+ /* s u */ 'b' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0,
+ 0x2979 _ 0)
+NAMED_CHARACTER_REFERENCE(1965,
+ /* s u */ 'b' _ 's' _ 'e' _ 't' _ ';', 5, 0,
+ 0x2282 _ 0)
+NAMED_CHARACTER_REFERENCE(1966,
+ /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7,
+ 0, 0x2286 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1967,
+ /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1968,
+ /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228a _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1969,
+ /* s u */ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0,
+ 0x2acb _ 0)
+NAMED_CHARACTER_REFERENCE(1970,
+ /* s u */ 'b' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x2ac7 _ 0)
+NAMED_CHARACTER_REFERENCE(1971,
+ /* s u */ 'b' _ 's' _ 'u' _ 'b' _ ';', 5, 0,
+ 0x2ad5 _ 0)
+NAMED_CHARACTER_REFERENCE(1972,
+ /* s u */ 'b' _ 's' _ 'u' _ 'p' _ ';', 5, 0,
+ 0x2ad3 _ 0)
+NAMED_CHARACTER_REFERENCE(1973, /* s u */ 'c' _ 'c' _ ';', 3, 0, 0x227b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1974,
+ /* s u */ 'c' _ 'c' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 9, 0,
+ 0x2ab8 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1975,
+ /* s u */ 'c' _ 'c' _ 'c' _ 'u' _ 'r' _ 'l' _ 'y' _ 'e' _ 'q' _ ';', 10, 0,
+ 0x227d _ 0)
+NAMED_CHARACTER_REFERENCE(1976,
+ /* s u */ 'c' _ 'c' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x2ab0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 1977,
+ /* s u */ 'c' _ 'c' _ 'n' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0,
+ 0x2aba _ 0)
+NAMED_CHARACTER_REFERENCE(1978,
+ /* s u */ 'c' _ 'c' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 7,
+ 0, 0x2ab6 _ 0)
+NAMED_CHARACTER_REFERENCE(1979,
+ /* s u */ 'c' _ 'c' _ 'n' _ 's' _ 'i' _ 'm' _ ';', 7,
+ 0, 0x22e9 _ 0)
+NAMED_CHARACTER_REFERENCE(1980,
+ /* s u */ 'c' _ 'c' _ 's' _ 'i' _ 'm' _ ';', 6, 0,
+ 0x227f _ 0)
+NAMED_CHARACTER_REFERENCE(1981, /* s u */ 'm' _ ';', 2, 0, 0x2211 _ 0)
+NAMED_CHARACTER_REFERENCE(1982, /* s u */ 'n' _ 'g' _ ';', 3, 0, 0x266a _ 0)
+NAMED_CHARACTER_REFERENCE(1983, /* s u */ 'p' _ '1', 2, 0, 0x00b9 _ 0)
+NAMED_CHARACTER_REFERENCE(1984, /* s u */ 'p' _ '1' _ ';', 3, 0, 0x00b9 _ 0)
+NAMED_CHARACTER_REFERENCE(1985, /* s u */ 'p' _ '2', 2, 0, 0x00b2 _ 0)
+NAMED_CHARACTER_REFERENCE(1986, /* s u */ 'p' _ '2' _ ';', 3, 0, 0x00b2 _ 0)
+NAMED_CHARACTER_REFERENCE(1987, /* s u */ 'p' _ '3', 2, 0, 0x00b3 _ 0)
+NAMED_CHARACTER_REFERENCE(1988, /* s u */ 'p' _ '3' _ ';', 3, 0, 0x00b3 _ 0)
+NAMED_CHARACTER_REFERENCE(1989, /* s u */ 'p' _ ';', 2, 0, 0x2283 _ 0)
+NAMED_CHARACTER_REFERENCE(1990, /* s u */ 'p' _ 'E' _ ';', 3, 0, 0x2ac6 _ 0)
+NAMED_CHARACTER_REFERENCE(1991,
+ /* s u */ 'p' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2abe _ 0)
+NAMED_CHARACTER_REFERENCE(1992,
+ /* s u */ 'p' _ 'd' _ 's' _ 'u' _ 'b' _ ';', 6, 0,
+ 0x2ad8 _ 0)
+NAMED_CHARACTER_REFERENCE(1993, /* s u */ 'p' _ 'e' _ ';', 3, 0, 0x2287 _ 0)
+NAMED_CHARACTER_REFERENCE(1994,
+ /* s u */ 'p' _ 'e' _ 'd' _ 'o' _ 't' _ ';', 6, 0,
+ 0x2ac4 _ 0)
+NAMED_CHARACTER_REFERENCE(1995,
+ /* s u */ 'p' _ 'h' _ 's' _ 'o' _ 'l' _ ';', 6, 0,
+ 0x27c9 _ 0)
+NAMED_CHARACTER_REFERENCE(1996,
+ /* s u */ 'p' _ 'h' _ 's' _ 'u' _ 'b' _ ';', 6, 0,
+ 0x2ad7 _ 0)
+NAMED_CHARACTER_REFERENCE(1997,
+ /* s u */ 'p' _ 'l' _ 'a' _ 'r' _ 'r' _ ';', 6, 0,
+ 0x297b _ 0)
+NAMED_CHARACTER_REFERENCE(1998,
+ /* s u */ 'p' _ 'm' _ 'u' _ 'l' _ 't' _ ';', 6, 0,
+ 0x2ac2 _ 0)
+NAMED_CHARACTER_REFERENCE(1999,
+ /* s u */ 'p' _ 'n' _ 'E' _ ';', 4, 0, 0x2acc _ 0)
+NAMED_CHARACTER_REFERENCE(2000,
+ /* s u */ 'p' _ 'n' _ 'e' _ ';', 4, 0, 0x228b _ 0)
+NAMED_CHARACTER_REFERENCE(2001,
+ /* s u */ 'p' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0,
+ 0x2ac0 _ 0)
+NAMED_CHARACTER_REFERENCE(2002,
+ /* s u */ 'p' _ 's' _ 'e' _ 't' _ ';', 5, 0,
+ 0x2283 _ 0)
+NAMED_CHARACTER_REFERENCE(2003,
+ /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ ';', 7,
+ 0, 0x2287 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2004,
+ /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'e' _ 'q' _ 'q' _ ';', 8, 0, 0x2ac6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2005,
+ /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';', 8, 0, 0x228b _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2006,
+ /* s u */ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 9, 0,
+ 0x2acc _ 0)
+NAMED_CHARACTER_REFERENCE(2007,
+ /* s u */ 'p' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x2ac8 _ 0)
+NAMED_CHARACTER_REFERENCE(2008,
+ /* s u */ 'p' _ 's' _ 'u' _ 'b' _ ';', 5, 0,
+ 0x2ad4 _ 0)
+NAMED_CHARACTER_REFERENCE(2009,
+ /* s u */ 'p' _ 's' _ 'u' _ 'p' _ ';', 5, 0,
+ 0x2ad6 _ 0)
+NAMED_CHARACTER_REFERENCE(2010,
+ /* s w */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x21d9 _ 0)
+NAMED_CHARACTER_REFERENCE(2011,
+ /* s w */ 'a' _ 'r' _ 'h' _ 'k' _ ';', 5, 0,
+ 0x2926 _ 0)
+NAMED_CHARACTER_REFERENCE(2012,
+ /* s w */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x2199 _ 0)
+NAMED_CHARACTER_REFERENCE(2013,
+ /* s w */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x2199 _ 0)
+NAMED_CHARACTER_REFERENCE(2014,
+ /* s w */ 'n' _ 'w' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x292a _ 0)
+NAMED_CHARACTER_REFERENCE(2015, /* s z */ 'l' _ 'i' _ 'g', 3, 0, 0x00df _ 0)
+NAMED_CHARACTER_REFERENCE(2016,
+ /* s z */ 'l' _ 'i' _ 'g' _ ';', 4, 0, 0x00df _ 0)
+NAMED_CHARACTER_REFERENCE(2017,
+ /* t a */ 'r' _ 'g' _ 'e' _ 't' _ ';', 5, 0,
+ 0x2316 _ 0)
+NAMED_CHARACTER_REFERENCE(2018, /* t a */ 'u' _ ';', 2, 0, 0x03c4 _ 0)
+NAMED_CHARACTER_REFERENCE(2019, /* t b */ 'r' _ 'k' _ ';', 3, 0, 0x23b4 _ 0)
+NAMED_CHARACTER_REFERENCE(2020,
+ /* t c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x0165 _ 0)
+NAMED_CHARACTER_REFERENCE(2021,
+ /* t c */ 'e' _ 'd' _ 'i' _ 'l' _ ';', 5, 0,
+ 0x0163 _ 0)
+NAMED_CHARACTER_REFERENCE(2022, /* t c */ 'y' _ ';', 2, 0, 0x0442 _ 0)
+NAMED_CHARACTER_REFERENCE(2023, /* t d */ 'o' _ 't' _ ';', 3, 0, 0x20db _ 0)
+NAMED_CHARACTER_REFERENCE(2024,
+ /* t e */ 'l' _ 'r' _ 'e' _ 'c' _ ';', 5, 0,
+ 0x2315 _ 0)
+NAMED_CHARACTER_REFERENCE(2025, /* t f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd31)
+NAMED_CHARACTER_REFERENCE(2026,
+ /* t h */ 'e' _ 'r' _ 'e' _ '4' _ ';', 5, 0,
+ 0x2234 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2027,
+ /* t h */ 'e' _ 'r' _ 'e' _ 'f' _ 'o' _ 'r' _ 'e' _ ';', 8, 0, 0x2234 _ 0)
+NAMED_CHARACTER_REFERENCE(2028,
+ /* t h */ 'e' _ 't' _ 'a' _ ';', 4, 0, 0x03b8 _ 0)
+NAMED_CHARACTER_REFERENCE(2029,
+ /* t h */ 'e' _ 't' _ 'a' _ 's' _ 'y' _ 'm' _ ';', 7,
+ 0, 0x03d1 _ 0)
+NAMED_CHARACTER_REFERENCE(2030,
+ /* t h */ 'e' _ 't' _ 'a' _ 'v' _ ';', 5, 0,
+ 0x03d1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2031,
+ /* t h */ 'i' _ 'c' _ 'k' _ 'a' _ 'p' _ 'p' _ 'r' _ 'o' _ 'x' _ ';', 10, 0,
+ 0x2248 _ 0)
+NAMED_CHARACTER_REFERENCE(2032,
+ /* t h */ 'i' _ 'c' _ 'k' _ 's' _ 'i' _ 'm' _ ';', 7,
+ 0, 0x223c _ 0)
+NAMED_CHARACTER_REFERENCE(2033,
+ /* t h */ 'i' _ 'n' _ 's' _ 'p' _ ';', 5, 0,
+ 0x2009 _ 0)
+NAMED_CHARACTER_REFERENCE(2034,
+ /* t h */ 'k' _ 'a' _ 'p' _ ';', 4, 0, 0x2248 _ 0)
+NAMED_CHARACTER_REFERENCE(2035,
+ /* t h */ 'k' _ 's' _ 'i' _ 'm' _ ';', 5, 0,
+ 0x223c _ 0)
+NAMED_CHARACTER_REFERENCE(2036, /* t h */ 'o' _ 'r' _ 'n', 3, 0, 0x00fe _ 0)
+NAMED_CHARACTER_REFERENCE(2037,
+ /* t h */ 'o' _ 'r' _ 'n' _ ';', 4, 0, 0x00fe _ 0)
+NAMED_CHARACTER_REFERENCE(2038,
+ /* t i */ 'l' _ 'd' _ 'e' _ ';', 4, 0, 0x02dc _ 0)
+NAMED_CHARACTER_REFERENCE(2039, /* t i */ 'm' _ 'e' _ 's', 3, 0, 0x00d7 _ 0)
+NAMED_CHARACTER_REFERENCE(2040,
+ /* t i */ 'm' _ 'e' _ 's' _ ';', 4, 0, 0x00d7 _ 0)
+NAMED_CHARACTER_REFERENCE(2041,
+ /* t i */ 'm' _ 'e' _ 's' _ 'b' _ ';', 5, 0,
+ 0x22a0 _ 0)
+NAMED_CHARACTER_REFERENCE(2042,
+ /* t i */ 'm' _ 'e' _ 's' _ 'b' _ 'a' _ 'r' _ ';', 7,
+ 0, 0x2a31 _ 0)
+NAMED_CHARACTER_REFERENCE(2043,
+ /* t i */ 'm' _ 'e' _ 's' _ 'd' _ ';', 5, 0,
+ 0x2a30 _ 0)
+NAMED_CHARACTER_REFERENCE(2044, /* t i */ 'n' _ 't' _ ';', 3, 0, 0x222d _ 0)
+NAMED_CHARACTER_REFERENCE(2045, /* t o */ 'e' _ 'a' _ ';', 3, 0, 0x2928 _ 0)
+NAMED_CHARACTER_REFERENCE(2046, /* t o */ 'p' _ ';', 2, 0, 0x22a4 _ 0)
+NAMED_CHARACTER_REFERENCE(2047,
+ /* t o */ 'p' _ 'b' _ 'o' _ 't' _ ';', 5, 0,
+ 0x2336 _ 0)
+NAMED_CHARACTER_REFERENCE(2048,
+ /* t o */ 'p' _ 'c' _ 'i' _ 'r' _ ';', 5, 0,
+ 0x2af1 _ 0)
+NAMED_CHARACTER_REFERENCE(2049,
+ /* t o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd65)
+NAMED_CHARACTER_REFERENCE(2050,
+ /* t o */ 'p' _ 'f' _ 'o' _ 'r' _ 'k' _ ';', 6, 0,
+ 0x2ada _ 0)
+NAMED_CHARACTER_REFERENCE(2051, /* t o */ 's' _ 'a' _ ';', 3, 0, 0x2929 _ 0)
+NAMED_CHARACTER_REFERENCE(2052,
+ /* t p */ 'r' _ 'i' _ 'm' _ 'e' _ ';', 5, 0,
+ 0x2034 _ 0)
+NAMED_CHARACTER_REFERENCE(2053,
+ /* t r */ 'a' _ 'd' _ 'e' _ ';', 4, 0, 0x2122 _ 0)
+NAMED_CHARACTER_REFERENCE(2054,
+ /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 7,
+ 0, 0x25b5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2055,
+ /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'd' _ 'o' _ 'w' _ 'n' _ ';',
+ 11, 0, 0x25bf _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2056,
+ /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';',
+ 11, 0, 0x25c3 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2057,
+ /* t r */
+ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ 'e' _ 'q' _ ';',
+ 13, 0, 0x22b4 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2058,
+ /* t r */ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'q' _ ';', 8, 0, 0x225c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2059,
+ /* t r */
+ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';', 12,
+ 0, 0x25b9 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2060,
+ /* t r */
+ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'e' _ 'q' _ ';',
+ 14, 0, 0x22b5 _ 0)
+NAMED_CHARACTER_REFERENCE(2061,
+ /* t r */ 'i' _ 'd' _ 'o' _ 't' _ ';', 5, 0,
+ 0x25ec _ 0)
+NAMED_CHARACTER_REFERENCE(2062, /* t r */ 'i' _ 'e' _ ';', 3, 0, 0x225c _ 0)
+NAMED_CHARACTER_REFERENCE(2063,
+ /* t r */ 'i' _ 'm' _ 'i' _ 'n' _ 'u' _ 's' _ ';', 7,
+ 0, 0x2a3a _ 0)
+NAMED_CHARACTER_REFERENCE(2064,
+ /* t r */ 'i' _ 'p' _ 'l' _ 'u' _ 's' _ ';', 6, 0,
+ 0x2a39 _ 0)
+NAMED_CHARACTER_REFERENCE(2065,
+ /* t r */ 'i' _ 's' _ 'b' _ ';', 4, 0, 0x29cd _ 0)
+NAMED_CHARACTER_REFERENCE(2066,
+ /* t r */ 'i' _ 't' _ 'i' _ 'm' _ 'e' _ ';', 6, 0,
+ 0x2a3b _ 0)
+NAMED_CHARACTER_REFERENCE(2067,
+ /* t r */ 'p' _ 'e' _ 'z' _ 'i' _ 'u' _ 'm' _ ';', 7,
+ 0, 0x23e2 _ 0)
+NAMED_CHARACTER_REFERENCE(2068,
+ /* t s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcc9)
+NAMED_CHARACTER_REFERENCE(2069, /* t s */ 'c' _ 'y' _ ';', 3, 0, 0x0446 _ 0)
+NAMED_CHARACTER_REFERENCE(2070,
+ /* t s */ 'h' _ 'c' _ 'y' _ ';', 4, 0, 0x045b _ 0)
+NAMED_CHARACTER_REFERENCE(2071,
+ /* t s */ 't' _ 'r' _ 'o' _ 'k' _ ';', 5, 0,
+ 0x0167 _ 0)
+NAMED_CHARACTER_REFERENCE(2072,
+ /* t w */ 'i' _ 'x' _ 't' _ ';', 4, 0, 0x226c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2073,
+ /* t w */
+ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'l' _ 'e' _ 'f' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 15, 0, 0x219e _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2074,
+ /* t w */
+ 'o' _ 'h' _ 'e' _ 'a' _ 'd' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';',
+ 16, 0, 0x21a0 _ 0)
+NAMED_CHARACTER_REFERENCE(2075, /* u A */ 'r' _ 'r' _ ';', 3, 0, 0x21d1 _ 0)
+NAMED_CHARACTER_REFERENCE(2076, /* u H */ 'a' _ 'r' _ ';', 3, 0, 0x2963 _ 0)
+NAMED_CHARACTER_REFERENCE(2077,
+ /* u a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fa _ 0)
+NAMED_CHARACTER_REFERENCE(2078,
+ /* u a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00fa _ 0)
+NAMED_CHARACTER_REFERENCE(2079, /* u a */ 'r' _ 'r' _ ';', 3, 0, 0x2191 _ 0)
+NAMED_CHARACTER_REFERENCE(2080,
+ /* u b */ 'r' _ 'c' _ 'y' _ ';', 4, 0, 0x045e _ 0)
+NAMED_CHARACTER_REFERENCE(2081,
+ /* u b */ 'r' _ 'e' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x016d _ 0)
+NAMED_CHARACTER_REFERENCE(2082, /* u c */ 'i' _ 'r' _ 'c', 3, 0, 0x00fb _ 0)
+NAMED_CHARACTER_REFERENCE(2083,
+ /* u c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x00fb _ 0)
+NAMED_CHARACTER_REFERENCE(2084, /* u c */ 'y' _ ';', 2, 0, 0x0443 _ 0)
+NAMED_CHARACTER_REFERENCE(2085,
+ /* u d */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c5 _ 0)
+NAMED_CHARACTER_REFERENCE(2086,
+ /* u d */ 'b' _ 'l' _ 'a' _ 'c' _ ';', 5, 0,
+ 0x0171 _ 0)
+NAMED_CHARACTER_REFERENCE(2087,
+ /* u d */ 'h' _ 'a' _ 'r' _ ';', 4, 0, 0x296e _ 0)
+NAMED_CHARACTER_REFERENCE(2088,
+ /* u f */ 'i' _ 's' _ 'h' _ 't' _ ';', 5, 0,
+ 0x297e _ 0)
+NAMED_CHARACTER_REFERENCE(2089, /* u f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd32)
+NAMED_CHARACTER_REFERENCE(2090,
+ /* u g */ 'r' _ 'a' _ 'v' _ 'e', 4, 0, 0x00f9 _ 0)
+NAMED_CHARACTER_REFERENCE(2091,
+ /* u g */ 'r' _ 'a' _ 'v' _ 'e' _ ';', 5, 0,
+ 0x00f9 _ 0)
+NAMED_CHARACTER_REFERENCE(2092,
+ /* u h */ 'a' _ 'r' _ 'l' _ ';', 4, 0, 0x21bf _ 0)
+NAMED_CHARACTER_REFERENCE(2093,
+ /* u h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21be _ 0)
+NAMED_CHARACTER_REFERENCE(2094,
+ /* u h */ 'b' _ 'l' _ 'k' _ ';', 4, 0, 0x2580 _ 0)
+NAMED_CHARACTER_REFERENCE(2095,
+ /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0,
+ 0x231c _ 0)
+NAMED_CHARACTER_REFERENCE(2096,
+ /* u l */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7,
+ 0, 0x231c _ 0)
+NAMED_CHARACTER_REFERENCE(2097,
+ /* u l */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0,
+ 0x230f _ 0)
+NAMED_CHARACTER_REFERENCE(2098,
+ /* u l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f8 _ 0)
+NAMED_CHARACTER_REFERENCE(2099,
+ /* u m */ 'a' _ 'c' _ 'r' _ ';', 4, 0, 0x016b _ 0)
+NAMED_CHARACTER_REFERENCE(2100, /* u m */ 'l', 1, 0, 0x00a8 _ 0)
+NAMED_CHARACTER_REFERENCE(2101, /* u m */ 'l' _ ';', 2, 0, 0x00a8 _ 0)
+NAMED_CHARACTER_REFERENCE(2102,
+ /* u o */ 'g' _ 'o' _ 'n' _ ';', 4, 0, 0x0173 _ 0)
+NAMED_CHARACTER_REFERENCE(2103,
+ /* u o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd66)
+NAMED_CHARACTER_REFERENCE(2104,
+ /* u p */ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 6, 0,
+ 0x2191 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2105,
+ /* u p */ 'd' _ 'o' _ 'w' _ 'n' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ ';', 10, 0,
+ 0x2195 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2106,
+ /* u p */
+ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'l' _ 'e' _ 'f' _ 't' _ ';', 12,
+ 0, 0x21bf _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2107,
+ /* u p */
+ 'h' _ 'a' _ 'r' _ 'p' _ 'o' _ 'o' _ 'n' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 13, 0, 0x21be _ 0)
+NAMED_CHARACTER_REFERENCE(2108,
+ /* u p */ 'l' _ 'u' _ 's' _ ';', 4, 0, 0x228e _ 0)
+NAMED_CHARACTER_REFERENCE(2109, /* u p */ 's' _ 'i' _ ';', 3, 0, 0x03c5 _ 0)
+NAMED_CHARACTER_REFERENCE(2110,
+ /* u p */ 's' _ 'i' _ 'h' _ ';', 4, 0, 0x03d2 _ 0)
+NAMED_CHARACTER_REFERENCE(2111,
+ /* u p */ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 6, 0,
+ 0x03c5 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2112,
+ /* u p */ 'u' _ 'p' _ 'a' _ 'r' _ 'r' _ 'o' _ 'w' _ 's' _ ';', 9, 0,
+ 0x21c8 _ 0)
+NAMED_CHARACTER_REFERENCE(2113,
+ /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ ';', 5, 0,
+ 0x231d _ 0)
+NAMED_CHARACTER_REFERENCE(2114,
+ /* u r */ 'c' _ 'o' _ 'r' _ 'n' _ 'e' _ 'r' _ ';', 7,
+ 0, 0x231d _ 0)
+NAMED_CHARACTER_REFERENCE(2115,
+ /* u r */ 'c' _ 'r' _ 'o' _ 'p' _ ';', 5, 0,
+ 0x230e _ 0)
+NAMED_CHARACTER_REFERENCE(2116,
+ /* u r */ 'i' _ 'n' _ 'g' _ ';', 4, 0, 0x016f _ 0)
+NAMED_CHARACTER_REFERENCE(2117,
+ /* u r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25f9 _ 0)
+NAMED_CHARACTER_REFERENCE(2118,
+ /* u s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcca)
+NAMED_CHARACTER_REFERENCE(2119,
+ /* u t */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x22f0 _ 0)
+NAMED_CHARACTER_REFERENCE(2120,
+ /* u t */ 'i' _ 'l' _ 'd' _ 'e' _ ';', 5, 0,
+ 0x0169 _ 0)
+NAMED_CHARACTER_REFERENCE(2121, /* u t */ 'r' _ 'i' _ ';', 3, 0, 0x25b5 _ 0)
+NAMED_CHARACTER_REFERENCE(2122,
+ /* u t */ 'r' _ 'i' _ 'f' _ ';', 4, 0, 0x25b4 _ 0)
+NAMED_CHARACTER_REFERENCE(2123,
+ /* u u */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x21c8 _ 0)
+NAMED_CHARACTER_REFERENCE(2124, /* u u */ 'm' _ 'l', 2, 0, 0x00fc _ 0)
+NAMED_CHARACTER_REFERENCE(2125, /* u u */ 'm' _ 'l' _ ';', 3, 0, 0x00fc _ 0)
+NAMED_CHARACTER_REFERENCE(2126,
+ /* u w */ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ ';', 6, 0,
+ 0x29a7 _ 0)
+NAMED_CHARACTER_REFERENCE(2127, /* v A */ 'r' _ 'r' _ ';', 3, 0, 0x21d5 _ 0)
+NAMED_CHARACTER_REFERENCE(2128, /* v B */ 'a' _ 'r' _ ';', 3, 0, 0x2ae8 _ 0)
+NAMED_CHARACTER_REFERENCE(2129,
+ /* v B */ 'a' _ 'r' _ 'v' _ ';', 4, 0, 0x2ae9 _ 0)
+NAMED_CHARACTER_REFERENCE(2130,
+ /* v D */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a8 _ 0)
+NAMED_CHARACTER_REFERENCE(2131,
+ /* v a */ 'n' _ 'g' _ 'r' _ 't' _ ';', 5, 0,
+ 0x299c _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2132,
+ /* v a */ 'r' _ 'e' _ 'p' _ 's' _ 'i' _ 'l' _ 'o' _ 'n' _ ';', 9, 0,
+ 0x03f5 _ 0)
+NAMED_CHARACTER_REFERENCE(2133,
+ /* v a */ 'r' _ 'k' _ 'a' _ 'p' _ 'p' _ 'a' _ ';', 7,
+ 0, 0x03f0 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2134,
+ /* v a */ 'r' _ 'n' _ 'o' _ 't' _ 'h' _ 'i' _ 'n' _ 'g' _ ';', 9, 0,
+ 0x2205 _ 0)
+NAMED_CHARACTER_REFERENCE(2135,
+ /* v a */ 'r' _ 'p' _ 'h' _ 'i' _ ';', 5, 0,
+ 0x03d5 _ 0)
+NAMED_CHARACTER_REFERENCE(2136,
+ /* v a */ 'r' _ 'p' _ 'i' _ ';', 4, 0, 0x03d6 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2137,
+ /* v a */ 'r' _ 'p' _ 'r' _ 'o' _ 'p' _ 't' _ 'o' _ ';', 8, 0, 0x221d _ 0)
+NAMED_CHARACTER_REFERENCE(2138, /* v a */ 'r' _ 'r' _ ';', 3, 0, 0x2195 _ 0)
+NAMED_CHARACTER_REFERENCE(2139,
+ /* v a */ 'r' _ 'r' _ 'h' _ 'o' _ ';', 5, 0,
+ 0x03f1 _ 0)
+NAMED_CHARACTER_REFERENCE(2140,
+ /* v a */ 'r' _ 's' _ 'i' _ 'g' _ 'm' _ 'a' _ ';', 7,
+ 0, 0x03c2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2141,
+ /* v a */ 'r' _ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';',
+ 11, 0, 0x228a _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(
+ 2142,
+ /* v a */
+ 'r' _ 's' _ 'u' _ 'b' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 12,
+ 0, 0x2acb _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(
+ 2143,
+ /* v a */ 'r' _ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ ';',
+ 11, 0, 0x228b _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(
+ 2144,
+ /* v a */
+ 'r' _ 's' _ 'u' _ 'p' _ 's' _ 'e' _ 't' _ 'n' _ 'e' _ 'q' _ 'q' _ ';', 12,
+ 0, 0x2acc _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(2145,
+ /* v a */ 'r' _ 't' _ 'h' _ 'e' _ 't' _ 'a' _ ';', 7,
+ 0, 0x03d1 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2146,
+ /* v a */
+ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'l' _ 'e' _ 'f' _ 't' _ ';',
+ 14, 0, 0x22b2 _ 0)
+NAMED_CHARACTER_REFERENCE(
+ 2147,
+ /* v a */
+ 'r' _ 't' _ 'r' _ 'i' _ 'a' _ 'n' _ 'g' _ 'l' _ 'e' _ 'r' _ 'i' _ 'g' _ 'h' _ 't' _ ';',
+ 15, 0, 0x22b3 _ 0)
+NAMED_CHARACTER_REFERENCE(2148, /* v c */ 'y' _ ';', 2, 0, 0x0432 _ 0)
+NAMED_CHARACTER_REFERENCE(2149,
+ /* v d */ 'a' _ 's' _ 'h' _ ';', 4, 0, 0x22a2 _ 0)
+NAMED_CHARACTER_REFERENCE(2150, /* v e */ 'e' _ ';', 2, 0, 0x2228 _ 0)
+NAMED_CHARACTER_REFERENCE(2151,
+ /* v e */ 'e' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x22bb _ 0)
+NAMED_CHARACTER_REFERENCE(2152,
+ /* v e */ 'e' _ 'e' _ 'q' _ ';', 4, 0, 0x225a _ 0)
+NAMED_CHARACTER_REFERENCE(2153,
+ /* v e */ 'l' _ 'l' _ 'i' _ 'p' _ ';', 5, 0,
+ 0x22ee _ 0)
+NAMED_CHARACTER_REFERENCE(2154,
+ /* v e */ 'r' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x007c _ 0)
+NAMED_CHARACTER_REFERENCE(2155, /* v e */ 'r' _ 't' _ ';', 3, 0, 0x007c _ 0)
+NAMED_CHARACTER_REFERENCE(2156, /* v f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd33)
+NAMED_CHARACTER_REFERENCE(2157,
+ /* v l */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b2 _ 0)
+NAMED_CHARACTER_REFERENCE(2158,
+ /* v n */ 's' _ 'u' _ 'b' _ ';', 4, 0,
+ 0x2282 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(2159,
+ /* v n */ 's' _ 'u' _ 'p' _ ';', 4, 0,
+ 0x2283 _ 0x20d2)
+NAMED_CHARACTER_REFERENCE(2160,
+ /* v o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd67)
+NAMED_CHARACTER_REFERENCE(2161,
+ /* v p */ 'r' _ 'o' _ 'p' _ ';', 4, 0, 0x221d _ 0)
+NAMED_CHARACTER_REFERENCE(2162,
+ /* v r */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x22b3 _ 0)
+NAMED_CHARACTER_REFERENCE(2163,
+ /* v s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccb)
+NAMED_CHARACTER_REFERENCE(2164,
+ /* v s */ 'u' _ 'b' _ 'n' _ 'E' _ ';', 5, 0,
+ 0x2acb _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(2165,
+ /* v s */ 'u' _ 'b' _ 'n' _ 'e' _ ';', 5, 0,
+ 0x228a _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(2166,
+ /* v s */ 'u' _ 'p' _ 'n' _ 'E' _ ';', 5, 0,
+ 0x2acc _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(2167,
+ /* v s */ 'u' _ 'p' _ 'n' _ 'e' _ ';', 5, 0,
+ 0x228b _ 0xfe00)
+NAMED_CHARACTER_REFERENCE(2168,
+ /* v z */ 'i' _ 'g' _ 'z' _ 'a' _ 'g' _ ';', 6, 0,
+ 0x299a _ 0)
+NAMED_CHARACTER_REFERENCE(2169,
+ /* w c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0175 _ 0)
+NAMED_CHARACTER_REFERENCE(2170,
+ /* w e */ 'd' _ 'b' _ 'a' _ 'r' _ ';', 5, 0,
+ 0x2a5f _ 0)
+NAMED_CHARACTER_REFERENCE(2171,
+ /* w e */ 'd' _ 'g' _ 'e' _ ';', 4, 0, 0x2227 _ 0)
+NAMED_CHARACTER_REFERENCE(2172,
+ /* w e */ 'd' _ 'g' _ 'e' _ 'q' _ ';', 5, 0,
+ 0x2259 _ 0)
+NAMED_CHARACTER_REFERENCE(2173,
+ /* w e */ 'i' _ 'e' _ 'r' _ 'p' _ ';', 5, 0,
+ 0x2118 _ 0)
+NAMED_CHARACTER_REFERENCE(2174, /* w f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd34)
+NAMED_CHARACTER_REFERENCE(2175,
+ /* w o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd68)
+NAMED_CHARACTER_REFERENCE(2176, /* w p */ ';', 1, 0, 0x2118 _ 0)
+NAMED_CHARACTER_REFERENCE(2177, /* w r */ ';', 1, 0, 0x2240 _ 0)
+NAMED_CHARACTER_REFERENCE(2178,
+ /* w r */ 'e' _ 'a' _ 't' _ 'h' _ ';', 5, 0,
+ 0x2240 _ 0)
+NAMED_CHARACTER_REFERENCE(2179,
+ /* w s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccc)
+NAMED_CHARACTER_REFERENCE(2180, /* x c */ 'a' _ 'p' _ ';', 3, 0, 0x22c2 _ 0)
+NAMED_CHARACTER_REFERENCE(2181,
+ /* x c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x25ef _ 0)
+NAMED_CHARACTER_REFERENCE(2182, /* x c */ 'u' _ 'p' _ ';', 3, 0, 0x22c3 _ 0)
+NAMED_CHARACTER_REFERENCE(2183,
+ /* x d */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25bd _ 0)
+NAMED_CHARACTER_REFERENCE(2184, /* x f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd35)
+NAMED_CHARACTER_REFERENCE(2185,
+ /* x h */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27fa _ 0)
+NAMED_CHARACTER_REFERENCE(2186,
+ /* x h */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f7 _ 0)
+NAMED_CHARACTER_REFERENCE(2187, /* x i */ ';', 1, 0, 0x03be _ 0)
+NAMED_CHARACTER_REFERENCE(2188,
+ /* x l */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f8 _ 0)
+NAMED_CHARACTER_REFERENCE(2189,
+ /* x l */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f5 _ 0)
+NAMED_CHARACTER_REFERENCE(2190, /* x m */ 'a' _ 'p' _ ';', 3, 0, 0x27fc _ 0)
+NAMED_CHARACTER_REFERENCE(2191, /* x n */ 'i' _ 's' _ ';', 3, 0, 0x22fb _ 0)
+NAMED_CHARACTER_REFERENCE(2192,
+ /* x o */ 'd' _ 'o' _ 't' _ ';', 4, 0, 0x2a00 _ 0)
+NAMED_CHARACTER_REFERENCE(2193,
+ /* x o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd69)
+NAMED_CHARACTER_REFERENCE(2194,
+ /* x o */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2a01 _ 0)
+NAMED_CHARACTER_REFERENCE(2195,
+ /* x o */ 't' _ 'i' _ 'm' _ 'e' _ ';', 5, 0,
+ 0x2a02 _ 0)
+NAMED_CHARACTER_REFERENCE(2196,
+ /* x r */ 'A' _ 'r' _ 'r' _ ';', 4, 0, 0x27f9 _ 0)
+NAMED_CHARACTER_REFERENCE(2197,
+ /* x r */ 'a' _ 'r' _ 'r' _ ';', 4, 0, 0x27f6 _ 0)
+NAMED_CHARACTER_REFERENCE(2198,
+ /* x s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccd)
+NAMED_CHARACTER_REFERENCE(2199,
+ /* x s */ 'q' _ 'c' _ 'u' _ 'p' _ ';', 5, 0,
+ 0x2a06 _ 0)
+NAMED_CHARACTER_REFERENCE(2200,
+ /* x u */ 'p' _ 'l' _ 'u' _ 's' _ ';', 5, 0,
+ 0x2a04 _ 0)
+NAMED_CHARACTER_REFERENCE(2201,
+ /* x u */ 't' _ 'r' _ 'i' _ ';', 4, 0, 0x25b3 _ 0)
+NAMED_CHARACTER_REFERENCE(2202, /* x v */ 'e' _ 'e' _ ';', 3, 0, 0x22c1 _ 0)
+NAMED_CHARACTER_REFERENCE(2203,
+ /* x w */ 'e' _ 'd' _ 'g' _ 'e' _ ';', 5, 0,
+ 0x22c0 _ 0)
+NAMED_CHARACTER_REFERENCE(2204,
+ /* y a */ 'c' _ 'u' _ 't' _ 'e', 4, 0, 0x00fd _ 0)
+NAMED_CHARACTER_REFERENCE(2205,
+ /* y a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x00fd _ 0)
+NAMED_CHARACTER_REFERENCE(2206, /* y a */ 'c' _ 'y' _ ';', 3, 0, 0x044f _ 0)
+NAMED_CHARACTER_REFERENCE(2207,
+ /* y c */ 'i' _ 'r' _ 'c' _ ';', 4, 0, 0x0177 _ 0)
+NAMED_CHARACTER_REFERENCE(2208, /* y c */ 'y' _ ';', 2, 0, 0x044b _ 0)
+NAMED_CHARACTER_REFERENCE(2209, /* y e */ 'n', 1, 0, 0x00a5 _ 0)
+NAMED_CHARACTER_REFERENCE(2210, /* y e */ 'n' _ ';', 2, 0, 0x00a5 _ 0)
+NAMED_CHARACTER_REFERENCE(2211, /* y f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd36)
+NAMED_CHARACTER_REFERENCE(2212, /* y i */ 'c' _ 'y' _ ';', 3, 0, 0x0457 _ 0)
+NAMED_CHARACTER_REFERENCE(2213,
+ /* y o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6a)
+NAMED_CHARACTER_REFERENCE(2214,
+ /* y s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdcce)
+NAMED_CHARACTER_REFERENCE(2215, /* y u */ 'c' _ 'y' _ ';', 3, 0, 0x044e _ 0)
+NAMED_CHARACTER_REFERENCE(2216, /* y u */ 'm' _ 'l', 2, 0, 0x00ff _ 0)
+NAMED_CHARACTER_REFERENCE(2217, /* y u */ 'm' _ 'l' _ ';', 3, 0, 0x00ff _ 0)
+NAMED_CHARACTER_REFERENCE(2218,
+ /* z a */ 'c' _ 'u' _ 't' _ 'e' _ ';', 5, 0,
+ 0x017a _ 0)
+NAMED_CHARACTER_REFERENCE(2219,
+ /* z c */ 'a' _ 'r' _ 'o' _ 'n' _ ';', 5, 0,
+ 0x017e _ 0)
+NAMED_CHARACTER_REFERENCE(2220, /* z c */ 'y' _ ';', 2, 0, 0x0437 _ 0)
+NAMED_CHARACTER_REFERENCE(2221, /* z d */ 'o' _ 't' _ ';', 3, 0, 0x017c _ 0)
+NAMED_CHARACTER_REFERENCE(2222,
+ /* z e */ 'e' _ 't' _ 'r' _ 'f' _ ';', 5, 0,
+ 0x2128 _ 0)
+NAMED_CHARACTER_REFERENCE(2223, /* z e */ 't' _ 'a' _ ';', 3, 0, 0x03b6 _ 0)
+NAMED_CHARACTER_REFERENCE(2224, /* z f */ 'r' _ ';', 2, 0, 0xd835 _ 0xdd37)
+NAMED_CHARACTER_REFERENCE(2225, /* z h */ 'c' _ 'y' _ ';', 3, 0, 0x0436 _ 0)
+NAMED_CHARACTER_REFERENCE(2226,
+ /* z i */ 'g' _ 'r' _ 'a' _ 'r' _ 'r' _ ';', 6, 0,
+ 0x21dd _ 0)
+NAMED_CHARACTER_REFERENCE(2227,
+ /* z o */ 'p' _ 'f' _ ';', 3, 0, 0xd835 _ 0xdd6b)
+NAMED_CHARACTER_REFERENCE(2228,
+ /* z s */ 'c' _ 'r' _ ';', 3, 0, 0xd835 _ 0xdccf)
+NAMED_CHARACTER_REFERENCE(2229, /* z w */ 'j' _ ';', 2, 0, 0x200d _ 0)
+NAMED_CHARACTER_REFERENCE(2230, /* z w */ 'n' _ 'j' _ ';', 3, 0, 0x200c _ 0)
+
+#undef _
diff --git a/parser/html/nsHtml5OplessBuilder.cpp b/parser/html/nsHtml5OplessBuilder.cpp
new file mode 100644
index 0000000000..60bbe72928
--- /dev/null
+++ b/parser/html/nsHtml5OplessBuilder.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5OplessBuilder.h"
+
+#include "mozilla/css/Loader.h"
+#include "mozilla/dom/ScriptLoader.h"
+#include "nsIDocShell.h"
+
+nsHtml5OplessBuilder::nsHtml5OplessBuilder() : nsHtml5DocumentBuilder(true) {}
+
+nsHtml5OplessBuilder::~nsHtml5OplessBuilder() {}
+
+void nsHtml5OplessBuilder::Start() {
+ BeginFlush();
+ BeginDocUpdate();
+}
+
+void nsHtml5OplessBuilder::Finish() {
+ EndDocUpdate();
+ EndFlush();
+ DropParserAndPerfHint();
+ mScriptLoader = nullptr;
+ mDocument = nullptr;
+ mNodeInfoManager = nullptr;
+ mCSSLoader = nullptr;
+ mDocumentURI = nullptr;
+ mDocShell = nullptr;
+ mOwnedElements.Clear();
+}
+
+void nsHtml5OplessBuilder::SetParser(nsParserBase* aParser) {
+ mParser = aParser;
+}
diff --git a/parser/html/nsHtml5OplessBuilder.h b/parser/html/nsHtml5OplessBuilder.h
new file mode 100644
index 0000000000..4fa4f4e735
--- /dev/null
+++ b/parser/html/nsHtml5OplessBuilder.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5OplessBuilder_h
+#define nsHtml5OplessBuilder_h
+
+#include "nsHtml5DocumentBuilder.h"
+
+class nsParserBase;
+
+/**
+ * This class implements a minimal subclass of nsHtml5DocumentBuilder that
+ * works when tree operation queues that are part of the off-the-main-thread
+ * parsing machinery are not used and, therefore, nsHtml5TreeOpExecutor is
+ * not used.
+ *
+ * This class is mostly responsible for wrapping tree building in an update
+ * batch and resetting various fields in nsContentSink upon finishing.
+ */
+class nsHtml5OplessBuilder : public nsHtml5DocumentBuilder {
+ public:
+ nsHtml5OplessBuilder();
+ ~nsHtml5OplessBuilder();
+ void Start();
+ void Finish();
+ void SetParser(nsParserBase* aParser);
+};
+
+#endif // nsHtml5OplessBuilder_h
diff --git a/parser/html/nsHtml5OwningUTF16Buffer.cpp b/parser/html/nsHtml5OwningUTF16Buffer.cpp
new file mode 100644
index 0000000000..eec07a29ac
--- /dev/null
+++ b/parser/html/nsHtml5OwningUTF16Buffer.cpp
@@ -0,0 +1,57 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5OwningUTF16Buffer.h"
+
+#include "mozilla/Span.h"
+
+using namespace mozilla;
+
+nsHtml5OwningUTF16Buffer::nsHtml5OwningUTF16Buffer(char16_t* aBuffer)
+ : nsHtml5UTF16Buffer(aBuffer, 0), next(nullptr), key(nullptr) {}
+
+nsHtml5OwningUTF16Buffer::nsHtml5OwningUTF16Buffer(void* aKey)
+ : nsHtml5UTF16Buffer(nullptr, 0), next(nullptr), key(aKey) {}
+
+nsHtml5OwningUTF16Buffer::~nsHtml5OwningUTF16Buffer() {
+ DeleteBuffer();
+
+ // This is to avoid dtor recursion on 'next', bug 706932.
+ RefPtr<nsHtml5OwningUTF16Buffer> tail;
+ tail.swap(next);
+ while (tail && tail->mRefCnt == 1) {
+ RefPtr<nsHtml5OwningUTF16Buffer> tmp;
+ tmp.swap(tail->next);
+ tail.swap(tmp);
+ }
+}
+
+// static
+already_AddRefed<nsHtml5OwningUTF16Buffer>
+nsHtml5OwningUTF16Buffer::FalliblyCreate(int32_t aLength) {
+ char16_t* newBuf = new (mozilla::fallible) char16_t[aLength];
+ if (!newBuf) {
+ return nullptr;
+ }
+ RefPtr<nsHtml5OwningUTF16Buffer> newObj =
+ new (mozilla::fallible) nsHtml5OwningUTF16Buffer(newBuf);
+ if (!newObj) {
+ delete[] newBuf;
+ return nullptr;
+ }
+ return newObj.forget();
+}
+
+void nsHtml5OwningUTF16Buffer::Swap(nsHtml5OwningUTF16Buffer* aOther) {
+ nsHtml5UTF16Buffer::Swap(aOther);
+}
+
+Span<char16_t> nsHtml5OwningUTF16Buffer::TailAsSpan(int32_t aBufferSize) {
+ MOZ_ASSERT(aBufferSize >= getEnd());
+ return {getBuffer() + getEnd(), static_cast<size_t>(aBufferSize - getEnd())};
+}
+
+void nsHtml5OwningUTF16Buffer::AdvanceEnd(int32_t aNumberOfCodeUnits) {
+ setEnd(getEnd() + aNumberOfCodeUnits);
+}
diff --git a/parser/html/nsHtml5OwningUTF16Buffer.h b/parser/html/nsHtml5OwningUTF16Buffer.h
new file mode 100644
index 0000000000..2cc94583e7
--- /dev/null
+++ b/parser/html/nsHtml5OwningUTF16Buffer.h
@@ -0,0 +1,64 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5OwningUTF16Buffer_h
+#define nsHtml5OwningUTF16Buffer_h
+
+#include "nsHtml5UTF16Buffer.h"
+#include "mozilla/Span.h"
+
+class nsHtml5OwningUTF16Buffer : public nsHtml5UTF16Buffer {
+ public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHtml5OwningUTF16Buffer)
+
+ private:
+ /**
+ * Passes a buffer and its length to the superclass constructor.
+ */
+ explicit nsHtml5OwningUTF16Buffer(char16_t* aBuffer);
+
+ public:
+ /**
+ * Constructor for a parser key placeholder. (No actual buffer.)
+ * @param aKey a parser key
+ */
+ explicit nsHtml5OwningUTF16Buffer(void* aKey);
+
+ protected:
+ /**
+ * Takes care of releasing the owned buffer.
+ */
+ ~nsHtml5OwningUTF16Buffer();
+
+ public:
+ /**
+ * The next buffer in a queue.
+ */
+ RefPtr<nsHtml5OwningUTF16Buffer> next;
+
+ /**
+ * A parser key.
+ */
+ void* key;
+
+ static already_AddRefed<nsHtml5OwningUTF16Buffer> FalliblyCreate(
+ int32_t aLength);
+
+ /**
+ * Swap start, end and buffer fields with another object.
+ */
+ void Swap(nsHtml5OwningUTF16Buffer* aOther);
+
+ /**
+ * Return a span from `end` to `aBufferSize`.
+ */
+ mozilla::Span<char16_t> TailAsSpan(int32_t aBufferSize);
+
+ /**
+ * Add the argument to `end`.
+ */
+ void AdvanceEnd(int32_t aNumberOfCodeUnits);
+};
+
+#endif // nsHtml5OwningUTF16Buffer_h
diff --git a/parser/html/nsHtml5Parser.cpp b/parser/html/nsHtml5Parser.cpp
new file mode 100644
index 0000000000..f1916ca2d4
--- /dev/null
+++ b/parser/html/nsHtml5Parser.cpp
@@ -0,0 +1,695 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5Parser.h"
+
+#include "mozilla/AutoRestore.h"
+#include "mozilla/UniquePtr.h"
+#include "nsCRT.h"
+#include "nsContentUtils.h" // for kLoadAsData
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5DependentUTF16Buffer.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsNetUtil.h"
+
+NS_INTERFACE_TABLE_HEAD(nsHtml5Parser)
+ NS_INTERFACE_TABLE(nsHtml5Parser, nsIParser, nsISupportsWeakReference)
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5Parser)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5Parser)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5Parser)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5Parser)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5Parser)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExecutor)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetStreamParser())
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5Parser)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mExecutor)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
+ tmp->DropStreamParser();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+nsHtml5Parser::nsHtml5Parser()
+ : mLastWasCR(false),
+ mDocWriteSpeculativeLastWasCR(false),
+ mBlocked(0),
+ mDocWriteSpeculatorActive(false),
+ mScriptNestingLevel(0),
+ mDocumentClosed(false),
+ mInDocumentWrite(false),
+ mInsertionPointPermanentlyUndefined(false),
+ mFirstBuffer(new nsHtml5OwningUTF16Buffer((void*)nullptr)),
+ mLastBuffer(mFirstBuffer),
+ mExecutor(new nsHtml5TreeOpExecutor()),
+ mTreeBuilder(new nsHtml5TreeBuilder(mExecutor, nullptr, false)),
+ mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)),
+ mRootContextLineNumber(1),
+ mReturnToStreamParserPermitted(false) {
+ mTokenizer->setInterner(&mAtomTable);
+}
+
+nsHtml5Parser::~nsHtml5Parser() {
+ mTokenizer->end();
+ if (mDocWriteSpeculativeTokenizer) {
+ mDocWriteSpeculativeTokenizer->end();
+ }
+}
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::SetContentSink(nsIContentSink* aSink) {
+ NS_ASSERTION(aSink == static_cast<nsIContentSink*>(mExecutor),
+ "Attempt to set a foreign sink.");
+}
+
+NS_IMETHODIMP_(nsIContentSink*)
+nsHtml5Parser::GetContentSink() {
+ return static_cast<nsIContentSink*>(mExecutor);
+}
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::GetCommand(nsCString& aCommand) {
+ aCommand.AssignLiteral("view");
+}
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::SetCommand(const char* aCommand) {
+ NS_ASSERTION(!strcmp(aCommand, "view") || !strcmp(aCommand, "view-source") ||
+ !strcmp(aCommand, "external-resource") ||
+ !strcmp(aCommand, "import") ||
+ !strcmp(aCommand, kLoadAsData),
+ "Unsupported parser command");
+}
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::SetCommand(eParserCommands aParserCommand) {
+ NS_ASSERTION(aParserCommand == eViewNormal,
+ "Parser command was not eViewNormal.");
+}
+
+void nsHtml5Parser::SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ int32_t aCharsetSource,
+ bool aForceAutoDetection) {
+ MOZ_ASSERT(!mExecutor->HasStarted(), "Document charset set too late.");
+ MOZ_ASSERT(GetStreamParser(), "Setting charset on a script-only parser.");
+ GetStreamParser()->SetDocumentCharset(
+ aEncoding, (nsCharsetSource)aCharsetSource, aForceAutoDetection);
+ mExecutor->SetDocumentCharsetAndSource(aEncoding,
+ (nsCharsetSource)aCharsetSource);
+}
+
+nsresult nsHtml5Parser::GetChannel(nsIChannel** aChannel) {
+ if (GetStreamParser()) {
+ return GetStreamParser()->GetChannel(aChannel);
+ } else {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+}
+
+nsIStreamListener* nsHtml5Parser::GetStreamListener() {
+ return mStreamListener;
+}
+
+NS_IMETHODIMP
+nsHtml5Parser::ContinueInterruptedParsing() {
+ MOZ_ASSERT_UNREACHABLE("Don't call. For interface compat only.");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::BlockParser() { mBlocked++; }
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::UnblockParser() {
+ MOZ_DIAGNOSTIC_ASSERT(mBlocked > 0);
+ if (MOZ_LIKELY(mBlocked > 0)) {
+ mBlocked--;
+ }
+ if (MOZ_LIKELY(mBlocked == 0) && mExecutor) {
+ mExecutor->ContinueInterruptedParsingAsync();
+ }
+}
+
+NS_IMETHODIMP_(void)
+nsHtml5Parser::ContinueInterruptedParsingAsync() {
+ if (mExecutor) {
+ mExecutor->ContinueInterruptedParsingAsync();
+ }
+}
+
+NS_IMETHODIMP_(bool)
+nsHtml5Parser::IsParserEnabled() { return !mBlocked; }
+
+NS_IMETHODIMP_(bool)
+nsHtml5Parser::IsComplete() { return mExecutor->IsComplete(); }
+
+NS_IMETHODIMP
+nsHtml5Parser::Parse(nsIURI* aURL) {
+ /*
+ * Do NOT cause WillBuildModel to be called synchronously from here!
+ * The document won't be ready for it until OnStartRequest!
+ */
+ MOZ_ASSERT(!mExecutor->HasStarted(),
+ "Tried to start parse without initializing the parser.");
+ MOZ_ASSERT(GetStreamParser(),
+ "Can't call this Parse() variant on script-created parser");
+
+ GetStreamParser()->SetViewSourceTitle(aURL); // In case we're viewing source
+ mExecutor->SetStreamParser(GetStreamParser());
+ mExecutor->SetParser(this);
+ return NS_OK;
+}
+
+nsresult nsHtml5Parser::Parse(const nsAString& aSourceBuffer, void* aKey,
+ bool aLastCall) {
+ nsresult rv;
+ if (NS_FAILED(rv = mExecutor->IsBroken())) {
+ return rv;
+ }
+ if (aSourceBuffer.Length() > INT32_MAX) {
+ return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+
+ // Maintain a reference to ourselves so we don't go away
+ // till we're completely done. The old parser grips itself in this method.
+ nsCOMPtr<nsIParser> kungFuDeathGrip(this);
+
+ // Gripping the other objects just in case, since the other old grip
+ // required grips to these, too.
+ RefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(GetStreamParser());
+ mozilla::Unused << streamKungFuDeathGrip; // Not used within function
+ RefPtr<nsHtml5TreeOpExecutor> executor(mExecutor);
+
+ MOZ_RELEASE_ASSERT(executor->HasStarted());
+
+ // Return early if the parser has processed EOF
+ if (executor->IsComplete()) {
+ return NS_OK;
+ }
+
+ if (aLastCall && aSourceBuffer.IsEmpty() && !aKey) {
+ // document.close()
+ NS_ASSERTION(!GetStreamParser(),
+ "Had stream parser but got document.close().");
+ if (mDocumentClosed) {
+ // already closed
+ return NS_OK;
+ }
+ mDocumentClosed = true;
+ if (!mBlocked && !mInDocumentWrite) {
+ return ParseUntilBlocked();
+ }
+ return NS_OK;
+ }
+
+ // If we got this far, we are dealing with a document.write or
+ // document.writeln call--not document.close().
+
+ MOZ_RELEASE_ASSERT(
+ IsInsertionPointDefined(),
+ "Doc.write reached parser with undefined insertion point.");
+
+ MOZ_RELEASE_ASSERT(!(GetStreamParser() && !aKey),
+ "Got a null key in a non-script-created parser");
+
+ // XXX is this optimization bogus?
+ if (aSourceBuffer.IsEmpty()) {
+ return NS_OK;
+ }
+
+ // This guard is here to prevent document.close from tokenizing synchronously
+ // while a document.write (that wrote the script that called document.close!)
+ // is still on the call stack.
+ mozilla::AutoRestore<bool> guard(mInDocumentWrite);
+ mInDocumentWrite = true;
+
+ // The script is identified by aKey. If there's nothing in the buffer
+ // chain for that key, we'll insert at the head of the queue.
+ // When the script leaves something in the queue, a zero-length
+ // key-holder "buffer" is inserted in the queue. If the same script
+ // leaves something in the chain again, it will be inserted immediately
+ // before the old key holder belonging to the same script.
+ //
+ // We don't do the actual data insertion yet in the hope that the data gets
+ // tokenized and there no data or less data to copy to the heap after
+ // tokenization. Also, this way, we avoid inserting one empty data buffer
+ // per document.write, which matters for performance when the parser isn't
+ // blocked and a badly-authored script calls document.write() once per
+ // input character. (As seen in a benchmark!)
+ //
+ // The insertion into the input stream happens conceptually before anything
+ // gets tokenized. To make sure multi-level document.write works right,
+ // it's necessary to establish the location of our parser key up front
+ // in case this is the first write with this key.
+ //
+ // In a document.open() case, the first write level has a null key, so that
+ // case is handled separately, because normal buffers containing data
+ // have null keys.
+
+ // These don't need to be owning references, because they always point to
+ // the buffer queue and buffers can't be removed from the buffer queue
+ // before document.write() returns. The buffer queue clean-up happens the
+ // next time ParseUntilBlocked() is called.
+ // However, they are made owning just in case the reasoning above is flawed
+ // and a flaw would lead to worse problems with plain pointers. If this
+ // turns out to be a perf problem, it's worthwhile to consider making
+ // prevSearchbuf a plain pointer again.
+ RefPtr<nsHtml5OwningUTF16Buffer> prevSearchBuf;
+ RefPtr<nsHtml5OwningUTF16Buffer> firstLevelMarker;
+
+ if (aKey) {
+ if (mFirstBuffer == mLastBuffer) {
+ nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey);
+ keyHolder->next = mLastBuffer;
+ mFirstBuffer = keyHolder;
+ } else if (mFirstBuffer->key != aKey) {
+ prevSearchBuf = mFirstBuffer;
+ for (;;) {
+ if (prevSearchBuf->next == mLastBuffer) {
+ // key was not found
+ nsHtml5OwningUTF16Buffer* keyHolder =
+ new nsHtml5OwningUTF16Buffer(aKey);
+ keyHolder->next = mFirstBuffer;
+ mFirstBuffer = keyHolder;
+ prevSearchBuf = nullptr;
+ break;
+ }
+ if (prevSearchBuf->next->key == aKey) {
+ // found a key holder
+ break;
+ }
+ prevSearchBuf = prevSearchBuf->next;
+ }
+ } // else mFirstBuffer is the keyholder
+
+ // prevSearchBuf is the previous buffer before the keyholder or null if
+ // there isn't one.
+ } else {
+ // We have a first-level write in the document.open() case. We insert before
+ // mLastBuffer, effectively, by making mLastBuffer be a new sentinel object
+ // and redesignating the previous mLastBuffer as our firstLevelMarker. We
+ // need to put a marker there, because otherwise additional document.writes
+ // from nested event loops would insert in the wrong place. Sigh.
+ mLastBuffer->next = new nsHtml5OwningUTF16Buffer((void*)nullptr);
+ firstLevelMarker = mLastBuffer;
+ mLastBuffer = mLastBuffer->next;
+ }
+
+ nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer);
+
+ while (!mBlocked && stackBuffer.hasMore()) {
+ stackBuffer.adjust(mLastWasCR);
+ mLastWasCR = false;
+ if (stackBuffer.hasMore()) {
+ int32_t lineNumberSave;
+ bool inRootContext = (!GetStreamParser() && !aKey);
+ if (inRootContext) {
+ mTokenizer->setLineNumber(mRootContextLineNumber);
+ } else {
+ // we aren't the root context, so save the line number on the
+ // *stack* so that we can restore it.
+ lineNumberSave = mTokenizer->getLineNumber();
+ }
+
+ if (!mTokenizer->EnsureBufferSpace(stackBuffer.getLength())) {
+ return executor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer);
+ if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
+ return executor->MarkAsBroken(rv);
+ }
+
+ if (inRootContext) {
+ mRootContextLineNumber = mTokenizer->getLineNumber();
+ } else {
+ mTokenizer->setLineNumber(lineNumberSave);
+ }
+
+ if (mTreeBuilder->HasScript()) {
+ auto r = mTreeBuilder->Flush(); // Move ops to the executor
+ if (r.isErr()) {
+ return executor->MarkAsBroken(r.unwrapErr());
+ }
+ rv = executor->FlushDocumentWrite(); // run the ops
+ NS_ENSURE_SUCCESS(rv, rv);
+ // Flushing tree ops can cause all sorts of things.
+ // Return early if the parser got terminated.
+ if (executor->IsComplete()) {
+ return NS_OK;
+ }
+ }
+ // Ignore suspension requests
+ }
+ }
+
+ RefPtr<nsHtml5OwningUTF16Buffer> heapBuffer;
+ if (stackBuffer.hasMore()) {
+ // The buffer wasn't tokenized to completion. Create a copy of the tail
+ // on the heap.
+ heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer();
+ if (!heapBuffer) {
+ // Allocation failed. The parser is now broken.
+ return executor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ }
+
+ if (heapBuffer) {
+ // We have something to insert before the keyholder holding in the non-null
+ // aKey case and we have something to swap into firstLevelMarker in the
+ // null aKey case.
+ if (aKey) {
+ NS_ASSERTION(mFirstBuffer != mLastBuffer, "Where's the keyholder?");
+ // the key holder is still somewhere further down the list from
+ // prevSearchBuf (which may be null)
+ if (mFirstBuffer->key == aKey) {
+ NS_ASSERTION(
+ !prevSearchBuf,
+ "Non-null prevSearchBuf when mFirstBuffer is the key holder?");
+ heapBuffer->next = mFirstBuffer;
+ mFirstBuffer = heapBuffer;
+ } else {
+ if (!prevSearchBuf) {
+ prevSearchBuf = mFirstBuffer;
+ }
+ // We created a key holder earlier, so we will find it without walking
+ // past the end of the list.
+ while (prevSearchBuf->next->key != aKey) {
+ prevSearchBuf = prevSearchBuf->next;
+ }
+ heapBuffer->next = prevSearchBuf->next;
+ prevSearchBuf->next = heapBuffer;
+ }
+ } else {
+ NS_ASSERTION(firstLevelMarker, "How come we don't have a marker.");
+ firstLevelMarker->Swap(heapBuffer);
+ }
+ }
+
+ if (!mBlocked) { // buffer was tokenized to completion
+ NS_ASSERTION(!stackBuffer.hasMore(),
+ "Buffer wasn't tokenized to completion?");
+ // Scripting semantics require a forced tree builder flush here
+ auto r = mTreeBuilder->Flush(); // Move ops to the executor
+ if (r.isErr()) {
+ return executor->MarkAsBroken(r.unwrapErr());
+ }
+ rv = executor->FlushDocumentWrite(); // run the ops
+ NS_ENSURE_SUCCESS(rv, rv);
+ } else if (stackBuffer.hasMore()) {
+ // The buffer wasn't tokenized to completion. Tokenize the untokenized
+ // content in order to preload stuff. This content will be retokenized
+ // later for normal parsing.
+ if (!mDocWriteSpeculatorActive) {
+ mDocWriteSpeculatorActive = true;
+ if (!mDocWriteSpeculativeTreeBuilder) {
+ // Lazily initialize if uninitialized
+ mDocWriteSpeculativeTreeBuilder =
+ mozilla::MakeUnique<nsHtml5TreeBuilder>(nullptr,
+ executor->GetStage(), true);
+ mDocWriteSpeculativeTreeBuilder->setScriptingEnabled(
+ mTreeBuilder->isScriptingEnabled());
+ mDocWriteSpeculativeTokenizer = mozilla::MakeUnique<nsHtml5Tokenizer>(
+ mDocWriteSpeculativeTreeBuilder.get(), false);
+ mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable);
+ mDocWriteSpeculativeTokenizer->start();
+ }
+ mDocWriteSpeculativeTokenizer->resetToDataState();
+ mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder.get());
+ mDocWriteSpeculativeLastWasCR = false;
+ }
+
+ // Note that with multilevel document.write if we didn't just activate the
+ // speculator, it's possible that the speculator is now in the wrong state.
+ // That's OK for the sake of simplicity. The worst that can happen is
+ // that the speculative loads aren't exactly right. The content will be
+ // reparsed anyway for non-preload purposes.
+
+ // The buffer position for subsequent non-speculative parsing now lives
+ // in heapBuffer, so it's ok to let the buffer position of stackBuffer
+ // to be overwritten and not restored below.
+ while (stackBuffer.hasMore()) {
+ stackBuffer.adjust(mDocWriteSpeculativeLastWasCR);
+ if (stackBuffer.hasMore()) {
+ if (!mDocWriteSpeculativeTokenizer->EnsureBufferSpace(
+ stackBuffer.getLength())) {
+ return executor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ mDocWriteSpeculativeLastWasCR =
+ mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer);
+ nsresult rv;
+ if (NS_FAILED((rv = mDocWriteSpeculativeTreeBuilder->IsBroken()))) {
+ return executor->MarkAsBroken(rv);
+ }
+ }
+ }
+
+ auto r = mDocWriteSpeculativeTreeBuilder->Flush();
+ if (r.isErr()) {
+ return executor->MarkAsBroken(r.unwrapErr());
+ }
+ mDocWriteSpeculativeTreeBuilder->DropHandles();
+ executor->FlushSpeculativeLoads();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHtml5Parser::Terminate() {
+ // Prevent a second call to DidBuildModel via document.close()
+ mDocumentClosed = true;
+ // We should only call DidBuildModel once, so don't do anything if this is
+ // the second time that Terminate has been called.
+ if (mExecutor->IsComplete()) {
+ return NS_OK;
+ }
+ // XXX - [ until we figure out a way to break parser-sink circularity ]
+ // Hack - Hold a reference until we are completely done...
+ nsCOMPtr<nsIParser> kungFuDeathGrip(this);
+ RefPtr<nsHtml5StreamParser> streamParser(GetStreamParser());
+ RefPtr<nsHtml5TreeOpExecutor> executor(mExecutor);
+ if (streamParser) {
+ streamParser->Terminate();
+ }
+ return executor->DidBuildModel(true);
+}
+
+bool nsHtml5Parser::IsInsertionPointDefined() {
+ return !mExecutor->IsFlushing() && !mInsertionPointPermanentlyUndefined &&
+ (!GetStreamParser() || mScriptNestingLevel != 0);
+}
+
+void nsHtml5Parser::IncrementScriptNestingLevel() { ++mScriptNestingLevel; }
+
+void nsHtml5Parser::DecrementScriptNestingLevel() { --mScriptNestingLevel; }
+
+bool nsHtml5Parser::HasNonzeroScriptNestingLevel() const {
+ return mScriptNestingLevel != 0;
+}
+
+void nsHtml5Parser::MarkAsNotScriptCreated(const char* aCommand) {
+ MOZ_ASSERT(!mStreamListener, "Must not call this twice.");
+ eParserMode mode = NORMAL;
+ if (!nsCRT::strcmp(aCommand, "view-source")) {
+ mode = VIEW_SOURCE_HTML;
+ } else if (!nsCRT::strcmp(aCommand, "view-source-xml")) {
+ mode = VIEW_SOURCE_XML;
+ } else if (!nsCRT::strcmp(aCommand, "view-source-plain")) {
+ mode = VIEW_SOURCE_PLAIN;
+ } else if (!nsCRT::strcmp(aCommand, "plain-text")) {
+ mode = PLAIN_TEXT;
+ } else if (!nsCRT::strcmp(aCommand, kLoadAsData)) {
+ mode = LOAD_AS_DATA;
+ }
+#ifdef DEBUG
+ else {
+ NS_ASSERTION(!nsCRT::strcmp(aCommand, "view") ||
+ !nsCRT::strcmp(aCommand, "external-resource") ||
+ !nsCRT::strcmp(aCommand, "import"),
+ "Unsupported parser command!");
+ }
+#endif
+ mStreamListener =
+ new nsHtml5StreamListener(new nsHtml5StreamParser(mExecutor, this, mode));
+}
+
+bool nsHtml5Parser::IsScriptCreated() { return !GetStreamParser(); }
+
+/* End nsIParser */
+
+// not from interface
+nsresult nsHtml5Parser::ParseUntilBlocked() {
+ nsresult rv = mExecutor->IsBroken();
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (mBlocked || mInsertionPointPermanentlyUndefined ||
+ mExecutor->IsComplete()) {
+ return NS_OK;
+ }
+ NS_ASSERTION(mExecutor->HasStarted(), "Bad life cycle.");
+ NS_ASSERTION(!mInDocumentWrite,
+ "ParseUntilBlocked entered while in doc.write!");
+
+ mDocWriteSpeculatorActive = false;
+
+ for (;;) {
+ if (!mFirstBuffer->hasMore()) {
+ if (mFirstBuffer == mLastBuffer) {
+ if (mExecutor->IsComplete()) {
+ // something like cache manisfests stopped the parse in mid-flight
+ return NS_OK;
+ }
+ if (mDocumentClosed) {
+ PermanentlyUndefineInsertionPoint();
+ nsresult rv;
+ MOZ_RELEASE_ASSERT(
+ !GetStreamParser(),
+ "This should only happen with script-created parser.");
+ if (NS_SUCCEEDED((rv = mExecutor->IsBroken()))) {
+ mTokenizer->eof();
+ if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
+ mExecutor->MarkAsBroken(rv);
+ } else {
+ mTreeBuilder->StreamEnded();
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ mExecutor->FlushDocumentWrite();
+ // The below call does memory cleanup, so call it even if the
+ // parser has been marked as broken.
+ mTokenizer->end();
+ return rv;
+ }
+ // never release the last buffer.
+ NS_ASSERTION(!mLastBuffer->getStart() && !mLastBuffer->getEnd(),
+ "Sentinel buffer had its indeces changed.");
+ if (GetStreamParser()) {
+ if (mReturnToStreamParserPermitted &&
+ !mExecutor->IsScriptExecuting()) {
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ mReturnToStreamParserPermitted = false;
+ GetStreamParser()->ContinueAfterScriptsOrEncodingCommitment(
+ mTokenizer.get(), mTreeBuilder.get(), mLastWasCR);
+ }
+ } else {
+ // Script-created parser
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ // No need to flush the executor, because the executor is already
+ // in a flush
+ NS_ASSERTION(mExecutor->IsInFlushLoop(),
+ "How did we come here without being in the flush loop?");
+ }
+ return NS_OK; // no more data for now but expecting more
+ }
+ mFirstBuffer = mFirstBuffer->next;
+ continue;
+ }
+
+ if (mBlocked || mExecutor->IsComplete()) {
+ return NS_OK;
+ }
+
+ // now we have a non-empty buffer
+ mFirstBuffer->adjust(mLastWasCR);
+ mLastWasCR = false;
+ if (mFirstBuffer->hasMore()) {
+ bool inRootContext = (!GetStreamParser() && !mFirstBuffer->key);
+ if (inRootContext) {
+ mTokenizer->setLineNumber(mRootContextLineNumber);
+ }
+ if (!mTokenizer->EnsureBufferSpace(mFirstBuffer->getLength())) {
+ return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer);
+ nsresult rv;
+ if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
+ return mExecutor->MarkAsBroken(rv);
+ }
+ if (inRootContext) {
+ mRootContextLineNumber = mTokenizer->getLineNumber();
+ }
+ if (mTreeBuilder->HasScript()) {
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ rv = mExecutor->FlushDocumentWrite();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ if (mBlocked) {
+ return NS_OK;
+ }
+ }
+ }
+}
+
+nsresult nsHtml5Parser::StartExecutor() {
+ MOZ_ASSERT(!GetStreamParser(),
+ "Had stream parser but document.write started life cycle.");
+ // This is part of the setup document.open() does.
+ RefPtr<nsHtml5TreeOpExecutor> executor(mExecutor);
+ executor->SetParser(this);
+ mTreeBuilder->setScriptingEnabled(executor->IsScriptEnabled());
+
+ mTreeBuilder->setIsSrcdocDocument(false);
+
+ mTokenizer->start();
+ executor->Start();
+
+ /*
+ * We know we're in document.open(), so our document must already
+ * have a script global andthe WillBuildModel call is safe.
+ */
+ return executor->WillBuildModel();
+}
+
+nsresult nsHtml5Parser::Initialize(mozilla::dom::Document* aDoc, nsIURI* aURI,
+ nsISupports* aContainer,
+ nsIChannel* aChannel) {
+ return mExecutor->Init(aDoc, aURI, aContainer, aChannel);
+}
+
+void nsHtml5Parser::StartTokenizer(bool aScriptingEnabled) {
+ bool isSrcdoc = false;
+ nsCOMPtr<nsIChannel> channel;
+ nsresult rv = GetChannel(getter_AddRefs(channel));
+ if (NS_SUCCEEDED(rv)) {
+ isSrcdoc = NS_IsSrcdocChannel(channel);
+ }
+ mTreeBuilder->setIsSrcdocDocument(isSrcdoc);
+
+ mTreeBuilder->SetPreventScriptExecution(!aScriptingEnabled);
+ mTreeBuilder->setScriptingEnabled(aScriptingEnabled);
+ mTokenizer->start();
+}
+
+void nsHtml5Parser::InitializeDocWriteParserState(
+ nsAHtml5TreeBuilderState* aState, int32_t aLine) {
+ mTokenizer->resetToDataState();
+ mTokenizer->setLineNumber(aLine);
+ mTreeBuilder->loadState(aState);
+ mLastWasCR = false;
+ mReturnToStreamParserPermitted = true;
+}
+
+void nsHtml5Parser::ContinueAfterFailedCharsetSwitch() {
+ MOZ_ASSERT(
+ GetStreamParser(),
+ "Tried to continue after failed charset switch without a stream parser");
+ GetStreamParser()->ContinueAfterFailedCharsetSwitch();
+}
diff --git a/parser/html/nsHtml5Parser.h b/parser/html/nsHtml5Parser.h
new file mode 100644
index 0000000000..593d52bc42
--- /dev/null
+++ b/parser/html/nsHtml5Parser.h
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef NS_HTML5_PARSER
+#define NS_HTML5_PARSER
+
+#include "mozilla/UniquePtr.h"
+#include "nsIParser.h"
+#include "nsDeque.h"
+#include "nsIContentSink.h"
+#include "nsIRequest.h"
+#include "nsIChannel.h"
+#include "nsCOMArray.h"
+#include "nsContentSink.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsHtml5OwningUTF16Buffer.h"
+#include "nsHtml5TreeOpExecutor.h"
+#include "nsHtml5StreamParser.h"
+#include "nsHtml5AtomTable.h"
+#include "nsWeakReference.h"
+#include "nsHtml5StreamListener.h"
+#include "nsCharsetSource.h"
+
+class nsHtml5Parser final : public nsIParser, public nsSupportsWeakReference {
+ public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHtml5Parser, nsIParser)
+
+ nsHtml5Parser();
+
+ /* Start nsIParser */
+ /**
+ * No-op for backwards compat.
+ */
+ NS_IMETHOD_(void) SetContentSink(nsIContentSink* aSink) override;
+
+ /**
+ * Returns the tree op executor for backwards compat.
+ */
+ NS_IMETHOD_(nsIContentSink*) GetContentSink() override;
+
+ /**
+ * Always returns "view" for backwards compat.
+ */
+ NS_IMETHOD_(void) GetCommand(nsCString& aCommand) override;
+
+ /**
+ * No-op for backwards compat.
+ */
+ NS_IMETHOD_(void) SetCommand(const char* aCommand) override;
+
+ /**
+ * No-op for backwards compat.
+ */
+ NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand) override;
+
+ /**
+ * Call this method once you've created a parser, and want to instruct it
+ * about what charset to load
+ *
+ * @param aEncoding the charset of a document
+ * @param aCharsetSource the source of the charset
+ */
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ int32_t aSource,
+ bool aForceAutoDetection) override;
+
+ /**
+ * Get the channel associated with this parser
+ * @param aChannel out param that will contain the result
+ * @return NS_OK if successful or NS_NOT_AVAILABLE if not
+ */
+ nsresult GetChannel(nsIChannel** aChannel);
+
+ /**
+ * Get the stream parser for this parser
+ */
+ virtual nsIStreamListener* GetStreamListener() override;
+
+ /**
+ * Don't call. For interface compat only.
+ */
+ NS_IMETHOD ContinueInterruptedParsing() override;
+
+ /**
+ * Blocks the parser.
+ */
+ NS_IMETHOD_(void) BlockParser() override;
+
+ /**
+ * Unblocks the parser.
+ */
+ NS_IMETHOD_(void) UnblockParser() override;
+
+ /**
+ * Asynchronously continues parsing.
+ */
+ NS_IMETHOD_(void) ContinueInterruptedParsingAsync() override;
+
+ /**
+ * Query whether the parser is enabled (i.e. not blocked) or not.
+ */
+ NS_IMETHOD_(bool) IsParserEnabled() override;
+
+ /**
+ * Query whether the parser thinks it's done with parsing.
+ */
+ NS_IMETHOD_(bool) IsComplete() override;
+
+ /**
+ * Set up request observer.
+ *
+ * @param aURL used for View Source title
+ */
+ NS_IMETHOD Parse(nsIURI* aURL) override;
+
+ /**
+ * document.write and document.close
+ *
+ * @param aSourceBuffer the argument of document.write (empty for .close())
+ * @param aKey a key unique to the script element that caused this call
+ * @param aLastCall true if .close() false if .write()
+ */
+ nsresult Parse(const nsAString& aSourceBuffer, void* aKey, bool aLastCall);
+
+ /**
+ * Stops the parser prematurely
+ */
+ NS_IMETHOD Terminate() override;
+
+ /**
+ * True if the insertion point (per HTML5) is defined.
+ */
+ virtual bool IsInsertionPointDefined() override;
+
+ /**
+ * Call immediately before starting to evaluate a parser-inserted script or
+ * in general when the spec says to increment the script nesting level.
+ */
+ void IncrementScriptNestingLevel() final;
+
+ /**
+ * Call immediately after having evaluated a parser-inserted script or
+ * generally want to restore to the state before the last
+ * IncrementScriptNestingLevel call.
+ */
+ void DecrementScriptNestingLevel() final;
+
+ /**
+ * True if this is an HTML5 parser whose script nesting level (in
+ * the sense of
+ * <https://html.spec.whatwg.org/multipage/parsing.html#script-nesting-level>)
+ * is nonzero.
+ */
+ bool HasNonzeroScriptNestingLevel() const final;
+
+ /**
+ * Marks the HTML5 parser as not a script-created parser: Prepares the
+ * parser to be able to read a stream.
+ *
+ * @param aCommand the parser command (Yeah, this is bad API design. Let's
+ * make this better when retiring nsIParser)
+ */
+ void MarkAsNotScriptCreated(const char* aCommand);
+
+ /**
+ * True if this is a script-created HTML5 parser.
+ */
+ virtual bool IsScriptCreated() override;
+
+ /* End nsIParser */
+
+ // Not from an external interface
+ // Non-inherited methods
+
+ public:
+ /**
+ * Initializes the parser to load from a channel.
+ */
+ virtual nsresult Initialize(mozilla::dom::Document* aDoc, nsIURI* aURI,
+ nsISupports* aContainer, nsIChannel* aChannel);
+
+ inline nsHtml5Tokenizer* GetTokenizer() { return mTokenizer.get(); }
+
+ void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState,
+ int32_t aLine);
+
+ void DropStreamParser() {
+ if (GetStreamParser()) {
+ GetStreamParser()->DropTimer();
+ mStreamListener->DropDelegate();
+ mStreamListener = nullptr;
+ }
+ }
+
+ void StartTokenizer(bool aScriptingEnabled);
+
+ void ContinueAfterFailedCharsetSwitch();
+
+ nsHtml5StreamParser* GetStreamParser() {
+ if (!mStreamListener) {
+ return nullptr;
+ }
+ return mStreamListener->GetDelegate();
+ }
+
+ void PermanentlyUndefineInsertionPoint() {
+ mInsertionPointPermanentlyUndefined = true;
+ }
+
+ /**
+ * Parse until pending data is exhausted or a script blocks the parser
+ */
+ nsresult ParseUntilBlocked();
+
+ /**
+ * Start our executor. This is meant to be used from document.open() _only_
+ * and does some work similar to what nsHtml5StreamParser::OnStartRequest does
+ * for normal parses.
+ */
+ nsresult StartExecutor();
+
+ private:
+ virtual ~nsHtml5Parser();
+
+ // State variables
+
+ /**
+ * Whether the last character tokenized was a carriage return (for CRLF)
+ */
+ bool mLastWasCR;
+
+ /**
+ * Whether the last character tokenized was a carriage return (for CRLF)
+ * when preparsing document.write.
+ */
+ bool mDocWriteSpeculativeLastWasCR;
+
+ /**
+ * The parser is blocking on the load of an external script from a web
+ * page, or any number of extension content scripts.
+ */
+ uint32_t mBlocked;
+
+ /**
+ * Whether the document.write() speculator is already active.
+ */
+ bool mDocWriteSpeculatorActive;
+
+ /**
+ * The number of IncrementScriptNestingLevel calls we've seen without a
+ * matching DecrementScriptNestingLevel.
+ */
+ int32_t mScriptNestingLevel;
+
+ /**
+ * True if document.close() has been called.
+ */
+ bool mDocumentClosed;
+
+ bool mInDocumentWrite;
+
+ /**
+ * This is set when the tokenizer has seen EOF. The purpose is to
+ * keep the insertion point undefined between the time the
+ * parser has reached the point where it can't accept more input
+ * and the time the document's mParser is set to nullptr.
+ * Scripts can run during this time period due to an update
+ * batch ending and due to various end-of-parse events firing.
+ * (Setting mParser on the document to nullptr at the point
+ * where this flag gets set to true would break things that for
+ * legacy reasons assume that mParser on the document stays
+ * non-null though the end-of-parse events.)
+ */
+ bool mInsertionPointPermanentlyUndefined;
+
+ // Portable parser objects
+ /**
+ * The first buffer in the pending UTF-16 buffer queue
+ */
+ RefPtr<nsHtml5OwningUTF16Buffer> mFirstBuffer;
+
+ /**
+ * The last buffer in the pending UTF-16 buffer queue. Always points
+ * to a sentinel object with nullptr as its parser key.
+ */
+ nsHtml5OwningUTF16Buffer* mLastBuffer; // weak ref;
+
+ /**
+ * The tree operation executor
+ */
+ RefPtr<nsHtml5TreeOpExecutor> mExecutor;
+
+ /**
+ * The HTML5 tree builder
+ */
+ const mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder;
+
+ /**
+ * The HTML5 tokenizer
+ */
+ const mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer;
+
+ /**
+ * Another HTML5 tree builder for preloading document.written content.
+ */
+ mozilla::UniquePtr<nsHtml5TreeBuilder> mDocWriteSpeculativeTreeBuilder;
+
+ /**
+ * Another HTML5 tokenizer for preloading document.written content.
+ */
+ mozilla::UniquePtr<nsHtml5Tokenizer> mDocWriteSpeculativeTokenizer;
+
+ /**
+ * The stream listener holding the stream parser.
+ */
+ RefPtr<nsHtml5StreamListener> mStreamListener;
+
+ /**
+ *
+ */
+ int32_t mRootContextLineNumber;
+
+ /**
+ * Whether it's OK to transfer parsing back to the stream parser
+ */
+ bool mReturnToStreamParserPermitted;
+
+ /**
+ * The scoped atom table
+ */
+ nsHtml5AtomTable mAtomTable;
+};
+#endif
diff --git a/parser/html/nsHtml5PlainTextUtils.cpp b/parser/html/nsHtml5PlainTextUtils.cpp
new file mode 100644
index 0000000000..17bf83c6ca
--- /dev/null
+++ b/parser/html/nsHtml5PlainTextUtils.cpp
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5PlainTextUtils.h"
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5String.h"
+#include "nsGkAtoms.h"
+#include "mozilla/StaticPrefs_plain_text.h"
+
+// static
+nsHtml5HtmlAttributes* nsHtml5PlainTextUtils::NewLinkAttributes() {
+ nsHtml5HtmlAttributes* linkAttrs = new nsHtml5HtmlAttributes(0);
+ nsHtml5String rel = nsHtml5Portability::newStringFromLiteral("stylesheet");
+ linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_REL, rel, -1);
+ nsHtml5String href = nsHtml5Portability::newStringFromLiteral(
+ "resource://content-accessible/plaintext.css");
+ linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1);
+ return linkAttrs;
+}
+
+// static
+nsHtml5HtmlAttributes* nsHtml5PlainTextUtils::NewBodyAttributes() {
+ if (mozilla::StaticPrefs::plain_text_wrap_long_lines()) {
+ return nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES;
+ }
+ nsHtml5HtmlAttributes* bodyAttrs = new nsHtml5HtmlAttributes(0);
+ RefPtr<nsAtom> nowrap = nsGkAtoms::nowrap;
+ bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_CLASS,
+ nsHtml5String::FromAtom(nowrap.forget()), -1);
+ return bodyAttrs;
+}
diff --git a/parser/html/nsHtml5PlainTextUtils.h b/parser/html/nsHtml5PlainTextUtils.h
new file mode 100644
index 0000000000..a56a8fc81a
--- /dev/null
+++ b/parser/html/nsHtml5PlainTextUtils.h
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5PlainTextUtils_h
+#define nsHtml5PlainTextUtils_h
+
+#include "nsHtml5HtmlAttributes.h"
+
+class nsHtml5PlainTextUtils {
+ public:
+ static nsHtml5HtmlAttributes* NewLinkAttributes();
+ static nsHtml5HtmlAttributes* NewBodyAttributes();
+};
+
+#endif // nsHtml5PlainTextUtils_h
diff --git a/parser/html/nsHtml5Portability.cpp b/parser/html/nsHtml5Portability.cpp
new file mode 100644
index 0000000000..e947c9e257
--- /dev/null
+++ b/parser/html/nsHtml5Portability.cpp
@@ -0,0 +1,109 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5Portability.h"
+#include "jArray.h"
+#include "nsAtom.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsString.h"
+#include "mozilla/CheckedInt.h"
+
+int32_t nsHtml5Portability::checkedAdd(int32_t a, int32_t b) {
+ mozilla::CheckedInt<int32_t> sum(a);
+ sum += b;
+ MOZ_RELEASE_ASSERT(sum.isValid(),
+ "HTML input too large for signed 32-bit integer.");
+ return sum.value();
+}
+
+nsAtom* nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf,
+ int32_t length,
+ nsHtml5AtomTable* interner) {
+ NS_ASSERTION(interner, "Didn't get an atom service.");
+ return interner->GetAtom(nsDependentSubstring(buf, buf + length));
+}
+
+static bool ContainsWhiteSpace(mozilla::Span<char16_t> aSpan) {
+ for (char16_t c : aSpan) {
+ if (nsContentUtils::IsHTMLWhitespace(c)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+nsHtml5String nsHtml5Portability::newStringFromBuffer(
+ char16_t* buf, int32_t offset, int32_t length,
+ nsHtml5TreeBuilder* treeBuilder, bool maybeAtomize) {
+ if (!length) {
+ return nsHtml5String::EmptyString();
+ }
+ if (maybeAtomize &&
+ !ContainsWhiteSpace(mozilla::Span(buf + offset, length))) {
+ return nsHtml5String::FromAtom(
+ NS_AtomizeMainThread(nsDependentSubstring(buf + offset, length)));
+ }
+ return nsHtml5String::FromBuffer(buf + offset, length, treeBuilder);
+}
+
+nsHtml5String nsHtml5Portability::newEmptyString() {
+ return nsHtml5String::EmptyString();
+}
+
+nsHtml5String nsHtml5Portability::newStringFromLiteral(const char* literal) {
+ return nsHtml5String::FromLiteral(literal);
+}
+
+nsHtml5String nsHtml5Portability::newStringFromString(nsHtml5String string) {
+ return string.Clone();
+}
+
+jArray<char16_t, int32_t> nsHtml5Portability::newCharArrayFromLocal(
+ nsAtom* local) {
+ nsAutoString temp;
+ local->ToString(temp);
+ int32_t len = temp.Length();
+ jArray<char16_t, int32_t> arr = jArray<char16_t, int32_t>::newJArray(len);
+ memcpy(arr, temp.BeginReading(), len * sizeof(char16_t));
+ return arr;
+}
+
+jArray<char16_t, int32_t> nsHtml5Portability::newCharArrayFromString(
+ nsHtml5String string) {
+ MOZ_RELEASE_ASSERT(string);
+ uint32_t len = string.Length();
+ MOZ_RELEASE_ASSERT(len < INT32_MAX);
+ jArray<char16_t, int32_t> arr = jArray<char16_t, int32_t>::newJArray(len);
+ string.CopyToBuffer(arr);
+ return arr;
+}
+
+bool nsHtml5Portability::localEqualsBuffer(nsAtom* local, char16_t* buf,
+ int32_t length) {
+ return local->Equals(buf, length);
+}
+
+bool nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ const char* lowerCaseLiteral, nsHtml5String string) {
+ return string.LowerCaseStartsWithASCII(lowerCaseLiteral);
+}
+
+bool nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ const char* lowerCaseLiteral, nsHtml5String string) {
+ return string.LowerCaseEqualsASCII(lowerCaseLiteral);
+}
+
+bool nsHtml5Portability::literalEqualsString(const char* literal,
+ nsHtml5String string) {
+ return string.EqualsASCII(literal);
+}
+
+bool nsHtml5Portability::stringEqualsString(nsHtml5String one,
+ nsHtml5String other) {
+ return one.Equals(other);
+}
+
+void nsHtml5Portability::initializeStatics() {}
+
+void nsHtml5Portability::releaseStatics() {}
diff --git a/parser/html/nsHtml5Portability.h b/parser/html/nsHtml5Portability.h
new file mode 100644
index 0000000000..18d2bd6b7e
--- /dev/null
+++ b/parser/html/nsHtml5Portability.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008-2015 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit Portability.java instead and regenerate.
+ */
+
+#ifndef nsHtml5Portability_h
+#define nsHtml5Portability_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+
+class nsHtml5Portability {
+ public:
+ static int32_t checkedAdd(int32_t a, int32_t b);
+ static nsAtom* newLocalNameFromBuffer(char16_t* buf, int32_t length,
+ nsHtml5AtomTable* interner);
+ static nsHtml5String newStringFromBuffer(char16_t* buf, int32_t offset,
+ int32_t length,
+ nsHtml5TreeBuilder* treeBuilder,
+ bool maybeAtomize);
+ static nsHtml5String newEmptyString();
+ static nsHtml5String newStringFromLiteral(const char* literal);
+ static nsHtml5String newStringFromString(nsHtml5String string);
+ static jArray<char16_t, int32_t> newCharArrayFromLocal(nsAtom* local);
+ static jArray<char16_t, int32_t> newCharArrayFromString(nsHtml5String string);
+ static bool localEqualsBuffer(nsAtom* local, char16_t* buf, int32_t length);
+ static bool lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ const char* lowerCaseLiteral, nsHtml5String string);
+ static bool lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ const char* lowerCaseLiteral, nsHtml5String string);
+ static bool literalEqualsString(const char* literal, nsHtml5String string);
+ static bool stringEqualsString(nsHtml5String one, nsHtml5String other);
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif
diff --git a/parser/html/nsHtml5SVGLoadDispatcher.cpp b/parser/html/nsHtml5SVGLoadDispatcher.cpp
new file mode 100644
index 0000000000..cbd711a98f
--- /dev/null
+++ b/parser/html/nsHtml5SVGLoadDispatcher.cpp
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5SVGLoadDispatcher.h"
+#include "mozilla/BasicEvents.h"
+#include "mozilla/EventDispatcher.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
+#include "nsPresContext.h"
+
+using namespace mozilla;
+
+nsHtml5SVGLoadDispatcher::nsHtml5SVGLoadDispatcher(nsIContent* aElement)
+ : Runnable("nsHtml5SVGLoadDispatcher"),
+ mElement(aElement),
+ mDocument(mElement->OwnerDoc()) {
+ mDocument->BlockOnload();
+}
+
+// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230, bug 1535398)
+MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP nsHtml5SVGLoadDispatcher::Run() {
+ WidgetEvent event(true, eSVGLoad);
+ event.mFlags.mBubbles = false;
+ // Do we care about forcing presshell creation if it hasn't happened yet?
+ // That is, should this code flush or something? Does it really matter?
+ // For that matter, do we really want to try getting the prescontext?
+ // Does this event ever want one?
+ RefPtr<nsPresContext> ctx = mElement->OwnerDoc()->GetPresContext();
+ EventDispatcher::Dispatch(mElement, ctx, &event);
+ // Unblocking onload on the same document that it was blocked even if
+ // the element has moved between docs since blocking.
+ mDocument->UnblockOnload(false);
+ return NS_OK;
+}
diff --git a/parser/html/nsHtml5SVGLoadDispatcher.h b/parser/html/nsHtml5SVGLoadDispatcher.h
new file mode 100644
index 0000000000..9079e5f430
--- /dev/null
+++ b/parser/html/nsHtml5SVGLoadDispatcher.h
@@ -0,0 +1,21 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5SVGLoadDispatcher_h
+#define nsHtml5SVGLoadDispatcher_h
+
+#include "nsThreadUtils.h"
+#include "nsIContent.h"
+
+class nsHtml5SVGLoadDispatcher : public mozilla::Runnable {
+ private:
+ const nsCOMPtr<nsIContent> mElement;
+ const RefPtr<mozilla::dom::Document> mDocument;
+
+ public:
+ explicit nsHtml5SVGLoadDispatcher(nsIContent* aElement);
+ NS_IMETHOD Run() override;
+};
+
+#endif // nsHtml5SVGLoadDispatcher_h
diff --git a/parser/html/nsHtml5Speculation.cpp b/parser/html/nsHtml5Speculation.cpp
new file mode 100644
index 0000000000..0cf7816ff6
--- /dev/null
+++ b/parser/html/nsHtml5Speculation.cpp
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5Speculation.h"
+
+using namespace mozilla;
+
+nsHtml5Speculation::nsHtml5Speculation(nsHtml5OwningUTF16Buffer* aBuffer,
+ int32_t aStart, int32_t aStartLineNumber,
+ int32_t aStartColumnNumber,
+ nsAHtml5TreeBuilderState* aSnapshot)
+ : mBuffer(aBuffer),
+ mStart(aStart),
+ mStartLineNumber(aStartLineNumber),
+ mStartColumnNumber(aStartColumnNumber),
+ mSnapshot(aSnapshot) {
+ MOZ_COUNT_CTOR(nsHtml5Speculation);
+}
+
+nsHtml5Speculation::~nsHtml5Speculation() {
+ MOZ_COUNT_DTOR(nsHtml5Speculation);
+}
+
+[[nodiscard]] bool nsHtml5Speculation::MoveOpsFrom(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) {
+ return !!mOpQueue.AppendElements(std::move(aOpQueue), mozilla::fallible_t());
+}
+
+[[nodiscard]] bool nsHtml5Speculation::FlushToSink(nsAHtml5TreeOpSink* aSink) {
+ return aSink->MoveOpsFrom(mOpQueue);
+}
diff --git a/parser/html/nsHtml5Speculation.h b/parser/html/nsHtml5Speculation.h
new file mode 100644
index 0000000000..9bd04a7c19
--- /dev/null
+++ b/parser/html/nsHtml5Speculation.h
@@ -0,0 +1,69 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5Speculation_h
+#define nsHtml5Speculation_h
+
+#include "nsHtml5OwningUTF16Buffer.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsAHtml5TreeOpSink.h"
+#include "nsTArray.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/UniquePtr.h"
+
+class nsHtml5Speculation final : public nsAHtml5TreeOpSink {
+ public:
+ nsHtml5Speculation(nsHtml5OwningUTF16Buffer* aBuffer, int32_t aStart,
+ int32_t aStartLineNumber, int32_t aStartColumnNumber,
+ nsAHtml5TreeBuilderState* aSnapshot);
+
+ ~nsHtml5Speculation();
+
+ nsHtml5OwningUTF16Buffer* GetBuffer() { return mBuffer; }
+
+ int32_t GetStart() { return mStart; }
+
+ int32_t GetStartLineNumber() { return mStartLineNumber; }
+
+ int32_t GetStartColumnNumber() { return mStartColumnNumber; }
+
+ nsAHtml5TreeBuilderState* GetSnapshot() { return mSnapshot.get(); }
+
+ /**
+ * Flush the operations from the tree operations from the argument
+ * queue unconditionally.
+ */
+ [[nodiscard]] virtual bool MoveOpsFrom(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) override;
+
+ [[nodiscard]] bool FlushToSink(nsAHtml5TreeOpSink* aSink);
+
+ private:
+ /**
+ * The first buffer in the pending UTF-16 buffer queue
+ */
+ RefPtr<nsHtml5OwningUTF16Buffer> mBuffer;
+
+ /**
+ * The start index of this speculation in the first buffer
+ */
+ int32_t mStart;
+
+ /**
+ * The current line number at the start of the speculation
+ */
+ int32_t mStartLineNumber;
+
+ /**
+ * The current line number at the start of the speculation.
+ */
+ int32_t mStartColumnNumber;
+
+ mozilla::UniquePtr<nsAHtml5TreeBuilderState> mSnapshot;
+
+ nsTArray<nsHtml5TreeOperation> mOpQueue;
+};
+
+#endif // nsHtml5Speculation_h
diff --git a/parser/html/nsHtml5SpeculativeLoad.cpp b/parser/html/nsHtml5SpeculativeLoad.cpp
new file mode 100644
index 0000000000..f7994495a6
--- /dev/null
+++ b/parser/html/nsHtml5SpeculativeLoad.cpp
@@ -0,0 +1,158 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5SpeculativeLoad.h"
+#include "mozilla/Encoding.h"
+#include "nsHtml5TreeOpExecutor.h"
+
+using namespace mozilla;
+
+nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
+ : mOpCode(eSpeculativeLoadUninitialized),
+ mIsAsync(false),
+ mIsDefer(false),
+ mIsLinkPreload(false),
+ mIsError(false),
+ mEncoding(nullptr) {
+ MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad);
+ new (&mCharsetOrSrcset) nsString;
+}
+
+nsHtml5SpeculativeLoad::~nsHtml5SpeculativeLoad() {
+ MOZ_COUNT_DTOR(nsHtml5SpeculativeLoad);
+ NS_ASSERTION(mOpCode != eSpeculativeLoadUninitialized,
+ "Uninitialized speculative load.");
+ if (!(mOpCode == eSpeculativeLoadSetDocumentCharset ||
+ mOpCode == eSpeculativeLoadMaybeComplainAboutCharset)) {
+ mCharsetOrSrcset.~nsString();
+ }
+}
+
+void nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor) {
+ switch (mOpCode) {
+ case eSpeculativeLoadBase:
+ aExecutor->SetSpeculationBase(mUrlOrSizes);
+ break;
+ case eSpeculativeLoadCSP:
+ aExecutor->AddSpeculationCSP(
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
+ break;
+ case eSpeculativeLoadMetaReferrer:
+ aExecutor->UpdateReferrerInfoFromMeta(mReferrerPolicyOrIntegrity);
+ break;
+ case eSpeculativeLoadImage:
+ aExecutor->PreloadImage(
+ mUrlOrSizes, mCrossOrigin, mMedia, mCharsetOrSrcset,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mReferrerPolicyOrIntegrity, mIsLinkPreload, mInitTimestamp);
+ break;
+ case eSpeculativeLoadOpenPicture:
+ aExecutor->PreloadOpenPicture();
+ break;
+ case eSpeculativeLoadEndPicture:
+ aExecutor->PreloadEndPicture();
+ break;
+ case eSpeculativeLoadPictureSource:
+ aExecutor->PreloadPictureSource(
+ mCharsetOrSrcset, mUrlOrSizes,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mMedia);
+ break;
+ case eSpeculativeLoadScript:
+ aExecutor->PreloadScript(
+ mUrlOrSizes, mCharsetOrSrcset,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity,
+ mScriptReferrerPolicy, false, mIsAsync, mIsDefer, false,
+ mIsLinkPreload);
+ break;
+ case eSpeculativeLoadScriptFromHead:
+ aExecutor->PreloadScript(
+ mUrlOrSizes, mCharsetOrSrcset,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity,
+ mScriptReferrerPolicy, true, mIsAsync, mIsDefer, false,
+ mIsLinkPreload);
+ break;
+ case eSpeculativeLoadNoModuleScript:
+ aExecutor->PreloadScript(
+ mUrlOrSizes, mCharsetOrSrcset,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity,
+ mScriptReferrerPolicy, false, mIsAsync, mIsDefer, true,
+ mIsLinkPreload);
+ break;
+ case eSpeculativeLoadNoModuleScriptFromHead:
+ aExecutor->PreloadScript(
+ mUrlOrSizes, mCharsetOrSrcset,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mCrossOrigin, mMedia, mReferrerPolicyOrIntegrity,
+ mScriptReferrerPolicy, true, mIsAsync, mIsDefer, true,
+ mIsLinkPreload);
+ break;
+ case eSpeculativeLoadStyle:
+ aExecutor->PreloadStyle(
+ mUrlOrSizes, mCharsetOrSrcset, mCrossOrigin, mMedia,
+ mReferrerPolicyOrIntegrity,
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
+ mIsLinkPreload);
+ break;
+ case eSpeculativeLoadManifest:
+ // TODO: remove this
+ break;
+ case eSpeculativeLoadSetDocumentCharset: {
+ MOZ_ASSERT(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .Length() == 1,
+ "Unexpected charset source string");
+ nsCharsetSource enumSource =
+ (nsCharsetSource)
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .First();
+ aExecutor->SetDocumentCharsetAndSource(WrapNotNull(mEncoding),
+ enumSource);
+ if (mCommitEncodingSpeculation) {
+ aExecutor->CommitToInternalEncoding();
+ }
+ } break;
+ case eSpeculativeLoadSetDocumentMode: {
+ NS_ASSERTION(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .Length() == 1,
+ "Unexpected document mode string");
+ nsHtml5DocumentMode mode =
+ (nsHtml5DocumentMode)
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .First();
+ aExecutor->SetDocumentMode(mode);
+ } break;
+ case eSpeculativeLoadPreconnect:
+ aExecutor->Preconnect(mUrlOrSizes, mCrossOrigin);
+ break;
+ case eSpeculativeLoadFont:
+ aExecutor->PreloadFont(mUrlOrSizes, mCrossOrigin, mMedia,
+ mReferrerPolicyOrIntegrity);
+ break;
+ case eSpeculativeLoadFetch:
+ aExecutor->PreloadFetch(mUrlOrSizes, mCrossOrigin, mMedia,
+ mReferrerPolicyOrIntegrity);
+ break;
+ case eSpeculativeLoadMaybeComplainAboutCharset: {
+ MOZ_ASSERT(mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .Length() == 2,
+ "Unexpected line number string");
+ uint32_t high =
+ (uint32_t)
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .CharAt(0);
+ uint32_t low =
+ (uint32_t)
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
+ .CharAt(1);
+ uint32_t line = (high << 16) | low;
+ aExecutor->MaybeComplainAboutCharset(mMsgId, mIsError, (int32_t)line);
+ } break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Bogus speculative load.");
+ break;
+ }
+}
diff --git a/parser/html/nsHtml5SpeculativeLoad.h b/parser/html/nsHtml5SpeculativeLoad.h
new file mode 100644
index 0000000000..4b2f755857
--- /dev/null
+++ b/parser/html/nsHtml5SpeculativeLoad.h
@@ -0,0 +1,419 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5SpeculativeLoad_h
+#define nsHtml5SpeculativeLoad_h
+
+#include "nsString.h"
+#include "nsContentUtils.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5String.h"
+#include "ReferrerInfo.h"
+
+class nsHtml5TreeOpExecutor;
+
+enum eHtml5SpeculativeLoad {
+ eSpeculativeLoadUninitialized,
+ eSpeculativeLoadBase,
+ eSpeculativeLoadCSP,
+ eSpeculativeLoadMetaReferrer,
+ eSpeculativeLoadImage,
+ eSpeculativeLoadOpenPicture,
+ eSpeculativeLoadEndPicture,
+ eSpeculativeLoadPictureSource,
+ eSpeculativeLoadScript,
+ eSpeculativeLoadScriptFromHead,
+ eSpeculativeLoadNoModuleScript,
+ eSpeculativeLoadNoModuleScriptFromHead,
+ eSpeculativeLoadStyle,
+ eSpeculativeLoadManifest,
+ eSpeculativeLoadSetDocumentCharset,
+ eSpeculativeLoadSetDocumentMode,
+ eSpeculativeLoadPreconnect,
+ eSpeculativeLoadFont,
+ eSpeculativeLoadFetch,
+ eSpeculativeLoadMaybeComplainAboutCharset
+};
+
+class nsHtml5SpeculativeLoad {
+ using Encoding = mozilla::Encoding;
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+
+ public:
+ nsHtml5SpeculativeLoad();
+ ~nsHtml5SpeculativeLoad();
+
+ inline void InitBase(nsHtml5String aUrl) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadBase;
+ aUrl.ToString(mUrlOrSizes);
+ }
+
+ inline void InitMetaCSP(nsHtml5String aCSP) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadCSP;
+ nsString csp; // Not Auto, because using it to hold nsStringBuffer*
+ aCSP.ToString(csp);
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp));
+ }
+
+ inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadMetaReferrer;
+ nsString
+ referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
+ aReferrerPolicy.ToString(referrerPolicy);
+ mReferrerPolicyOrIntegrity.Assign(
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ referrerPolicy));
+ }
+
+ inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
+ nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
+ nsHtml5String aSrcset, nsHtml5String aSizes,
+ bool aLinkPreload) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadImage;
+ aUrl.ToString(mUrlOrSizes);
+ aCrossOrigin.ToString(mCrossOrigin);
+ aMedia.ToString(mMedia);
+ nsString
+ referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
+ aReferrerPolicy.ToString(referrerPolicy);
+ mReferrerPolicyOrIntegrity.Assign(
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ referrerPolicy));
+ aSrcset.ToString(mCharsetOrSrcset);
+ aSizes.ToString(
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
+ mIsLinkPreload = aLinkPreload;
+ mInitTimestamp = mozilla::TimeStamp::Now();
+ }
+
+ inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
+ nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadFont;
+ aUrl.ToString(mUrlOrSizes);
+ aCrossOrigin.ToString(mCrossOrigin);
+ aMedia.ToString(mMedia);
+ nsString
+ referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
+ aReferrerPolicy.ToString(referrerPolicy);
+ mReferrerPolicyOrIntegrity.Assign(
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ referrerPolicy));
+ // This can be only triggered by <link rel=preload type=font>
+ mIsLinkPreload = true;
+ }
+
+ inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
+ nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadFetch;
+ aUrl.ToString(mUrlOrSizes);
+ aCrossOrigin.ToString(mCrossOrigin);
+ aMedia.ToString(mMedia);
+ nsString
+ referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
+ aReferrerPolicy.ToString(referrerPolicy);
+ mReferrerPolicyOrIntegrity.Assign(
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ referrerPolicy));
+
+ // This method can be only be triggered by <link rel=preload type=fetch>,
+ // hence this operation is always a preload.
+ mIsLinkPreload = true;
+ }
+
+ // <picture> elements have multiple <source> nodes followed by an <img>,
+ // where we use the first valid source, which may be the img. Because we
+ // can't determine validity at this point without parsing CSS and getting
+ // main thread state, we push preload operations for picture pushed and
+ // popped, so that the target of the preload ops can determine what picture
+ // and nesting level each source/img from the main preloading code exists
+ // at.
+ inline void InitOpenPicture() {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadOpenPicture;
+ }
+
+ inline void InitEndPicture() {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadEndPicture;
+ }
+
+ inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes,
+ nsHtml5String aType, nsHtml5String aMedia) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadPictureSource;
+ aSrcset.ToString(mCharsetOrSrcset);
+ aSizes.ToString(mUrlOrSizes);
+ aType.ToString(
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
+ aMedia.ToString(mMedia);
+ }
+
+ inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset,
+ nsHtml5String aType, nsHtml5String aCrossOrigin,
+ nsHtml5String aMedia, nsHtml5String aIntegrity,
+ nsHtml5String aReferrerPolicy, bool aParserInHead,
+ bool aAsync, bool aDefer, bool aNoModule,
+ bool aLinkPreload) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ if (aNoModule) {
+ mOpCode = aParserInHead ? eSpeculativeLoadNoModuleScriptFromHead
+ : eSpeculativeLoadNoModuleScript;
+ } else {
+ mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead
+ : eSpeculativeLoadScript;
+ }
+ aUrl.ToString(mUrlOrSizes);
+ aCharset.ToString(mCharsetOrSrcset);
+ aType.ToString(
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
+ aCrossOrigin.ToString(mCrossOrigin);
+ aMedia.ToString(mMedia);
+ aIntegrity.ToString(mReferrerPolicyOrIntegrity);
+ nsAutoString referrerPolicy;
+ aReferrerPolicy.ToString(referrerPolicy);
+ referrerPolicy =
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ referrerPolicy);
+ mScriptReferrerPolicy =
+ mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
+ referrerPolicy);
+
+ mIsAsync = aAsync;
+ mIsDefer = aDefer;
+ mIsLinkPreload = aLinkPreload;
+ }
+
+ inline void InitImportStyle(nsString&& aUrl) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadStyle;
+ mUrlOrSizes = std::move(aUrl);
+ mCharsetOrSrcset.SetIsVoid(true);
+ mCrossOrigin.SetIsVoid(true);
+ mMedia.SetIsVoid(true);
+ mReferrerPolicyOrIntegrity.SetIsVoid(true);
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid(
+ true);
+ }
+
+ inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset,
+ nsHtml5String aCrossOrigin, nsHtml5String aMedia,
+ nsHtml5String aReferrerPolicy, nsHtml5String aIntegrity,
+ bool aLinkPreload) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadStyle;
+ aUrl.ToString(mUrlOrSizes);
+ aCharset.ToString(mCharsetOrSrcset);
+ aCrossOrigin.ToString(mCrossOrigin);
+ aMedia.ToString(mMedia);
+ nsString
+ referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
+ aReferrerPolicy.ToString(referrerPolicy);
+ mReferrerPolicyOrIntegrity.Assign(
+ nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ referrerPolicy));
+ aIntegrity.ToString(
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
+ mIsLinkPreload = aLinkPreload;
+ }
+
+ /**
+ * "Speculative" manifest loads aren't truly speculative--if a manifest
+ * gets loaded, we are committed to it. There can never be a <script>
+ * before the manifest, so the situation of having to undo a manifest due
+ * to document.write() never arises. The reason why a parser
+ * thread-discovered manifest gets loaded via the speculative load queue
+ * as opposed to tree operation queue is that the manifest must get
+ * processed before any actual speculative loads such as scripts. Thus,
+ * manifests seen by the parser thread have to maintain the queue order
+ * relative to true speculative loads. See bug 541079.
+ */
+ inline void InitManifest(nsHtml5String aUrl) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadManifest;
+ aUrl.ToString(mUrlOrSizes);
+ }
+
+ /**
+ * We communicate the encoding change via the speculative operation
+ * queue in order to act upon it as soon as possible and so as not to
+ * have speculative loads generated after an encoding change fail to
+ * make use of the encoding change.
+ */
+ inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ int32_t aCharsetSource,
+ bool aCommitEncodingSpeculation) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadSetDocumentCharset;
+ mCharsetOrSrcset.~nsString();
+ mEncoding = aEncoding;
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
+ (char16_t)aCharsetSource);
+ mCommitEncodingSpeculation = aCommitEncodingSpeculation;
+ }
+
+ inline void InitMaybeComplainAboutCharset(const char* aMsgId, bool aError,
+ int32_t aLineNumber) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadMaybeComplainAboutCharset;
+ mCharsetOrSrcset.~nsString();
+ mMsgId = aMsgId;
+ mIsError = aError;
+ // Transport a 32-bit integer as two 16-bit code units of a string
+ // in order to avoid adding an integer field to the object.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=1733043 for a better
+ // eventual approach.
+ char16_t high = (char16_t)(((uint32_t)aLineNumber) >> 16);
+ char16_t low = (char16_t)(((uint32_t)aLineNumber) & 0xFFFF);
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(high);
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Append(low);
+ }
+
+ /**
+ * Speculative document mode setting isn't really speculative. Once it
+ * happens, we are committed to it. However, this information needs to
+ * travel in the speculation queue in order to have this information
+ * available before parsing the speculatively loaded style sheets.
+ */
+ inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadSetDocumentMode;
+ mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
+ (char16_t)aMode);
+ }
+
+ inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) {
+ MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
+ "Trying to reinitialize a speculative load!");
+ mOpCode = eSpeculativeLoadPreconnect;
+ aUrl.ToString(mUrlOrSizes);
+ aCrossOrigin.ToString(mCrossOrigin);
+ }
+
+ void Perform(nsHtml5TreeOpExecutor* aExecutor);
+
+ private:
+ nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete;
+ nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete;
+
+ eHtml5SpeculativeLoad mOpCode;
+
+ /**
+ * Whether the refering element has async attribute.
+ */
+ bool mIsAsync;
+
+ /**
+ * Whether the refering element has defer attribute.
+ */
+ bool mIsDefer;
+
+ /**
+ * True if and only if this is a speculative load initiated by <link
+ * rel="preload"> or <link rel="modulepreload"> tag encounter. Passed to the
+ * handling loader as an indication to raise the priority.
+ */
+ bool mIsLinkPreload;
+
+ /**
+ * Whether the charset complaint is an error.
+ */
+ bool mIsError;
+
+ /**
+ * Whether setting document encoding involves also committing to an encoding
+ * speculation.
+ */
+ bool mCommitEncodingSpeculation;
+
+ /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
+ * "sizes" attribute. If the attribute is not set, this will be a void
+ * string. Otherwise it empty or the value of the url.
+ */
+ nsString mUrlOrSizes;
+ /**
+ * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
+ * "integrity" attribute. If the attribute is not set, this will be a void
+ * string. Otherwise it is empty or the value of the referrer policy.
+ */
+ nsString mReferrerPolicyOrIntegrity;
+ /**
+ * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
+ * then this is the value of the "charset" attribute. For
+ * eSpeculativeLoadSetDocumentCharset it is the charset that the
+ * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
+ * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
+ * attribute. If the attribute is not set, this will be a void string.
+ * Otherwise it's empty.
+ * For eSpeculativeLoadMaybeComplainAboutCharset mMsgId is used.
+ */
+ union {
+ nsString mCharsetOrSrcset;
+ const Encoding* mEncoding;
+ const char* mMsgId;
+ };
+ /**
+ * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
+ * one-character string whose single character's code point is to be
+ * interpreted as a charset source integer. If mOpCode is
+ * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
+ * single character's code point is to be interpreted as an
+ * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
+ * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
+ * value of the "sizes" attribute. If the attribute is not set, this will
+ * be a void string. If mOpCode is eSpeculativeLoadStyle, this
+ * is the value of the "integrity" attribute. If the attribute is not set,
+ * this will be a void string. Otherwise, it is empty or the value of the type
+ * attribute.
+ */
+ nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity;
+ /**
+ * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
+ * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of
+ * the "crossorigin" attribute. If the attribute is not set, this will be a
+ * void string.
+ */
+ nsString mCrossOrigin;
+ /**
+ * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or
+ * Fetch or Image or Media or Script this is the value of the relevant "media"
+ * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the
+ * attribute is not set, or the preload didn't originate from a <link>, this
+ * will be a void string.
+ */
+ nsString mMedia;
+ /**
+ * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
+ * of the "referrerpolicy" attribute. This field holds one of the values
+ * (REFERRER_POLICY_*) defined in nsIHttpChannel.
+ */
+ mozilla::dom::ReferrerPolicy mScriptReferrerPolicy;
+
+ mozilla::TimeStamp mInitTimestamp;
+};
+
+#endif // nsHtml5SpeculativeLoad_h
diff --git a/parser/html/nsHtml5StackNode.cpp b/parser/html/nsHtml5StackNode.cpp
new file mode 100644
index 0000000000..34b5ab1b12
--- /dev/null
+++ b/parser/html/nsHtml5StackNode.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2007-2011 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit StackNode.java instead and regenerate.
+ */
+
+#define nsHtml5StackNode_cpp__
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5StackNode.h"
+
+int32_t nsHtml5StackNode::getGroup() {
+ return flags & nsHtml5ElementName::GROUP_MASK;
+}
+
+bool nsHtml5StackNode::isScoping() {
+ return (flags & nsHtml5ElementName::SCOPING);
+}
+
+bool nsHtml5StackNode::isSpecial() {
+ return (flags & nsHtml5ElementName::SPECIAL);
+}
+
+bool nsHtml5StackNode::isFosterParenting() {
+ return (flags & nsHtml5ElementName::FOSTER_PARENTING);
+}
+
+bool nsHtml5StackNode::isHtmlIntegrationPoint() {
+ return (flags & nsHtml5ElementName::HTML_INTEGRATION_POINT);
+}
+
+nsHtml5StackNode::nsHtml5StackNode(int32_t idxInTreeBuilder)
+ : idxInTreeBuilder(idxInTreeBuilder),
+ flags(0),
+ name(nullptr),
+ popName(nullptr),
+ ns(0),
+ node(nullptr),
+ attributes(nullptr),
+ refcount(0),
+ htmlCreator(nullptr) {
+ MOZ_COUNT_CTOR(nsHtml5StackNode);
+}
+
+mozilla::dom::HTMLContentCreatorFunction nsHtml5StackNode::getHtmlCreator() {
+ return htmlCreator;
+}
+
+void nsHtml5StackNode::setValues(
+ int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node,
+ nsAtom* popName, nsHtml5HtmlAttributes* attributes,
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator) {
+ MOZ_ASSERT(isUnused());
+ this->flags = flags;
+ this->name = name;
+ this->popName = popName;
+ this->ns = ns;
+ this->node = node;
+ this->attributes = attributes;
+ this->refcount = 1;
+ this->htmlCreator = htmlCreator;
+}
+
+void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
+ nsIContentHandle* node) {
+ MOZ_ASSERT(isUnused());
+ this->flags = elementName->getFlags();
+ this->name = elementName->getName();
+ this->popName = elementName->getName();
+ this->ns = kNameSpaceID_XHTML;
+ this->node = node;
+ this->attributes = nullptr;
+ this->refcount = 1;
+ MOZ_ASSERT(elementName->isInterned(),
+ "Don't use this constructor for custom elements.");
+ this->htmlCreator = nullptr;
+}
+
+void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
+ nsIContentHandle* node,
+ nsHtml5HtmlAttributes* attributes) {
+ MOZ_ASSERT(isUnused());
+ this->flags = elementName->getFlags();
+ this->name = elementName->getName();
+ this->popName = elementName->getName();
+ this->ns = kNameSpaceID_XHTML;
+ this->node = node;
+ this->attributes = attributes;
+ this->refcount = 1;
+ MOZ_ASSERT(elementName->isInterned(),
+ "Don't use this constructor for custom elements.");
+ this->htmlCreator = elementName->getHtmlCreator();
+}
+
+void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
+ nsIContentHandle* node, nsAtom* popName) {
+ MOZ_ASSERT(isUnused());
+ this->flags = elementName->getFlags();
+ this->name = elementName->getName();
+ this->popName = popName;
+ this->ns = kNameSpaceID_XHTML;
+ this->node = node;
+ this->attributes = nullptr;
+ this->refcount = 1;
+ this->htmlCreator = nullptr;
+}
+
+void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
+ nsAtom* popName, nsIContentHandle* node) {
+ MOZ_ASSERT(isUnused());
+ this->flags = prepareSvgFlags(elementName->getFlags());
+ this->name = elementName->getName();
+ this->popName = popName;
+ this->ns = kNameSpaceID_SVG;
+ this->node = node;
+ this->attributes = nullptr;
+ this->refcount = 1;
+ this->htmlCreator = nullptr;
+}
+
+void nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
+ nsIContentHandle* node, nsAtom* popName,
+ bool markAsIntegrationPoint) {
+ MOZ_ASSERT(isUnused());
+ this->flags =
+ prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint);
+ this->name = elementName->getName();
+ this->popName = popName;
+ this->ns = kNameSpaceID_MathML;
+ this->node = node;
+ this->attributes = nullptr;
+ this->refcount = 1;
+ this->htmlCreator = nullptr;
+}
+
+int32_t nsHtml5StackNode::prepareSvgFlags(int32_t flags) {
+ flags &=
+ ~(nsHtml5ElementName::FOSTER_PARENTING | nsHtml5ElementName::SCOPING |
+ nsHtml5ElementName::SPECIAL | nsHtml5ElementName::OPTIONAL_END_TAG);
+ if ((flags & nsHtml5ElementName::SCOPING_AS_SVG)) {
+ flags |= (nsHtml5ElementName::SCOPING | nsHtml5ElementName::SPECIAL |
+ nsHtml5ElementName::HTML_INTEGRATION_POINT);
+ }
+ return flags;
+}
+
+int32_t nsHtml5StackNode::prepareMathFlags(int32_t flags,
+ bool markAsIntegrationPoint) {
+ flags &=
+ ~(nsHtml5ElementName::FOSTER_PARENTING | nsHtml5ElementName::SCOPING |
+ nsHtml5ElementName::SPECIAL | nsHtml5ElementName::OPTIONAL_END_TAG);
+ if ((flags & nsHtml5ElementName::SCOPING_AS_MATHML)) {
+ flags |= (nsHtml5ElementName::SCOPING | nsHtml5ElementName::SPECIAL);
+ }
+ if (markAsIntegrationPoint) {
+ flags |= nsHtml5ElementName::HTML_INTEGRATION_POINT;
+ }
+ return flags;
+}
+
+nsHtml5StackNode::~nsHtml5StackNode() { MOZ_COUNT_DTOR(nsHtml5StackNode); }
+
+void nsHtml5StackNode::dropAttributes() { attributes = nullptr; }
+
+void nsHtml5StackNode::retain() { refcount++; }
+
+void nsHtml5StackNode::release(nsHtml5TreeBuilder* owningTreeBuilder) {
+ refcount--;
+ MOZ_ASSERT(refcount >= 0);
+ if (!refcount) {
+ delete attributes;
+ if (idxInTreeBuilder >= 0) {
+ owningTreeBuilder->notifyUnusedStackNode(idxInTreeBuilder);
+ } else {
+ MOZ_ASSERT(!owningTreeBuilder);
+ delete this;
+ }
+ }
+}
+
+bool nsHtml5StackNode::isUnused() { return !refcount; }
+
+void nsHtml5StackNode::initializeStatics() {}
+
+void nsHtml5StackNode::releaseStatics() {}
diff --git a/parser/html/nsHtml5StackNode.h b/parser/html/nsHtml5StackNode.h
new file mode 100644
index 0000000000..b73dc57a69
--- /dev/null
+++ b/parser/html/nsHtml5StackNode.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2007-2011 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit StackNode.java instead and regenerate.
+ */
+
+#ifndef nsHtml5StackNode_h
+#define nsHtml5StackNode_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5HtmlAttributes.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5StackNode {
+ public:
+ int32_t idxInTreeBuilder;
+ int32_t flags;
+ RefPtr<nsAtom> name;
+ RefPtr<nsAtom> popName;
+ int32_t ns;
+ nsIContentHandle* node;
+ nsHtml5HtmlAttributes* attributes;
+
+ private:
+ int32_t refcount;
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator;
+
+ public:
+ inline int32_t getFlags() { return flags; }
+
+ int32_t getGroup();
+ bool isScoping();
+ bool isSpecial();
+ bool isFosterParenting();
+ bool isHtmlIntegrationPoint();
+ explicit nsHtml5StackNode(int32_t idxInTreeBuilder);
+ mozilla::dom::HTMLContentCreatorFunction getHtmlCreator();
+ void setValues(int32_t flags, int32_t ns, nsAtom* name,
+ nsIContentHandle* node, nsAtom* popName,
+ nsHtml5HtmlAttributes* attributes,
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator);
+ void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node);
+ void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node,
+ nsHtml5HtmlAttributes* attributes);
+ void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node,
+ nsAtom* popName);
+ void setValues(nsHtml5ElementName* elementName, nsAtom* popName,
+ nsIContentHandle* node);
+ void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node,
+ nsAtom* popName, bool markAsIntegrationPoint);
+
+ private:
+ static int32_t prepareSvgFlags(int32_t flags);
+ static int32_t prepareMathFlags(int32_t flags, bool markAsIntegrationPoint);
+
+ public:
+ ~nsHtml5StackNode();
+ void dropAttributes();
+ void retain();
+ void release(nsHtml5TreeBuilder* owningTreeBuilder);
+ bool isUnused();
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif
diff --git a/parser/html/nsHtml5StateSnapshot.cpp b/parser/html/nsHtml5StateSnapshot.cpp
new file mode 100644
index 0000000000..2a38e0c7d0
--- /dev/null
+++ b/parser/html/nsHtml5StateSnapshot.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2009-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit StateSnapshot.java instead and regenerate.
+ */
+
+#define nsHtml5StateSnapshot_cpp__
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5StateSnapshot.h"
+
+nsHtml5StateSnapshot::nsHtml5StateSnapshot(
+ jArray<nsHtml5StackNode*, int32_t> stack,
+ jArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements,
+ jArray<int32_t, int32_t> templateModeStack, nsIContentHandle* formPointer,
+ nsIContentHandle* headPointer, int32_t mode, int32_t originalMode,
+ bool framesetOk, bool needToDropLF, bool quirks)
+ : stack(stack),
+ listOfActiveFormattingElements(listOfActiveFormattingElements),
+ templateModeStack(templateModeStack),
+ formPointer(formPointer),
+ headPointer(headPointer),
+ mode(mode),
+ originalMode(originalMode),
+ framesetOk(framesetOk),
+ needToDropLF(needToDropLF),
+ quirks(quirks) {
+ MOZ_COUNT_CTOR(nsHtml5StateSnapshot);
+}
+
+jArray<nsHtml5StackNode*, int32_t> nsHtml5StateSnapshot::getStack() {
+ return stack;
+}
+
+jArray<int32_t, int32_t> nsHtml5StateSnapshot::getTemplateModeStack() {
+ return templateModeStack;
+}
+
+jArray<nsHtml5StackNode*, int32_t>
+nsHtml5StateSnapshot::getListOfActiveFormattingElements() {
+ return listOfActiveFormattingElements;
+}
+
+nsIContentHandle* nsHtml5StateSnapshot::getFormPointer() { return formPointer; }
+
+nsIContentHandle* nsHtml5StateSnapshot::getHeadPointer() { return headPointer; }
+
+int32_t nsHtml5StateSnapshot::getMode() { return mode; }
+
+int32_t nsHtml5StateSnapshot::getOriginalMode() { return originalMode; }
+
+bool nsHtml5StateSnapshot::isFramesetOk() { return framesetOk; }
+
+bool nsHtml5StateSnapshot::isNeedToDropLF() { return needToDropLF; }
+
+bool nsHtml5StateSnapshot::isQuirks() { return quirks; }
+
+int32_t nsHtml5StateSnapshot::getListOfActiveFormattingElementsLength() {
+ return listOfActiveFormattingElements.length;
+}
+
+int32_t nsHtml5StateSnapshot::getStackLength() { return stack.length; }
+
+int32_t nsHtml5StateSnapshot::getTemplateModeStackLength() {
+ return templateModeStack.length;
+}
+
+nsHtml5StateSnapshot::~nsHtml5StateSnapshot() {
+ MOZ_COUNT_DTOR(nsHtml5StateSnapshot);
+ for (int32_t i = 0; i < stack.length; i++) {
+ stack[i]->release(nullptr);
+ }
+ for (int32_t i = 0; i < listOfActiveFormattingElements.length; i++) {
+ if (listOfActiveFormattingElements[i]) {
+ listOfActiveFormattingElements[i]->release(nullptr);
+ }
+ }
+}
+
+void nsHtml5StateSnapshot::initializeStatics() {}
+
+void nsHtml5StateSnapshot::releaseStatics() {}
diff --git a/parser/html/nsHtml5StateSnapshot.h b/parser/html/nsHtml5StateSnapshot.h
new file mode 100644
index 0000000000..b5c80bf346
--- /dev/null
+++ b/parser/html/nsHtml5StateSnapshot.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit StateSnapshot.java instead and regenerate.
+ */
+
+#ifndef nsHtml5StateSnapshot_h
+#define nsHtml5StateSnapshot_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5UTF16Buffer;
+class nsHtml5Portability;
+
+class nsHtml5StateSnapshot : public nsAHtml5TreeBuilderState {
+ private:
+ autoJArray<nsHtml5StackNode*, int32_t> stack;
+ autoJArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements;
+ autoJArray<int32_t, int32_t> templateModeStack;
+ nsIContentHandle* formPointer;
+ nsIContentHandle* headPointer;
+ int32_t mode;
+ int32_t originalMode;
+ bool framesetOk;
+ bool needToDropLF;
+ bool quirks;
+
+ public:
+ nsHtml5StateSnapshot(
+ jArray<nsHtml5StackNode*, int32_t> stack,
+ jArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements,
+ jArray<int32_t, int32_t> templateModeStack, nsIContentHandle* formPointer,
+ nsIContentHandle* headPointer, int32_t mode, int32_t originalMode,
+ bool framesetOk, bool needToDropLF, bool quirks);
+ jArray<nsHtml5StackNode*, int32_t> getStack() override;
+ jArray<int32_t, int32_t> getTemplateModeStack() override;
+ jArray<nsHtml5StackNode*, int32_t> getListOfActiveFormattingElements()
+ override;
+ nsIContentHandle* getFormPointer() override;
+ nsIContentHandle* getHeadPointer() override;
+ int32_t getMode() override;
+ int32_t getOriginalMode() override;
+ bool isFramesetOk() override;
+ bool isNeedToDropLF() override;
+ bool isQuirks() override;
+ int32_t getListOfActiveFormattingElementsLength() override;
+ int32_t getStackLength() override;
+ int32_t getTemplateModeStackLength() override;
+ ~nsHtml5StateSnapshot();
+ static void initializeStatics();
+ static void releaseStatics();
+};
+
+#endif
diff --git a/parser/html/nsHtml5StreamListener.cpp b/parser/html/nsHtml5StreamListener.cpp
new file mode 100644
index 0000000000..86e18c0296
--- /dev/null
+++ b/parser/html/nsHtml5StreamListener.cpp
@@ -0,0 +1,92 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5StreamListener.h"
+
+#include "nsHtml5StreamParserReleaser.h"
+
+NS_IMPL_ADDREF(nsHtml5StreamListener)
+NS_IMPL_RELEASE(nsHtml5StreamListener)
+
+NS_INTERFACE_MAP_BEGIN(nsHtml5StreamListener)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+ NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)
+NS_INTERFACE_MAP_END
+
+nsHtml5StreamListener::nsHtml5StreamListener(nsHtml5StreamParser* aDelegate)
+ : mDelegateMonitor("nsHtml5StreamListener mDelegateMonitor"),
+ mDelegate(aDelegate) {
+ MOZ_ASSERT(aDelegate, "Must have delegate");
+ aDelegate->AddRef();
+}
+
+nsHtml5StreamListener::~nsHtml5StreamListener() { DropDelegateImpl(); }
+
+void nsHtml5StreamListener::DropDelegate() {
+ MOZ_ASSERT(NS_IsMainThread(),
+ "Must not call DropDelegate from non-main threads.");
+ DropDelegateImpl();
+}
+
+void nsHtml5StreamListener::DropDelegateImpl() {
+ mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
+ if (mDelegate) {
+ nsCOMPtr<nsIRunnable> releaser = new nsHtml5StreamParserReleaser(mDelegate);
+ if (NS_FAILED(((nsHtml5StreamParser*)mDelegate)
+ ->DispatchToMain(releaser.forget()))) {
+ NS_WARNING("Failed to dispatch releaser event.");
+ }
+ mDelegate = nullptr;
+ }
+}
+
+nsHtml5StreamParser* nsHtml5StreamListener::GetDelegate() {
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ // Since this can be called only on the main
+ // thread and DropDelegate() can only be called on the main thread
+ // it's OK that the monitor here doesn't protect the use of the
+ // return value.
+ return mDelegate;
+}
+
+NS_IMETHODIMP
+nsHtml5StreamListener::CheckListenerChain() {
+ if (MOZ_UNLIKELY(!mDelegate)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHtml5StreamListener::OnStartRequest(nsIRequest* aRequest) {
+ mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
+ if (MOZ_UNLIKELY(!mDelegate)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return ((nsHtml5StreamParser*)mDelegate)->OnStartRequest(aRequest);
+}
+
+NS_IMETHODIMP
+nsHtml5StreamListener::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) {
+ mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
+ if (MOZ_UNLIKELY(!mDelegate)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return ((nsHtml5StreamParser*)mDelegate)->OnStopRequest(aRequest, aStatus);
+}
+
+NS_IMETHODIMP
+nsHtml5StreamListener::OnDataAvailable(nsIRequest* aRequest,
+ nsIInputStream* aInStream,
+ uint64_t aSourceOffset,
+ uint32_t aLength) {
+ mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
+ if (MOZ_UNLIKELY(!mDelegate)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return ((nsHtml5StreamParser*)mDelegate)
+ ->OnDataAvailable(aRequest, aInStream, aSourceOffset, aLength);
+}
diff --git a/parser/html/nsHtml5StreamListener.h b/parser/html/nsHtml5StreamListener.h
new file mode 100644
index 0000000000..46056eacee
--- /dev/null
+++ b/parser/html/nsHtml5StreamListener.h
@@ -0,0 +1,62 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5StreamListener_h
+#define nsHtml5StreamListener_h
+
+#include "nsIStreamListener.h"
+#include "nsIThreadRetargetableStreamListener.h"
+#include "nsHtml5StreamParser.h"
+#include "mozilla/ReentrantMonitor.h"
+
+/**
+ * The purpose of this class is to reconcile the problem that
+ * nsHtml5StreamParser is a cycle collection participant, which means that it
+ * can only be refcounted on the main thread, but
+ * nsIThreadRetargetableStreamListener can be refcounted from another thread,
+ * so nsHtml5StreamParser being an nsIThreadRetargetableStreamListener was
+ * a memory corruption problem.
+ *
+ * mDelegate is an nsHtml5StreamParserPtr, which releases the object that it
+ * points to from a runnable on the main thread. DropDelegate() is only called
+ * on the main thread. This call will finish before the main-thread derefs the
+ * nsHtml5StreamListener itself, so there is no risk of another thread making
+ * the refcount of nsHtml5StreamListener go to zero and running the destructor
+ * concurrently. Other than that, the thread-safe nsISupports implementation
+ * takes care of the destructor not running concurrently from different
+ * threads, so there is no need to have a mutex around nsHtml5StreamParserPtr to
+ * prevent it from double-releasing nsHtml5StreamParser.
+ */
+class nsHtml5StreamListener : public nsIStreamListener,
+ public nsIThreadRetargetableStreamListener {
+ public:
+ explicit nsHtml5StreamListener(nsHtml5StreamParser* aDelegate);
+
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
+
+ // Main-thread-only
+ nsHtml5StreamParser* GetDelegate();
+
+ // Main-thread-only
+ void DropDelegate();
+
+ private:
+ void DropDelegateImpl();
+ virtual ~nsHtml5StreamListener();
+
+ // ReentrantMonitor instead of Mutex, because `GetDelegate()`
+ // can be called from within the Necko callbacks when Necko events
+ // are delivered on the main thread.
+ mozilla::ReentrantMonitor mDelegateMonitor MOZ_UNANNOTATED;
+ // Owning pointer with manually-managed refcounting, protected by
+ // mDelegateMonitor. Access to it is Atomic, which avoids getting a lock
+ // to check if it's set or to return the pointer. Access to the data within
+ // it needs the monitor. MOZ_PT_GUARDED_BY() can't be used with Atomic<...*>
+ mozilla::Atomic<nsHtml5StreamParser*, mozilla::ReleaseAcquire> mDelegate;
+};
+
+#endif // nsHtml5StreamListener_h
diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp
new file mode 100644
index 0000000000..8f53b37057
--- /dev/null
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -0,0 +1,2865 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5StreamParser.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <new>
+#include <type_traits>
+#include <utility>
+#include "ErrorList.h"
+#include "GeckoProfiler.h"
+#include "js/GCAPI.h"
+#include "mozilla/ArrayIterator.h"
+#include "mozilla/Buffer.h"
+#include "mozilla/CheckedInt.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Encoding.h"
+#include "mozilla/EncodingDetector.h"
+#include "mozilla/Likely.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/SchedulerGroup.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPrefs_html5.h"
+#include "mozilla/StaticPrefs_intl.h"
+#include "mozilla/TaskCategory.h"
+#include "mozilla/TextUtils.h"
+
+#include "mozilla/UniquePtrExtensions.h"
+#include "mozilla/Unused.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/BrowsingContext.h"
+#include "mozilla/dom/DebuggerUtilsBinding.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/mozalloc.h"
+#include "mozilla/Vector.h"
+#include "nsContentSink.h"
+#include "nsContentUtils.h"
+#include "nsCycleCollectionTraversalCallback.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Highlighter.h"
+#include "nsHtml5Module.h"
+#include "nsHtml5OwningUTF16Buffer.h"
+#include "nsHtml5Parser.h"
+#include "nsHtml5Speculation.h"
+#include "nsHtml5StreamParserPtr.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5TreeOpExecutor.h"
+#include "nsHtml5TreeOpStage.h"
+#include "nsIChannel.h"
+#include "nsIContentSink.h"
+#include "nsID.h"
+#include "nsIDTD.h"
+#include "nsIDocShell.h"
+#include "nsIEventTarget.h"
+#include "nsIHttpChannel.h"
+#include "nsIInputStream.h"
+#include "nsINestedURI.h"
+#include "nsIObserverService.h"
+#include "nsIRequest.h"
+#include "nsIRunnable.h"
+#include "nsIScriptError.h"
+#include "nsIThread.h"
+#include "nsIThreadRetargetableRequest.h"
+#include "nsIThreadRetargetableStreamListener.h"
+#include "nsITimer.h"
+#include "nsIURI.h"
+#include "nsJSEnvironment.h"
+#include "nsLiteralString.h"
+#include "nsNetUtil.h"
+#include "nsString.h"
+#include "nsTPromiseFlatString.h"
+#include "nsThreadUtils.h"
+#include "nsXULAppAPI.h"
+
+extern "C" {
+// Defined in intl/encoding_glue/src/lib.rs
+const mozilla::Encoding* xmldecl_parse(const uint8_t* buf, size_t buf_len);
+};
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+/*
+ * Note that nsHtml5StreamParser implements cycle collecting AddRef and
+ * Release. Therefore, nsHtml5StreamParser must never be refcounted from
+ * the parser thread!
+ *
+ * To work around this limitation, runnables posted by the main thread to the
+ * parser thread hold their reference to the stream parser in an
+ * nsHtml5StreamParserPtr. Upon creation, nsHtml5StreamParserPtr addrefs the
+ * object it holds
+ * just like a regular nsRefPtr. This is OK, since the creation of the
+ * runnable and the nsHtml5StreamParserPtr happens on the main thread.
+ *
+ * When the runnable is done on the parser thread, the destructor of
+ * nsHtml5StreamParserPtr runs there. It doesn't call Release on the held object
+ * directly. Instead, it posts another runnable back to the main thread where
+ * that runnable calls Release on the wrapped object.
+ *
+ * When posting runnables in the other direction, the runnables have to be
+ * created on the main thread when nsHtml5StreamParser is instantiated and
+ * held for the lifetime of the nsHtml5StreamParser. This works, because the
+ * same runnabled can be dispatched multiple times and currently runnables
+ * posted from the parser thread to main thread don't need to wrap any
+ * runnable-specific data. (In the other direction, the runnables most notably
+ * wrap the byte data of the stream.)
+ */
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5StreamParser)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5StreamParser)
+
+NS_INTERFACE_TABLE_HEAD(nsHtml5StreamParser)
+ NS_INTERFACE_TABLE(nsHtml5StreamParser, nsISupports)
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5StreamParser)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHtml5StreamParser)
+ tmp->DropTimer();
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
+ tmp->mExecutorFlusher = nullptr;
+ tmp->mLoadFlusher = nullptr;
+ tmp->mExecutor = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHtml5StreamParser)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
+ // hack: count the strongly owned edge wrapped in the runnable
+ if (tmp->mExecutorFlusher) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExecutorFlusher->mExecutor");
+ cb.NoteXPCOMChild(static_cast<nsIContentSink*>(tmp->mExecutor));
+ }
+ // hack: count the strongly owned edge wrapped in the runnable
+ if (tmp->mLoadFlusher) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mLoadFlusher->mExecutor");
+ cb.NoteXPCOMChild(static_cast<nsIContentSink*>(tmp->mExecutor));
+ }
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+class nsHtml5ExecutorFlusher : public Runnable {
+ private:
+ RefPtr<nsHtml5TreeOpExecutor> mExecutor;
+
+ public:
+ explicit nsHtml5ExecutorFlusher(nsHtml5TreeOpExecutor* aExecutor)
+ : Runnable("nsHtml5ExecutorFlusher"), mExecutor(aExecutor) {}
+ NS_IMETHOD Run() override {
+ if (!mExecutor->isInList()) {
+ Document* doc = mExecutor->GetDocument();
+ if (XRE_IsContentProcess() &&
+ nsContentUtils::
+ HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
+ doc)) {
+ // Possible early paint pending, reuse the runnable and try to
+ // call RunFlushLoop later.
+ nsCOMPtr<nsIRunnable> flusher = this;
+ if (NS_SUCCEEDED(
+ doc->Dispatch(TaskCategory::Network, flusher.forget()))) {
+ PROFILER_MARKER_UNTYPED("HighPrio blocking parser flushing(1)", DOM);
+ return NS_OK;
+ }
+ }
+ mExecutor->RunFlushLoop();
+ }
+ return NS_OK;
+ }
+};
+
+class nsHtml5LoadFlusher : public Runnable {
+ private:
+ RefPtr<nsHtml5TreeOpExecutor> mExecutor;
+
+ public:
+ explicit nsHtml5LoadFlusher(nsHtml5TreeOpExecutor* aExecutor)
+ : Runnable("nsHtml5LoadFlusher"), mExecutor(aExecutor) {}
+ NS_IMETHOD Run() override {
+ mExecutor->FlushSpeculativeLoads();
+ return NS_OK;
+ }
+};
+
+nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
+ nsHtml5Parser* aOwner,
+ eParserMode aMode)
+ : mBomState(eBomState::BOM_SNIFFING_NOT_STARTED),
+ mCharsetSource(kCharsetUninitialized),
+ mEncodingSwitchSource(kCharsetUninitialized),
+ mEncoding(X_USER_DEFINED_ENCODING), // Obviously bogus value to notice if
+ // not updated
+ mNeedsEncodingSwitchTo(nullptr),
+ mSeenEligibleMetaCharset(false),
+ mChardetEof(false),
+#ifdef DEBUG
+ mStartedFeedingDetector(false),
+ mStartedFeedingDevTools(false),
+#endif
+ mReparseForbidden(false),
+ mForceAutoDetection(false),
+ mChannelHadCharset(false),
+ mLookingForMetaCharset(false),
+ mStartsWithLtQuestion(false),
+ mLookingForXmlDeclarationForXmlViewSource(false),
+ mTemplatePushedOrHeadPopped(false),
+ mGtBuffer(nullptr),
+ mGtPos(0),
+ mLastBuffer(nullptr), // Will be filled when starting
+ mExecutor(aExecutor),
+ mTreeBuilder(new nsHtml5TreeBuilder(
+ (aMode == VIEW_SOURCE_HTML || aMode == VIEW_SOURCE_XML)
+ ? nullptr
+ : mExecutor->GetStage(),
+ mExecutor->GetStage(), aMode == NORMAL)),
+ mTokenizer(
+ new nsHtml5Tokenizer(mTreeBuilder.get(), aMode == VIEW_SOURCE_XML)),
+ mTokenizerMutex("nsHtml5StreamParser mTokenizerMutex"),
+ mOwner(aOwner),
+ mLastWasCR(false),
+ mStreamState(eHtml5StreamState::STREAM_NOT_STARTED),
+ mSpeculating(false),
+ mAtEOF(false),
+ mSpeculationMutex("nsHtml5StreamParser mSpeculationMutex"),
+ mSpeculationFailureCount(0),
+ mNumBytesBuffered(0),
+ mTerminated(false),
+ mInterrupted(false),
+ mEventTarget(nsHtml5Module::GetStreamParserEventTarget()),
+ mExecutorFlusher(new nsHtml5ExecutorFlusher(aExecutor)),
+ mLoadFlusher(new nsHtml5LoadFlusher(aExecutor)),
+ mInitialEncodingWasFromParentFrame(false),
+ mHasHadErrors(false),
+ mDetectorHasSeenNonAscii(false),
+ mDecodingLocalFileWithoutTokenizing(false),
+ mBufferingBytes(false),
+ mFlushTimer(NS_NewTimer(mEventTarget)),
+ mFlushTimerMutex("nsHtml5StreamParser mFlushTimerMutex"),
+ mFlushTimerArmed(false),
+ mFlushTimerEverFired(false),
+ mMode(aMode) {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+#ifdef DEBUG
+ mAtomTable.SetPermittedLookupEventTarget(mEventTarget);
+#endif
+ mTokenizer->setInterner(&mAtomTable);
+ mTokenizer->setEncodingDeclarationHandler(this);
+
+ if (aMode == VIEW_SOURCE_HTML || aMode == VIEW_SOURCE_XML) {
+ nsHtml5Highlighter* highlighter =
+ new nsHtml5Highlighter(mExecutor->GetStage());
+ mTokenizer->EnableViewSource(highlighter); // takes ownership
+ mTreeBuilder->EnableViewSource(highlighter); // doesn't own
+ }
+
+ // There's a zeroing operator new for everything else
+}
+
+nsHtml5StreamParser::~nsHtml5StreamParser() {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+ mTokenizer->end();
+#ifdef DEBUG
+ {
+ mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
+ MOZ_ASSERT(!mFlushTimer, "Flush timer was not dropped before dtor!");
+ }
+ mRequest = nullptr;
+ mUnicodeDecoder = nullptr;
+ mFirstBuffer = nullptr;
+ mExecutor = nullptr;
+ mTreeBuilder = nullptr;
+ mTokenizer = nullptr;
+ mOwner = nullptr;
+#endif
+}
+
+nsresult nsHtml5StreamParser::GetChannel(nsIChannel** aChannel) {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+ return mRequest ? CallQueryInterface(mRequest, aChannel)
+ : NS_ERROR_NOT_AVAILABLE;
+}
+
+std::tuple<NotNull<const Encoding*>, nsCharsetSource>
+nsHtml5StreamParser::GuessEncoding(bool aInitial) {
+ MOZ_ASSERT(
+ mCharsetSource != kCharsetFromFinalUserForcedAutoDetection &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD &&
+ mCharsetSource !=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII &&
+ mCharsetSource != kCharsetFromFinalAutoDetectionFile);
+ auto ifHadBeenForced = mDetector->Guess(EmptyCString(), true);
+ auto encoding =
+ mForceAutoDetection
+ ? ifHadBeenForced
+ : mDetector->Guess(mTLD, mDecodingLocalFileWithoutTokenizing);
+ nsCharsetSource source =
+ aInitial
+ ? (mForceAutoDetection
+ ? kCharsetFromInitialUserForcedAutoDetection
+ : (mDecodingLocalFileWithoutTokenizing
+ ? kCharsetFromFinalAutoDetectionFile
+ : kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic))
+ : (mForceAutoDetection
+ ? kCharsetFromFinalUserForcedAutoDetection
+ : (mDecodingLocalFileWithoutTokenizing
+ ? kCharsetFromFinalAutoDetectionFile
+ : kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic));
+ if (source == kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic) {
+ if (encoding == ISO_2022_JP_ENCODING) {
+ if (EncodingDetector::TldMayAffectGuess(mTLD)) {
+ source = kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content;
+ }
+ } else if (!mDetectorHasSeenNonAscii) {
+ source = kCharsetFromInitialAutoDetectionASCII; // deliberately Initial
+ } else if (ifHadBeenForced == UTF_8_ENCODING) {
+ MOZ_ASSERT(mCharsetSource == kCharsetFromInitialAutoDetectionASCII ||
+ mCharsetSource ==
+ kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8 ||
+ mEncoding == ISO_2022_JP_ENCODING);
+ source = kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII;
+ } else if (encoding != ifHadBeenForced) {
+ if (mCharsetSource == kCharsetFromInitialAutoDetectionASCII) {
+ source =
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII;
+ } else {
+ source =
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD;
+ }
+ } else if (EncodingDetector::TldMayAffectGuess(mTLD)) {
+ if (mCharsetSource == kCharsetFromInitialAutoDetectionASCII) {
+ source =
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII;
+ } else {
+ source = kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content;
+ }
+ } else if (mCharsetSource == kCharsetFromInitialAutoDetectionASCII) {
+ source =
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII;
+ }
+ } else if (source ==
+ kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic) {
+ if (encoding == ISO_2022_JP_ENCODING) {
+ if (EncodingDetector::TldMayAffectGuess(mTLD)) {
+ source = kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content;
+ }
+ } else if (!mDetectorHasSeenNonAscii) {
+ source = kCharsetFromInitialAutoDetectionASCII;
+ } else if (ifHadBeenForced == UTF_8_ENCODING) {
+ source = kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8;
+ } else if (encoding != ifHadBeenForced) {
+ source =
+ kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD;
+ } else if (EncodingDetector::TldMayAffectGuess(mTLD)) {
+ source = kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content;
+ }
+ }
+ return {encoding, source};
+}
+
+void nsHtml5StreamParser::FeedDetector(Span<const uint8_t> aBuffer) {
+#ifdef DEBUG
+ mStartedFeedingDetector = true;
+#endif
+ MOZ_ASSERT(!mChardetEof);
+ mDetectorHasSeenNonAscii = mDetector->Feed(aBuffer, false);
+}
+
+void nsHtml5StreamParser::DetectorEof() {
+#ifdef DEBUG
+ mStartedFeedingDetector = true;
+#endif
+ if (mChardetEof) {
+ return;
+ }
+ mChardetEof = true;
+ mDetectorHasSeenNonAscii = mDetector->Feed(Span<const uint8_t>(), true);
+}
+
+void nsHtml5StreamParser::SetViewSourceTitle(nsIURI* aURL) {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ BrowsingContext* browsingContext =
+ mExecutor->GetDocument()->GetBrowsingContext();
+ if (browsingContext && browsingContext->WatchedByDevTools()) {
+ mURIToSendToDevtools = aURL;
+
+ nsID uuid;
+ nsresult rv = nsID::GenerateUUIDInPlace(uuid);
+ if (!NS_FAILED(rv)) {
+ char buffer[NSID_LENGTH];
+ uuid.ToProvidedString(buffer);
+ mUUIDForDevtools = NS_ConvertASCIItoUTF16(buffer);
+ }
+ }
+
+ if (aURL) {
+ nsCOMPtr<nsIURI> temp;
+ if (aURL->SchemeIs("view-source")) {
+ nsCOMPtr<nsINestedURI> nested = do_QueryInterface(aURL);
+ nested->GetInnerURI(getter_AddRefs(temp));
+ } else {
+ temp = aURL;
+ }
+ if (temp->SchemeIs("data")) {
+ // Avoid showing potentially huge data: URLs. The three last bytes are
+ // UTF-8 for an ellipsis.
+ mViewSourceTitle.AssignLiteral("data:\xE2\x80\xA6");
+ } else {
+ nsresult rv = temp->GetSpec(mViewSourceTitle);
+ if (NS_FAILED(rv)) {
+ mViewSourceTitle.AssignLiteral("\xE2\x80\xA6");
+ }
+ }
+ }
+}
+
+nsresult
+nsHtml5StreamParser::SetupDecodingAndWriteSniffingBufferAndCurrentSegment(
+ Span<const uint8_t> aPrefix, Span<const uint8_t> aFromSegment) {
+ NS_ASSERTION(IsParserThread(), "Wrong thread!");
+ mUnicodeDecoder = mEncoding->NewDecoderWithBOMRemoval();
+ nsresult rv = WriteStreamBytes(aPrefix);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return WriteStreamBytes(aFromSegment);
+}
+
+void nsHtml5StreamParser::SetupDecodingFromBom(
+ NotNull<const Encoding*> aEncoding) {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mEncoding = aEncoding;
+ mDecodingLocalFileWithoutTokenizing = false;
+ mLookingForMetaCharset = false;
+ mBufferingBytes = false;
+ mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling();
+ mCharsetSource = kCharsetFromByteOrderMark;
+ mForceAutoDetection = false;
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
+ mBomState = BOM_SNIFFING_OVER;
+ if (mMode == VIEW_SOURCE_HTML) {
+ mTokenizer->StartViewSourceCharacters();
+ }
+}
+
+void nsHtml5StreamParser::SetupDecodingFromUtf16BogoXml(
+ NotNull<const Encoding*> aEncoding) {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mEncoding = aEncoding;
+ mDecodingLocalFileWithoutTokenizing = false;
+ mLookingForMetaCharset = false;
+ mBufferingBytes = false;
+ mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling();
+ mCharsetSource = kCharsetFromXmlDeclarationUtf16;
+ mForceAutoDetection = false;
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
+ mBomState = BOM_SNIFFING_OVER;
+ if (mMode == VIEW_SOURCE_HTML) {
+ mTokenizer->StartViewSourceCharacters();
+ }
+ auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE);
+ dst[0] = '<';
+ dst[1] = '?';
+ dst[2] = 'x';
+ mLastBuffer->AdvanceEnd(3);
+ MOZ_ASSERT(!mStartedFeedingDevTools);
+ OnNewContent(dst.To(3));
+}
+
+size_t nsHtml5StreamParser::LengthOfLtContainingPrefixInSecondBuffer() {
+ MOZ_ASSERT(mBufferedBytes.Length() <= 2);
+ if (mBufferedBytes.Length() < 2) {
+ return 0;
+ }
+ Buffer<uint8_t>& second = mBufferedBytes[1];
+ const uint8_t* elements = second.Elements();
+ const uint8_t* lt = (const uint8_t*)memchr(elements, '>', second.Length());
+ if (lt) {
+ return (lt - elements) + 1;
+ }
+ return 0;
+}
+
+nsresult nsHtml5StreamParser::SniffStreamBytes(Span<const uint8_t> aFromSegment,
+ bool aEof) {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ MOZ_ASSERT_IF(aEof, aFromSegment.IsEmpty());
+
+ if (mCharsetSource >=
+ kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII &&
+ mCharsetSource <= kCharsetFromFinalUserForcedAutoDetection) {
+ if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncDetectorReloadPlain", true,
+ 0);
+ } else {
+ mTreeBuilder->MaybeComplainAboutCharset("EncDetectorReload", true, 0);
+ }
+ }
+
+ // mEncoding and mCharsetSource potentially have come from channel or higher
+ // by now. If we find a BOM, SetupDecodingFromBom() will overwrite them.
+ // If we don't find a BOM, the previously set values of mEncoding and
+ // mCharsetSource are not modified by the BOM sniffing here.
+ static uint8_t utf8[] = {0xEF, 0xBB};
+ static uint8_t utf16le[] = {0xFF};
+ static uint8_t utf16be[] = {0xFE};
+ static uint8_t utf16leXml[] = {'<', 0x00, '?', 0x00, 'x'};
+ static uint8_t utf16beXml[] = {0x00, '<', 0x00, '?', 0x00};
+ // Buffer for replaying past bytes based on state machine state. If
+ // writing this from scratch, probably wouldn't do it this way, but
+ // let's keep the changes to a minimum.
+ const uint8_t* prefix = utf8;
+ size_t prefixLength = 0;
+ if (aEof && mBomState == BOM_SNIFFING_NOT_STARTED) {
+ // Avoid handling aEof in the BOM_SNIFFING_NOT_STARTED state below.
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ for (size_t i = 0;
+ (i < aFromSegment.Length() && mBomState != BOM_SNIFFING_OVER) || aEof;
+ i++) {
+ switch (mBomState) {
+ case BOM_SNIFFING_NOT_STARTED:
+ MOZ_ASSERT(i == 0, "Bad BOM sniffing state.");
+ MOZ_ASSERT(!aEof, "Should have checked for aEof above!");
+ switch (aFromSegment[0]) {
+ case 0xEF:
+ mBomState = SEEN_UTF_8_FIRST_BYTE;
+ break;
+ case 0xFF:
+ mBomState = SEEN_UTF_16_LE_FIRST_BYTE;
+ break;
+ case 0xFE:
+ mBomState = SEEN_UTF_16_BE_FIRST_BYTE;
+ break;
+ case 0x00:
+ if (mCharsetSource < kCharsetFromXmlDeclarationUtf16 &&
+ mCharsetSource != kCharsetFromChannel) {
+ mBomState = SEEN_UTF_16_BE_XML_FIRST;
+ } else {
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case '<':
+ if (mCharsetSource < kCharsetFromXmlDeclarationUtf16 &&
+ mCharsetSource != kCharsetFromChannel) {
+ mBomState = SEEN_UTF_16_LE_XML_FIRST;
+ } else {
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ default:
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ }
+ break;
+ case SEEN_UTF_16_LE_FIRST_BYTE:
+ if (!aEof && aFromSegment[i] == 0xFE) {
+ SetupDecodingFromBom(UTF_16LE_ENCODING);
+ return WriteStreamBytes(aFromSegment.From(i + 1));
+ }
+ prefix = utf16le;
+ prefixLength = 1 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ case SEEN_UTF_16_BE_FIRST_BYTE:
+ if (!aEof && aFromSegment[i] == 0xFF) {
+ SetupDecodingFromBom(UTF_16BE_ENCODING);
+ return WriteStreamBytes(aFromSegment.From(i + 1));
+ }
+ prefix = utf16be;
+ prefixLength = 1 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ case SEEN_UTF_8_FIRST_BYTE:
+ if (!aEof && aFromSegment[i] == 0xBB) {
+ mBomState = SEEN_UTF_8_SECOND_BYTE;
+ } else {
+ prefixLength = 1 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_8_SECOND_BYTE:
+ if (!aEof && aFromSegment[i] == 0xBF) {
+ SetupDecodingFromBom(UTF_8_ENCODING);
+ return WriteStreamBytes(aFromSegment.From(i + 1));
+ }
+ prefixLength = 2 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ case SEEN_UTF_16_BE_XML_FIRST:
+ if (!aEof && aFromSegment[i] == '<') {
+ mBomState = SEEN_UTF_16_BE_XML_SECOND;
+ } else {
+ prefix = utf16beXml;
+ prefixLength = 1 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_BE_XML_SECOND:
+ if (!aEof && aFromSegment[i] == 0x00) {
+ mBomState = SEEN_UTF_16_BE_XML_THIRD;
+ } else {
+ prefix = utf16beXml;
+ prefixLength = 2 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_BE_XML_THIRD:
+ if (!aEof && aFromSegment[i] == '?') {
+ mBomState = SEEN_UTF_16_BE_XML_FOURTH;
+ } else {
+ prefix = utf16beXml;
+ prefixLength = 3 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_BE_XML_FOURTH:
+ if (!aEof && aFromSegment[i] == 0x00) {
+ mBomState = SEEN_UTF_16_BE_XML_FIFTH;
+ } else {
+ prefix = utf16beXml;
+ prefixLength = 4 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_BE_XML_FIFTH:
+ if (!aEof && aFromSegment[i] == 'x') {
+ SetupDecodingFromUtf16BogoXml(UTF_16BE_ENCODING);
+ return WriteStreamBytes(aFromSegment.From(i + 1));
+ }
+ prefix = utf16beXml;
+ prefixLength = 5 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ case SEEN_UTF_16_LE_XML_FIRST:
+ if (!aEof && aFromSegment[i] == 0x00) {
+ mBomState = SEEN_UTF_16_LE_XML_SECOND;
+ } else {
+ if (!aEof && aFromSegment[i] == '?' &&
+ !(mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN)) {
+ mStartsWithLtQuestion = true;
+ }
+ prefix = utf16leXml;
+ prefixLength = 1 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_LE_XML_SECOND:
+ if (!aEof && aFromSegment[i] == '?') {
+ mBomState = SEEN_UTF_16_LE_XML_THIRD;
+ } else {
+ prefix = utf16leXml;
+ prefixLength = 2 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_LE_XML_THIRD:
+ if (!aEof && aFromSegment[i] == 0x00) {
+ mBomState = SEEN_UTF_16_LE_XML_FOURTH;
+ } else {
+ prefix = utf16leXml;
+ prefixLength = 3 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_LE_XML_FOURTH:
+ if (!aEof && aFromSegment[i] == 'x') {
+ mBomState = SEEN_UTF_16_LE_XML_FIFTH;
+ } else {
+ prefix = utf16leXml;
+ prefixLength = 4 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ }
+ break;
+ case SEEN_UTF_16_LE_XML_FIFTH:
+ if (!aEof && aFromSegment[i] == 0x00) {
+ SetupDecodingFromUtf16BogoXml(UTF_16LE_ENCODING);
+ return WriteStreamBytes(aFromSegment.From(i + 1));
+ }
+ prefix = utf16leXml;
+ prefixLength = 5 - i;
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ default:
+ mBomState = BOM_SNIFFING_OVER;
+ break;
+ }
+ if (aEof) {
+ break;
+ }
+ }
+ // if we get here, there either was no BOM or the BOM sniffing isn't complete
+ // yet
+
+ MOZ_ASSERT(mCharsetSource != kCharsetFromByteOrderMark,
+ "Should not come here if BOM was found.");
+ MOZ_ASSERT(mCharsetSource != kCharsetFromXmlDeclarationUtf16,
+ "Should not come here if UTF-16 bogo-XML declaration was found.");
+ MOZ_ASSERT(mCharsetSource != kCharsetFromOtherComponent,
+ "kCharsetFromOtherComponent is for XSLT.");
+
+ if (mBomState == BOM_SNIFFING_OVER) {
+ if (mMode == VIEW_SOURCE_XML && mStartsWithLtQuestion &&
+ mCharsetSource < kCharsetFromChannel) {
+ // Sniff for XML declaration only.
+ MOZ_ASSERT(!mLookingForXmlDeclarationForXmlViewSource);
+ MOZ_ASSERT(!aEof);
+ MOZ_ASSERT(!mLookingForMetaCharset);
+ MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing);
+ // Maybe we've already buffered a '>'.
+ MOZ_ASSERT(!mBufferedBytes.IsEmpty(),
+ "How did at least <? not get buffered?");
+ Buffer<uint8_t>& first = mBufferedBytes[0];
+ const Encoding* encoding =
+ xmldecl_parse(first.Elements(), first.Length());
+ if (encoding) {
+ mEncoding = WrapNotNull(encoding);
+ mCharsetSource = kCharsetFromXmlDeclaration;
+ } else if (memchr(first.Elements(), '>', first.Length())) {
+ // There was a '>', but an encoding still wasn't found.
+ ; // fall through to commit to the UTF-8 default.
+ } else if (size_t lengthOfPrefix =
+ LengthOfLtContainingPrefixInSecondBuffer()) {
+ // This can only happen if the first buffer was a lone '<', because
+ // we come here upon seeing the second byte '?' if the first two bytes
+ // were "<?". That is, the only way how we aren't dealing with the first
+ // buffer is if the first buffer only contained a single '<' and we are
+ // dealing with the second buffer that starts with '?'.
+ MOZ_ASSERT(first.Length() == 1);
+ MOZ_ASSERT(mBufferedBytes[1][0] == '?');
+ // Our scanner for XML declaration-like syntax wants to see a contiguous
+ // buffer, so let's linearize the data. (Ideally, the XML declaration
+ // scanner would be incremental, but this is the rare path anyway.)
+ Vector<uint8_t> contiguous;
+ if (!contiguous.append(first.Elements(), first.Length())) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (!contiguous.append(mBufferedBytes[1].Elements(), lengthOfPrefix)) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ encoding = xmldecl_parse(contiguous.begin(), contiguous.length());
+ if (encoding) {
+ mEncoding = WrapNotNull(encoding);
+ mCharsetSource = kCharsetFromXmlDeclaration;
+ }
+ // else no XML decl, commit to the UTF-8 default.
+ } else {
+ MOZ_ASSERT(mBufferingBytes);
+ mLookingForXmlDeclarationForXmlViewSource = true;
+ return NS_OK;
+ }
+ } else if (mMode != VIEW_SOURCE_XML &&
+ (mForceAutoDetection || mCharsetSource < kCharsetFromChannel)) {
+ // In order to use the buffering logic for meta with mForceAutoDetection,
+ // we set mLookingForMetaCharset but still actually potentially ignore the
+ // meta.
+ mFirstBufferOfMetaScan = mFirstBuffer;
+ MOZ_ASSERT(mLookingForMetaCharset);
+
+ if (mMode == VIEW_SOURCE_HTML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ return r.unwrapErr();
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return r.unwrapErr();
+ }
+ // Encoding committer flushes the ops on the main thread.
+
+ mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
+ nsHtml5Speculation* speculation = new nsHtml5Speculation(
+ mFirstBuffer, mFirstBuffer->getStart(), mTokenizer->getLineNumber(),
+ mTokenizer->getColumnNumber(), mTreeBuilder->newSnapshot());
+ MOZ_ASSERT(!mFlushTimerArmed, "How did we end up arming the timer?");
+ if (mMode == VIEW_SOURCE_HTML) {
+ mTokenizer->SetViewSourceOpSink(speculation);
+ mTokenizer->StartViewSourceCharacters();
+ } else {
+ MOZ_ASSERT(mMode != VIEW_SOURCE_XML);
+ mTreeBuilder->SetOpSink(speculation);
+ }
+ mSpeculations.AppendElement(speculation); // adopts the pointer
+ mSpeculating = true;
+ } else {
+ mLookingForMetaCharset = false;
+ mBufferingBytes = false;
+ mDecodingLocalFileWithoutTokenizing = false;
+ if (mMode == VIEW_SOURCE_HTML) {
+ mTokenizer->StartViewSourceCharacters();
+ }
+ }
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
+ return SetupDecodingAndWriteSniffingBufferAndCurrentSegment(
+ Span(prefix, prefixLength), aFromSegment);
+ }
+
+ return NS_OK;
+}
+
+class AddContentRunnable : public Runnable {
+ public:
+ AddContentRunnable(const nsAString& aParserID, nsIURI* aURI,
+ Span<const char16_t> aData, bool aComplete)
+ : Runnable("AddContent") {
+ nsAutoCString spec;
+ aURI->GetSpec(spec);
+ mData.mUri.Construct(NS_ConvertUTF8toUTF16(spec));
+ mData.mParserID.Construct(aParserID);
+ mData.mContents.Construct(aData.Elements(), aData.Length());
+ mData.mComplete.Construct(aComplete);
+ }
+
+ NS_IMETHOD Run() override {
+ nsAutoString json;
+ if (!mData.ToJSON(json)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
+ if (obsService) {
+ obsService->NotifyObservers(nullptr, "devtools-html-content",
+ PromiseFlatString(json).get());
+ }
+
+ return NS_OK;
+ }
+
+ HTMLContent mData;
+};
+
+inline void nsHtml5StreamParser::OnNewContent(Span<const char16_t> aData) {
+#ifdef DEBUG
+ mStartedFeedingDevTools = true;
+#endif
+ if (mURIToSendToDevtools) {
+ if (aData.IsEmpty()) {
+ // Optimize out the runnable.
+ return;
+ }
+ NS_DispatchToMainThread(new AddContentRunnable(mUUIDForDevtools,
+ mURIToSendToDevtools, aData,
+ /* aComplete */ false));
+ }
+}
+
+inline void nsHtml5StreamParser::OnContentComplete() {
+#ifdef DEBUG
+ mStartedFeedingDevTools = true;
+#endif
+ if (mURIToSendToDevtools) {
+ NS_DispatchToMainThread(new AddContentRunnable(
+ mUUIDForDevtools, mURIToSendToDevtools, Span<const char16_t>(),
+ /* aComplete */ true));
+ mURIToSendToDevtools = nullptr;
+ }
+}
+
+nsresult nsHtml5StreamParser::WriteStreamBytes(
+ Span<const uint8_t> aFromSegment) {
+ NS_ASSERTION(IsParserThread(), "Wrong thread!");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+ // mLastBuffer should always point to a buffer of the size
+ // READ_BUFFER_SIZE.
+ if (!mLastBuffer) {
+ NS_WARNING("mLastBuffer should not be null!");
+ MarkAsBroken(NS_ERROR_NULL_POINTER);
+ return NS_ERROR_NULL_POINTER;
+ }
+ size_t totalRead = 0;
+ auto src = aFromSegment;
+ for (;;) {
+ auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE);
+ auto [result, read, written, hadErrors] =
+ mUnicodeDecoder->DecodeToUTF16(src, dst, false);
+ if (!(mLookingForMetaCharset || mDecodingLocalFileWithoutTokenizing)) {
+ OnNewContent(dst.To(written));
+ }
+ if (hadErrors && !mHasHadErrors) {
+ mHasHadErrors = true;
+ if (mEncoding == UTF_8_ENCODING) {
+ mTreeBuilder->TryToEnableEncodingMenu();
+ }
+ }
+ src = src.From(read);
+ totalRead += read;
+ mLastBuffer->AdvanceEnd(written);
+ if (result == kOutputFull) {
+ RefPtr<nsHtml5OwningUTF16Buffer> newBuf =
+ nsHtml5OwningUTF16Buffer::FalliblyCreate(READ_BUFFER_SIZE);
+ if (!newBuf) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mLastBuffer = (mLastBuffer->next = std::move(newBuf));
+ } else {
+ MOZ_ASSERT(totalRead == aFromSegment.Length(),
+ "The Unicode decoder consumed the wrong number of bytes.");
+ (void)totalRead;
+ if (!mLookingForMetaCharset && mDecodingLocalFileWithoutTokenizing &&
+ mNumBytesBuffered == LOCAL_FILE_UTF_8_BUFFER_SIZE) {
+ MOZ_ASSERT(!mStartedFeedingDetector);
+ for (auto&& buffer : mBufferedBytes) {
+ FeedDetector(buffer);
+ }
+ // If the file is exactly LOCAL_FILE_UTF_8_BUFFER_SIZE bytes long
+ // we end up not considering the EOF. That's not fatal, since we
+ // don't consider the EOF if the file is
+ // LOCAL_FILE_UTF_8_BUFFER_SIZE + 1 bytes long.
+ auto [encoding, source] = GuessEncoding(true);
+ mCharsetSource = source;
+ if (encoding != mEncoding) {
+ mEncoding = encoding;
+ nsresult rv = ReDecodeLocalFile();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ } else {
+ MOZ_ASSERT(mEncoding == UTF_8_ENCODING);
+ nsresult rv = CommitLocalFileToEncoding();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ }
+ return NS_OK;
+ }
+ }
+}
+
+[[nodiscard]] nsresult nsHtml5StreamParser::ReDecodeLocalFile() {
+ MOZ_ASSERT(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset);
+ MOZ_ASSERT(mFirstBufferOfMetaScan);
+ MOZ_ASSERT(mCharsetSource == kCharsetFromFinalAutoDetectionFile ||
+ (mForceAutoDetection &&
+ mCharsetSource == kCharsetFromInitialUserForcedAutoDetection));
+
+ DiscardMetaSpeculation();
+
+ MOZ_ASSERT(mEncoding != UTF_8_ENCODING);
+
+ mDecodingLocalFileWithoutTokenizing = false;
+
+ mEncoding->NewDecoderWithBOMRemovalInto(*mUnicodeDecoder);
+ mHasHadErrors = false;
+
+ // Throw away previous decoded data
+ mLastBuffer = mFirstBuffer;
+ mLastBuffer->next = nullptr;
+ mLastBuffer->setStart(0);
+ mLastBuffer->setEnd(0);
+
+ mBufferingBytes = false;
+ mForceAutoDetection = false; // To stop feeding the detector
+ mFirstBufferOfMetaScan = nullptr;
+
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, true);
+
+ // Decode again
+ for (auto&& buffer : mBufferedBytes) {
+ DoDataAvailable(buffer);
+ }
+
+ if (mMode == VIEW_SOURCE_HTML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ return r.unwrapErr();
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return r.unwrapErr();
+ }
+ return NS_OK;
+}
+
+[[nodiscard]] nsresult nsHtml5StreamParser::CommitLocalFileToEncoding() {
+ MOZ_ASSERT(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset);
+ MOZ_ASSERT(mFirstBufferOfMetaScan);
+ mDecodingLocalFileWithoutTokenizing = false;
+ MOZ_ASSERT(mCharsetSource == kCharsetFromFinalAutoDetectionFile ||
+ (mForceAutoDetection &&
+ mCharsetSource == kCharsetFromInitialUserForcedAutoDetection));
+ MOZ_ASSERT(mEncoding == UTF_8_ENCODING);
+
+ MOZ_ASSERT(!mStartedFeedingDevTools);
+ if (mURIToSendToDevtools) {
+ nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan;
+ while (buffer) {
+ Span<const char16_t> data(buffer->getBuffer() + buffer->getStart(),
+ buffer->getLength());
+ OnNewContent(data);
+ buffer = buffer->next;
+ }
+ }
+
+ mFirstBufferOfMetaScan = nullptr;
+
+ mBufferingBytes = false;
+ mForceAutoDetection = false; // To stop feeding the detector
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, true);
+ if (mMode == VIEW_SOURCE_HTML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ return r.unwrapErr();
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return r.unwrapErr();
+ }
+ return NS_OK;
+}
+
+class MaybeRunCollector : public Runnable {
+ public:
+ explicit MaybeRunCollector(nsIDocShell* aDocShell)
+ : Runnable("MaybeRunCollector"), mDocShell(aDocShell) {}
+
+ NS_IMETHOD Run() override {
+ nsJSContext::MaybeRunNextCollectorSlice(mDocShell,
+ JS::GCReason::HTML_PARSER);
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIDocShell> mDocShell;
+};
+
+nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
+ MOZ_RELEASE_ASSERT(STREAM_NOT_STARTED == mStreamState,
+ "Got OnStartRequest when the stream had already started.");
+ MOZ_ASSERT(
+ !mExecutor->HasStarted(),
+ "Got OnStartRequest at the wrong stage in the executor life cycle.");
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+
+ // To avoid the cost of instantiating the detector when it's not needed,
+ // let's instantiate only if we make it out of this method with the
+ // intent to use it.
+ auto detectorCreator = MakeScopeExit([&] {
+ if ((mForceAutoDetection || mCharsetSource < kCharsetFromParentFrame) ||
+ !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML)) {
+ mDetector = mozilla::EncodingDetector::Create();
+ }
+ });
+
+ mRequest = aRequest;
+
+ mStreamState = STREAM_BEING_READ;
+
+ // For View Source, the parser should run with scripts "enabled" if a normal
+ // load would have scripts enabled.
+ bool scriptingEnabled =
+ mMode == LOAD_AS_DATA ? false : mExecutor->IsScriptEnabled();
+ mOwner->StartTokenizer(scriptingEnabled);
+
+ MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing);
+ bool isSrcdoc = false;
+ nsCOMPtr<nsIChannel> channel;
+ nsresult rv = GetChannel(getter_AddRefs(channel));
+ if (NS_SUCCEEDED(rv)) {
+ isSrcdoc = NS_IsSrcdocChannel(channel);
+ if (!isSrcdoc && mCharsetSource <= kCharsetFromFallback) {
+ nsCOMPtr<nsIURI> originalURI;
+ rv = channel->GetOriginalURI(getter_AddRefs(originalURI));
+ if (NS_SUCCEEDED(rv)) {
+ if (originalURI->SchemeIs("resource")) {
+ mCharsetSource = kCharsetFromBuiltIn;
+ mEncoding = UTF_8_ENCODING;
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
+ } else {
+ nsCOMPtr<nsIURI> currentURI;
+ rv = channel->GetURI(getter_AddRefs(currentURI));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIURI> innermost = NS_GetInnermostURI(currentURI);
+ if (innermost->SchemeIs("file")) {
+ MOZ_ASSERT(mEncoding == UTF_8_ENCODING);
+ if (!(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML)) {
+ mDecodingLocalFileWithoutTokenizing = true;
+ }
+ } else {
+ nsAutoCString host;
+ innermost->GetAsciiHost(host);
+ if (!host.IsEmpty()) {
+ // First let's see if the host is DNS-absolute and ends with a
+ // dot and get rid of that one.
+ if (host.Last() == '.') {
+ host.SetLength(host.Length() - 1);
+ }
+ int32_t index = host.RFindChar('.');
+ if (index != kNotFound) {
+ // We tolerate an IPv4 component as generic "TLD", so don't
+ // bother checking.
+ ToLowerCase(
+ Substring(host, index + 1, host.Length() - (index + 1)),
+ mTLD);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ mTreeBuilder->setIsSrcdocDocument(isSrcdoc);
+ mTreeBuilder->setScriptingEnabled(scriptingEnabled);
+ mTreeBuilder->SetPreventScriptExecution(
+ !((mMode == NORMAL) && scriptingEnabled));
+ mTokenizer->start();
+ mExecutor->Start();
+ mExecutor->StartReadingFromStage();
+
+ if (mMode == PLAIN_TEXT) {
+ mTreeBuilder->StartPlainText();
+ mTokenizer->StartPlainText();
+ MOZ_ASSERT(
+ mTemplatePushedOrHeadPopped); // Needed to force 1024-byte sniffing
+ // Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment
+ // can find them.
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ } else if (mMode == VIEW_SOURCE_PLAIN) {
+ nsAutoString viewSourceTitle;
+ CopyUTF8toUTF16(mViewSourceTitle, viewSourceTitle);
+ mTreeBuilder->EnsureBufferSpace(viewSourceTitle.Length());
+ mTreeBuilder->StartPlainTextViewSource(viewSourceTitle);
+ mTokenizer->StartPlainText();
+ MOZ_ASSERT(
+ mTemplatePushedOrHeadPopped); // Needed to force 1024-byte sniffing
+ // Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment
+ // can find them.
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ } else if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
+ // Generate and flush the View Source document up to and including the
+ // pre element start.
+ mTokenizer->StartViewSource(NS_ConvertUTF8toUTF16(mViewSourceTitle));
+ if (mMode == VIEW_SOURCE_XML) {
+ mTokenizer->StartViewSourceCharacters();
+ }
+ // Flush the ops to put them where ContinueAfterScriptsOrEncodingCommitment
+ // can find them.
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ return mExecutor->MarkAsBroken(r.unwrapErr());
+ }
+ }
+
+ /*
+ * If you move the following line, be very careful not to cause
+ * WillBuildModel to be called before the document has had its
+ * script global object set.
+ */
+ rv = mExecutor->WillBuildModel();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ RefPtr<nsHtml5OwningUTF16Buffer> newBuf =
+ nsHtml5OwningUTF16Buffer::FalliblyCreate(READ_BUFFER_SIZE);
+ if (!newBuf) {
+ // marks this stream parser as terminated,
+ // which prevents entry to code paths that
+ // would use mFirstBuffer or mLastBuffer.
+ return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ MOZ_ASSERT(!mFirstBuffer, "How come we have the first buffer set?");
+ MOZ_ASSERT(!mLastBuffer, "How come we have the last buffer set?");
+ mFirstBuffer = mLastBuffer = newBuf;
+
+ rv = NS_OK;
+
+ mNetworkEventTarget =
+ mExecutor->GetDocument()->EventTargetFor(TaskCategory::Network);
+
+ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mRequest, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ // Non-HTTP channels are bogus enough that we let them work with unlabeled
+ // runnables for now. Asserting for HTTP channels only.
+ MOZ_ASSERT(mNetworkEventTarget || mMode == LOAD_AS_DATA,
+ "How come the network event target is still null?");
+
+ nsAutoCString method;
+ Unused << httpChannel->GetRequestMethod(method);
+ // XXX does Necko have a way to renavigate POST, etc. without hitting
+ // the network?
+ if (!method.EqualsLiteral("GET")) {
+ // This is the old Gecko behavior but the HTML5 spec disagrees.
+ // Don't reparse on POST.
+ mReparseForbidden = true;
+ }
+ }
+
+ // Attempt to retarget delivery of data (via OnDataAvailable) to the parser
+ // thread, rather than through the main thread.
+ nsCOMPtr<nsIThreadRetargetableRequest> threadRetargetableRequest =
+ do_QueryInterface(mRequest, &rv);
+ if (threadRetargetableRequest) {
+ rv = threadRetargetableRequest->RetargetDeliveryTo(mEventTarget);
+ if (NS_SUCCEEDED(rv)) {
+ // Parser thread should be now ready to get data from necko and parse it
+ // and main thread might have a chance to process a collector slice.
+ // We need to do this asynchronously so that necko may continue processing
+ // the request.
+ nsCOMPtr<nsIRunnable> runnable =
+ new MaybeRunCollector(mExecutor->GetDocument()->GetDocShell());
+ mozilla::SchedulerGroup::Dispatch(
+ mozilla::TaskCategory::GarbageCollection, runnable.forget());
+ }
+ }
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to retarget HTML data delivery to the parser thread.");
+ }
+
+ if (mCharsetSource == kCharsetFromParentFrame) {
+ // Remember this for error reporting.
+ mInitialEncodingWasFromParentFrame = true;
+ MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing);
+ }
+
+ if (mForceAutoDetection || mCharsetSource < kCharsetFromChannel) {
+ mBufferingBytes = true;
+ if (mMode != VIEW_SOURCE_XML) {
+ // We need to set mLookingForMetaCharset to true here in case the first
+ // buffer to arrive is larger than 1024. We need the code that splits
+ // the buffers at 1024 bytes to work even in that case.
+ mLookingForMetaCharset = true;
+ }
+ }
+
+ if (mCharsetSource < kCharsetFromUtf8OnlyMime) {
+ // we aren't ready to commit to an encoding yet
+ // leave converter uninstantiated for now
+ return NS_OK;
+ }
+
+ MOZ_ASSERT(!(mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML));
+
+ MOZ_ASSERT(mEncoding == UTF_8_ENCODING,
+ "How come UTF-8-only MIME type didn't set encoding to UTF-8?");
+
+ // We are loading JSON/WebVTT/etc. into a browsing context.
+ // There's no need to remove the BOM manually here, because
+ // the UTF-8 decoder removes it.
+ mReparseForbidden = true;
+ mForceAutoDetection = false;
+
+ // Instantiate the converter here to avoid BOM sniffing.
+ mDecodingLocalFileWithoutTokenizing = false;
+ mUnicodeDecoder = mEncoding->NewDecoderWithBOMRemoval();
+ return NS_OK;
+}
+
+void nsHtml5StreamParser::DoStopRequest() {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ MOZ_RELEASE_ASSERT(STREAM_BEING_READ == mStreamState,
+ "Stream ended without being open.");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+
+ auto guard = MakeScopeExit([&] { OnContentComplete(); });
+
+ if (IsTerminated()) {
+ return;
+ }
+
+ if (MOZ_UNLIKELY(mLookingForXmlDeclarationForXmlViewSource)) {
+ mLookingForXmlDeclarationForXmlViewSource = false;
+ mBufferingBytes = false;
+ mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling();
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
+
+ for (auto&& buffer : mBufferedBytes) {
+ nsresult rv = WriteStreamBytes(buffer);
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ return;
+ }
+ }
+ } else if (!mUnicodeDecoder) {
+ nsresult rv;
+ if (NS_FAILED(rv = SniffStreamBytes(Span<const uint8_t>(), true))) {
+ MarkAsBroken(rv);
+ return;
+ }
+ }
+
+ MOZ_ASSERT(mUnicodeDecoder,
+ "Should have a decoder after finalizing sniffing.");
+
+ // mLastBuffer should always point to a buffer of the size
+ // READ_BUFFER_SIZE.
+ if (!mLastBuffer) {
+ NS_WARNING("mLastBuffer should not be null!");
+ MarkAsBroken(NS_ERROR_NULL_POINTER);
+ return;
+ }
+
+ Span<uint8_t> src; // empty span
+ for (;;) {
+ auto dst = mLastBuffer->TailAsSpan(READ_BUFFER_SIZE);
+ uint32_t result;
+ size_t read;
+ size_t written;
+ bool hadErrors;
+ // Do not use structured binding lest deal with [-Werror=unused-variable]
+ std::tie(result, read, written, hadErrors) =
+ mUnicodeDecoder->DecodeToUTF16(src, dst, true);
+ if (!(mLookingForMetaCharset || mDecodingLocalFileWithoutTokenizing)) {
+ OnNewContent(dst.To(written));
+ }
+ if (hadErrors) {
+ mHasHadErrors = true;
+ }
+ MOZ_ASSERT(read == 0, "How come an empty span was read form?");
+ mLastBuffer->AdvanceEnd(written);
+ if (result == kOutputFull) {
+ RefPtr<nsHtml5OwningUTF16Buffer> newBuf =
+ nsHtml5OwningUTF16Buffer::FalliblyCreate(READ_BUFFER_SIZE);
+ if (!newBuf) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ mLastBuffer = (mLastBuffer->next = std::move(newBuf));
+ } else {
+ if (!mLookingForMetaCharset && mDecodingLocalFileWithoutTokenizing) {
+ MOZ_ASSERT(mNumBytesBuffered < LOCAL_FILE_UTF_8_BUFFER_SIZE);
+ MOZ_ASSERT(!mStartedFeedingDetector);
+ for (auto&& buffer : mBufferedBytes) {
+ FeedDetector(buffer);
+ }
+ MOZ_ASSERT(!mChardetEof);
+ DetectorEof();
+ auto [encoding, source] = GuessEncoding(true);
+ mCharsetSource = source;
+ if (encoding != mEncoding) {
+ mEncoding = encoding;
+ nsresult rv = ReDecodeLocalFile();
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ return;
+ }
+ DoStopRequest();
+ return;
+ }
+ MOZ_ASSERT(mEncoding == UTF_8_ENCODING);
+ nsresult rv = CommitLocalFileToEncoding();
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ mStreamState = STREAM_ENDED;
+
+ if (IsTerminatedOrInterrupted()) {
+ return;
+ }
+
+ ParseAvailableData();
+}
+
+class nsHtml5RequestStopper : public Runnable {
+ private:
+ nsHtml5StreamParserPtr mStreamParser;
+
+ public:
+ explicit nsHtml5RequestStopper(nsHtml5StreamParser* aStreamParser)
+ : Runnable("nsHtml5RequestStopper"), mStreamParser(aStreamParser) {}
+ NS_IMETHOD Run() override {
+ mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex);
+ mStreamParser->DoStopRequest();
+ mStreamParser->PostLoadFlusher();
+ return NS_OK;
+ }
+};
+
+nsresult nsHtml5StreamParser::OnStopRequest(nsIRequest* aRequest,
+ nsresult status) {
+ MOZ_ASSERT(mRequest == aRequest, "Got Stop on wrong stream.");
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ nsCOMPtr<nsIRunnable> stopper = new nsHtml5RequestStopper(this);
+ if (NS_FAILED(mEventTarget->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) {
+ NS_WARNING("Dispatching StopRequest event failed.");
+ }
+ return NS_OK;
+}
+
+void nsHtml5StreamParser::DoDataAvailableBuffer(
+ mozilla::Buffer<uint8_t>&& aBuffer) {
+ if (MOZ_UNLIKELY(!mBufferingBytes)) {
+ DoDataAvailable(aBuffer);
+ return;
+ }
+ if (MOZ_UNLIKELY(mLookingForXmlDeclarationForXmlViewSource)) {
+ const uint8_t* elements = aBuffer.Elements();
+ size_t length = aBuffer.Length();
+ const uint8_t* lt = (const uint8_t*)memchr(elements, '>', length);
+ if (!lt) {
+ mBufferedBytes.AppendElement(std::move(aBuffer));
+ return;
+ }
+
+ // We found an '>'. Now there either is or isn't an XML decl.
+ length = (lt - elements) + 1;
+ Vector<uint8_t> contiguous;
+ for (auto&& buffer : mBufferedBytes) {
+ if (!contiguous.append(buffer.Elements(), buffer.Length())) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ }
+ if (!contiguous.append(elements, length)) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+
+ const Encoding* encoding =
+ xmldecl_parse(contiguous.begin(), contiguous.length());
+ if (encoding) {
+ mEncoding = WrapNotNull(encoding);
+ mCharsetSource = kCharsetFromXmlDeclaration;
+ }
+
+ mLookingForXmlDeclarationForXmlViewSource = false;
+ mBufferingBytes = false;
+ mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling();
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, false);
+
+ for (auto&& buffer : mBufferedBytes) {
+ DoDataAvailable(buffer);
+ }
+ DoDataAvailable(aBuffer);
+ mBufferedBytes.Clear();
+ return;
+ }
+ CheckedInt<size_t> bufferedPlusLength(aBuffer.Length());
+ bufferedPlusLength += mNumBytesBuffered;
+ if (!bufferedPlusLength.isValid()) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ // Ensure that WriteStreamBytes() sees buffers ending
+ // exactly at the two special boundaries.
+ bool metaBoundaryWithinBuffer =
+ mLookingForMetaCharset &&
+ mNumBytesBuffered < UNCONDITIONAL_META_SCAN_BOUNDARY &&
+ bufferedPlusLength.value() > UNCONDITIONAL_META_SCAN_BOUNDARY;
+ bool localFileLimitWithinBuffer =
+ mDecodingLocalFileWithoutTokenizing &&
+ mNumBytesBuffered < LOCAL_FILE_UTF_8_BUFFER_SIZE &&
+ bufferedPlusLength.value() > LOCAL_FILE_UTF_8_BUFFER_SIZE;
+ if (!metaBoundaryWithinBuffer && !localFileLimitWithinBuffer) {
+ // Truncation OK, because we just checked the range.
+ mNumBytesBuffered = bufferedPlusLength.value();
+ mBufferedBytes.AppendElement(std::move(aBuffer));
+ DoDataAvailable(mBufferedBytes.LastElement());
+ } else {
+ MOZ_RELEASE_ASSERT(
+ !(metaBoundaryWithinBuffer && localFileLimitWithinBuffer),
+ "How can Necko give us a buffer this large?");
+ size_t boundary = metaBoundaryWithinBuffer
+ ? UNCONDITIONAL_META_SCAN_BOUNDARY
+ : LOCAL_FILE_UTF_8_BUFFER_SIZE;
+ // Truncation OK, because the constant is small enough.
+ size_t overBoundary = bufferedPlusLength.value() - boundary;
+ MOZ_RELEASE_ASSERT(overBoundary < aBuffer.Length());
+ size_t untilBoundary = aBuffer.Length() - overBoundary;
+ auto span = aBuffer.AsSpan();
+ auto head = span.To(untilBoundary);
+ auto tail = span.From(untilBoundary);
+ MOZ_RELEASE_ASSERT(mNumBytesBuffered + untilBoundary == boundary);
+ // The following copies may end up being useless, but optimizing
+ // them away would add complexity.
+ Maybe<Buffer<uint8_t>> maybeHead = Buffer<uint8_t>::CopyFrom(head);
+ if (maybeHead.isNothing()) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ mNumBytesBuffered = boundary;
+ mBufferedBytes.AppendElement(std::move(*maybeHead));
+ DoDataAvailable(mBufferedBytes.LastElement());
+ // Re-decode may have happened here.
+
+ Maybe<Buffer<uint8_t>> maybeTail = Buffer<uint8_t>::CopyFrom(tail);
+ if (maybeTail.isNothing()) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ mNumBytesBuffered += tail.Length();
+ mBufferedBytes.AppendElement(std::move(*maybeTail));
+ DoDataAvailable(mBufferedBytes.LastElement());
+ }
+ // Do this clean-up here to avoid use-after-free when
+ // DoDataAvailable is passed a span pointing into an
+ // element of mBufferedBytes.
+ if (!mBufferingBytes) {
+ mBufferedBytes.Clear();
+ }
+}
+
+void nsHtml5StreamParser::DoDataAvailable(Span<const uint8_t> aBuffer) {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ MOZ_RELEASE_ASSERT(STREAM_BEING_READ == mStreamState,
+ "DoDataAvailable called when stream not open.");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+
+ if (IsTerminated()) {
+ return;
+ }
+
+ nsresult rv;
+ if (HasDecoder()) {
+ if ((mForceAutoDetection || mCharsetSource < kCharsetFromParentFrame) &&
+ !mBufferingBytes && !mReparseForbidden &&
+ !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML)) {
+ MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing,
+ "How is mBufferingBytes false if "
+ "mDecodingLocalFileWithoutTokenizing is true?");
+ FeedDetector(aBuffer);
+ }
+ rv = WriteStreamBytes(aBuffer);
+ } else {
+ rv = SniffStreamBytes(aBuffer, false);
+ }
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ return;
+ }
+
+ if (IsTerminatedOrInterrupted()) {
+ return;
+ }
+
+ if (!mLookingForMetaCharset && mDecodingLocalFileWithoutTokenizing) {
+ return;
+ }
+
+ ParseAvailableData();
+
+ if (mBomState != BOM_SNIFFING_OVER || mFlushTimerArmed || mSpeculating) {
+ return;
+ }
+
+ {
+ mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
+ mFlushTimer->InitWithNamedFuncCallback(
+ nsHtml5StreamParser::TimerCallback, static_cast<void*>(this),
+ mFlushTimerEverFired ? StaticPrefs::html5_flushtimer_initialdelay()
+ : StaticPrefs::html5_flushtimer_subsequentdelay(),
+ nsITimer::TYPE_ONE_SHOT, "nsHtml5StreamParser::DoDataAvailable");
+ }
+ mFlushTimerArmed = true;
+}
+
+class nsHtml5DataAvailable : public Runnable {
+ private:
+ nsHtml5StreamParserPtr mStreamParser;
+ Buffer<uint8_t> mData;
+
+ public:
+ nsHtml5DataAvailable(nsHtml5StreamParser* aStreamParser,
+ Buffer<uint8_t>&& aData)
+ : Runnable("nsHtml5DataAvailable"),
+ mStreamParser(aStreamParser),
+ mData(std::move(aData)) {}
+ NS_IMETHOD Run() override {
+ mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex);
+ mStreamParser->DoDataAvailableBuffer(std::move(mData));
+ mStreamParser->PostLoadFlusher();
+ return NS_OK;
+ }
+};
+
+nsresult nsHtml5StreamParser::OnDataAvailable(nsIRequest* aRequest,
+ nsIInputStream* aInStream,
+ uint64_t aSourceOffset,
+ uint32_t aLength) {
+ nsresult rv;
+
+ MOZ_ASSERT(mRequest == aRequest, "Got data on wrong stream.");
+ uint32_t totalRead;
+ // Main thread to parser thread dispatch requires copying to buffer first.
+ if (MOZ_UNLIKELY(NS_IsMainThread())) {
+ if (NS_FAILED(rv = mExecutor->IsBroken())) {
+ return rv;
+ }
+ Maybe<Buffer<uint8_t>> maybe = Buffer<uint8_t>::Alloc(aLength);
+ if (maybe.isNothing()) {
+ return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ Buffer<uint8_t> data(std::move(*maybe));
+ rv = aInStream->Read(reinterpret_cast<char*>(data.Elements()),
+ data.Length(), &totalRead);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(totalRead == aLength);
+
+ nsCOMPtr<nsIRunnable> dataAvailable =
+ new nsHtml5DataAvailable(this, std::move(data));
+ if (NS_FAILED(mEventTarget->Dispatch(dataAvailable,
+ nsIThread::DISPATCH_NORMAL))) {
+ NS_WARNING("Dispatching DataAvailable event failed.");
+ }
+ return rv;
+ }
+
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mozilla::MutexAutoLock autoLock(mTokenizerMutex);
+
+ if (NS_FAILED(rv = mTreeBuilder->IsBroken())) {
+ return rv;
+ }
+
+ // Since we're getting OnDataAvailable directly on the parser thread,
+ // there is no nsHtml5DataAvailable that would call PostLoadFlusher.
+ // Hence, we need to call PostLoadFlusher() before this method returns.
+ // Braces for RAII clarity relative to the mutex despite not being
+ // strictly necessary.
+ {
+ auto speculationFlusher = MakeScopeExit([&] { PostLoadFlusher(); });
+
+ if (mBufferingBytes) {
+ Maybe<Buffer<uint8_t>> maybe = Buffer<uint8_t>::Alloc(aLength);
+ if (maybe.isNothing()) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ Buffer<uint8_t> data(std::move(*maybe));
+ rv = aInStream->Read(reinterpret_cast<char*>(data.Elements()),
+ data.Length(), &totalRead);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(totalRead == aLength);
+ DoDataAvailableBuffer(std::move(data));
+ return rv;
+ }
+ // Read directly from response buffer.
+ rv = aInStream->ReadSegments(CopySegmentsToParser, this, aLength,
+ &totalRead);
+ NS_ENSURE_SUCCESS(rv, rv);
+ MOZ_ASSERT(totalRead == aLength);
+ return rv;
+ }
+}
+
+// Called under lock by function ptr
+/* static */
+nsresult nsHtml5StreamParser::CopySegmentsToParser(
+ nsIInputStream* aInStream, void* aClosure, const char* aFromSegment,
+ uint32_t aToOffset, uint32_t aCount,
+ uint32_t* aWriteCount) MOZ_NO_THREAD_SAFETY_ANALYSIS {
+ nsHtml5StreamParser* parser = static_cast<nsHtml5StreamParser*>(aClosure);
+
+ parser->DoDataAvailable(AsBytes(Span(aFromSegment, aCount)));
+ // Assume DoDataAvailable consumed all available bytes.
+ *aWriteCount = aCount;
+ return NS_OK;
+}
+
+const Encoding* nsHtml5StreamParser::PreferredForInternalEncodingDecl(
+ const nsAString& aEncoding) {
+ const Encoding* newEncoding = Encoding::ForLabel(aEncoding);
+ if (!newEncoding) {
+ // the encoding name is bogus
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaUnsupported", true,
+ mTokenizer->getLineNumber());
+ return nullptr;
+ }
+
+ if (newEncoding == UTF_16BE_ENCODING || newEncoding == UTF_16LE_ENCODING) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaUtf16", true,
+ mTokenizer->getLineNumber());
+ newEncoding = UTF_8_ENCODING;
+ }
+
+ if (newEncoding == X_USER_DEFINED_ENCODING) {
+ // WebKit/Blink hack for Indian and Armenian legacy sites
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaUserDefined", true,
+ mTokenizer->getLineNumber());
+ newEncoding = WINDOWS_1252_ENCODING;
+ }
+
+ if (newEncoding == REPLACEMENT_ENCODING) {
+ // No line number, because the replacement encoding doesn't allow
+ // showing the lines.
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaReplacement", true, 0);
+ }
+
+ return newEncoding;
+}
+
+bool nsHtml5StreamParser::internalEncodingDeclaration(nsHtml5String aEncoding) {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ if ((mCharsetSource >= kCharsetFromMetaTag &&
+ mCharsetSource != kCharsetFromFinalAutoDetectionFile) ||
+ mSeenEligibleMetaCharset) {
+ return false;
+ }
+
+ nsString newEncoding; // Not Auto, because using it to hold nsStringBuffer*
+ aEncoding.ToString(newEncoding);
+ auto encoding = PreferredForInternalEncodingDecl(newEncoding);
+ if (!encoding) {
+ return false;
+ }
+
+ mSeenEligibleMetaCharset = true;
+
+ if (!mLookingForMetaCharset) {
+ if (mInitialEncodingWasFromParentFrame) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaTooLateFrame", true,
+ mTokenizer->getLineNumber());
+ } else {
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaTooLate", true,
+ mTokenizer->getLineNumber());
+ }
+ return false;
+ }
+ if (mTemplatePushedOrHeadPopped) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncMetaAfterHeadInKilobyte", false,
+ mTokenizer->getLineNumber());
+ }
+
+ if (mForceAutoDetection &&
+ (encoding->IsAsciiCompatible() || encoding == ISO_2022_JP_ENCODING)) {
+ return false;
+ }
+
+ mNeedsEncodingSwitchTo = encoding;
+ mEncodingSwitchSource = kCharsetFromMetaTag;
+ return true;
+}
+
+bool nsHtml5StreamParser::TemplatePushedOrHeadPopped() {
+ MOZ_ASSERT(
+ IsParserThread() || mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN,
+ "Wrong thread!");
+ mTemplatePushedOrHeadPopped = true;
+ return mNumBytesBuffered >= UNCONDITIONAL_META_SCAN_BOUNDARY;
+}
+
+void nsHtml5StreamParser::RememberGt(int32_t aPos) {
+ if (mLookingForMetaCharset) {
+ mGtBuffer = mFirstBuffer;
+ mGtPos = aPos;
+ }
+}
+
+void nsHtml5StreamParser::PostLoadFlusher() {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+
+ mTreeBuilder->FlushLoads();
+ // Dispatch this runnable unconditionally, because the loads
+ // that need flushing may have been flushed earlier even if the
+ // flush right above here did nothing. (Is this still true?)
+ nsCOMPtr<nsIRunnable> runnable(mLoadFlusher);
+ if (NS_FAILED(
+ DispatchToMain(CreateRenderBlockingRunnable(runnable.forget())))) {
+ NS_WARNING("failed to dispatch load flush event");
+ }
+
+ if ((mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) &&
+ mTokenizer->ShouldFlushViewSource()) {
+ auto r = mTreeBuilder->Flush(); // delete useless ops
+ MOZ_ASSERT(r.isOk(), "Should have null sink with View Source");
+ r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ if (r.unwrap()) {
+ nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
+ if (NS_FAILED(DispatchToMain(runnable.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+ }
+ }
+}
+
+void nsHtml5StreamParser::FlushTreeOpsAndDisarmTimer() {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ if (mFlushTimerArmed) {
+ // avoid calling Cancel if the flush timer isn't armed to avoid acquiring
+ // a mutex
+ {
+ mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
+ mFlushTimer->Cancel();
+ }
+ mFlushTimerArmed = false;
+ }
+ if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ }
+ nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
+ if (NS_FAILED(DispatchToMain(runnable.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+}
+
+void nsHtml5StreamParser::SwitchDecoderIfAsciiSoFar(
+ NotNull<const Encoding*> aEncoding) {
+ if (mEncoding == aEncoding) {
+ MOZ_ASSERT(!mStartedFeedingDevTools);
+ // Report all already-decoded buffers to the dev tools if needed.
+ if (mURIToSendToDevtools) {
+ nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan;
+ while (buffer) {
+ auto s = Span(buffer->getBuffer(), buffer->getEnd());
+ OnNewContent(s);
+ buffer = buffer->next;
+ }
+ }
+ return;
+ }
+ if (!mEncoding->IsAsciiCompatible() || !aEncoding->IsAsciiCompatible()) {
+ return;
+ }
+ size_t numAscii = 0;
+ MOZ_ASSERT(mFirstBufferOfMetaScan,
+ "Why did we come here without starting meta scan?");
+ nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan;
+ while (buffer != mFirstBuffer) {
+ MOZ_ASSERT(buffer, "mFirstBuffer should have acted as sentinel!");
+ MOZ_ASSERT(buffer->getStart() == buffer->getEnd(),
+ "Why wasn't an early buffer fully consumed?");
+ auto s = Span(buffer->getBuffer(), buffer->getStart());
+ if (!IsAscii(s)) {
+ return;
+ }
+ numAscii += s.Length();
+ buffer = buffer->next;
+ }
+ auto s = Span(mFirstBuffer->getBuffer(), mFirstBuffer->getStart());
+ if (!IsAscii(s)) {
+ return;
+ }
+ numAscii += s.Length();
+
+ MOZ_ASSERT(!mStartedFeedingDevTools);
+ // Report the ASCII prefix to dev tools if needed
+ if (mURIToSendToDevtools) {
+ buffer = mFirstBufferOfMetaScan;
+ while (buffer != mFirstBuffer) {
+ MOZ_ASSERT(buffer, "mFirstBuffer should have acted as sentinel!");
+ MOZ_ASSERT(buffer->getStart() == buffer->getEnd(),
+ "Why wasn't an early buffer fully consumed?");
+ auto s = Span(buffer->getBuffer(), buffer->getStart());
+ OnNewContent(s);
+ buffer = buffer->next;
+ }
+ auto s = Span(mFirstBuffer->getBuffer(), mFirstBuffer->getStart());
+ OnNewContent(s);
+ }
+
+ // Success! Now let's get rid of the already-decoded but not tokenized data:
+ mFirstBuffer->setEnd(mFirstBuffer->getStart());
+ mLastBuffer = mFirstBuffer;
+ mFirstBuffer->next = nullptr;
+
+ // Note: We could have scanned further for ASCII, which could avoid some
+ // buffer deallocation and reallocation. However, chances are that if we got
+ // until meta without non-ASCII before, there's going to be a title with
+ // non-ASCII soon after anyway, so let's avoid the complexity of finding out.
+
+ MOZ_ASSERT(mUnicodeDecoder, "How come we scanned meta without a decoder?");
+ mEncoding = aEncoding;
+ mEncoding->NewDecoderWithoutBOMHandlingInto(*mUnicodeDecoder);
+ mHasHadErrors = false;
+
+ MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing,
+ "Must have set mDecodingLocalFileWithoutTokenizing to false to "
+ "report data to dev tools below");
+ MOZ_ASSERT(!mLookingForMetaCharset,
+ "Must have set mLookingForMetaCharset to false to report data to "
+ "dev tools below");
+
+ // Now skip over as many bytes and redecode the tail of the
+ // buffered bytes.
+ size_t skipped = 0;
+ for (auto&& buffer : mBufferedBytes) {
+ size_t nextSkipped = skipped + buffer.Length();
+ if (nextSkipped <= numAscii) {
+ skipped = nextSkipped;
+ continue;
+ }
+ if (skipped >= numAscii) {
+ WriteStreamBytes(buffer);
+ skipped = nextSkipped;
+ continue;
+ }
+ size_t tailLength = nextSkipped - numAscii;
+ WriteStreamBytes(Span<uint8_t>(buffer).From(buffer.Length() - tailLength));
+ skipped = nextSkipped;
+ }
+}
+
+size_t nsHtml5StreamParser::CountGts() {
+ if (!mGtBuffer) {
+ return 0;
+ }
+ size_t gts = 0;
+ nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan;
+ for (;;) {
+ MOZ_ASSERT(buffer, "How did we walk past mGtBuffer?");
+ char16_t* buf = buffer->getBuffer();
+ if (buffer == mGtBuffer) {
+ for (int32_t i = 0; i <= mGtPos; ++i) {
+ if (buf[i] == u'>') {
+ ++gts;
+ }
+ }
+ break;
+ }
+ for (int32_t i = 0; i < buffer->getEnd(); ++i) {
+ if (buf[i] == u'>') {
+ ++gts;
+ }
+ }
+ buffer = buffer->next;
+ }
+ return gts;
+}
+
+void nsHtml5StreamParser::DiscardMetaSpeculation() {
+ mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
+ // Rewind the stream
+ MOZ_ASSERT(!mAtEOF, "How did we end up setting this?");
+ mTokenizer->resetToDataState();
+ mTokenizer->setLineNumber(1);
+ mLastWasCR = false;
+
+ if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) {
+ // resetToDataState() above logically rewinds to the state before
+ // the plain text start, so we need to start plain text again to
+ // put the tokenizer into the plain text state.
+ mTokenizer->StartPlainText();
+ }
+
+ mFirstBuffer = mLastBuffer;
+ mFirstBuffer->setStart(0);
+ mFirstBuffer->setEnd(0);
+ mFirstBuffer->next = nullptr;
+
+ mTreeBuilder->flushCharacters(); // empty the pending buffer
+ mTreeBuilder->ClearOps(); // now get rid of the failed ops
+
+ if (mMode == VIEW_SOURCE_HTML) {
+ mTokenizer->RewindViewSource();
+ }
+
+ {
+ // We know that this resets the tree builder back to the start state.
+ // This must happen _after_ the flushCharacters() call above!
+ const auto& speculation = mSpeculations.ElementAt(0);
+ mTreeBuilder->loadState(speculation->GetSnapshot());
+ }
+
+ // Experimentation suggests that we don't need to do anything special
+ // for ignoring the leading LF in View Source here.
+
+ mSpeculations.Clear(); // potentially a huge number of destructors
+ // run here synchronously...
+
+ // Now set up a new speculation for the main thread to find.
+ // Note that we stay in the speculating state, because the main thread
+ // knows how to come out of that state and this thread does not.
+
+ nsHtml5Speculation* speculation = new nsHtml5Speculation(
+ mFirstBuffer, mFirstBuffer->getStart(), mTokenizer->getLineNumber(),
+ mTokenizer->getColumnNumber(), mTreeBuilder->newSnapshot());
+ MOZ_ASSERT(!mFlushTimerArmed, "How did we end up arming the timer?");
+ if (mMode == VIEW_SOURCE_HTML) {
+ mTokenizer->SetViewSourceOpSink(speculation);
+ mTokenizer->StartViewSourceCharacters();
+ } else {
+ MOZ_ASSERT(mMode != VIEW_SOURCE_XML);
+ mTreeBuilder->SetOpSink(speculation);
+ }
+ mSpeculations.AppendElement(speculation); // adopts the pointer
+ MOZ_ASSERT(mSpeculating, "How did we end speculating?");
+}
+
+/*
+ * The general idea is to match WebKit and Blink exactly for meta
+ * scan except:
+ *
+ * 1. WebKit and Blink look for meta as if scripting was disabled
+ * for `noscript` purposes. This implementation matches the
+ * `noscript` treatment of the observable DOM building (in order
+ * to be able to use the same tree builder run).
+ * 2. WebKit and Blink look for meta as if the foreign content
+ * feedback from the tree builder to the tokenizer didn't exist.
+ * This implementation considers the foreign content rules in
+ * order to be able to use the same tree builder run for meta
+ * and the observable DOM building. Note that since <svg> and
+ * <math> imply the end of head, this only matters for meta after
+ * head but starting within the 1024-byte zone.
+ *
+ * Template is treated specially, because that WebKit/Blink behavior
+ * is easy to emulate unlike the above two exceptions. In general,
+ * the meta scan token handler in WebKit and Blink behaves as if there
+ * was a scripting-disabled tree builder predating the introduction
+ * of foreign content and template.
+ *
+ * Meta is honored if it _starts_ within the first 1024 kilobytes or,
+ * if by the 1024-byte boundary head hasn't ended and a template
+ * element hasn't started, a meta occurs before the first of the head
+ * ending or a template element starting.
+ *
+ * If a meta isn't honored according to the above definition, and
+ * we aren't dealing with plain text, the buffered bytes, which by
+ * now have to contain `>` character unless we encountered EOF, are
+ * scanned for syntax resembling an XML declaration.
+ *
+ * If neither a meta nor syntax resembling an XML declaration has
+ * been honored and we aren't inheriting the encoding from a
+ * same-origin parent or parsing for XHR, chardetng is used.
+ * chardetng runs first for the part of the document that was searched
+ * for meta and then at EOF. The part searched for meta is defined as
+ * follows in order to avoid network buffer boundary-dependent
+ * behavior:
+ *
+ * 1. At least the first 1024 bytes. (This is what happens for plain
+ * text.)
+ * 2. If the 1024-byte boundary is within a tag, comment, doctype,
+ * or CDATA section, at least up to the end of that token or CDATA
+ * section. (Exception: If the 1024-byte boundary is in an RCDATA
+ * end tag that hasn't yet been decided to be an end tag, the
+ * token is not considered.)
+ * 3. If at the 1024-byte boundary, head hasn't ended and there hasn't
+ * been a template tag, up to the end of the first template tag
+ * or token ending the head, whichever comes first.
+ * 4. Except if head is ended by a text token, only to the end of the
+ * most recent tag, comment, or doctype token. (Because text is
+ * coalesced, so it would be harder to correlate the text to the
+ * bytes.)
+ *
+ * An encoding-related reload is still possible if chardetng's guess
+ * at EOF differs from its initial guess.
+ */
+bool nsHtml5StreamParser::ProcessLookingForMetaCharset(bool aEof) {
+ MOZ_ASSERT(mBomState == BOM_SNIFFING_OVER);
+ MOZ_ASSERT(mMode != VIEW_SOURCE_XML);
+ bool rewound = false;
+ MOZ_ASSERT(mForceAutoDetection ||
+ mCharsetSource < kCharsetFromInitialAutoDetectionASCII ||
+ mCharsetSource == kCharsetFromParentFrame,
+ "Why are we looking for meta charset if we've seen it?");
+ // NOTE! We may come here multiple times with
+ // mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY
+ // if the tokenizer suspends multiple times after decoding has reached
+ // mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY. That's why
+ // we need to also check whether the we are at the end of the last
+ // decoded buffer.
+ // Note that DoDataAvailableBuffer() ensures that the code here has
+ // the opportunity to run at the exact UNCONDITIONAL_META_SCAN_BOUNDARY
+ // even if there isn't a network buffer boundary there.
+ bool atKilobyte = false;
+ if ((mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY &&
+ mFirstBuffer == mLastBuffer && !mFirstBuffer->hasMore())) {
+ atKilobyte = true;
+ mTokenizer->AtKilobyteBoundary();
+ }
+ if (!mNeedsEncodingSwitchTo &&
+ (aEof || (mTemplatePushedOrHeadPopped &&
+ !mTokenizer->IsInTokenStartedAtKilobyteBoundary() &&
+ (atKilobyte ||
+ mNumBytesBuffered > UNCONDITIONAL_META_SCAN_BOUNDARY)))) {
+ // meta charset was not found
+ mLookingForMetaCharset = false;
+ if (mStartsWithLtQuestion && mCharsetSource < kCharsetFromXmlDeclaration) {
+ // Look for bogo XML declaration.
+ // Search the first buffer in the hope that '>' is within it.
+ MOZ_ASSERT(!mBufferedBytes.IsEmpty(),
+ "How did at least <? not get buffered?");
+ Buffer<uint8_t>& first = mBufferedBytes[0];
+ const Encoding* encoding =
+ xmldecl_parse(first.Elements(), first.Length());
+ if (!encoding) {
+ // Our bogo XML declaration scanner wants to see a contiguous buffer, so
+ // let's linearize the data. (Ideally, the XML declaration scanner would
+ // be incremental, but this is the rare path anyway.)
+ Vector<uint8_t> contiguous;
+ if (!contiguous.append(first.Elements(), first.Length())) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return false;
+ }
+ for (size_t i = 1; i < mBufferedBytes.Length(); ++i) {
+ Buffer<uint8_t>& buffer = mBufferedBytes[i];
+ const uint8_t* elements = buffer.Elements();
+ size_t length = buffer.Length();
+ const uint8_t* lt = (const uint8_t*)memchr(elements, '>', length);
+ bool stop = false;
+ if (lt) {
+ length = (lt - elements) + 1;
+ stop = true;
+ }
+ if (!contiguous.append(elements, length)) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return false;
+ }
+ if (stop) {
+ // Avoid linearizing all buffered bytes unnecessarily.
+ break;
+ }
+ }
+ encoding = xmldecl_parse(contiguous.begin(), contiguous.length());
+ }
+ if (encoding) {
+ if (!(mForceAutoDetection && (encoding->IsAsciiCompatible() ||
+ encoding == ISO_2022_JP_ENCODING))) {
+ mForceAutoDetection = false;
+ mNeedsEncodingSwitchTo = encoding;
+ mEncodingSwitchSource = kCharsetFromXmlDeclaration;
+ }
+ }
+ }
+ // Check again in case we found an encoding in the bogo XML declaration.
+ if (!mNeedsEncodingSwitchTo &&
+ (mForceAutoDetection ||
+ mCharsetSource < kCharsetFromInitialAutoDetectionASCII) &&
+ !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML) &&
+ !(mDecodingLocalFileWithoutTokenizing && !aEof &&
+ mNumBytesBuffered <= LOCAL_FILE_UTF_8_BUFFER_SIZE)) {
+ MOZ_ASSERT(!mStartedFeedingDetector);
+ if (mNumBytesBuffered == UNCONDITIONAL_META_SCAN_BOUNDARY || aEof) {
+ // We know that all the buffered bytes have been tokenized, so feed
+ // them all to chardetng.
+ for (auto&& buffer : mBufferedBytes) {
+ FeedDetector(buffer);
+ }
+ if (aEof) {
+ MOZ_ASSERT(!mChardetEof);
+ DetectorEof();
+ }
+ auto [encoding, source] = GuessEncoding(true);
+ mNeedsEncodingSwitchTo = encoding;
+ mEncodingSwitchSource = source;
+ } else if (mNumBytesBuffered > UNCONDITIONAL_META_SCAN_BOUNDARY) {
+ size_t gtsLeftToFind = CountGts();
+ size_t bytesSeen = 0;
+ // We sync the bytes to the UTF-16 code units seen to avoid depending
+ // on network buffer boundaries. We do the syncing by counting '>'
+ // bytes / code units. However, we always scan at least 1024 bytes.
+ // The 1024-byte boundary is guaranteed to be between buffers.
+ // The guarantee is implemented in DoDataAvailableBuffer().
+ for (auto&& buffer : mBufferedBytes) {
+ if (!mNeedsEncodingSwitchTo) {
+ if (gtsLeftToFind) {
+ auto span = buffer.AsSpan();
+ bool feed = true;
+ for (size_t i = 0; i < span.Length(); ++i) {
+ if (span[i] == uint8_t('>')) {
+ --gtsLeftToFind;
+ if (!gtsLeftToFind) {
+ if (bytesSeen < UNCONDITIONAL_META_SCAN_BOUNDARY) {
+ break;
+ }
+ ++i; // Skip the gt
+ FeedDetector(span.To(i));
+ auto [encoding, source] = GuessEncoding(true);
+ mNeedsEncodingSwitchTo = encoding;
+ mEncodingSwitchSource = source;
+ FeedDetector(span.From(i));
+ bytesSeen += buffer.Length();
+ // No need to update bytesSeen anymore, but let's do it for
+ // debugging.
+ // We should do `continue outer;` but C++ can't.
+ feed = false;
+ break;
+ }
+ }
+ }
+ if (feed) {
+ FeedDetector(buffer);
+ bytesSeen += buffer.Length();
+ }
+ continue;
+ }
+ if (bytesSeen == UNCONDITIONAL_META_SCAN_BOUNDARY) {
+ auto [encoding, source] = GuessEncoding(true);
+ mNeedsEncodingSwitchTo = encoding;
+ mEncodingSwitchSource = source;
+ }
+ }
+ FeedDetector(buffer);
+ bytesSeen += buffer.Length();
+ }
+ }
+ MOZ_ASSERT(mNeedsEncodingSwitchTo,
+ "How come we didn't call GuessEncoding()?");
+ }
+ }
+ if (mNeedsEncodingSwitchTo) {
+ mDecodingLocalFileWithoutTokenizing = false;
+ mLookingForMetaCharset = false;
+
+ auto needsEncodingSwitchTo = WrapNotNull(mNeedsEncodingSwitchTo);
+ mNeedsEncodingSwitchTo = nullptr;
+
+ SwitchDecoderIfAsciiSoFar(needsEncodingSwitchTo);
+ // The above line may have changed mEncoding so that mEncoding equals
+ // needsEncodingSwitchTo.
+
+ mCharsetSource = mEncodingSwitchSource;
+
+ if (mMode == VIEW_SOURCE_HTML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return false;
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return false;
+ }
+
+ if (mEncoding != needsEncodingSwitchTo) {
+ // Speculation failed
+ rewound = true;
+
+ if (mEncoding == ISO_2022_JP_ENCODING ||
+ needsEncodingSwitchTo == ISO_2022_JP_ENCODING) {
+ // Chances are no Web author will fix anything due to this message, so
+ // this is here to help understanding issues when debugging sites made
+ // by someone else.
+ mTreeBuilder->MaybeComplainAboutCharset("EncSpeculationFail2022", false,
+ mTokenizer->getLineNumber());
+ } else {
+ if (mCharsetSource == kCharsetFromMetaTag) {
+ mTreeBuilder->MaybeComplainAboutCharset(
+ "EncSpeculationFailMeta", false, mTokenizer->getLineNumber());
+ } else if (mCharsetSource == kCharsetFromXmlDeclaration) {
+ // This intentionally refers to the line number of how far ahead
+ // the document was parsed even though the bogo XML decl is always
+ // on line 1.
+ mTreeBuilder->MaybeComplainAboutCharset(
+ "EncSpeculationFailXml", false, mTokenizer->getLineNumber());
+ }
+ }
+
+ DiscardMetaSpeculation();
+ // Redecode the stream.
+ mEncoding = needsEncodingSwitchTo;
+ mUnicodeDecoder = mEncoding->NewDecoderWithBOMRemoval();
+ mHasHadErrors = false;
+
+ MOZ_ASSERT(!mDecodingLocalFileWithoutTokenizing,
+ "Must have set mDecodingLocalFileWithoutTokenizing to false "
+ "to report data to dev tools below");
+ MOZ_ASSERT(!mLookingForMetaCharset,
+ "Must have set mLookingForMetaCharset to false to report data "
+ "to dev tools below");
+ for (auto&& buffer : mBufferedBytes) {
+ nsresult rv = WriteStreamBytes(buffer);
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ return false;
+ }
+ }
+ }
+ } else if (!mLookingForMetaCharset && !mDecodingLocalFileWithoutTokenizing) {
+ MOZ_ASSERT(!mStartedFeedingDevTools);
+ // Report all already-decoded buffers to the dev tools if needed.
+ if (mURIToSendToDevtools) {
+ nsHtml5OwningUTF16Buffer* buffer = mFirstBufferOfMetaScan;
+ while (buffer) {
+ auto s = Span(buffer->getBuffer(), buffer->getEnd());
+ OnNewContent(s);
+ buffer = buffer->next;
+ }
+ }
+ }
+ if (!mLookingForMetaCharset) {
+ mGtBuffer = nullptr;
+ mGtPos = 0;
+
+ if (!mDecodingLocalFileWithoutTokenizing) {
+ mFirstBufferOfMetaScan = nullptr;
+ mBufferingBytes = false;
+ mBufferedBytes.Clear();
+ mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource, true);
+ if (mMode == VIEW_SOURCE_HTML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return false;
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return false;
+ }
+ }
+ }
+ return rewound;
+}
+
+void nsHtml5StreamParser::ParseAvailableData() {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+ MOZ_ASSERT(!(mDecodingLocalFileWithoutTokenizing && !mLookingForMetaCharset));
+
+ if (IsTerminatedOrInterrupted()) {
+ return;
+ }
+
+ if (mSpeculating && !IsSpeculationEnabled()) {
+ return;
+ }
+
+ bool requestedReload = false;
+ for (;;) {
+ if (!mFirstBuffer->hasMore()) {
+ if (mFirstBuffer == mLastBuffer) {
+ switch (mStreamState) {
+ case STREAM_BEING_READ:
+ // never release the last buffer.
+ if (!mSpeculating) {
+ // reuse buffer space if not speculating
+ mFirstBuffer->setStart(0);
+ mFirstBuffer->setEnd(0);
+ }
+ return; // no more data for now but expecting more
+ case STREAM_ENDED:
+ if (mAtEOF) {
+ return;
+ }
+ if (mLookingForMetaCharset) {
+ // When called with aEof=true, ProcessLookingForMetaCharset()
+ // is guaranteed to set mLookingForMetaCharset to false so
+ // that we can't come here twice.
+ if (ProcessLookingForMetaCharset(true)) {
+ if (IsTerminatedOrInterrupted()) {
+ return;
+ }
+ continue;
+ }
+ } else if ((mForceAutoDetection ||
+ mCharsetSource < kCharsetFromParentFrame) &&
+ !(mMode == LOAD_AS_DATA || mMode == VIEW_SOURCE_XML) &&
+ !mReparseForbidden) {
+ // An earlier DetectorEof() call is possible in which case
+ // the one here is a no-op.
+ DetectorEof();
+ auto [encoding, source] = GuessEncoding(false);
+ if (encoding != mEncoding) {
+ // Request a reload from the docshell.
+ MOZ_ASSERT(
+ (source >=
+ kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII &&
+ source <=
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII) ||
+ source == kCharsetFromFinalUserForcedAutoDetection);
+ mTreeBuilder->NeedsCharsetSwitchTo(encoding, source, 0);
+ requestedReload = true;
+ } else if (mCharsetSource ==
+ kCharsetFromInitialAutoDetectionASCII &&
+ mDetectorHasSeenNonAscii) {
+ mCharsetSource = source;
+ mTreeBuilder->UpdateCharsetSource(mCharsetSource);
+ }
+ }
+
+ mAtEOF = true;
+ if (!mForceAutoDetection && !requestedReload) {
+ if (mCharsetSource == kCharsetFromParentFrame) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncNoDeclarationFrame",
+ false, 0);
+ } else if (mCharsetSource == kCharsetFromXmlDeclaration) {
+ // We know the bogo XML decl is always on the first line.
+ mTreeBuilder->MaybeComplainAboutCharset("EncXmlDecl", false, 1);
+ } else if (
+ mCharsetSource >=
+ kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8 &&
+ mCharsetSource <=
+ kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD) {
+ if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncNoDeclPlain",
+ true, 0);
+ } else {
+ mTreeBuilder->MaybeComplainAboutCharset("EncNoDecl", true, 0);
+ }
+ }
+
+ if (mHasHadErrors && mEncoding != REPLACEMENT_ENCODING) {
+ if (mEncoding == UTF_8_ENCODING) {
+ mTreeBuilder->TryToEnableEncodingMenu();
+ }
+ if (mCharsetSource == kCharsetFromParentFrame) {
+ if (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN) {
+ mTreeBuilder->MaybeComplainAboutCharset(
+ "EncErrorFramePlain", true, 0);
+ } else {
+ mTreeBuilder->MaybeComplainAboutCharset("EncErrorFrame",
+ true, 0);
+ }
+ } else if (
+ mCharsetSource >= kCharsetFromXmlDeclaration &&
+ !(mCharsetSource >=
+ kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII &&
+ mCharsetSource <=
+ kCharsetFromFinalUserForcedAutoDetection)) {
+ mTreeBuilder->MaybeComplainAboutCharset("EncError", true, 0);
+ }
+ }
+ }
+ if (NS_SUCCEEDED(mTreeBuilder->IsBroken())) {
+ mTokenizer->eof();
+ nsresult rv;
+ if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
+ MarkAsBroken(rv);
+ } else {
+ mTreeBuilder->StreamEnded();
+ if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
+ if (!mTokenizer->EndViewSource()) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ }
+ }
+ }
+ }
+ FlushTreeOpsAndDisarmTimer();
+ return; // no more data and not expecting more
+ default:
+ MOZ_ASSERT_UNREACHABLE("It should be impossible to reach this.");
+ return;
+ }
+ }
+ mFirstBuffer = mFirstBuffer->next;
+ continue;
+ }
+
+ // now we have a non-empty buffer
+ mFirstBuffer->adjust(mLastWasCR);
+ mLastWasCR = false;
+ if (mFirstBuffer->hasMore()) {
+ if (!mTokenizer->EnsureBufferSpace(mFirstBuffer->getLength())) {
+ MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer);
+ nsresult rv;
+ if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
+ MarkAsBroken(rv);
+ return;
+ }
+ if (mTreeBuilder->HasScript()) {
+ // HasScript() cannot return true if the tree builder is preventing
+ // script execution.
+ MOZ_ASSERT(mMode == NORMAL);
+ mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
+ nsHtml5Speculation* speculation = new nsHtml5Speculation(
+ mFirstBuffer, mFirstBuffer->getStart(), mTokenizer->getLineNumber(),
+ mTokenizer->getColumnNumber(), mTreeBuilder->newSnapshot());
+ mTreeBuilder->AddSnapshotToScript(speculation->GetSnapshot(),
+ speculation->GetStartLineNumber());
+ if (mLookingForMetaCharset) {
+ if (mMode == VIEW_SOURCE_HTML) {
+ auto r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ }
+ auto r = mTreeBuilder->Flush();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ } else {
+ FlushTreeOpsAndDisarmTimer();
+ }
+ mTreeBuilder->SetOpSink(speculation);
+ mSpeculations.AppendElement(speculation); // adopts the pointer
+ mSpeculating = true;
+ }
+ if (IsTerminatedOrInterrupted()) {
+ return;
+ }
+ }
+ if (mLookingForMetaCharset) {
+ Unused << ProcessLookingForMetaCharset(false);
+ }
+ }
+}
+
+class nsHtml5StreamParserContinuation : public Runnable {
+ private:
+ nsHtml5StreamParserPtr mStreamParser;
+
+ public:
+ explicit nsHtml5StreamParserContinuation(nsHtml5StreamParser* aStreamParser)
+ : Runnable("nsHtml5StreamParserContinuation"),
+ mStreamParser(aStreamParser) {}
+ NS_IMETHOD Run() override {
+ mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex);
+ mStreamParser->Uninterrupt();
+ mStreamParser->ParseAvailableData();
+ return NS_OK;
+ }
+};
+
+void nsHtml5StreamParser::ContinueAfterScriptsOrEncodingCommitment(
+ nsHtml5Tokenizer* aTokenizer, nsHtml5TreeBuilder* aTreeBuilder,
+ bool aLastWasCR) {
+ // nullptr for aTokenizer means encoding commitment as opposed to the "after
+ // scripts" case.
+
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ MOZ_ASSERT(mMode != VIEW_SOURCE_XML,
+ "ContinueAfterScriptsOrEncodingCommitment called in XML view "
+ "source mode!");
+ MOZ_ASSERT(!(aTokenizer && mMode == VIEW_SOURCE_HTML),
+ "ContinueAfterScriptsOrEncodingCommitment called with non-null "
+ "tokenizer in HTML view "
+ "source mode.");
+ if (NS_FAILED(mExecutor->IsBroken())) {
+ return;
+ }
+ MOZ_ASSERT(!(aTokenizer && mMode != NORMAL),
+ "We should only be executing scripts in the normal mode.");
+ if (!aTokenizer && (mMode == PLAIN_TEXT || mMode == VIEW_SOURCE_PLAIN ||
+ mMode == VIEW_SOURCE_HTML)) {
+ // Take the ops that were generated from OnStartRequest for the synthetic
+ // head section of the document for plain text and HTML View Source.
+ // XML View Source never needs this kind of encoding commitment.
+ // We need to take the ops here so that they end up in the queue before
+ // the ops that we take from a speculation later in this method.
+ if (!mExecutor->TakeOpsFromStage()) {
+ mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ } else {
+#ifdef DEBUG
+ mExecutor->AssertStageEmpty();
+#endif
+ }
+ bool speculationFailed = false;
+ {
+ mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
+ if (mSpeculations.IsEmpty()) {
+ MOZ_ASSERT_UNREACHABLE(
+ "ContinueAfterScriptsOrEncodingCommitment called without "
+ "speculations.");
+ return;
+ }
+
+ const auto& speculation = mSpeculations.ElementAt(0);
+ if (aTokenizer &&
+ (aLastWasCR || !aTokenizer->isInDataState() ||
+ !aTreeBuilder->snapshotMatches(speculation->GetSnapshot()))) {
+ speculationFailed = true;
+ // We've got a failed speculation :-(
+ MaybeDisableFutureSpeculation();
+ Interrupt(); // Make the parser thread release the tokenizer mutex sooner
+ // Note that the interrupted state continues across possible intervening
+ // Necko events until the nsHtml5StreamParserContinuation posted at the
+ // end of this method runs. Therefore, this thread is guaranteed to
+ // acquire mTokenizerMutex soon even if an intervening Necko event grabbed
+ // it between now and the acquisition below.
+
+ // now fall out of the speculationAutoLock into the tokenizerAutoLock
+ // block
+ } else {
+ // We've got a successful speculation!
+ if (mSpeculations.Length() > 1) {
+ // the first speculation isn't the current speculation, so there's
+ // no need to bother the parser thread.
+ if (!speculation->FlushToSink(mExecutor)) {
+ mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ MOZ_ASSERT(!mExecutor->IsScriptExecuting(),
+ "ParseUntilBlocked() was supposed to ensure we don't come "
+ "here when scripts are executing.");
+ MOZ_ASSERT(!aTokenizer || mExecutor->IsInFlushLoop(),
+ "How are we here if "
+ "RunFlushLoop() didn't call ParseUntilBlocked() or we're "
+ "not committing to an encoding?");
+ mSpeculations.RemoveElementAt(0);
+ return;
+ }
+ // else
+ Interrupt(); // Make the parser thread release the tokenizer mutex sooner
+ // Note that the interrupted state continues across possible intervening
+ // Necko events until the nsHtml5StreamParserContinuation posted at the
+ // end of this method runs. Therefore, this thread is guaranteed to
+ // acquire mTokenizerMutex soon even if an intervening Necko event grabbed
+ // it between now and the acquisition below.
+
+ // now fall through
+ // the first speculation is the current speculation. Need to
+ // release the the speculation mutex and acquire the tokenizer
+ // mutex. (Just acquiring the other mutex here would deadlock)
+ }
+ }
+ {
+ mozilla::MutexAutoLock tokenizerAutoLock(mTokenizerMutex);
+#ifdef DEBUG
+ {
+ mAtomTable.SetPermittedLookupEventTarget(
+ GetMainThreadSerialEventTarget());
+ }
+#endif
+ // In principle, the speculation mutex should be acquired here,
+ // but there's no point, because the parser thread only acquires it
+ // when it has also acquired the tokenizer mutex and we are already
+ // holding the tokenizer mutex.
+ if (speculationFailed) {
+ MOZ_ASSERT(mMode == NORMAL);
+ // Rewind the stream
+ mAtEOF = false;
+ const auto& speculation = mSpeculations.ElementAt(0);
+ mFirstBuffer = speculation->GetBuffer();
+ mFirstBuffer->setStart(speculation->GetStart());
+ mTokenizer->setLineNumber(speculation->GetStartLineNumber());
+ mTokenizer->setColumnNumberAndResetNextLine(
+ speculation->GetStartColumnNumber());
+
+ nsContentUtils::ReportToConsole(
+ nsIScriptError::warningFlag, "DOM Events"_ns,
+ mExecutor->GetDocument(), nsContentUtils::eDOM_PROPERTIES,
+ "SpeculationFailed2", nsTArray<nsString>(), nullptr, u""_ns,
+ speculation->GetStartLineNumber(),
+ speculation->GetStartColumnNumber());
+
+ nsHtml5OwningUTF16Buffer* buffer = mFirstBuffer->next;
+ while (buffer) {
+ buffer->setStart(0);
+ buffer = buffer->next;
+ }
+
+ mSpeculations.Clear(); // potentially a huge number of destructors
+ // run here synchronously on the main thread...
+
+ mTreeBuilder->flushCharacters(); // empty the pending buffer
+ mTreeBuilder->ClearOps(); // now get rid of the failed ops
+
+ mTreeBuilder->SetOpSink(mExecutor->GetStage());
+ mExecutor->StartReadingFromStage();
+ mSpeculating = false;
+
+ // Copy state over
+ mLastWasCR = aLastWasCR;
+ mTokenizer->loadState(aTokenizer);
+ mTreeBuilder->loadState(aTreeBuilder);
+ } else {
+ // We've got a successful speculation and at least a moment ago it was
+ // the current speculation
+ if (!mSpeculations.ElementAt(0)->FlushToSink(mExecutor)) {
+ mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ MOZ_ASSERT(!mExecutor->IsScriptExecuting(),
+ "ParseUntilBlocked() was supposed to ensure we don't come "
+ "here when scripts are executing.");
+ MOZ_ASSERT(!aTokenizer || mExecutor->IsInFlushLoop(),
+ "How are we here if "
+ "RunFlushLoop() didn't call ParseUntilBlocked() or we're not "
+ "committing to an encoding?");
+ mSpeculations.RemoveElementAt(0);
+ if (mSpeculations.IsEmpty()) {
+ if (mMode == VIEW_SOURCE_HTML) {
+ // If we looked for meta charset in the HTML View Source case.
+ mTokenizer->SetViewSourceOpSink(mExecutor->GetStage());
+ } else {
+ // yes, it was still the only speculation. Now stop speculating
+ // However, before telling the executor to read from stage, flush
+ // any pending ops straight to the executor, because otherwise
+ // they remain unflushed until we get more data from the network.
+ mTreeBuilder->SetOpSink(mExecutor);
+ auto r = mTreeBuilder->Flush(true);
+ if (r.isErr()) {
+ mExecutor->MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ mTreeBuilder->SetOpSink(mExecutor->GetStage());
+ }
+ mExecutor->StartReadingFromStage();
+ mSpeculating = false;
+ }
+ }
+ nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserContinuation(this);
+ if (NS_FAILED(mEventTarget->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
+ NS_WARNING("Failed to dispatch nsHtml5StreamParserContinuation");
+ }
+// A stream event might run before this event runs, but that's harmless.
+#ifdef DEBUG
+ mAtomTable.SetPermittedLookupEventTarget(mEventTarget);
+#endif
+ }
+}
+
+void nsHtml5StreamParser::ContinueAfterFailedCharsetSwitch() {
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ nsCOMPtr<nsIRunnable> event = new nsHtml5StreamParserContinuation(this);
+ if (NS_FAILED(mEventTarget->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
+ NS_WARNING("Failed to dispatch nsHtml5StreamParserContinuation");
+ }
+}
+
+class nsHtml5TimerKungFu : public Runnable {
+ private:
+ nsHtml5StreamParserPtr mStreamParser;
+
+ public:
+ explicit nsHtml5TimerKungFu(nsHtml5StreamParser* aStreamParser)
+ : Runnable("nsHtml5TimerKungFu"), mStreamParser(aStreamParser) {}
+ NS_IMETHOD Run() override {
+ mozilla::MutexAutoLock flushTimerLock(mStreamParser->mFlushTimerMutex);
+ if (mStreamParser->mFlushTimer) {
+ mStreamParser->mFlushTimer->Cancel();
+ mStreamParser->mFlushTimer = nullptr;
+ }
+ return NS_OK;
+ }
+};
+
+void nsHtml5StreamParser::DropTimer() {
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ /*
+ * Simply nulling out the timer wouldn't work, because if the timer is
+ * armed, it needs to be canceled first. Simply canceling it first wouldn't
+ * work, because nsTimerImpl::Cancel is not safe for calling from outside
+ * the thread where nsTimerImpl::Fire would run. It's not safe to
+ * dispatch a runnable to cancel the timer from the destructor of this
+ * class, because the timer has a weak (void*) pointer back to this instance
+ * of the stream parser and having the timer fire before the runnable
+ * cancels it would make the timer access a deleted object.
+ *
+ * This DropTimer method addresses these issues. This method must be called
+ * on the main thread before the destructor of this class is reached.
+ * The nsHtml5TimerKungFu object has an nsHtml5StreamParserPtr that addrefs
+ * this
+ * stream parser object to keep it alive until the runnable is done.
+ * The runnable cancels the timer on the parser thread, drops the timer
+ * and lets nsHtml5StreamParserPtr send a runnable back to the main thread to
+ * release the stream parser.
+ */
+ mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
+ if (mFlushTimer) {
+ nsCOMPtr<nsIRunnable> event = new nsHtml5TimerKungFu(this);
+ if (NS_FAILED(mEventTarget->Dispatch(event, nsIThread::DISPATCH_NORMAL))) {
+ NS_WARNING("Failed to dispatch TimerKungFu event");
+ }
+ }
+}
+
+// Using a static, because the method name Notify is taken by the chardet
+// callback.
+void nsHtml5StreamParser::TimerCallback(nsITimer* aTimer, void* aClosure) {
+ (static_cast<nsHtml5StreamParser*>(aClosure))->TimerFlush();
+}
+
+void nsHtml5StreamParser::TimerFlush() {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mozilla::MutexAutoLock autoLock(mTokenizerMutex);
+
+ MOZ_ASSERT(!mSpeculating, "Flush timer fired while speculating.");
+
+ // The timer fired if we got here. No need to cancel it. Mark it as
+ // not armed, though.
+ mFlushTimerArmed = false;
+
+ mFlushTimerEverFired = true;
+
+ if (IsTerminatedOrInterrupted()) {
+ return;
+ }
+
+ if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
+ auto r = mTreeBuilder->Flush(); // delete useless ops
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ r = mTokenizer->FlushViewSource();
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ if (r.unwrap()) {
+ nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
+ if (NS_FAILED(DispatchToMain(runnable.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+ }
+ } else {
+ // we aren't speculating and we don't know when new data is
+ // going to arrive. Send data to the main thread.
+ auto r = mTreeBuilder->Flush(true);
+ if (r.isErr()) {
+ MarkAsBroken(r.unwrapErr());
+ return;
+ }
+ if (r.unwrap()) {
+ nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
+ if (NS_FAILED(DispatchToMain(runnable.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+ }
+ }
+}
+
+void nsHtml5StreamParser::MarkAsBroken(nsresult aRv) {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+
+ Terminate();
+ mTreeBuilder->MarkAsBroken(aRv);
+ auto r = mTreeBuilder->Flush(false);
+ if (r.isOk()) {
+ MOZ_ASSERT(r.unwrap(), "Should have had the markAsBroken op!");
+ } else {
+ MOZ_CRASH("OOM prevents propagation of OOM state");
+ }
+ nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
+ if (NS_FAILED(DispatchToMain(runnable.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+}
+
+nsresult nsHtml5StreamParser::DispatchToMain(
+ already_AddRefed<nsIRunnable>&& aRunnable) {
+ if (mNetworkEventTarget) {
+ return mNetworkEventTarget->Dispatch(std::move(aRunnable));
+ }
+ return SchedulerGroup::UnlabeledDispatch(TaskCategory::Network,
+ std::move(aRunnable));
+}
diff --git a/parser/html/nsHtml5StreamParser.h b/parser/html/nsHtml5StreamParser.h
new file mode 100644
index 0000000000..0dacf257bf
--- /dev/null
+++ b/parser/html/nsHtml5StreamParser.h
@@ -0,0 +1,766 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5StreamParser_h
+#define nsHtml5StreamParser_h
+
+#include <tuple>
+
+#include "MainThreadUtils.h"
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Encoding.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/NotNull.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/Span.h"
+#include "mozilla/UniquePtr.h"
+#include "nsCharsetSource.h"
+#include "nsCOMPtr.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsDebug.h"
+#include "nsHtml5AtomTable.h"
+#include "nsIRequestObserver.h"
+#include "nsISerialEventTarget.h"
+#include "nsISupports.h"
+#include "nsStringFwd.h"
+#include "nsTArray.h"
+#include "nscore.h"
+
+class nsCycleCollectionTraversalCallback;
+class nsHtml5OwningUTF16Buffer;
+class nsHtml5Parser;
+class nsHtml5Speculation;
+class nsHtml5String;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5TreeOpExecutor;
+class nsIChannel;
+class nsIInputStream;
+class nsIRequest;
+class nsIRunnable;
+class nsITimer;
+class nsIURI;
+
+namespace mozilla {
+class EncodingDetector;
+template <typename T>
+class Buffer;
+
+namespace dom {
+class DocGroup;
+}
+} // namespace mozilla
+
+enum eParserMode {
+ /**
+ * Parse a document normally as HTML.
+ */
+ NORMAL,
+
+ /**
+ * View document as HTML source.
+ */
+ VIEW_SOURCE_HTML,
+
+ /**
+ * View document as XML source
+ */
+ VIEW_SOURCE_XML,
+
+ /**
+ * View document as plain text source
+ */
+ VIEW_SOURCE_PLAIN,
+
+ /**
+ * View document as plain text
+ */
+ PLAIN_TEXT,
+
+ /**
+ * Load as data (XHR)
+ */
+ LOAD_AS_DATA
+};
+
+enum eBomState {
+ /**
+ * BOM sniffing hasn't started.
+ */
+ BOM_SNIFFING_NOT_STARTED,
+
+ /**
+ * BOM sniffing is ongoing, and the first byte of an UTF-16LE BOM has been
+ * seen.
+ */
+ SEEN_UTF_16_LE_FIRST_BYTE,
+
+ /**
+ * BOM sniffing is ongoing, and the first byte of an UTF-16BE BOM has been
+ * seen.
+ */
+ SEEN_UTF_16_BE_FIRST_BYTE,
+
+ /**
+ * BOM sniffing is ongoing, and the first byte of an UTF-8 BOM has been
+ * seen.
+ */
+ SEEN_UTF_8_FIRST_BYTE,
+
+ /**
+ * BOM sniffing is ongoing, and the first and second bytes of an UTF-8 BOM
+ * have been seen.
+ */
+ SEEN_UTF_8_SECOND_BYTE,
+
+ /**
+ * Seen \x00 in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_BE_XML_FIRST,
+
+ /**
+ * Seen \x00< in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_BE_XML_SECOND,
+
+ /**
+ * Seen \x00<\x00 in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_BE_XML_THIRD,
+
+ /**
+ * Seen \x00<\x00? in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_BE_XML_FOURTH,
+
+ /**
+ * Seen \x00<\x00?\x00 in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_BE_XML_FIFTH,
+
+ /**
+ * Seen < in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_LE_XML_FIRST,
+
+ /**
+ * Seen <\x00 in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_LE_XML_SECOND,
+
+ /**
+ * Seen <\x00? in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_LE_XML_THIRD,
+
+ /**
+ * Seen <\x00?\x00 in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_LE_XML_FOURTH,
+
+ /**
+ * Seen <\x00?\x00x in UTF-16BE bogo-XML declaration.
+ */
+ SEEN_UTF_16_LE_XML_FIFTH,
+
+ /**
+ * BOM sniffing was started but is now over for whatever reason.
+ */
+ BOM_SNIFFING_OVER,
+};
+
+enum eHtml5StreamState {
+ STREAM_NOT_STARTED = 0,
+ STREAM_BEING_READ = 1,
+ STREAM_ENDED = 2
+};
+
+class nsHtml5StreamParser final : public nsISupports {
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+ using Encoding = mozilla::Encoding;
+
+ const uint32_t UNCONDITIONAL_META_SCAN_BOUNDARY = 1024;
+ const uint32_t READ_BUFFER_SIZE = 1024;
+ const uint32_t LOCAL_FILE_UTF_8_BUFFER_SIZE = 1024 * 1024 * 4; // 4 MB
+
+ friend class nsHtml5RequestStopper;
+ friend class nsHtml5DataAvailable;
+ friend class nsHtml5StreamParserContinuation;
+ friend class nsHtml5TimerKungFu;
+ friend class nsHtml5StreamParserPtr;
+ friend class nsHtml5StreamListener;
+
+ public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser)
+
+ nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor, nsHtml5Parser* aOwner,
+ eParserMode aMode);
+
+ nsresult OnStartRequest(nsIRequest* aRequest);
+
+ nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInStream,
+ uint64_t aSourceOffset, uint32_t aLength);
+
+ nsresult OnStopRequest(nsIRequest* aRequest, nsresult status);
+
+ // EncodingDeclarationHandler
+ // https://hg.mozilla.org/projects/htmlparser/file/tip/src/nu/validator/htmlparser/common/EncodingDeclarationHandler.java
+ /**
+ * Tree builder uses this to report a late <meta charset>
+ */
+ bool internalEncodingDeclaration(nsHtml5String aEncoding);
+
+ bool TemplatePushedOrHeadPopped();
+
+ void RememberGt(int32_t aPos);
+
+ // Not from an external interface
+
+ /**
+ * Post a runnable to the main thread to perform the speculative load
+ * operations without performing the tree operations.
+ *
+ * This should be called at the end of each data available or stop
+ * request runnable running on the parser thread.
+ */
+ void PostLoadFlusher();
+
+ /**
+ * Pass a buffer to chardetng.
+ */
+ void FeedDetector(mozilla::Span<const uint8_t> aBuffer);
+
+ /**
+ * Report EOF to chardetng.
+ */
+ void DetectorEof();
+
+ /**
+ * Call this method once you've created a parser, and want to instruct it
+ * about what charset to load
+ *
+ * @param aEncoding the charset of a document
+ * @param aCharsetSource the source of the charset
+ */
+ inline void SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ nsCharsetSource aSource,
+ bool aForceAutoDetection) {
+ MOZ_ASSERT(mStreamState == STREAM_NOT_STARTED,
+ "SetDocumentCharset called too late.");
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ MOZ_ASSERT(!(aForceAutoDetection && aSource >= kCharsetFromOtherComponent),
+ "Can't force with high-ranking source.");
+ mEncoding = aEncoding;
+ mCharsetSource = aSource;
+ mForceAutoDetection = aForceAutoDetection;
+ mChannelHadCharset = (aSource == kCharsetFromChannel);
+ }
+
+ nsresult GetChannel(nsIChannel** aChannel);
+
+ /**
+ * The owner parser must call this after script execution
+ * when no scripts are executing and the document.written
+ * buffer has been exhausted.
+ *
+ * If the first two arguments are nullptr, instead of
+ * continuing after scripts, this method commits to an
+ * internally-discovered encoding.
+ */
+ void ContinueAfterScriptsOrEncodingCommitment(
+ nsHtml5Tokenizer* aTokenizer, nsHtml5TreeBuilder* aTreeBuilder,
+ bool aLastWasCR);
+
+ /**
+ * Continues the stream parser if the charset switch failed.
+ */
+ void ContinueAfterFailedCharsetSwitch();
+
+ void Terminate() { mTerminated = true; }
+
+ void DropTimer();
+
+ /**
+ * Sets the URL for View Source title in case this parser ends up being
+ * used for View Source. If aURL is a view-source: URL, takes the inner
+ * URL. data: URLs are shown with an ellipsis instead of the actual data.
+ */
+ void SetViewSourceTitle(nsIURI* aURL);
+
+ private:
+ virtual ~nsHtml5StreamParser();
+
+#ifdef DEBUG
+ bool IsParserThread() { return mEventTarget->IsOnCurrentThread(); }
+#endif
+
+ void MarkAsBroken(nsresult aRv);
+
+ /**
+ * Marks the stream parser as interrupted. If you ever add calls to this
+ * method, be sure to review Uninterrupt usage very, very carefully to
+ * avoid having a previous in-flight runnable cancel your Interrupt()
+ * call on the other thread too soon.
+ */
+ void Interrupt() {
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ mInterrupted = true;
+ }
+
+ void Uninterrupt() MOZ_NO_THREAD_SAFETY_ANALYSIS {
+ MOZ_ASSERT(IsParserThread(), "Wrong thread!");
+ mTokenizerMutex.AssertCurrentThreadOwns();
+ mInterrupted = false;
+ }
+
+ /**
+ * Flushes the tree ops from the tree builder and disarms the flush
+ * timer.
+ */
+ void FlushTreeOpsAndDisarmTimer();
+
+ void SwitchDecoderIfAsciiSoFar(NotNull<const Encoding*> aEncoding)
+ MOZ_REQUIRES(mTokenizerMutex);
+ ;
+
+ size_t CountGts();
+
+ void DiscardMetaSpeculation();
+
+ bool ProcessLookingForMetaCharset(bool aEof) MOZ_REQUIRES(mTokenizerMutex);
+
+ void ParseAvailableData();
+
+ void DoStopRequest();
+
+ void DoDataAvailableBuffer(mozilla::Buffer<uint8_t>&& aBuffer)
+ MOZ_REQUIRES(mTokenizerMutex);
+
+ void DoDataAvailable(mozilla::Span<const uint8_t> aBuffer)
+ MOZ_REQUIRES(mTokenizerMutex);
+
+ static nsresult CopySegmentsToParser(nsIInputStream* aInStream,
+ void* aClosure, const char* aFromSegment,
+ uint32_t aToOffset, uint32_t aCount,
+ uint32_t* aWriteCount)
+ MOZ_REQUIRES(mTokenizerMutex);
+
+ bool IsTerminatedOrInterrupted() { return mTerminated || mInterrupted; }
+
+ bool IsTerminated() { return mTerminated; }
+
+ /**
+ * True when there is a Unicode decoder already
+ */
+ inline bool HasDecoder() { return !!mUnicodeDecoder; }
+
+ /**
+ * Returns 0 if 1) there aren't at least 2 buffers in mBufferedBytes
+ * or 2) there is no byte '>' in the second buffer.
+ * Otherwise, returns the length of the prefix of the second buffer
+ * that is long enough to contain the first byte '>' in the second
+ * buffer (including the '>' byte).
+ */
+ size_t LengthOfLtContainingPrefixInSecondBuffer();
+
+ /**
+ * Push bytes from network when there is no Unicode decoder yet
+ */
+ nsresult SniffStreamBytes(mozilla::Span<const uint8_t> aFromSegment,
+ bool aEof) MOZ_REQUIRES(mTokenizerMutex);
+
+ /**
+ * Push bytes from network when there is a Unicode decoder already
+ */
+ nsresult WriteStreamBytes(mozilla::Span<const uint8_t> aFromSegment)
+ MOZ_REQUIRES(mTokenizerMutex);
+
+ /**
+ * Set up the Unicode decoder and write the sniffing buffer into it
+ * followed by the current network buffer.
+ *
+ * @param aPrefix the part of the stream that has already been seen
+ * prior to aFromSegment. In practice, these are the
+ * bytes that are baked into the state of the BOM
+ * and UTF-16 XML declaration-like sniffing state
+ * machine state.
+ * @param aFromSegment The current network buffer
+ */
+ nsresult SetupDecodingAndWriteSniffingBufferAndCurrentSegment(
+ mozilla::Span<const uint8_t> aPrefix,
+ mozilla::Span<const uint8_t> aFromSegment) MOZ_REQUIRES(mTokenizerMutex);
+
+ /**
+ * Initialize the Unicode decoder, mark the BOM as the source and
+ * drop the sniffer.
+ *
+ * @param aDecoderCharsetName The name for the decoder's charset
+ * (UTF-16BE, UTF-16LE or UTF-8; the BOM has
+ * been swallowed)
+ */
+ void SetupDecodingFromBom(NotNull<const Encoding*> aEncoding);
+
+ void SetupDecodingFromUtf16BogoXml(NotNull<const Encoding*> aEncoding);
+
+ /**
+ * When speculatively decoding from file: URL as UTF-8, commit
+ * to UTF-8 as the non-speculative encoding and start processing
+ * the decoded data.
+ */
+ [[nodiscard]] nsresult CommitLocalFileToEncoding();
+
+ /**
+ * When speculatively decoding from file: URL as UTF-8, redecode
+ * using fallback and then continue normally with the fallback.
+ */
+ [[nodiscard]] nsresult ReDecodeLocalFile() MOZ_REQUIRES(mTokenizerMutex);
+
+ /**
+ * Potentially guess the encoding using mozilla::EncodingDetector.
+ * Returns the guessed encoding and a telemetry-appropriate source.
+ */
+ std::tuple<NotNull<const Encoding*>, nsCharsetSource> GuessEncoding(
+ bool aInitial);
+
+ /**
+ * Become confident or resolve and encoding name to its preferred form.
+ * @param aEncoding the value of an internal encoding decl. Acts as an
+ * out param, too, when the method returns true.
+ * @return true if the parser needs to start using the new value of
+ * aEncoding and false if the parser became confident or if
+ * the encoding name did not specify a usable encoding
+ */
+ const Encoding* PreferredForInternalEncodingDecl(const nsAString& aEncoding);
+
+ /**
+ * Callback for mFlushTimer.
+ */
+ static void TimerCallback(nsITimer* aTimer, void* aClosure);
+
+ /**
+ * Parser thread entry point for (maybe) flushing the ops and posting
+ * a flush runnable back on the main thread.
+ */
+ void TimerFlush();
+
+ /**
+ * Called when speculation fails.
+ */
+ void MaybeDisableFutureSpeculation() { mSpeculationFailureCount++; }
+
+ /**
+ * Used to check whether we're getting too many speculation failures and
+ * should just stop trying. The 100 is picked pretty randomly to be not too
+ * small (so most pages are not affected) but small enough that we don't end
+ * up with failed speculations over and over in pathological cases.
+ */
+ bool IsSpeculationEnabled() { return mSpeculationFailureCount < 100; }
+
+ /**
+ * Dispatch an event to a Quantum DOM main thread-ish thread.
+ * (Not the parser thread.)
+ */
+ nsresult DispatchToMain(already_AddRefed<nsIRunnable>&& aRunnable);
+
+ /**
+ * Notify any devtools listeners about content newly received for parsing.
+ */
+ inline void OnNewContent(mozilla::Span<const char16_t> aData);
+
+ /**
+ * Notify any devtools listeners after all parse content has been received.
+ */
+ inline void OnContentComplete();
+
+ nsCOMPtr<nsIRequest> mRequest;
+
+ /**
+ * The document title to use if this turns out to be a View Source parser.
+ */
+ nsCString mViewSourceTitle;
+
+ /**
+ * The Unicode decoder
+ */
+ mozilla::UniquePtr<mozilla::Decoder> mUnicodeDecoder;
+
+ /**
+ * BOM sniffing state
+ */
+ eBomState mBomState;
+
+ // encoding-related stuff
+ /**
+ * The source (confidence) of the character encoding in use
+ */
+ nsCharsetSource mCharsetSource;
+
+ nsCharsetSource mEncodingSwitchSource;
+
+ /**
+ * The character encoding in use
+ */
+ NotNull<const Encoding*> mEncoding;
+
+ const Encoding* mNeedsEncodingSwitchTo;
+
+ bool mSeenEligibleMetaCharset;
+
+ bool mChardetEof;
+
+#ifdef DEBUG
+
+ bool mStartedFeedingDetector;
+
+ bool mStartedFeedingDevTools;
+
+#endif
+
+ /**
+ * Whether reparse is forbidden
+ */
+ bool mReparseForbidden;
+
+ /**
+ * Whether the Repair Text Encoding menu item was invoked
+ */
+ bool mForceAutoDetection;
+
+ /**
+ * Whether there was a valid charset parameter on the HTTP layer.
+ */
+ bool mChannelHadCharset;
+
+ /**
+ * We are in the process of looking for <meta charset>
+ */
+ bool mLookingForMetaCharset;
+
+ /**
+ * Whether the byte stream started with ASCII <?
+ */
+ bool mStartsWithLtQuestion;
+
+ /**
+ * If we are viewing XML source and are waiting for a '>' form the network.
+ */
+ bool mLookingForXmlDeclarationForXmlViewSource;
+
+ /**
+ * Whether template has been pushed or head popped within the first 1024
+ * bytes.
+ */
+ bool mTemplatePushedOrHeadPopped;
+
+ // Portable parser objects
+ /**
+ * The first buffer in the pending UTF-16 buffer queue
+ */
+ RefPtr<nsHtml5OwningUTF16Buffer> mFirstBuffer;
+
+ /**
+ * Non-owning pointer to the most recent buffer that contains the most recent
+ * remembered greater-than sign. Used only while mLookingForMetaCharset is
+ * true. While mLookingForMetaCharset is true, mFirstBuffer is not changed and
+ * keeps the whole linked list of buffers alive. This pointer is non-owning to
+ * avoid frequent refcounting.
+ */
+ nsHtml5OwningUTF16Buffer* mGtBuffer;
+
+ int32_t mGtPos;
+
+ /**
+ * The last buffer in the pending UTF-16 buffer queue
+ */
+ nsHtml5OwningUTF16Buffer*
+ mLastBuffer; // weak ref; always points to
+ // a buffer of the size
+ // NS_HTML5_STREAM_PARSER_READ_BUFFER_SIZE
+
+ /**
+ * The first buffer of the document if looking for <meta charset> or
+ * nullptr afterwards.
+ */
+ RefPtr<nsHtml5OwningUTF16Buffer> mFirstBufferOfMetaScan;
+
+ /**
+ * The tree operation executor
+ */
+ nsHtml5TreeOpExecutor* mExecutor;
+
+ /**
+ * Network event target for mExecutor->mDocument
+ */
+ nsCOMPtr<nsISerialEventTarget> mNetworkEventTarget;
+
+ /**
+ * The HTML5 tree builder
+ */
+ mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder;
+
+ /**
+ * The HTML5 tokenizer
+ */
+ mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer;
+
+ /**
+ * Makes sure the main thread can't mess the tokenizer state while it's
+ * tokenizing. This mutex also protects the current speculation.
+ */
+ mozilla::Mutex mTokenizerMutex;
+
+ /**
+ * The scoped atom table
+ */
+ nsHtml5AtomTable mAtomTable;
+
+ /**
+ * The owner parser.
+ */
+ RefPtr<nsHtml5Parser> mOwner;
+
+ /**
+ * Whether the last character tokenized was a carriage return (for CRLF)
+ */
+ bool mLastWasCR;
+
+ /**
+ * For tracking stream life cycle
+ */
+ eHtml5StreamState mStreamState;
+
+ /**
+ * Whether we are speculating.
+ */
+ bool mSpeculating;
+
+ /**
+ * Whether the tokenizer has reached EOF. (Reset when stream rewinded.)
+ */
+ bool mAtEOF;
+
+ /**
+ * The speculations. The mutex protects the nsTArray itself.
+ * To access the queue of current speculation, mTokenizerMutex must be
+ * obtained.
+ * The current speculation is the last element
+ */
+ nsTArray<mozilla::UniquePtr<nsHtml5Speculation>> mSpeculations;
+ mozilla::Mutex mSpeculationMutex;
+
+ /**
+ * Number of times speculation has failed for this parser.
+ */
+ mozilla::Atomic<uint32_t> mSpeculationFailureCount;
+
+ /**
+ * Number of bytes already buffered into mBufferedBytes.
+ */
+ uint32_t mNumBytesBuffered;
+
+ nsTArray<mozilla::Buffer<uint8_t>> mBufferedBytes;
+
+ /**
+ * True to terminate early.
+ */
+ mozilla::Atomic<bool> mTerminated;
+
+ /**
+ * True to release mTokenizerMutex early.
+ */
+ mozilla::Atomic<bool> mInterrupted;
+
+ /**
+ * The thread this stream parser runs on.
+ */
+ nsCOMPtr<nsISerialEventTarget> mEventTarget;
+
+ nsCOMPtr<nsIRunnable> mExecutorFlusher;
+
+ nsCOMPtr<nsIRunnable> mLoadFlusher;
+
+ /**
+ * This runnable is distinct from the regular flushers to
+ * signal the intent of encoding commitment without having to
+ * protect mPendingEncodingCommitment in the executer with a
+ * mutex.
+ */
+ nsCOMPtr<nsIRunnable> mEncodingCommitter;
+
+ /**
+ * The generict detector.
+ */
+ mozilla::UniquePtr<mozilla::EncodingDetector> mDetector;
+
+ /**
+ * The TLD we're loading from or empty if unknown.
+ */
+ nsCString mTLD;
+
+ /**
+ * Whether the initial charset source was kCharsetFromParentFrame
+ */
+ bool mInitialEncodingWasFromParentFrame;
+
+ bool mHasHadErrors;
+
+ bool mDetectorHasSeenNonAscii;
+
+ /**
+ * If true, we are decoding a local file that lacks an encoding
+ * declaration and we are not tokenizing yet.
+ */
+ bool mDecodingLocalFileWithoutTokenizing;
+
+ /**
+ * Whether we are keeping the incoming bytes.
+ */
+ bool mBufferingBytes;
+
+ /**
+ * Timer for flushing tree ops once in a while when not speculating.
+ */
+ nsCOMPtr<nsITimer> mFlushTimer;
+
+ /**
+ * Mutex for protecting access to mFlushTimer (but not for the two
+ * mFlushTimerFoo booleans below).
+ */
+ mozilla::Mutex mFlushTimerMutex;
+
+ /**
+ * Keeps track whether mFlushTimer has been armed. Unfortunately,
+ * nsITimer doesn't enable querying this from the timer itself.
+ */
+ bool mFlushTimerArmed;
+
+ /**
+ * False initially and true after the timer has fired at least once.
+ */
+ bool mFlushTimerEverFired;
+
+ /**
+ * Whether the parser is doing a normal parse, view source or plain text.
+ */
+ eParserMode mMode;
+
+ /**
+ * If the associated docshell is being watched by the devtools, this is
+ * set to the URI associated with the parse. All parse data is sent to the
+ * devtools, along with this URI. This URI is cleared out after the parse has
+ * been marked as completed.
+ */
+ nsCOMPtr<nsIURI> mURIToSendToDevtools;
+
+ /**
+ * If content is being sent to the devtools, an encoded UUID for the parser.
+ */
+ nsString mUUIDForDevtools;
+};
+
+#endif // nsHtml5StreamParser_h
diff --git a/parser/html/nsHtml5StreamParserPtr.h b/parser/html/nsHtml5StreamParserPtr.h
new file mode 100644
index 0000000000..09bb2a0ea7
--- /dev/null
+++ b/parser/html/nsHtml5StreamParserPtr.h
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5StreamParserPtr_h
+#define nsHtml5StreamParserPtr_h
+
+#include "nsHtml5StreamParser.h"
+#include "nsHtml5StreamParserReleaser.h"
+#include "nsThreadUtils.h"
+#include "mozilla/dom/DocGroup.h"
+
+/**
+ * Like nsRefPtr except release is proxied to the main
+ * thread. Mostly copied from nsRefPtr.
+ */
+class nsHtml5StreamParserPtr {
+ private:
+ void assign_with_AddRef(nsHtml5StreamParser* rawPtr) {
+ if (rawPtr) rawPtr->AddRef();
+ assign_assuming_AddRef(rawPtr);
+ }
+ void** begin_assignment() {
+ assign_assuming_AddRef(0);
+ return reinterpret_cast<void**>(&mRawPtr);
+ }
+ void assign_assuming_AddRef(nsHtml5StreamParser* newPtr) {
+ nsHtml5StreamParser* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ if (oldPtr) release(oldPtr);
+ }
+ void release(nsHtml5StreamParser* aPtr) {
+ nsCOMPtr<nsIRunnable> releaser = new nsHtml5StreamParserReleaser(aPtr);
+ if (NS_FAILED(aPtr->DispatchToMain(releaser.forget()))) {
+ NS_WARNING("Failed to dispatch releaser event.");
+ }
+ }
+
+ private:
+ nsHtml5StreamParser* mRawPtr;
+
+ public:
+ ~nsHtml5StreamParserPtr() {
+ if (mRawPtr) release(mRawPtr);
+ }
+ // Constructors
+ nsHtml5StreamParserPtr()
+ : mRawPtr(0)
+ // default constructor
+ {}
+ nsHtml5StreamParserPtr(const nsHtml5StreamParserPtr& aSmartPtr)
+ : mRawPtr(aSmartPtr.mRawPtr)
+ // copy-constructor
+ {
+ if (mRawPtr) mRawPtr->AddRef();
+ }
+ explicit nsHtml5StreamParserPtr(nsHtml5StreamParser* aRawPtr)
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if (mRawPtr) mRawPtr->AddRef();
+ }
+ // Assignment operators
+ nsHtml5StreamParserPtr& operator=(const nsHtml5StreamParserPtr& rhs)
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+ nsHtml5StreamParserPtr& operator=(nsHtml5StreamParser* rhs)
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ return *this;
+ }
+ // Other pointer operators
+ void swap(nsHtml5StreamParserPtr& rhs)
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ nsHtml5StreamParser* temp = rhs.mRawPtr;
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ }
+ void swap(nsHtml5StreamParser*& rhs)
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ nsHtml5StreamParser* temp = rhs;
+ rhs = mRawPtr;
+ mRawPtr = temp;
+ }
+ template <typename I>
+ void forget(I** rhs)
+ // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
+ // Useful to avoid unnecessary AddRef/Release pairs with "out"
+ // parameters where rhs bay be a T** or an I** where I is a base class
+ // of T.
+ {
+ NS_ASSERTION(rhs, "Null pointer passed to forget!");
+ *rhs = mRawPtr;
+ mRawPtr = 0;
+ }
+ nsHtml5StreamParser* get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator
+ nsHtml5StreamParser*() const|. Use |get()| to resolve ambiguity or to get a
+ castable pointer.
+ */
+ {
+ return const_cast<nsHtml5StreamParser*>(mRawPtr);
+ }
+ operator nsHtml5StreamParser*() const
+ /*
+ ...makes an |nsHtml5StreamParserPtr| act like its underlying raw
+ pointer type whenever it is used in a context where a raw pointer is
+ expected. It is this operator that makes an |nsHtml5StreamParserPtr|
+ substitutable for a raw pointer. Prefer the implicit use of this operator
+ to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+ nsHtml5StreamParser* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
+ MOZ_ASSERT(mRawPtr != 0,
+ "You can't dereference a NULL nsHtml5StreamParserPtr with "
+ "operator->().");
+ return get();
+ }
+ nsHtml5StreamParserPtr* get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+ const nsHtml5StreamParserPtr* get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ public:
+ nsHtml5StreamParser& operator*() const {
+ MOZ_ASSERT(mRawPtr != 0,
+ "You can't dereference a NULL nsHtml5StreamParserPtr with "
+ "operator*().");
+ return *get();
+ }
+ nsHtml5StreamParser** StartAssignment() {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return reinterpret_cast<nsHtml5StreamParser**>(begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return reinterpret_cast<nsHtml5StreamParser**>(&mRawPtr);
+#endif
+ }
+};
+
+inline nsHtml5StreamParserPtr* address_of(nsHtml5StreamParserPtr& aPtr) {
+ return aPtr.get_address();
+}
+
+inline const nsHtml5StreamParserPtr* address_of(
+ const nsHtml5StreamParserPtr& aPtr) {
+ return aPtr.get_address();
+}
+
+class nsHtml5StreamParserPtrGetterAddRefs
+/*
+ ...
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+ nsHtml5StreamParserPtr<IFoo> fooP;
+ ...->GetAddRefedPointer(getter_AddRefs(fooP))
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()|
+ instead. When initialized with a |nsHtml5StreamParserPtr|, as in the example
+ above, it returns a |void**|, a |T**|, or an |nsISupports**| as needed, that
+ the outer call (|GetAddRefedPointer| in this case) can fill in. This type
+ should be a nested class inside |nsHtml5StreamParserPtr<T>|.
+ */
+{
+ public:
+ explicit nsHtml5StreamParserPtrGetterAddRefs(
+ nsHtml5StreamParserPtr& aSmartPtr)
+ : mTargetSmartPtr(aSmartPtr) {
+ // nothing else to do
+ }
+ operator void**() {
+ return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
+ }
+ operator nsHtml5StreamParser**() { return mTargetSmartPtr.StartAssignment(); }
+ nsHtml5StreamParser*& operator*() {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsHtml5StreamParserPtr& mTargetSmartPtr;
+};
+
+inline nsHtml5StreamParserPtrGetterAddRefs getter_AddRefs(
+ nsHtml5StreamParserPtr& aSmartPtr)
+/*
+ Used around a |nsHtml5StreamParserPtr| when
+ ...makes the class |nsHtml5StreamParserPtrGetterAddRefs| invisible.
+ */
+{
+ return nsHtml5StreamParserPtrGetterAddRefs(aSmartPtr);
+}
+
+// Comparing an |nsHtml5StreamParserPtr| to |0|
+
+inline bool operator==(const nsHtml5StreamParserPtr& lhs, decltype(nullptr)) {
+ return lhs.get() == nullptr;
+}
+
+inline bool operator==(decltype(nullptr), const nsHtml5StreamParserPtr& rhs) {
+ return nullptr == rhs.get();
+}
+
+inline bool operator!=(const nsHtml5StreamParserPtr& lhs, decltype(nullptr)) {
+ return lhs.get() != nullptr;
+}
+
+inline bool operator!=(decltype(nullptr), const nsHtml5StreamParserPtr& rhs) {
+ return nullptr != rhs.get();
+}
+
+#endif // !defined(nsHtml5StreamParserPtr_h)
diff --git a/parser/html/nsHtml5StreamParserReleaser.h b/parser/html/nsHtml5StreamParserReleaser.h
new file mode 100644
index 0000000000..e1273197d9
--- /dev/null
+++ b/parser/html/nsHtml5StreamParserReleaser.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5StreamParserReleaser_h
+#define nsHtml5StreamParserReleaser_h
+
+#include "nsHtml5StreamParser.h"
+#include "nsThreadUtils.h"
+
+class nsHtml5StreamParserReleaser : public mozilla::Runnable {
+ private:
+ nsHtml5StreamParser* mPtr;
+
+ public:
+ explicit nsHtml5StreamParserReleaser(nsHtml5StreamParser* aPtr)
+ : mozilla::Runnable("nsHtml5StreamParserReleaser"), mPtr(aPtr) {}
+ NS_IMETHOD Run() override {
+ mPtr->Release();
+ return NS_OK;
+ }
+};
+
+#endif // nsHtml5StreamParserReleaser_h
diff --git a/parser/html/nsHtml5String.cpp b/parser/html/nsHtml5String.cpp
new file mode 100644
index 0000000000..5f30869cbb
--- /dev/null
+++ b/parser/html/nsHtml5String.cpp
@@ -0,0 +1,188 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5String.h"
+#include "nsCharTraits.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsUTF8Utils.h"
+
+void nsHtml5String::ToString(nsAString& aString) {
+ switch (GetKind()) {
+ case eStringBuffer:
+ return AsStringBuffer()->ToString(Length(), aString);
+ case eAtom:
+ return AsAtom()->ToString(aString);
+ case eEmpty:
+ aString.Truncate();
+ return;
+ default:
+ aString.Truncate();
+ aString.SetIsVoid(true);
+ return;
+ }
+}
+
+void nsHtml5String::CopyToBuffer(char16_t* aBuffer) const {
+ memcpy(aBuffer, AsPtr(), Length() * sizeof(char16_t));
+}
+
+bool nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const {
+ return !nsCharTraits<char16_t>::compareLowerCaseToASCIINullTerminated(
+ AsPtr(), Length(), aLowerCaseLiteral);
+}
+
+bool nsHtml5String::EqualsASCII(const char* aLiteral) const {
+ return !nsCharTraits<char16_t>::compareASCIINullTerminated(AsPtr(), Length(),
+ aLiteral);
+}
+
+bool nsHtml5String::LowerCaseStartsWithASCII(
+ const char* aLowerCaseLiteral) const {
+ const char* litPtr = aLowerCaseLiteral;
+ const char16_t* strPtr = AsPtr();
+ const char16_t* end = strPtr + Length();
+ char16_t litChar;
+ while ((litChar = *litPtr)) {
+ MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'),
+ "Literal isn't in lower case.");
+ if (strPtr == end) {
+ return false;
+ }
+ char16_t strChar = *strPtr;
+ if (strChar >= 'A' && strChar <= 'Z') {
+ strChar += 0x20;
+ }
+ if (litChar != strChar) {
+ return false;
+ }
+ ++litPtr;
+ ++strPtr;
+ }
+ return true;
+}
+
+bool nsHtml5String::Equals(nsHtml5String aOther) const {
+ MOZ_ASSERT(operator bool());
+ MOZ_ASSERT(aOther);
+ if (Length() != aOther.Length()) {
+ return false;
+ }
+ return !memcmp(AsPtr(), aOther.AsPtr(), Length() * sizeof(char16_t));
+}
+
+nsHtml5String nsHtml5String::Clone() {
+ switch (GetKind()) {
+ case eStringBuffer:
+ AsStringBuffer()->AddRef();
+ break;
+ case eAtom:
+ AsAtom()->AddRef();
+ break;
+ default:
+ break;
+ }
+ return nsHtml5String(mBits);
+}
+
+void nsHtml5String::Release() {
+ switch (GetKind()) {
+ case eStringBuffer:
+ AsStringBuffer()->Release();
+ break;
+ case eAtom:
+ AsAtom()->Release();
+ break;
+ default:
+ break;
+ }
+ mBits = eNull;
+}
+
+// static
+nsHtml5String nsHtml5String::FromBuffer(char16_t* aBuffer, int32_t aLength,
+ nsHtml5TreeBuilder* aTreeBuilder) {
+ if (!aLength) {
+ return nsHtml5String(eEmpty);
+ }
+ // Work with nsStringBuffer directly to make sure that storage is actually
+ // nsStringBuffer and to make sure the allocation strategy matches
+ // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
+ // copy.
+ RefPtr<nsStringBuffer> buffer(
+ nsStringBuffer::Alloc((aLength + 1) * sizeof(char16_t)));
+ if (!buffer) {
+ if (!aTreeBuilder) {
+ MOZ_CRASH("Out of memory.");
+ }
+ aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ buffer = nsStringBuffer::Alloc(2 * sizeof(char16_t));
+ if (!buffer) {
+ MOZ_CRASH(
+ "Out of memory so badly that couldn't even allocate placeholder.");
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ data[0] = 0xFFFD;
+ data[1] = 0;
+ return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
+ eStringBuffer);
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ memcpy(data, aBuffer, aLength * sizeof(char16_t));
+ data[aLength] = 0;
+ return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
+ eStringBuffer);
+}
+
+// static
+nsHtml5String nsHtml5String::FromLiteral(const char* aLiteral) {
+ size_t length = std::strlen(aLiteral);
+ if (!length) {
+ return nsHtml5String(eEmpty);
+ }
+ // Work with nsStringBuffer directly to make sure that storage is actually
+ // nsStringBuffer and to make sure the allocation strategy matches
+ // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
+ // copy.
+ RefPtr<nsStringBuffer> buffer(
+ nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)));
+ if (!buffer) {
+ MOZ_CRASH("Out of memory.");
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ ConvertAsciitoUtf16(mozilla::Span(aLiteral, length),
+ mozilla::Span(data, length));
+ data[length] = 0;
+ return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
+ eStringBuffer);
+}
+
+// static
+nsHtml5String nsHtml5String::FromString(const nsAString& aString) {
+ auto length = aString.Length();
+ if (!length) {
+ return nsHtml5String(eEmpty);
+ }
+ RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aString);
+ if (buffer && (length == buffer->StorageSize() / sizeof(char16_t) - 1)) {
+ return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
+ eStringBuffer);
+ }
+ buffer = nsStringBuffer::Alloc((length + 1) * sizeof(char16_t));
+ if (!buffer) {
+ MOZ_CRASH("Out of memory.");
+ }
+ char16_t* data = reinterpret_cast<char16_t*>(buffer->Data());
+ memcpy(data, aString.BeginReading(), length * sizeof(char16_t));
+ data[length] = 0;
+ return nsHtml5String(reinterpret_cast<uintptr_t>(buffer.forget().take()) |
+ eStringBuffer);
+}
+
+// static
+nsHtml5String nsHtml5String::FromAtom(already_AddRefed<nsAtom> aAtom) {
+ return nsHtml5String(reinterpret_cast<uintptr_t>(aAtom.take()) | eAtom);
+}
+
+// static
+nsHtml5String nsHtml5String::EmptyString() { return nsHtml5String(eEmpty); }
diff --git a/parser/html/nsHtml5String.h b/parser/html/nsHtml5String.h
new file mode 100644
index 0000000000..f725630f9e
--- /dev/null
+++ b/parser/html/nsHtml5String.h
@@ -0,0 +1,139 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5String_h
+#define nsHtml5String_h
+
+#include "nsAtom.h"
+#include "nsString.h"
+#include "nsStringBuffer.h"
+
+class nsHtml5TreeBuilder;
+
+/**
+ * A pass-by-value type that can represent
+ * * nullptr
+ * * empty string
+ * * Non-empty string as exactly-sized (capacity is length) `nsStringBuffer*`
+ * * Non-empty string as an nsAtom*
+ *
+ * Holding or passing this type is as unsafe as holding or passing
+ * `nsStringBuffer*`/`nsAtom*`.
+ */
+class nsHtml5String final {
+ private:
+ static const uintptr_t kKindMask = uintptr_t(3);
+
+ static const uintptr_t kPtrMask = ~kKindMask;
+
+ enum Kind : uintptr_t {
+ eNull = 0,
+ eEmpty = 1,
+ eStringBuffer = 2,
+ eAtom = 3,
+ };
+
+ inline Kind GetKind() const { return (Kind)(mBits & kKindMask); }
+
+ inline nsStringBuffer* AsStringBuffer() const {
+ MOZ_ASSERT(GetKind() == eStringBuffer);
+ return reinterpret_cast<nsStringBuffer*>(mBits & kPtrMask);
+ }
+
+ inline nsAtom* AsAtom() const {
+ MOZ_ASSERT(GetKind() == eAtom);
+ return reinterpret_cast<nsAtom*>(mBits & kPtrMask);
+ }
+
+ inline const char16_t* AsPtr() const {
+ switch (GetKind()) {
+ case eStringBuffer:
+ return reinterpret_cast<char16_t*>(AsStringBuffer()->Data());
+ case eAtom:
+ return AsAtom()->GetUTF16String();
+ default:
+ return nsCharTraits<char16_t>::sEmptyBuffer;
+ }
+ }
+
+ public:
+ /**
+ * Default constructor.
+ */
+ inline nsHtml5String() : nsHtml5String(nullptr) {}
+
+ /**
+ * Constructor from nullptr.
+ */
+ inline MOZ_IMPLICIT nsHtml5String(decltype(nullptr)) : mBits(eNull) {}
+
+ inline uint32_t Length() const {
+ switch (GetKind()) {
+ case eStringBuffer:
+ return (AsStringBuffer()->StorageSize() / sizeof(char16_t) - 1);
+ case eAtom:
+ return AsAtom()->GetLength();
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * False iff the string is logically null
+ */
+ inline MOZ_IMPLICIT operator bool() const { return mBits; }
+
+ /**
+ * Get the underlying nsAtom* or nullptr if this nsHtml5String
+ * does not hold an atom.
+ */
+ inline nsAtom* MaybeAsAtom() {
+ if (GetKind() == eAtom) {
+ return AsAtom();
+ }
+ return nullptr;
+ }
+
+ void ToString(nsAString& aString);
+
+ void CopyToBuffer(char16_t* aBuffer) const;
+
+ bool LowerCaseEqualsASCII(const char* aLowerCaseLiteral) const;
+
+ bool EqualsASCII(const char* aLiteral) const;
+
+ bool LowerCaseStartsWithASCII(const char* aLowerCaseLiteral) const;
+
+ bool Equals(nsHtml5String aOther) const;
+
+ nsHtml5String Clone();
+
+ void Release();
+
+ static nsHtml5String FromBuffer(char16_t* aBuffer, int32_t aLength,
+ nsHtml5TreeBuilder* aTreeBuilder);
+
+ static nsHtml5String FromLiteral(const char* aLiteral);
+
+ static nsHtml5String FromString(const nsAString& aString);
+
+ static nsHtml5String FromAtom(already_AddRefed<nsAtom> aAtom);
+
+ static nsHtml5String EmptyString();
+
+ private:
+ /**
+ * Constructor from raw bits.
+ */
+ explicit nsHtml5String(uintptr_t aBits) : mBits(aBits){};
+
+ /**
+ * Zero if null, one if empty, otherwise tagged pointer
+ * to either nsAtom or nsStringBuffer. The two least-significant
+ * bits are tag bits.
+ */
+ uintptr_t mBits;
+};
+
+#endif // nsHtml5String_h
diff --git a/parser/html/nsHtml5StringParser.cpp b/parser/html/nsHtml5StringParser.cpp
new file mode 100644
index 0000000000..98f643abb4
--- /dev/null
+++ b/parser/html/nsHtml5StringParser.cpp
@@ -0,0 +1,115 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5StringParser.h"
+#include "nsHtml5DependentUTF16Buffer.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5TreeOpExecutor.h"
+#include "nsIContent.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentFragment.h"
+
+using mozilla::dom::Document;
+
+NS_IMPL_ISUPPORTS0(nsHtml5StringParser)
+
+nsHtml5StringParser::nsHtml5StringParser()
+ : mBuilder(new nsHtml5OplessBuilder()),
+ mTreeBuilder(new nsHtml5TreeBuilder(mBuilder)),
+ mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)) {
+ mTokenizer->setInterner(&mAtomTable);
+}
+
+nsHtml5StringParser::~nsHtml5StringParser() {}
+
+nsresult nsHtml5StringParser::ParseFragment(const nsAString& aSourceBuffer,
+ nsIContent* aTargetNode,
+ nsAtom* aContextLocalName,
+ int32_t aContextNamespace,
+ bool aQuirks,
+ bool aPreventScriptExecution) {
+ NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
+
+ Document* doc = aTargetNode->OwnerDoc();
+ nsIURI* uri = doc->GetDocumentURI();
+ NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
+
+ mTreeBuilder->setFragmentContext(aContextLocalName, aContextNamespace,
+ aTargetNode, aQuirks);
+
+#ifdef DEBUG
+ if (!aPreventScriptExecution) {
+ NS_ASSERTION(!aTargetNode->IsInUncomposedDoc(),
+ "If script execution isn't prevented, "
+ "the target node must not be in doc.");
+ NS_ASSERTION(
+ aTargetNode->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE,
+ "If script execution isn't prevented, must parse to DOM fragment.");
+ }
+#endif
+
+ mTreeBuilder->SetPreventScriptExecution(aPreventScriptExecution);
+
+ return Tokenize(aSourceBuffer, doc, true);
+}
+
+nsresult nsHtml5StringParser::ParseDocument(
+ const nsAString& aSourceBuffer, Document* aTargetDoc,
+ bool aScriptingEnabledForNoscriptParsing) {
+ MOZ_ASSERT(!aTargetDoc->GetFirstChild());
+
+ NS_ENSURE_TRUE(aSourceBuffer.Length() <= INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
+
+ mTreeBuilder->setFragmentContext(nullptr, kNameSpaceID_None, nullptr, false);
+
+ mTreeBuilder->SetPreventScriptExecution(true);
+
+ return Tokenize(aSourceBuffer, aTargetDoc,
+ aScriptingEnabledForNoscriptParsing);
+}
+
+nsresult nsHtml5StringParser::Tokenize(
+ const nsAString& aSourceBuffer, Document* aDocument,
+ bool aScriptingEnabledForNoscriptParsing) {
+ nsIURI* uri = aDocument->GetDocumentURI();
+
+ mBuilder->Init(aDocument, uri, nullptr, nullptr);
+
+ mBuilder->SetParser(this);
+ mBuilder->SetNodeInfoManager(aDocument->NodeInfoManager());
+
+ // Mark the parser as *not* broken by passing NS_OK
+ nsresult rv = mBuilder->MarkAsBroken(NS_OK);
+
+ mTreeBuilder->setScriptingEnabled(aScriptingEnabledForNoscriptParsing);
+ mTreeBuilder->setIsSrcdocDocument(aDocument->IsSrcdocDocument());
+ mBuilder->Start();
+ mTokenizer->start();
+ if (!aSourceBuffer.IsEmpty()) {
+ bool lastWasCR = false;
+ nsHtml5DependentUTF16Buffer buffer(aSourceBuffer);
+ while (buffer.hasMore()) {
+ buffer.adjust(lastWasCR);
+ lastWasCR = false;
+ if (buffer.hasMore()) {
+ if (!mTokenizer->EnsureBufferSpace(buffer.getLength())) {
+ rv = mBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
+ break;
+ }
+ lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
+ if (NS_FAILED(rv = mBuilder->IsBroken())) {
+ break;
+ }
+ }
+ }
+ }
+ if (NS_SUCCEEDED(rv)) {
+ mTokenizer->eof();
+ }
+ mTokenizer->end();
+ mBuilder->Finish();
+ mAtomTable.Clear();
+ return rv;
+}
diff --git a/parser/html/nsHtml5StringParser.h b/parser/html/nsHtml5StringParser.h
new file mode 100644
index 0000000000..098a913748
--- /dev/null
+++ b/parser/html/nsHtml5StringParser.h
@@ -0,0 +1,87 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5StringParser_h
+#define nsHtml5StringParser_h
+
+#include "mozilla/UniquePtr.h"
+#include "nsHtml5AtomTable.h"
+#include "nsParserBase.h"
+
+class nsHtml5OplessBuilder;
+class nsHtml5TreeBuilder;
+class nsHtml5Tokenizer;
+class nsIContent;
+namespace mozilla {
+namespace dom {
+class Document;
+}
+} // namespace mozilla
+
+class nsHtml5StringParser : public nsParserBase {
+ public:
+ NS_DECL_ISUPPORTS
+
+ /**
+ * Constructor for use ONLY by nsContentUtils. Others, please call the
+ * nsContentUtils statics that wrap this.
+ */
+ nsHtml5StringParser();
+
+ /**
+ * Invoke the fragment parsing algorithm (innerHTML).
+ * DO NOT CALL from outside nsContentUtils.cpp.
+ *
+ * @param aSourceBuffer the string being set as innerHTML
+ * @param aTargetNode the target container
+ * @param aContextLocalName local name of context node
+ * @param aContextNamespace namespace of context node
+ * @param aQuirks true to make <table> not close <p>
+ * @param aPreventScriptExecution true to prevent scripts from executing;
+ * don't set to false when parsing into a target node that has been bound
+ * to tree.
+ */
+ nsresult ParseFragment(const nsAString& aSourceBuffer,
+ nsIContent* aTargetNode, nsAtom* aContextLocalName,
+ int32_t aContextNamespace, bool aQuirks,
+ bool aPreventScriptExecution);
+
+ /**
+ * Parse an entire HTML document from a source string.
+ * DO NOT CALL from outside nsContentUtils.cpp.
+ *
+ */
+ nsresult ParseDocument(const nsAString& aSourceBuffer,
+ mozilla::dom::Document* aTargetDoc,
+ bool aScriptingEnabledForNoscriptParsing);
+
+ private:
+ virtual ~nsHtml5StringParser();
+
+ nsresult Tokenize(const nsAString& aSourceBuffer,
+ mozilla::dom::Document* aDocument,
+ bool aScriptingEnabledForNoscriptParsing);
+
+ /**
+ * The tree operation executor
+ */
+ RefPtr<nsHtml5OplessBuilder> mBuilder;
+
+ /**
+ * The HTML5 tree builder
+ */
+ const mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder;
+
+ /**
+ * The HTML5 tokenizer
+ */
+ const mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer;
+
+ /**
+ * The scoped atom table
+ */
+ nsHtml5AtomTable mAtomTable;
+};
+
+#endif // nsHtml5StringParser_h
diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp
new file mode 100644
index 0000000000..b5de5a9266
--- /dev/null
+++ b/parser/html/nsHtml5Tokenizer.cpp
@@ -0,0 +1,5153 @@
+/*
+ * Copyright (c) 2005-2007 Henri Sivonen
+ * Copyright (c) 2007-2017 Mozilla Foundation
+ * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla
+ * Foundation, and Opera Software ASA.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit Tokenizer.java instead and regenerate.
+ */
+
+#define nsHtml5Tokenizer_cpp__
+
+#include "jArray.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsAtom.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5Highlighter.h"
+#include "nsHtml5Macros.h"
+#include "nsHtml5NamedCharacters.h"
+#include "nsHtml5NamedCharactersAccel.h"
+#include "nsHtml5String.h"
+#include "nsHtml5TokenizerLoopPolicies.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5Tokenizer.h"
+
+char16_t nsHtml5Tokenizer::LT_GT[] = {'<', '>'};
+char16_t nsHtml5Tokenizer::LT_SOLIDUS[] = {'<', '/'};
+char16_t nsHtml5Tokenizer::RSQB_RSQB[] = {']', ']'};
+char16_t nsHtml5Tokenizer::REPLACEMENT_CHARACTER[] = {0xfffd};
+char16_t nsHtml5Tokenizer::LF[] = {'\n'};
+char16_t nsHtml5Tokenizer::CDATA_LSQB[] = {'C', 'D', 'A', 'T', 'A', '['};
+char16_t nsHtml5Tokenizer::OCTYPE[] = {'o', 'c', 't', 'y', 'p', 'e'};
+char16_t nsHtml5Tokenizer::UBLIC[] = {'u', 'b', 'l', 'i', 'c'};
+char16_t nsHtml5Tokenizer::YSTEM[] = {'y', 's', 't', 'e', 'm'};
+static char16_t const TITLE_ARR_DATA[] = {'t', 'i', 't', 'l', 'e'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::TITLE_ARR = {
+ TITLE_ARR_DATA, MOZ_ARRAY_LENGTH(TITLE_ARR_DATA)};
+static char16_t const SCRIPT_ARR_DATA[] = {'s', 'c', 'r', 'i', 'p', 't'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::SCRIPT_ARR = {
+ SCRIPT_ARR_DATA, MOZ_ARRAY_LENGTH(SCRIPT_ARR_DATA)};
+static char16_t const STYLE_ARR_DATA[] = {'s', 't', 'y', 'l', 'e'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::STYLE_ARR = {
+ STYLE_ARR_DATA, MOZ_ARRAY_LENGTH(STYLE_ARR_DATA)};
+static char16_t const PLAINTEXT_ARR_DATA[] = {'p', 'l', 'a', 'i', 'n',
+ 't', 'e', 'x', 't'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::PLAINTEXT_ARR = {
+ PLAINTEXT_ARR_DATA, MOZ_ARRAY_LENGTH(PLAINTEXT_ARR_DATA)};
+static char16_t const XMP_ARR_DATA[] = {'x', 'm', 'p'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::XMP_ARR = {
+ XMP_ARR_DATA, MOZ_ARRAY_LENGTH(XMP_ARR_DATA)};
+static char16_t const TEXTAREA_ARR_DATA[] = {'t', 'e', 'x', 't',
+ 'a', 'r', 'e', 'a'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::TEXTAREA_ARR = {
+ TEXTAREA_ARR_DATA, MOZ_ARRAY_LENGTH(TEXTAREA_ARR_DATA)};
+static char16_t const IFRAME_ARR_DATA[] = {'i', 'f', 'r', 'a', 'm', 'e'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::IFRAME_ARR = {
+ IFRAME_ARR_DATA, MOZ_ARRAY_LENGTH(IFRAME_ARR_DATA)};
+static char16_t const NOEMBED_ARR_DATA[] = {'n', 'o', 'e', 'm', 'b', 'e', 'd'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOEMBED_ARR = {
+ NOEMBED_ARR_DATA, MOZ_ARRAY_LENGTH(NOEMBED_ARR_DATA)};
+static char16_t const NOSCRIPT_ARR_DATA[] = {'n', 'o', 's', 'c',
+ 'r', 'i', 'p', 't'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOSCRIPT_ARR = {
+ NOSCRIPT_ARR_DATA, MOZ_ARRAY_LENGTH(NOSCRIPT_ARR_DATA)};
+static char16_t const NOFRAMES_ARR_DATA[] = {'n', 'o', 'f', 'r',
+ 'a', 'm', 'e', 's'};
+staticJArray<char16_t, int32_t> nsHtml5Tokenizer::NOFRAMES_ARR = {
+ NOFRAMES_ARR_DATA, MOZ_ARRAY_LENGTH(NOFRAMES_ARR_DATA)};
+
+nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler,
+ bool viewingXmlSource)
+ : tokenHandler(tokenHandler),
+ encodingDeclarationHandler(nullptr),
+ lastCR(false),
+ stateSave(0),
+ returnStateSave(0),
+ index(0),
+ forceQuirks(false),
+ additional('\0'),
+ entCol(0),
+ firstCharKey(0),
+ lo(0),
+ hi(0),
+ candidate(0),
+ charRefBufMark(0),
+ value(0),
+ seenDigits(false),
+ suspendAfterCurrentNonTextToken(false),
+ cstart(0),
+ strBufLen(0),
+ charRefBuf(jArray<char16_t, int32_t>::newJArray(32)),
+ charRefBufLen(0),
+ bmpChar(jArray<char16_t, int32_t>::newJArray(1)),
+ astralChar(jArray<char16_t, int32_t>::newJArray(2)),
+ endTagExpectation(nullptr),
+ endTagExpectationAsArray(nullptr),
+ endTag(false),
+ containsHyphen(false),
+ tagName(nullptr),
+ nonInternedTagName(new nsHtml5ElementName()),
+ attributeName(nullptr),
+ nonInternedAttributeName(new nsHtml5AttributeName()),
+ doctypeName(nullptr),
+ publicIdentifier(nullptr),
+ systemIdentifier(nullptr),
+ attributes(tokenHandler->HasBuilder() ? new nsHtml5HtmlAttributes(0)
+ : nullptr),
+ newAttributesEachTime(!tokenHandler->HasBuilder()),
+ shouldSuspend(false),
+ confident(false),
+ line(0),
+ attributeLine(0),
+ interner(nullptr),
+ viewingXmlSource(viewingXmlSource) {
+ MOZ_COUNT_CTOR(nsHtml5Tokenizer);
+}
+
+void nsHtml5Tokenizer::setInterner(nsHtml5AtomTable* interner) {
+ this->interner = interner;
+}
+
+void nsHtml5Tokenizer::initLocation(nsHtml5String newPublicId,
+ nsHtml5String newSystemId) {
+ this->systemId = newSystemId;
+ this->publicId = newPublicId;
+}
+
+bool nsHtml5Tokenizer::isViewingXmlSource() { return viewingXmlSource; }
+
+void nsHtml5Tokenizer::setState(int32_t specialTokenizerState) {
+ this->stateSave = specialTokenizerState;
+ this->endTagExpectation = nullptr;
+ this->endTagExpectationAsArray = nullptr;
+}
+
+void nsHtml5Tokenizer::setStateAndEndTagExpectation(
+ int32_t specialTokenizerState, nsHtml5ElementName* endTagExpectation) {
+ this->stateSave = specialTokenizerState;
+ this->endTagExpectation = endTagExpectation;
+ endTagExpectationToArray();
+}
+
+void nsHtml5Tokenizer::endTagExpectationToArray() {
+ switch (endTagExpectation->getGroup()) {
+ case nsHtml5TreeBuilder::TITLE: {
+ endTagExpectationAsArray = TITLE_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::SCRIPT: {
+ endTagExpectationAsArray = SCRIPT_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::STYLE: {
+ endTagExpectationAsArray = STYLE_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::PLAINTEXT: {
+ endTagExpectationAsArray = PLAINTEXT_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::XMP: {
+ endTagExpectationAsArray = XMP_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::TEXTAREA: {
+ endTagExpectationAsArray = TEXTAREA_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::IFRAME: {
+ endTagExpectationAsArray = IFRAME_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::NOEMBED: {
+ endTagExpectationAsArray = NOEMBED_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::NOSCRIPT: {
+ endTagExpectationAsArray = NOSCRIPT_ARR;
+ return;
+ }
+ case nsHtml5TreeBuilder::NOFRAMES: {
+ endTagExpectationAsArray = NOFRAMES_ARR;
+ return;
+ }
+ default: {
+ MOZ_ASSERT(false, "Bad end tag expectation.");
+ return;
+ }
+ }
+}
+
+void nsHtml5Tokenizer::setLineNumber(int32_t line) {
+ this->attributeLine = line;
+ this->line = line;
+}
+
+nsHtml5HtmlAttributes* nsHtml5Tokenizer::emptyAttributes() {
+ return nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES;
+}
+
+void nsHtml5Tokenizer::emitOrAppendCharRefBuf(int32_t returnState) {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ appendCharRefBufToStrBuf();
+ } else {
+ if (charRefBufLen > 0) {
+ tokenHandler->characters(charRefBuf, 0, charRefBufLen);
+ charRefBufLen = 0;
+ }
+ }
+}
+
+nsHtml5String nsHtml5Tokenizer::strBufToString() {
+ nsHtml5String str = nsHtml5Portability::newStringFromBuffer(
+ strBuf, 0, strBufLen, tokenHandler,
+ !newAttributesEachTime &&
+ attributeName == nsHtml5AttributeName::ATTR_CLASS);
+ clearStrBufAfterUse();
+ return str;
+}
+
+void nsHtml5Tokenizer::strBufToDoctypeName() {
+ doctypeName =
+ nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen, interner);
+ clearStrBufAfterUse();
+}
+
+void nsHtml5Tokenizer::emitStrBuf() {
+ if (strBufLen > 0) {
+ tokenHandler->characters(strBuf, 0, strBufLen);
+ clearStrBufAfterUse();
+ }
+}
+
+void nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset,
+ int32_t length) {
+ int32_t newLen = nsHtml5Portability::checkedAdd(strBufLen, length);
+ MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient.");
+ if (MOZ_UNLIKELY(strBuf.length < newLen)) {
+ if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) {
+ MOZ_CRASH("Unable to recover from buffer reallocation failure");
+ }
+ }
+ nsHtml5ArrayCopy::arraycopy(buffer, offset, strBuf, strBufLen, length);
+ strBufLen = newLen;
+}
+
+void nsHtml5Tokenizer::emitComment(int32_t provisionalHyphens, int32_t pos) {
+ RememberGt(pos);
+ tokenHandler->comment(strBuf, 0, strBufLen - provisionalHyphens);
+ clearStrBufAfterUse();
+ cstart = pos + 1;
+ suspendIfRequestedAfterCurrentNonTextToken();
+}
+
+void nsHtml5Tokenizer::flushChars(char16_t* buf, int32_t pos) {
+ if (pos > cstart) {
+ tokenHandler->characters(buf, cstart, pos - cstart);
+ }
+ cstart = INT32_MAX;
+}
+
+void nsHtml5Tokenizer::strBufToElementNameString() {
+ if (containsHyphen) {
+ nsAtom* annotationName = nsHtml5ElementName::ELT_ANNOTATION_XML->getName();
+ if (nsHtml5Portability::localEqualsBuffer(annotationName, strBuf,
+ strBufLen)) {
+ tagName = nsHtml5ElementName::ELT_ANNOTATION_XML;
+ } else {
+ nonInternedTagName->setNameForNonInterned(
+ nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen,
+ interner),
+ true);
+ tagName = nonInternedTagName;
+ }
+ } else {
+ tagName =
+ nsHtml5ElementName::elementNameByBuffer(strBuf, strBufLen, interner);
+ if (!tagName) {
+ nonInternedTagName->setNameForNonInterned(
+ nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen,
+ interner),
+ false);
+ tagName = nonInternedTagName;
+ }
+ }
+ containsHyphen = false;
+ clearStrBufAfterUse();
+}
+
+int32_t nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos) {
+ RememberGt(pos);
+ cstart = pos + 1;
+ maybeErrSlashInEndTag(selfClosing);
+ stateSave = nsHtml5Tokenizer::DATA;
+ nsHtml5HtmlAttributes* attrs =
+ (!attributes ? nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES : attributes);
+ if (endTag) {
+ maybeErrAttributesOnEndTag(attrs);
+ if (!viewingXmlSource) {
+ tokenHandler->endTag(tagName);
+ }
+ if (newAttributesEachTime) {
+ delete attributes;
+ attributes = nullptr;
+ }
+ } else {
+ if (viewingXmlSource) {
+ MOZ_ASSERT(newAttributesEachTime);
+ delete attributes;
+ attributes = nullptr;
+ } else {
+ tokenHandler->startTag(tagName, attrs, selfClosing);
+ }
+ }
+ tagName = nullptr;
+ if (newAttributesEachTime) {
+ attributes = nullptr;
+ } else {
+ attributes->clear(0);
+ }
+ suspendIfRequestedAfterCurrentNonTextToken();
+ return stateSave;
+}
+
+void nsHtml5Tokenizer::attributeNameComplete() {
+ attributeName =
+ nsHtml5AttributeName::nameByBuffer(strBuf, strBufLen, interner);
+ if (!attributeName) {
+ nonInternedAttributeName->setNameForNonInterned(
+ nsHtml5Portability::newLocalNameFromBuffer(strBuf, strBufLen,
+ interner));
+ attributeName = nonInternedAttributeName;
+ }
+ clearStrBufAfterUse();
+ if (!attributes) {
+ attributes = new nsHtml5HtmlAttributes(0);
+ }
+ if (attributes->contains(attributeName)) {
+ errDuplicateAttribute();
+ attributeName = nullptr;
+ }
+}
+
+void nsHtml5Tokenizer::addAttributeWithoutValue() {
+ if (attributeName) {
+ attributes->addAttribute(
+ attributeName, nsHtml5Portability::newEmptyString(), attributeLine);
+ attributeName = nullptr;
+ } else {
+ clearStrBufAfterUse();
+ }
+}
+
+void nsHtml5Tokenizer::addAttributeWithValue() {
+ if (attributeName) {
+ nsHtml5String val = strBufToString();
+ if (mViewSource) {
+ mViewSource->MaybeLinkifyAttributeValue(attributeName, val);
+ }
+ attributes->addAttribute(attributeName, val, attributeLine);
+ attributeName = nullptr;
+ } else {
+ clearStrBufAfterUse();
+ }
+}
+
+void nsHtml5Tokenizer::start() {
+ initializeWithoutStarting();
+ tokenHandler->startTokenization(this);
+ line = 0;
+ col = 1;
+ nextCharOnNewLine = true;
+}
+
+bool nsHtml5Tokenizer::tokenizeBuffer(nsHtml5UTF16Buffer* buffer) {
+ int32_t state = stateSave;
+ int32_t returnState = returnStateSave;
+ char16_t c = '\0';
+ shouldSuspend = false;
+ lastCR = false;
+ int32_t start = buffer->getStart();
+ int32_t end = buffer->getEnd();
+ int32_t pos = start - 1;
+ switch (state) {
+ case DATA:
+ case RCDATA:
+ case SCRIPT_DATA:
+ case PLAINTEXT:
+ case RAWTEXT:
+ case CDATA_SECTION:
+ case SCRIPT_DATA_ESCAPED:
+ case SCRIPT_DATA_ESCAPE_START:
+ case SCRIPT_DATA_ESCAPE_START_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_START:
+ case SCRIPT_DATA_DOUBLE_ESCAPED:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_END: {
+ cstart = start;
+ break;
+ }
+ default: {
+ cstart = INT32_MAX;
+ break;
+ }
+ }
+ if (mViewSource) {
+ mViewSource->SetBuffer(buffer);
+ pos = stateLoop<nsHtml5ViewSourcePolicy>(state, c, pos, buffer->getBuffer(),
+ false, returnState,
+ buffer->getEnd());
+ mViewSource->DropBuffer((pos == buffer->getEnd()) ? pos : pos + 1);
+ } else {
+ pos = stateLoop<nsHtml5SilentPolicy>(state, c, pos, buffer->getBuffer(),
+ false, returnState, buffer->getEnd());
+ }
+ if (pos == end) {
+ buffer->setStart(pos);
+ } else {
+ buffer->setStart(pos + 1);
+ }
+ return lastCR;
+}
+
+template <class P>
+int32_t nsHtml5Tokenizer::stateLoop(int32_t state, char16_t c, int32_t pos,
+ char16_t* buf, bool reconsume,
+ int32_t returnState, int32_t endPos) {
+ bool reportedConsecutiveHyphens = false;
+stateloop:
+ for (;;) {
+ switch (state) {
+ case DATA: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '&': {
+ flushChars(buf, pos);
+ MOZ_ASSERT(!charRefBufLen,
+ "charRefBufLen not reset after previous use!");
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\0');
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '<': {
+ flushChars(buf, pos);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::TAG_OPEN, reconsume, pos);
+ NS_HTML5_BREAK(dataloop);
+ }
+ case '\0': {
+ maybeEmitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ dataloop_end:;
+ [[fallthrough]];
+ }
+ case TAG_OPEN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (c >= 'A' && c <= 'Z') {
+ endTag = false;
+ clearStrBufBeforeUse();
+ appendStrBuf((char16_t)(c + 0x20));
+ containsHyphen = false;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::TAG_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(tagopenloop);
+ } else if (c >= 'a' && c <= 'z') {
+ endTag = false;
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ containsHyphen = false;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::TAG_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(tagopenloop);
+ }
+ switch (c) {
+ case '!': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::MARKUP_DECLARATION_OPEN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '/': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CLOSE_TAG_OPEN, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\?': {
+ if (viewingXmlSource) {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::PROCESSING_INSTRUCTION,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ if (P::reportErrors) {
+ errProcessingInstruction();
+ }
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errLtGt();
+ }
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 2);
+ cstart = pos + 1;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ if (P::reportErrors) {
+ errBadCharAfterLt(c);
+ }
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ tagopenloop_end:;
+ [[fallthrough]];
+ }
+ case TAG_NAME: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ strBufToElementNameString();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ strBufToElementNameString();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(tagnameloop);
+ }
+ case '/': {
+ strBufToElementNameString();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ strBufToElementNameString();
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ } else if (c == '-') {
+ containsHyphen = true;
+ }
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ tagnameloop_end:;
+ [[fallthrough]];
+ }
+ case BEFORE_ATTRIBUTE_NAME: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '/': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ case '\"':
+ case '\'':
+ case '<':
+ case '=': {
+ if (P::reportErrors) {
+ errBadCharBeforeAttributeNameOrNull(c);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ }
+ attributeLine = line;
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::ATTRIBUTE_NAME, reconsume,
+ pos);
+ NS_HTML5_BREAK(beforeattributenameloop);
+ }
+ }
+ }
+ beforeattributenameloop_end:;
+ [[fallthrough]];
+ }
+ case ATTRIBUTE_NAME: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ attributeNameComplete();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ attributeNameComplete();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '/': {
+ attributeNameComplete();
+ addAttributeWithoutValue();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '=': {
+ attributeNameComplete();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE,
+ reconsume, pos);
+ NS_HTML5_BREAK(attributenameloop);
+ }
+ case '>': {
+ attributeNameComplete();
+ addAttributeWithoutValue();
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ case '\"':
+ case '\'':
+ case '<': {
+ if (P::reportErrors) {
+ errQuoteOrLtInAttributeNameOrNull(c);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ }
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ attributenameloop_end:;
+ [[fallthrough]];
+ }
+ case BEFORE_ATTRIBUTE_VALUE: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '\"': {
+ attributeLine = line;
+ clearStrBufBeforeUse();
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::ATTRIBUTE_VALUE_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_BREAK(beforeattributevalueloop);
+ }
+ case '&': {
+ attributeLine = line;
+ clearStrBufBeforeUse();
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED,
+ reconsume, pos);
+
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\'': {
+ attributeLine = line;
+ clearStrBufBeforeUse();
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::ATTRIBUTE_VALUE_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errAttributeValueMissing();
+ }
+ addAttributeWithoutValue();
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ case '<':
+ case '=':
+ case '`': {
+ if (P::reportErrors) {
+ errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ attributeLine = line;
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::ATTRIBUTE_VALUE_UNQUOTED,
+ reconsume, pos);
+
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ beforeattributevalueloop_end:;
+ [[fallthrough]];
+ }
+ case ATTRIBUTE_VALUE_DOUBLE_QUOTED: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\"': {
+ addAttributeWithValue();
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_BREAK(attributevaluedoublequotedloop);
+ }
+ case '&': {
+ MOZ_ASSERT(!charRefBufLen,
+ "charRefBufLen not reset after previous use!");
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\"');
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ attributevaluedoublequotedloop_end:;
+ [[fallthrough]];
+ }
+ case AFTER_ATTRIBUTE_VALUE_QUOTED: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '/': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
+ reconsume, pos);
+ NS_HTML5_BREAK(afterattributevaluequotedloop);
+ }
+ case '>': {
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ if (P::reportErrors) {
+ errNoSpaceBetweenAttributes();
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ afterattributevaluequotedloop_end:;
+ [[fallthrough]];
+ }
+ case SELF_CLOSING_START_TAG: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ state =
+ P::transition(mViewSource.get(), emitCurrentTagToken(true, pos),
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ if (P::reportErrors) {
+ errSlashNotFollowedByGt();
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ case ATTRIBUTE_VALUE_UNQUOTED: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ addAttributeWithValue();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ addAttributeWithValue();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '&': {
+ MOZ_ASSERT(!charRefBufLen,
+ "charRefBufLen not reset after previous use!");
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('>');
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ addAttributeWithValue();
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ case '<':
+ case '\"':
+ case '\'':
+ case '=':
+ case '`': {
+ if (P::reportErrors) {
+ errUnquotedAttributeValOrNull(c);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ }
+ case AFTER_ATTRIBUTE_NAME: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '/': {
+ addAttributeWithoutValue();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '=': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_VALUE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ addAttributeWithoutValue();
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos), reconsume,
+ pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ case '\"':
+ case '\'':
+ case '<': {
+ if (P::reportErrors) {
+ errQuoteOrLtInAttributeNameOrNull(c);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ addAttributeWithoutValue();
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ }
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::ATTRIBUTE_NAME, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case MARKUP_DECLARATION_OPEN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::MARKUP_DECLARATION_HYPHEN,
+ reconsume, pos);
+ NS_HTML5_BREAK(markupdeclarationopenloop);
+ }
+ case 'd':
+ case 'D': {
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ index = 0;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::MARKUP_DECLARATION_OCTYPE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '[': {
+ if (tokenHandler->cdataSectionAllowed()) {
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ index = 0;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CDATA_START, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ if (P::reportErrors) {
+ errBogusComment();
+ }
+ clearStrBufBeforeUse();
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ markupdeclarationopenloop_end:;
+ [[fallthrough]];
+ }
+ case MARKUP_DECLARATION_HYPHEN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ clearStrBufAfterOneHyphen();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_START, reconsume,
+ pos);
+ NS_HTML5_BREAK(markupdeclarationhyphenloop);
+ }
+ default: {
+ if (P::reportErrors) {
+ errBogusComment();
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ markupdeclarationhyphenloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT_START: {
+ reportedConsecutiveHyphens = false;
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_START_DASH,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errPrematureEndOfComment();
+ }
+ emitComment(0, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(commentstartloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(commentstartloop);
+ }
+ }
+ }
+ commentstartloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_END_DASH,
+ reconsume, pos);
+ NS_HTML5_BREAK(commentloop);
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ commentloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT_END_DASH: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ appendStrBuf(c);
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_END, reconsume, pos);
+ NS_HTML5_BREAK(commentenddashloop);
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ commentenddashloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT_END: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ emitComment(2, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '-': {
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ continue;
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ adjustDoubleHyphenAndAppendToStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ adjustDoubleHyphenAndAppendToStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '!': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_END_BANG,
+ reconsume, pos);
+ NS_HTML5_BREAK(commentendloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ commentendloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT_END_BANG: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ emitComment(3, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '-': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_END_DASH,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case COMMENT_LESSTHAN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '!': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG,
+ reconsume, pos);
+ NS_HTML5_BREAK(commentlessthanloop);
+ }
+ case '<': {
+ appendStrBuf(c);
+ continue;
+ }
+ case '-': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_END_DASH,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ commentlessthanloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT_LESSTHAN_BANG: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ appendStrBuf(c);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG_DASH, reconsume, pos);
+ NS_HTML5_BREAK(commentlessthanbangloop);
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ commentlessthanbangloop_end:;
+ [[fallthrough]];
+ }
+ case COMMENT_LESSTHAN_BANG_DASH: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ appendStrBuf(c);
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN_BANG_DASH_DASH,
+ reconsume, pos);
+ break;
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ [[fallthrough]];
+ }
+ case COMMENT_LESSTHAN_BANG_DASH_DASH: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ appendStrBuf(c);
+ emitComment(3, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '-': {
+ if (P::reportErrors) {
+ errNestedComment();
+ }
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state =
+ P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT_END,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ c = '\n';
+ silentCarriageReturn();
+ if (P::reportErrors) {
+ errNestedComment();
+ }
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ if (P::reportErrors) {
+ errNestedComment();
+ }
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '!': {
+ if (P::reportErrors) {
+ errNestedComment();
+ }
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_END_BANG, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ if (P::reportErrors) {
+ errNestedComment();
+ }
+ adjustDoubleHyphenAndAppendToStrBufAndErr(
+ c, reportedConsecutiveHyphens);
+ reportedConsecutiveHyphens = true;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ case COMMENT_START_DASH: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ appendStrBuf(c);
+ state =
+ P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT_END,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errPrematureEndOfComment();
+ }
+ emitComment(1, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '<': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::COMMENT_LESSTHAN, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::COMMENT,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ case CDATA_START: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (index < 6) {
+ if (c == nsHtml5Tokenizer::CDATA_LSQB[index]) {
+ appendStrBuf(c);
+ } else {
+ if (P::reportErrors) {
+ errBogusComment();
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ index++;
+ continue;
+ } else {
+ clearStrBufAfterUse();
+ cstart = pos;
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CDATA_SECTION, reconsume, pos);
+ break;
+ }
+ }
+ [[fallthrough]];
+ }
+ case CDATA_SECTION: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case ']': {
+ flushChars(buf, pos);
+ state =
+ P::transition(mViewSource.get(), nsHtml5Tokenizer::CDATA_RSQB,
+ reconsume, pos);
+ NS_HTML5_BREAK(cdatasectionloop);
+ }
+ case '\0': {
+ maybeEmitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ cdatasectionloop_end:;
+ [[fallthrough]];
+ }
+ case CDATA_RSQB: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case ']': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CDATA_RSQB_RSQB, reconsume,
+ pos);
+ break;
+ }
+ default: {
+ tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CDATA_SECTION, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ [[fallthrough]];
+ }
+ case CDATA_RSQB_RSQB: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case ']': {
+ tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1);
+ continue;
+ }
+ case '>': {
+ cstart = pos + 1;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ suspendIfRequestedAfterCurrentNonTextToken();
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 2);
+ cstart = pos;
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CDATA_SECTION, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case ATTRIBUTE_VALUE_SINGLE_QUOTED: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\'': {
+ addAttributeWithValue();
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_ATTRIBUTE_VALUE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '&': {
+ MOZ_ASSERT(!charRefBufLen,
+ "charRefBufLen not reset after previous use!");
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\'');
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
+ reconsume, pos);
+ NS_HTML5_BREAK(attributevaluesinglequotedloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ attributevaluesinglequotedloop_end:;
+ [[fallthrough]];
+ }
+ case CONSUME_CHARACTER_REFERENCE: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\f':
+ case '<':
+ case '&':
+ case '\0':
+ case ';': {
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '#': {
+ appendCharRefBuf('#');
+ state =
+ P::transition(mViewSource.get(), nsHtml5Tokenizer::CONSUME_NCR,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ if (c == additional) {
+ emitOrAppendCharRefBuf(returnState);
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ if (c >= 'a' && c <= 'z') {
+ firstCharKey = c - 'a' + 26;
+ } else if (c >= 'A' && c <= 'Z') {
+ firstCharKey = c - 'A';
+ } else {
+ if (c == ';') {
+ if (P::reportErrors) {
+ errNoNamedCharacterMatch();
+ }
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ appendCharRefBuf(c);
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CHARACTER_REFERENCE_HILO_LOOKUP,
+ reconsume, pos);
+ break;
+ }
+ }
+ [[fallthrough]];
+ }
+ case CHARACTER_REFERENCE_HILO_LOOKUP: {
+ {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ int32_t hilo = 0;
+ if (c <= 'z') {
+ const int32_t* row = nsHtml5NamedCharactersAccel::HILO_ACCEL[c];
+ if (row) {
+ hilo = row[firstCharKey];
+ }
+ }
+ if (!hilo) {
+ if (c == ';') {
+ if (P::reportErrors) {
+ errNoNamedCharacterMatch();
+ }
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ appendCharRefBuf(c);
+ lo = hilo & 0xFFFF;
+ hi = hilo >> 16;
+ entCol = -1;
+ candidate = -1;
+ charRefBufMark = 0;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CHARACTER_REFERENCE_TAIL,
+ reconsume, pos);
+ }
+ [[fallthrough]];
+ }
+ case CHARACTER_REFERENCE_TAIL: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ entCol++;
+ for (;;) {
+ if (hi < lo) {
+ NS_HTML5_BREAK(outer);
+ }
+ if (entCol == nsHtml5NamedCharacters::NAMES[lo].length()) {
+ candidate = lo;
+ charRefBufMark = charRefBufLen;
+ lo++;
+ } else if (entCol > nsHtml5NamedCharacters::NAMES[lo].length()) {
+ NS_HTML5_BREAK(outer);
+ } else if (c > nsHtml5NamedCharacters::NAMES[lo].charAt(entCol)) {
+ lo++;
+ } else {
+ NS_HTML5_BREAK(loloop);
+ }
+ }
+ loloop_end:;
+ for (;;) {
+ if (hi < lo) {
+ NS_HTML5_BREAK(outer);
+ }
+ if (entCol == nsHtml5NamedCharacters::NAMES[hi].length()) {
+ NS_HTML5_BREAK(hiloop);
+ }
+ if (entCol > nsHtml5NamedCharacters::NAMES[hi].length()) {
+ NS_HTML5_BREAK(outer);
+ } else if (c < nsHtml5NamedCharacters::NAMES[hi].charAt(entCol)) {
+ hi--;
+ } else {
+ NS_HTML5_BREAK(hiloop);
+ }
+ }
+ hiloop_end:;
+ if (c == ';') {
+ if (entCol + 1 == nsHtml5NamedCharacters::NAMES[lo].length()) {
+ candidate = lo;
+ charRefBufMark = charRefBufLen;
+ }
+ NS_HTML5_BREAK(outer);
+ }
+ if (hi < lo) {
+ NS_HTML5_BREAK(outer);
+ }
+ appendCharRefBuf(c);
+ continue;
+ }
+ outer_end:;
+ if (candidate == -1) {
+ if (c == ';') {
+ if (P::reportErrors) {
+ errNoNamedCharacterMatch();
+ }
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ } else {
+ const nsHtml5CharacterName& candidateName =
+ nsHtml5NamedCharacters::NAMES[candidate];
+ if (!candidateName.length() ||
+ candidateName.charAt(candidateName.length() - 1) != ';') {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ char16_t ch;
+ if (charRefBufMark == charRefBufLen) {
+ ch = c;
+ } else {
+ ch = charRefBuf[charRefBufMark];
+ }
+ if (ch == '=' || (ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+ if (c == ';') {
+ if (P::reportErrors) {
+ errNoNamedCharacterMatch();
+ }
+ }
+ appendCharRefBufToStrBuf();
+ reconsume = true;
+ state = P::transition(mViewSource.get(), returnState, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ if (P::reportErrors) {
+ errUnescapedAmpersandInterpretedAsCharacterReference();
+ }
+ } else {
+ if (P::reportErrors) {
+ errNotSemicolonTerminated();
+ }
+ }
+ }
+ P::completedNamedCharacterReference(mViewSource.get());
+ const char16_t* val = nsHtml5NamedCharacters::VALUES[candidate];
+ if (!val[1]) {
+ emitOrAppendOne(val, returnState);
+ } else {
+ emitOrAppendTwo(val, returnState);
+ }
+ if (charRefBufMark < charRefBufLen) {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ appendStrBuf(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ } else {
+ tokenHandler->characters(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ }
+ }
+ bool earlyBreak = (c == ';' && charRefBufMark == charRefBufLen);
+ charRefBufLen = 0;
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = earlyBreak ? pos + 1 : pos;
+ }
+ reconsume = !earlyBreak;
+ state = P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ case CONSUME_NCR: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ value = 0;
+ seenDigits = false;
+ switch (c) {
+ case 'x':
+ case 'X': {
+ appendCharRefBuf(c);
+ state =
+ P::transition(mViewSource.get(), nsHtml5Tokenizer::HEX_NCR_LOOP,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::DECIMAL_NRC_LOOP, reconsume,
+ pos);
+ break;
+ }
+ }
+ [[fallthrough]];
+ }
+ case DECIMAL_NRC_LOOP: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ MOZ_ASSERT(value >= 0, "value must not become negative.");
+ if (c >= '0' && c <= '9') {
+ seenDigits = true;
+ if (value <= 0x10FFFF) {
+ value *= 10;
+ value += c - '0';
+ }
+ continue;
+ } else if (c == ';') {
+ if (seenDigits) {
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos + 1;
+ }
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::HANDLE_NCR_VALUE,
+ reconsume, pos);
+ NS_HTML5_BREAK(decimalloop);
+ } else {
+ if (P::reportErrors) {
+ errNoDigitsInNCR();
+ }
+ appendCharRefBuf(';');
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos + 1;
+ }
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ } else {
+ if (!seenDigits) {
+ if (P::reportErrors) {
+ errNoDigitsInNCR();
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ } else {
+ if (P::reportErrors) {
+ errCharRefLacksSemicolon();
+ }
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::HANDLE_NCR_VALUE,
+ reconsume, pos);
+ NS_HTML5_BREAK(decimalloop);
+ }
+ }
+ }
+ decimalloop_end:;
+ [[fallthrough]];
+ }
+ case HANDLE_NCR_VALUE: {
+ charRefBufLen = 0;
+ handleNcrValue(returnState);
+ state = P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case HEX_NCR_LOOP: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ MOZ_ASSERT(value >= 0, "value must not become negative.");
+ if (c >= '0' && c <= '9') {
+ seenDigits = true;
+ if (value <= 0x10FFFF) {
+ value *= 16;
+ value += c - '0';
+ }
+ continue;
+ } else if (c >= 'A' && c <= 'F') {
+ seenDigits = true;
+ if (value <= 0x10FFFF) {
+ value *= 16;
+ value += c - 'A' + 10;
+ }
+ continue;
+ } else if (c >= 'a' && c <= 'f') {
+ seenDigits = true;
+ if (value <= 0x10FFFF) {
+ value *= 16;
+ value += c - 'a' + 10;
+ }
+ continue;
+ } else if (c == ';') {
+ if (seenDigits) {
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos + 1;
+ }
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::HANDLE_NCR_VALUE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ } else {
+ if (P::reportErrors) {
+ errNoDigitsInNCR();
+ }
+ appendCharRefBuf(';');
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos + 1;
+ }
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ } else {
+ if (!seenDigits) {
+ if (P::reportErrors) {
+ errNoDigitsInNCR();
+ }
+ emitOrAppendCharRefBuf(returnState);
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ } else {
+ if (P::reportErrors) {
+ errCharRefLacksSemicolon();
+ }
+ if (!(returnState & DATA_AND_RCDATA_MASK)) {
+ cstart = pos;
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::HANDLE_NCR_VALUE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case PLAINTEXT: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\0': {
+ emitPlaintextReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ }
+ case CLOSE_TAG_OPEN: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ if (P::reportErrors) {
+ errLtSlashGt();
+ }
+ cstart = pos + 1;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ silentCarriageReturn();
+ if (P::reportErrors) {
+ errGarbageAfterLtSlash();
+ }
+ clearStrBufBeforeUse();
+ appendStrBuf('\n');
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ if (P::reportErrors) {
+ errGarbageAfterLtSlash();
+ }
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ }
+ if (c >= 'a' && c <= 'z') {
+ endTag = true;
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ containsHyphen = false;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::TAG_NAME, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ } else {
+ if (P::reportErrors) {
+ errGarbageAfterLtSlash();
+ }
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case RCDATA: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '&': {
+ flushChars(buf, pos);
+ MOZ_ASSERT(!charRefBufLen,
+ "charRefBufLen not reset after previous use!");
+ appendCharRefBuf(c);
+ setAdditionalAndRememberAmpersandLocation('\0');
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::CONSUME_CHARACTER_REFERENCE,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '<': {
+ flushChars(buf, pos);
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ }
+ case RAWTEXT: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '<': {
+ flushChars(buf, pos);
+ returnState = state;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::RAWTEXT_RCDATA_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_BREAK(rawtextloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ rawtextloop_end:;
+ [[fallthrough]];
+ }
+ case RAWTEXT_RCDATA_LESS_THAN_SIGN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '/': {
+ index = 0;
+ clearStrBufBeforeUse();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::NON_DATA_END_TAG_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(rawtextrcdatalessthansignloop);
+ }
+ default: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ rawtextrcdatalessthansignloop_end:;
+ [[fallthrough]];
+ }
+ case NON_DATA_END_TAG_NAME: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (!endTagExpectationAsArray) {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
+ cstart = pos;
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ } else if (index < endTagExpectationAsArray.length) {
+ char16_t e = endTagExpectationAsArray[index];
+ char16_t folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != e) {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
+ emitStrBuf();
+ cstart = pos;
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(), returnState, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ appendStrBuf(c);
+ index++;
+ continue;
+ } else {
+ endTag = true;
+ tagName = endTagExpectation;
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ clearStrBufAfterUse();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ clearStrBufAfterUse();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_ATTRIBUTE_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '/': {
+ clearStrBufAfterUse();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SELF_CLOSING_START_TAG,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ clearStrBufAfterUse();
+ state = P::transition(mViewSource.get(),
+ emitCurrentTagToken(false, pos),
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
+ emitStrBuf();
+ cstart = pos;
+ reconsume = true;
+ state = P::transition(mViewSource.get(), returnState, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ }
+ case BOGUS_COMMENT: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '>': {
+ emitComment(0, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '-': {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT_HYPHEN,
+ reconsume, pos);
+ NS_HTML5_BREAK(boguscommentloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ boguscommentloop_end:;
+ [[fallthrough]];
+ }
+ case BOGUS_COMMENT_HYPHEN: {
+ boguscommenthyphenloop:
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ emitComment(0, pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '-': {
+ appendSecondHyphenToBogusComment();
+ NS_HTML5_CONTINUE(boguscommenthyphenloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case SCRIPT_DATA: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '<': {
+ flushChars(buf, pos);
+ returnState = state;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_LESS_THAN_SIGN, reconsume, pos);
+ NS_HTML5_BREAK(scriptdataloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ scriptdataloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_LESS_THAN_SIGN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '/': {
+ index = 0;
+ clearStrBufBeforeUse();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::NON_DATA_END_TAG_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '!': {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ cstart = pos;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPE_START,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdatalessthansignloop);
+ }
+ default: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdatalessthansignloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_ESCAPE_START: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPE_START_DASH,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdataescapestartloop);
+ }
+ default: {
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdataescapestartloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_ESCAPE_START_DASH: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdataescapestartdashloop);
+ }
+ default: {
+ reconsume = true;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdataescapestartdashloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_ESCAPED_DASH_DASH: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ continue;
+ }
+ case '<': {
+ flushChars(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdataescapeddashdashloop);
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdataescapeddashdashloop);
+ }
+ }
+ }
+ scriptdataescapeddashdashloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_ESCAPED: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '-': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdataescapedloop);
+ }
+ case '<': {
+ flushChars(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ scriptdataescapedloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_ESCAPED_DASH: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_DASH_DASH,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '<': {
+ flushChars(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdataescapeddashloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdataescapeddashloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '/': {
+ index = 0;
+ clearStrBufBeforeUse();
+ returnState = nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::NON_DATA_END_TAG_NAME,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case 'S':
+ case 's': {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ cstart = pos;
+ index = 1;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPE_START, reconsume,
+ pos);
+ NS_HTML5_BREAK(scriptdataescapedlessthanloop);
+ }
+ default: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ cstart = pos;
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdataescapedlessthanloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_DOUBLE_ESCAPE_START: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ MOZ_ASSERT(index > 0);
+ if (index < 6) {
+ char16_t folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != nsHtml5Tokenizer::SCRIPT_ARR[index]) {
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ index++;
+ continue;
+ }
+ switch (c) {
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f':
+ case '/':
+ case '>': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_BREAK(scriptdatadoubleescapestartloop);
+ }
+ default: {
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdatadoubleescapestartloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_DOUBLE_ESCAPED: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '-': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_DASH, reconsume,
+ pos);
+ NS_HTML5_BREAK(scriptdatadoubleescapedloop);
+ }
+ case '<': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ continue;
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ scriptdatadoubleescapedloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdatadoubleescapeddashloop);
+ }
+ case '<': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdatadoubleescapeddashloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '-': {
+ continue;
+ }
+ case '<': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdatadoubleescapeddashdashloop);
+ }
+ case '>': {
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ emitReplacementCharacter(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdatadoubleescapeddashdashloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '/': {
+ index = 0;
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPE_END,
+ reconsume, pos);
+ NS_HTML5_BREAK(scriptdatadoubleescapedlessthanloop);
+ }
+ default: {
+ reconsume = true;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ scriptdatadoubleescapedlessthanloop_end:;
+ [[fallthrough]];
+ }
+ case SCRIPT_DATA_DOUBLE_ESCAPE_END: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (index < 6) {
+ char16_t folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != nsHtml5Tokenizer::SCRIPT_ARR[index]) {
+ reconsume = true;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ index++;
+ continue;
+ }
+ switch (c) {
+ case '\r': {
+ emitCarriageReturn(buf, pos);
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f':
+ case '/':
+ case '>': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_ESCAPED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ reconsume = true;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::SCRIPT_DATA_DOUBLE_ESCAPED, reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ case MARKUP_DECLARATION_OCTYPE: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (index < 6) {
+ char16_t folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded == nsHtml5Tokenizer::OCTYPE[index]) {
+ appendStrBuf(c);
+ } else {
+ if (P::reportErrors) {
+ errBogusComment();
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_COMMENT, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ index++;
+ continue;
+ } else {
+ reconsume = true;
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DOCTYPE,
+ reconsume, pos);
+ NS_HTML5_BREAK(markupdeclarationdoctypeloop);
+ }
+ }
+ markupdeclarationdoctypeloop_end:;
+ [[fallthrough]];
+ }
+ case DOCTYPE: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ initDoctypeFields();
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(doctypeloop);
+ }
+ default: {
+ if (P::reportErrors) {
+ errMissingSpaceBeforeDoctypeName();
+ }
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(doctypeloop);
+ }
+ }
+ }
+ doctypeloop_end:;
+ [[fallthrough]];
+ }
+ case BEFORE_DOCTYPE_NAME: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errNamelessDoctype();
+ }
+ forceQuirks = true;
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x20;
+ }
+ clearStrBufBeforeUse();
+ appendStrBuf(c);
+ state =
+ P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_NAME, reconsume, pos);
+ NS_HTML5_BREAK(beforedoctypenameloop);
+ }
+ }
+ }
+ beforedoctypenameloop_end:;
+ [[fallthrough]];
+ }
+ case DOCTYPE_NAME: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ strBufToDoctypeName();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ strBufToDoctypeName();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_NAME,
+ reconsume, pos);
+ NS_HTML5_BREAK(doctypenameloop);
+ }
+ case '>': {
+ strBufToDoctypeName();
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ if (c >= 'A' && c <= 'Z') {
+ c += 0x0020;
+ }
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ doctypenameloop_end:;
+ [[fallthrough]];
+ }
+ case AFTER_DOCTYPE_NAME: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '>': {
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case 'p':
+ case 'P': {
+ index = 0;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_UBLIC, reconsume,
+ pos);
+ NS_HTML5_BREAK(afterdoctypenameloop);
+ }
+ case 's':
+ case 'S': {
+ index = 0;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_YSTEM, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ afterdoctypenameloop_end:;
+ [[fallthrough]];
+ }
+ case DOCTYPE_UBLIC: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (index < 5) {
+ char16_t folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != nsHtml5Tokenizer::UBLIC[index]) {
+ bogusDoctype();
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ index++;
+ continue;
+ } else {
+ reconsume = true;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_KEYWORD, reconsume, pos);
+ NS_HTML5_BREAK(doctypeublicloop);
+ }
+ }
+ doctypeublicloop_end:;
+ [[fallthrough]];
+ }
+ case AFTER_DOCTYPE_PUBLIC_KEYWORD: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_BREAK(afterdoctypepublickeywordloop);
+ }
+ case '\"': {
+ if (P::reportErrors) {
+ errNoSpaceBetweenDoctypePublicKeywordAndQuote();
+ }
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\'': {
+ if (P::reportErrors) {
+ errNoSpaceBetweenDoctypePublicKeywordAndQuote();
+ }
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errExpectedPublicId();
+ }
+ forceQuirks = true;
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ afterdoctypepublickeywordloop_end:;
+ [[fallthrough]];
+ }
+ case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '\"': {
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_BREAK(beforedoctypepublicidentifierloop);
+ }
+ case '\'': {
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errExpectedPublicId();
+ }
+ forceQuirks = true;
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ beforedoctypepublicidentifierloop_end:;
+ [[fallthrough]];
+ }
+ case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\"': {
+ publicIdentifier = strBufToString();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_BREAK(doctypepublicidentifierdoublequotedloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errGtInPublicId();
+ }
+ forceQuirks = true;
+ publicIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ doctypepublicidentifierdoublequotedloop_end:;
+ [[fallthrough]];
+ }
+ case AFTER_DOCTYPE_PUBLIC_IDENTIFIER: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::
+ BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS,
+ reconsume, pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::
+ BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS,
+ reconsume, pos);
+ NS_HTML5_BREAK(afterdoctypepublicidentifierloop);
+ }
+ case '>': {
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\"': {
+ if (P::reportErrors) {
+ errNoSpaceBetweenPublicAndSystemIds();
+ }
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\'': {
+ if (P::reportErrors) {
+ errNoSpaceBetweenPublicAndSystemIds();
+ }
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ afterdoctypepublicidentifierloop_end:;
+ [[fallthrough]];
+ }
+ case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '>': {
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\"': {
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_BREAK(betweendoctypepublicandsystemidentifiersloop);
+ }
+ case '\'': {
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ betweendoctypepublicandsystemidentifiersloop_end:;
+ [[fallthrough]];
+ }
+ case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\"': {
+ systemIdentifier = strBufToString();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_BREAK(doctypesystemidentifierdoublequotedloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errGtInSystemId();
+ }
+ forceQuirks = true;
+ systemIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ doctypesystemidentifierdoublequotedloop_end:;
+ [[fallthrough]];
+ }
+ case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '>': {
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctypeWithoutQuirks();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_BREAK(afterdoctypesystemidentifierloop);
+ }
+ }
+ }
+ afterdoctypesystemidentifierloop_end:;
+ [[fallthrough]];
+ }
+ case BOGUS_DOCTYPE: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '>': {
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ }
+ case DOCTYPE_YSTEM: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ if (index < 5) {
+ char16_t folded = c;
+ if (c >= 'A' && c <= 'Z') {
+ folded += 0x20;
+ }
+ if (folded != nsHtml5Tokenizer::YSTEM[index]) {
+ bogusDoctype();
+ reconsume = true;
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ index++;
+ NS_HTML5_CONTINUE(stateloop);
+ } else {
+ reconsume = true;
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_KEYWORD, reconsume, pos);
+ NS_HTML5_BREAK(doctypeystemloop);
+ }
+ }
+ doctypeystemloop_end:;
+ [[fallthrough]];
+ }
+ case AFTER_DOCTYPE_SYSTEM_KEYWORD: {
+ for (;;) {
+ if (reconsume) {
+ reconsume = false;
+ } else {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ }
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_BREAK(afterdoctypesystemkeywordloop);
+ }
+ case '\"': {
+ if (P::reportErrors) {
+ errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
+ }
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\'': {
+ if (P::reportErrors) {
+ errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
+ }
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errExpectedPublicId();
+ }
+ forceQuirks = true;
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ afterdoctypesystemkeywordloop_end:;
+ [[fallthrough]];
+ }
+ case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\r': {
+ silentCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ silentLineFeed();
+ [[fallthrough]];
+ }
+ case ' ':
+ case '\t':
+ case '\f': {
+ continue;
+ }
+ case '\"': {
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\'': {
+ clearStrBufBeforeUse();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED,
+ reconsume, pos);
+ NS_HTML5_BREAK(beforedoctypesystemidentifierloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errExpectedSystemId();
+ }
+ forceQuirks = true;
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ bogusDoctype();
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::BOGUS_DOCTYPE, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ beforedoctypesystemidentifierloop_end:;
+ [[fallthrough]];
+ }
+ case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\'': {
+ systemIdentifier = strBufToString();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_SYSTEM_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errGtInSystemId();
+ }
+ forceQuirks = true;
+ systemIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ }
+ case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\'': {
+ publicIdentifier = strBufToString();
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::AFTER_DOCTYPE_PUBLIC_IDENTIFIER, reconsume,
+ pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '>': {
+ if (P::reportErrors) {
+ errGtInPublicId();
+ }
+ forceQuirks = true;
+ publicIdentifier = strBufToString();
+ emitDoctypeToken(pos);
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ case '\r': {
+ appendStrBufCarriageReturn();
+ NS_HTML5_BREAK(stateloop);
+ }
+ case '\n': {
+ appendStrBufLineFeed();
+ continue;
+ }
+ case '\0': {
+ c = 0xfffd;
+ [[fallthrough]];
+ }
+ default: {
+ appendStrBuf(c);
+ continue;
+ }
+ }
+ }
+ }
+ case PROCESSING_INSTRUCTION: {
+ for (;;) {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '\?': {
+ state = P::transition(
+ mViewSource.get(),
+ nsHtml5Tokenizer::PROCESSING_INSTRUCTION_QUESTION_MARK,
+ reconsume, pos);
+ NS_HTML5_BREAK(processinginstructionloop);
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ processinginstructionloop_end:;
+ [[fallthrough]];
+ }
+ case PROCESSING_INSTRUCTION_QUESTION_MARK: {
+ if (++pos == endPos) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ c = checkChar(buf, pos);
+ switch (c) {
+ case '>': {
+ state = P::transition(mViewSource.get(), nsHtml5Tokenizer::DATA,
+ reconsume, pos);
+ suspendIfRequestedAfterCurrentNonTextToken();
+ if (shouldSuspend) {
+ NS_HTML5_BREAK(stateloop);
+ }
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ default: {
+ state = P::transition(mViewSource.get(),
+ nsHtml5Tokenizer::PROCESSING_INSTRUCTION,
+ reconsume, pos);
+ NS_HTML5_CONTINUE(stateloop);
+ }
+ }
+ }
+ }
+ }
+stateloop_end:;
+ flushChars(buf, pos);
+ stateSave = state;
+ returnStateSave = returnState;
+ return pos;
+}
+
+void nsHtml5Tokenizer::initDoctypeFields() {
+ clearStrBufAfterUse();
+ doctypeName = nullptr;
+ if (systemIdentifier) {
+ systemIdentifier.Release();
+ systemIdentifier = nullptr;
+ }
+ if (publicIdentifier) {
+ publicIdentifier.Release();
+ publicIdentifier = nullptr;
+ }
+ forceQuirks = false;
+}
+
+void nsHtml5Tokenizer::emitCarriageReturn(char16_t* buf, int32_t pos) {
+ silentCarriageReturn();
+ flushChars(buf, pos);
+ tokenHandler->characters(nsHtml5Tokenizer::LF, 0, 1);
+ cstart = INT32_MAX;
+}
+
+void nsHtml5Tokenizer::emitReplacementCharacter(char16_t* buf, int32_t pos) {
+ flushChars(buf, pos);
+ tokenHandler->zeroOriginatingReplacementCharacter();
+ cstart = pos + 1;
+}
+
+void nsHtml5Tokenizer::maybeEmitReplacementCharacter(char16_t* buf,
+ int32_t pos) {
+ flushChars(buf, pos);
+ tokenHandler->zeroOrReplacementCharacter();
+ cstart = pos + 1;
+}
+
+void nsHtml5Tokenizer::emitPlaintextReplacementCharacter(char16_t* buf,
+ int32_t pos) {
+ flushChars(buf, pos);
+ tokenHandler->characters(REPLACEMENT_CHARACTER, 0, 1);
+ cstart = pos + 1;
+}
+
+void nsHtml5Tokenizer::setAdditionalAndRememberAmpersandLocation(char16_t add) {
+ additional = add;
+}
+
+void nsHtml5Tokenizer::bogusDoctype() {
+ errBogusDoctype();
+ forceQuirks = true;
+}
+
+void nsHtml5Tokenizer::bogusDoctypeWithoutQuirks() {
+ errBogusDoctype();
+ forceQuirks = false;
+}
+
+void nsHtml5Tokenizer::handleNcrValue(int32_t returnState) {
+ if (value <= 0xFFFF) {
+ if (value >= 0x80 && value <= 0x9f) {
+ errNcrInC1Range();
+ char16_t* val = nsHtml5NamedCharacters::WINDOWS_1252[value - 0x80];
+ emitOrAppendOne(val, returnState);
+ } else if (value == 0x0) {
+ errNcrZero();
+ emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState);
+ } else if ((value & 0xF800) == 0xD800) {
+ errNcrSurrogate();
+ emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState);
+ } else {
+ char16_t ch = (char16_t)value;
+ bmpChar[0] = ch;
+ emitOrAppendOne(bmpChar, returnState);
+ }
+ } else if (value <= 0x10FFFF) {
+ astralChar[0] = (char16_t)(nsHtml5Tokenizer::LEAD_OFFSET + (value >> 10));
+ astralChar[1] = (char16_t)(0xDC00 + (value & 0x3FF));
+ emitOrAppendTwo(astralChar, returnState);
+ } else {
+ errNcrOutOfRange();
+ emitOrAppendOne(nsHtml5Tokenizer::REPLACEMENT_CHARACTER, returnState);
+ }
+}
+
+void nsHtml5Tokenizer::eof() {
+ int32_t state = stateSave;
+ int32_t returnState = returnStateSave;
+eofloop:
+ for (;;) {
+ switch (state) {
+ case SCRIPT_DATA_LESS_THAN_SIGN:
+ case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case TAG_OPEN: {
+ errEofAfterLt();
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case RAWTEXT_RCDATA_LESS_THAN_SIGN: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case NON_DATA_END_TAG_NAME: {
+ tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
+ emitStrBuf();
+ NS_HTML5_BREAK(eofloop);
+ }
+ case CLOSE_TAG_OPEN: {
+ errEofAfterLt();
+ tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case TAG_NAME: {
+ errEofInTagName();
+ NS_HTML5_BREAK(eofloop);
+ }
+ case BEFORE_ATTRIBUTE_NAME:
+ case AFTER_ATTRIBUTE_VALUE_QUOTED:
+ case SELF_CLOSING_START_TAG: {
+ errEofWithoutGt();
+ NS_HTML5_BREAK(eofloop);
+ }
+ case ATTRIBUTE_NAME: {
+ errEofInAttributeName();
+ NS_HTML5_BREAK(eofloop);
+ }
+ case AFTER_ATTRIBUTE_NAME:
+ case BEFORE_ATTRIBUTE_VALUE: {
+ errEofWithoutGt();
+ NS_HTML5_BREAK(eofloop);
+ }
+ case ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ case ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ case ATTRIBUTE_VALUE_UNQUOTED: {
+ errEofInAttributeValue();
+ NS_HTML5_BREAK(eofloop);
+ }
+ case BOGUS_COMMENT: {
+ emitComment(0, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case BOGUS_COMMENT_HYPHEN: {
+ emitComment(0, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case MARKUP_DECLARATION_OPEN: {
+ errBogusComment();
+ emitComment(0, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case MARKUP_DECLARATION_HYPHEN: {
+ errBogusComment();
+ emitComment(0, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case MARKUP_DECLARATION_OCTYPE: {
+ if (index < 6) {
+ errBogusComment();
+ emitComment(0, 0);
+ } else {
+ errEofInDoctype();
+ doctypeName = nullptr;
+ if (systemIdentifier) {
+ systemIdentifier.Release();
+ systemIdentifier = nullptr;
+ }
+ if (publicIdentifier) {
+ publicIdentifier.Release();
+ publicIdentifier = nullptr;
+ }
+ forceQuirks = true;
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ NS_HTML5_BREAK(eofloop);
+ }
+ case COMMENT_START:
+ case COMMENT:
+ case COMMENT_LESSTHAN:
+ case COMMENT_LESSTHAN_BANG: {
+ errEofInComment();
+ emitComment(0, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case COMMENT_END:
+ case COMMENT_LESSTHAN_BANG_DASH_DASH: {
+ errEofInComment();
+ emitComment(2, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case COMMENT_END_DASH:
+ case COMMENT_START_DASH:
+ case COMMENT_LESSTHAN_BANG_DASH: {
+ errEofInComment();
+ emitComment(1, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case COMMENT_END_BANG: {
+ errEofInComment();
+ emitComment(3, 0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case DOCTYPE:
+ case BEFORE_DOCTYPE_NAME: {
+ errEofInDoctype();
+ forceQuirks = true;
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case DOCTYPE_NAME: {
+ errEofInDoctype();
+ strBufToDoctypeName();
+ forceQuirks = true;
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case DOCTYPE_UBLIC:
+ case DOCTYPE_YSTEM:
+ case AFTER_DOCTYPE_NAME:
+ case AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ case AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: {
+ errEofInDoctype();
+ forceQuirks = true;
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: {
+ errEofInPublicId();
+ forceQuirks = true;
+ publicIdentifier = strBufToString();
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: {
+ errEofInDoctype();
+ forceQuirks = true;
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: {
+ errEofInSystemId();
+ forceQuirks = true;
+ systemIdentifier = strBufToString();
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case AFTER_DOCTYPE_SYSTEM_IDENTIFIER: {
+ errEofInDoctype();
+ forceQuirks = true;
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case BOGUS_DOCTYPE: {
+ emitDoctypeToken(0);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case CONSUME_CHARACTER_REFERENCE: {
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue;
+ }
+ case CHARACTER_REFERENCE_HILO_LOOKUP: {
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue;
+ }
+ case CHARACTER_REFERENCE_TAIL: {
+ for (;;) {
+ char16_t c = '\0';
+ entCol++;
+ for (;;) {
+ if (hi == -1) {
+ NS_HTML5_BREAK(hiloop);
+ }
+ if (entCol == nsHtml5NamedCharacters::NAMES[hi].length()) {
+ NS_HTML5_BREAK(hiloop);
+ }
+ if (entCol > nsHtml5NamedCharacters::NAMES[hi].length()) {
+ NS_HTML5_BREAK(outer);
+ } else if (c < nsHtml5NamedCharacters::NAMES[hi].charAt(entCol)) {
+ hi--;
+ } else {
+ NS_HTML5_BREAK(hiloop);
+ }
+ }
+ hiloop_end:;
+ for (;;) {
+ if (hi < lo) {
+ NS_HTML5_BREAK(outer);
+ }
+ if (entCol == nsHtml5NamedCharacters::NAMES[lo].length()) {
+ candidate = lo;
+ charRefBufMark = charRefBufLen;
+ lo++;
+ } else if (entCol > nsHtml5NamedCharacters::NAMES[lo].length()) {
+ NS_HTML5_BREAK(outer);
+ } else if (c > nsHtml5NamedCharacters::NAMES[lo].charAt(entCol)) {
+ lo++;
+ } else {
+ NS_HTML5_BREAK(loloop);
+ }
+ }
+ loloop_end:;
+ if (hi < lo) {
+ NS_HTML5_BREAK(outer);
+ }
+ continue;
+ }
+ outer_end:;
+ if (candidate == -1) {
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ NS_HTML5_CONTINUE(eofloop);
+ } else {
+ const nsHtml5CharacterName& candidateName =
+ nsHtml5NamedCharacters::NAMES[candidate];
+ if (!candidateName.length() ||
+ candidateName.charAt(candidateName.length() - 1) != ';') {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ char16_t ch;
+ if (charRefBufMark == charRefBufLen) {
+ ch = '\0';
+ } else {
+ ch = charRefBuf[charRefBufMark];
+ }
+ if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') ||
+ (ch >= 'a' && ch <= 'z')) {
+ appendCharRefBufToStrBuf();
+ state = returnState;
+ NS_HTML5_CONTINUE(eofloop);
+ }
+ }
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ errUnescapedAmpersandInterpretedAsCharacterReference();
+ } else {
+ errNotSemicolonTerminated();
+ }
+ }
+ const char16_t* val = nsHtml5NamedCharacters::VALUES[candidate];
+ if (!val[1]) {
+ emitOrAppendOne(val, returnState);
+ } else {
+ emitOrAppendTwo(val, returnState);
+ }
+ if (charRefBufMark < charRefBufLen) {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ appendStrBuf(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ } else {
+ tokenHandler->characters(charRefBuf, charRefBufMark,
+ charRefBufLen - charRefBufMark);
+ }
+ }
+ charRefBufLen = 0;
+ state = returnState;
+ NS_HTML5_CONTINUE(eofloop);
+ }
+ }
+ case CONSUME_NCR:
+ case DECIMAL_NRC_LOOP:
+ case HEX_NCR_LOOP: {
+ if (!seenDigits) {
+ errNoDigitsInNCR();
+ emitOrAppendCharRefBuf(returnState);
+ state = returnState;
+ continue;
+ } else {
+ errCharRefLacksSemicolon();
+ }
+ handleNcrValue(returnState);
+ state = returnState;
+ continue;
+ }
+ case CDATA_RSQB: {
+ tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 1);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case CDATA_RSQB_RSQB: {
+ tokenHandler->characters(nsHtml5Tokenizer::RSQB_RSQB, 0, 2);
+ NS_HTML5_BREAK(eofloop);
+ }
+ case DATA:
+ default: {
+ NS_HTML5_BREAK(eofloop);
+ }
+ }
+ }
+eofloop_end:;
+ tokenHandler->eof();
+ return;
+}
+
+void nsHtml5Tokenizer::emitDoctypeToken(int32_t pos) {
+ RememberGt(pos);
+ cstart = pos + 1;
+ tokenHandler->doctype(doctypeName, publicIdentifier, systemIdentifier,
+ forceQuirks);
+ doctypeName = nullptr;
+ publicIdentifier.Release();
+ publicIdentifier = nullptr;
+ systemIdentifier.Release();
+ systemIdentifier = nullptr;
+ suspendIfRequestedAfterCurrentNonTextToken();
+}
+
+void nsHtml5Tokenizer::suspendIfRequestedAfterCurrentNonTextToken() {
+ if (suspendAfterCurrentNonTextToken) {
+ suspendAfterCurrentNonTextToken = false;
+ shouldSuspend = true;
+ }
+}
+
+void nsHtml5Tokenizer::suspendAfterCurrentTokenIfNotInText() {
+ switch (stateSave) {
+ case DATA:
+ case RCDATA:
+ case SCRIPT_DATA:
+ case RAWTEXT:
+ case SCRIPT_DATA_ESCAPED:
+ case PLAINTEXT:
+ case NON_DATA_END_TAG_NAME:
+ case SCRIPT_DATA_LESS_THAN_SIGN:
+ case SCRIPT_DATA_ESCAPE_START:
+ case SCRIPT_DATA_ESCAPE_START_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH:
+ case SCRIPT_DATA_ESCAPED_DASH_DASH:
+ case RAWTEXT_RCDATA_LESS_THAN_SIGN:
+ case SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_START:
+ case SCRIPT_DATA_DOUBLE_ESCAPED:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH:
+ case SCRIPT_DATA_DOUBLE_ESCAPE_END: {
+ return;
+ }
+ case TAG_NAME:
+ case BEFORE_ATTRIBUTE_NAME:
+ case ATTRIBUTE_NAME:
+ case AFTER_ATTRIBUTE_NAME:
+ case BEFORE_ATTRIBUTE_VALUE:
+ case AFTER_ATTRIBUTE_VALUE_QUOTED:
+ case BOGUS_COMMENT:
+ case MARKUP_DECLARATION_OPEN:
+ case DOCTYPE:
+ case BEFORE_DOCTYPE_NAME:
+ case DOCTYPE_NAME:
+ case AFTER_DOCTYPE_NAME:
+ case BEFORE_DOCTYPE_PUBLIC_IDENTIFIER:
+ case DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED:
+ case AFTER_DOCTYPE_PUBLIC_IDENTIFIER:
+ case BEFORE_DOCTYPE_SYSTEM_IDENTIFIER:
+ case DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED:
+ case DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED:
+ case AFTER_DOCTYPE_SYSTEM_IDENTIFIER:
+ case BOGUS_DOCTYPE:
+ case COMMENT_START:
+ case COMMENT_START_DASH:
+ case COMMENT:
+ case COMMENT_END_DASH:
+ case COMMENT_END:
+ case COMMENT_END_BANG:
+ case TAG_OPEN:
+ case CLOSE_TAG_OPEN:
+ case MARKUP_DECLARATION_HYPHEN:
+ case MARKUP_DECLARATION_OCTYPE:
+ case DOCTYPE_UBLIC:
+ case DOCTYPE_YSTEM:
+ case AFTER_DOCTYPE_PUBLIC_KEYWORD:
+ case BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS:
+ case AFTER_DOCTYPE_SYSTEM_KEYWORD:
+ case SELF_CLOSING_START_TAG:
+ case ATTRIBUTE_VALUE_DOUBLE_QUOTED:
+ case ATTRIBUTE_VALUE_SINGLE_QUOTED:
+ case ATTRIBUTE_VALUE_UNQUOTED:
+ case BOGUS_COMMENT_HYPHEN:
+ case COMMENT_LESSTHAN:
+ case COMMENT_LESSTHAN_BANG:
+ case COMMENT_LESSTHAN_BANG_DASH:
+ case COMMENT_LESSTHAN_BANG_DASH_DASH:
+ case CDATA_START:
+ case CDATA_SECTION:
+ case CDATA_RSQB:
+ case CDATA_RSQB_RSQB:
+ case PROCESSING_INSTRUCTION:
+ case PROCESSING_INSTRUCTION_QUESTION_MARK: {
+ break;
+ }
+ case CONSUME_CHARACTER_REFERENCE:
+ case CONSUME_NCR:
+ case CHARACTER_REFERENCE_TAIL:
+ case HEX_NCR_LOOP:
+ case DECIMAL_NRC_LOOP:
+ case HANDLE_NCR_VALUE:
+ case HANDLE_NCR_VALUE_RECONSUME:
+ case CHARACTER_REFERENCE_HILO_LOOKUP: {
+ if (returnStateSave == DATA || returnStateSave == RCDATA) {
+ return;
+ }
+ break;
+ }
+ default: {
+ MOZ_ASSERT(false, "Incomplete switch");
+ return;
+ }
+ }
+ suspendAfterCurrentNonTextToken = true;
+}
+
+bool nsHtml5Tokenizer::suspensionAfterCurrentNonTextTokenPending() {
+ return suspendAfterCurrentNonTextToken;
+}
+
+bool nsHtml5Tokenizer::internalEncodingDeclaration(
+ nsHtml5String internalCharset) {
+ if (encodingDeclarationHandler) {
+ return encodingDeclarationHandler->internalEncodingDeclaration(
+ internalCharset);
+ }
+ return false;
+}
+
+void nsHtml5Tokenizer::emitOrAppendTwo(const char16_t* val,
+ int32_t returnState) {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ appendStrBuf(val[0]);
+ appendStrBuf(val[1]);
+ } else {
+ tokenHandler->characters(val, 0, 2);
+ }
+}
+
+void nsHtml5Tokenizer::emitOrAppendOne(const char16_t* val,
+ int32_t returnState) {
+ if ((returnState & DATA_AND_RCDATA_MASK)) {
+ appendStrBuf(val[0]);
+ } else {
+ tokenHandler->characters(val, 0, 1);
+ }
+}
+
+void nsHtml5Tokenizer::end() {
+ strBuf = nullptr;
+ doctypeName = nullptr;
+ if (systemIdentifier) {
+ systemIdentifier.Release();
+ systemIdentifier = nullptr;
+ }
+ if (publicIdentifier) {
+ publicIdentifier.Release();
+ publicIdentifier = nullptr;
+ }
+ tagName = nullptr;
+ nonInternedTagName->setNameForNonInterned(nullptr, false);
+ attributeName = nullptr;
+ nonInternedAttributeName->setNameForNonInterned(nullptr);
+ tokenHandler->endTokenization();
+ if (attributes) {
+ attributes->clear(0);
+ }
+}
+
+void nsHtml5Tokenizer::requestSuspension() { shouldSuspend = true; }
+
+bool nsHtml5Tokenizer::isInDataState() { return (stateSave == DATA); }
+
+void nsHtml5Tokenizer::resetToDataState() {
+ clearStrBufAfterUse();
+ charRefBufLen = 0;
+ stateSave = nsHtml5Tokenizer::DATA;
+ lastCR = false;
+ index = 0;
+ forceQuirks = false;
+ additional = '\0';
+ entCol = -1;
+ firstCharKey = -1;
+ lo = 0;
+ hi = 0;
+ candidate = -1;
+ charRefBufMark = 0;
+ value = 0;
+ seenDigits = false;
+ suspendAfterCurrentNonTextToken = false;
+ endTag = false;
+ shouldSuspend = false;
+ initDoctypeFields();
+ containsHyphen = false;
+ tagName = nullptr;
+ attributeName = nullptr;
+ if (newAttributesEachTime) {
+ if (attributes) {
+ delete attributes;
+ attributes = nullptr;
+ }
+ }
+}
+
+void nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other) {
+ strBufLen = other->strBufLen;
+ if (strBufLen > strBuf.length) {
+ strBuf = jArray<char16_t, int32_t>::newJArray(strBufLen);
+ }
+ nsHtml5ArrayCopy::arraycopy(other->strBuf, strBuf, strBufLen);
+ charRefBufLen = other->charRefBufLen;
+ nsHtml5ArrayCopy::arraycopy(other->charRefBuf, charRefBuf, charRefBufLen);
+ stateSave = other->stateSave;
+ returnStateSave = other->returnStateSave;
+ endTagExpectation = other->endTagExpectation;
+ endTagExpectationAsArray = other->endTagExpectationAsArray;
+ lastCR = other->lastCR;
+ index = other->index;
+ forceQuirks = other->forceQuirks;
+ additional = other->additional;
+ entCol = other->entCol;
+ firstCharKey = other->firstCharKey;
+ lo = other->lo;
+ hi = other->hi;
+ candidate = other->candidate;
+ charRefBufMark = other->charRefBufMark;
+ value = other->value;
+ seenDigits = other->seenDigits;
+ endTag = other->endTag;
+ shouldSuspend = false;
+ suspendAfterCurrentNonTextToken = false;
+ doctypeName = other->doctypeName;
+ systemIdentifier.Release();
+ if (!other->systemIdentifier) {
+ systemIdentifier = nullptr;
+ } else {
+ systemIdentifier =
+ nsHtml5Portability::newStringFromString(other->systemIdentifier);
+ }
+ publicIdentifier.Release();
+ if (!other->publicIdentifier) {
+ publicIdentifier = nullptr;
+ } else {
+ publicIdentifier =
+ nsHtml5Portability::newStringFromString(other->publicIdentifier);
+ }
+ containsHyphen = other->containsHyphen;
+ if (!other->tagName) {
+ tagName = nullptr;
+ } else if (other->tagName->isInterned()) {
+ tagName = other->tagName;
+ } else {
+ nonInternedTagName->setNameForNonInterned(other->tagName->getName(),
+ other->tagName->isCustom());
+ tagName = nonInternedTagName;
+ }
+ if (!other->attributeName) {
+ attributeName = nullptr;
+ } else if (other->attributeName->isInterned()) {
+ attributeName = other->attributeName;
+ } else {
+ nonInternedAttributeName->setNameForNonInterned(
+ other->attributeName->getLocal(nsHtml5AttributeName::HTML));
+ attributeName = nonInternedAttributeName;
+ }
+ delete attributes;
+ if (!other->attributes) {
+ attributes = nullptr;
+ } else {
+ attributes = other->attributes->cloneAttributes();
+ }
+}
+
+void nsHtml5Tokenizer::initializeWithoutStarting() {
+ confident = false;
+ strBuf = nullptr;
+ line = 1;
+ attributeLine = 1;
+ resetToDataState();
+}
+
+void nsHtml5Tokenizer::setEncodingDeclarationHandler(
+ nsHtml5StreamParser* encodingDeclarationHandler) {
+ this->encodingDeclarationHandler = encodingDeclarationHandler;
+}
+
+nsHtml5Tokenizer::~nsHtml5Tokenizer() {
+ MOZ_COUNT_DTOR(nsHtml5Tokenizer);
+ delete nonInternedTagName;
+ nonInternedTagName = nullptr;
+ delete nonInternedAttributeName;
+ nonInternedAttributeName = nullptr;
+ delete attributes;
+ attributes = nullptr;
+}
+
+void nsHtml5Tokenizer::initializeStatics() {}
+
+void nsHtml5Tokenizer::releaseStatics() {}
+
+#include "nsHtml5TokenizerCppSupplement.h"
diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h
new file mode 100644
index 0000000000..7397bb8c03
--- /dev/null
+++ b/parser/html/nsHtml5Tokenizer.h
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2005-2007 Henri Sivonen
+ * Copyright (c) 2007-2017 Mozilla Foundation
+ * Portions of comments Copyright 2004-2010 Apple Computer, Inc., Mozilla
+ * Foundation, and Opera Software ASA.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit Tokenizer.java instead and regenerate.
+ */
+
+#ifndef nsHtml5Tokenizer_h
+#define nsHtml5Tokenizer_h
+
+#include "jArray.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsAtom.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5Highlighter.h"
+#include "nsHtml5Macros.h"
+#include "nsHtml5NamedCharacters.h"
+#include "nsHtml5NamedCharactersAccel.h"
+#include "nsHtml5String.h"
+#include "nsHtml5TokenizerLoopPolicies.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5TreeBuilder;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5Tokenizer {
+ private:
+ static const int32_t DATA_AND_RCDATA_MASK = ~1;
+
+ public:
+ static const int32_t DATA = 0;
+
+ static const int32_t RCDATA = 1;
+
+ static const int32_t SCRIPT_DATA = 2;
+
+ static const int32_t RAWTEXT = 3;
+
+ static const int32_t SCRIPT_DATA_ESCAPED = 4;
+
+ static const int32_t ATTRIBUTE_VALUE_DOUBLE_QUOTED = 5;
+
+ static const int32_t ATTRIBUTE_VALUE_SINGLE_QUOTED = 6;
+
+ static const int32_t ATTRIBUTE_VALUE_UNQUOTED = 7;
+
+ static const int32_t PLAINTEXT = 8;
+
+ static const int32_t TAG_OPEN = 9;
+
+ static const int32_t CLOSE_TAG_OPEN = 10;
+
+ static const int32_t TAG_NAME = 11;
+
+ static const int32_t BEFORE_ATTRIBUTE_NAME = 12;
+
+ static const int32_t ATTRIBUTE_NAME = 13;
+
+ static const int32_t AFTER_ATTRIBUTE_NAME = 14;
+
+ static const int32_t BEFORE_ATTRIBUTE_VALUE = 15;
+
+ static const int32_t AFTER_ATTRIBUTE_VALUE_QUOTED = 16;
+
+ static const int32_t BOGUS_COMMENT = 17;
+
+ static const int32_t MARKUP_DECLARATION_OPEN = 18;
+
+ static const int32_t DOCTYPE = 19;
+
+ static const int32_t BEFORE_DOCTYPE_NAME = 20;
+
+ static const int32_t DOCTYPE_NAME = 21;
+
+ static const int32_t AFTER_DOCTYPE_NAME = 22;
+
+ static const int32_t BEFORE_DOCTYPE_PUBLIC_IDENTIFIER = 23;
+
+ static const int32_t DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED = 24;
+
+ static const int32_t DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED = 25;
+
+ static const int32_t AFTER_DOCTYPE_PUBLIC_IDENTIFIER = 26;
+
+ static const int32_t BEFORE_DOCTYPE_SYSTEM_IDENTIFIER = 27;
+
+ static const int32_t DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED = 28;
+
+ static const int32_t DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED = 29;
+
+ static const int32_t AFTER_DOCTYPE_SYSTEM_IDENTIFIER = 30;
+
+ static const int32_t BOGUS_DOCTYPE = 31;
+
+ static const int32_t COMMENT_START = 32;
+
+ static const int32_t COMMENT_START_DASH = 33;
+
+ static const int32_t COMMENT = 34;
+
+ static const int32_t COMMENT_END_DASH = 35;
+
+ static const int32_t COMMENT_END = 36;
+
+ static const int32_t COMMENT_END_BANG = 37;
+
+ static const int32_t NON_DATA_END_TAG_NAME = 38;
+
+ static const int32_t MARKUP_DECLARATION_HYPHEN = 39;
+
+ static const int32_t MARKUP_DECLARATION_OCTYPE = 40;
+
+ static const int32_t DOCTYPE_UBLIC = 41;
+
+ static const int32_t DOCTYPE_YSTEM = 42;
+
+ static const int32_t AFTER_DOCTYPE_PUBLIC_KEYWORD = 43;
+
+ static const int32_t BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS = 44;
+
+ static const int32_t AFTER_DOCTYPE_SYSTEM_KEYWORD = 45;
+
+ static const int32_t CONSUME_CHARACTER_REFERENCE = 46;
+
+ static const int32_t CONSUME_NCR = 47;
+
+ static const int32_t CHARACTER_REFERENCE_TAIL = 48;
+
+ static const int32_t HEX_NCR_LOOP = 49;
+
+ static const int32_t DECIMAL_NRC_LOOP = 50;
+
+ static const int32_t HANDLE_NCR_VALUE = 51;
+
+ static const int32_t HANDLE_NCR_VALUE_RECONSUME = 52;
+
+ static const int32_t CHARACTER_REFERENCE_HILO_LOOKUP = 53;
+
+ static const int32_t SELF_CLOSING_START_TAG = 54;
+
+ static const int32_t CDATA_START = 55;
+
+ static const int32_t CDATA_SECTION = 56;
+
+ static const int32_t CDATA_RSQB = 57;
+
+ static const int32_t CDATA_RSQB_RSQB = 58;
+
+ static const int32_t SCRIPT_DATA_LESS_THAN_SIGN = 59;
+
+ static const int32_t SCRIPT_DATA_ESCAPE_START = 60;
+
+ static const int32_t SCRIPT_DATA_ESCAPE_START_DASH = 61;
+
+ static const int32_t SCRIPT_DATA_ESCAPED_DASH = 62;
+
+ static const int32_t SCRIPT_DATA_ESCAPED_DASH_DASH = 63;
+
+ static const int32_t BOGUS_COMMENT_HYPHEN = 64;
+
+ static const int32_t RAWTEXT_RCDATA_LESS_THAN_SIGN = 65;
+
+ static const int32_t SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN = 66;
+
+ static const int32_t SCRIPT_DATA_DOUBLE_ESCAPE_START = 67;
+
+ static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED = 68;
+
+ static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN = 69;
+
+ static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED_DASH = 70;
+
+ static const int32_t SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH = 71;
+
+ static const int32_t SCRIPT_DATA_DOUBLE_ESCAPE_END = 72;
+
+ static const int32_t PROCESSING_INSTRUCTION = 73;
+
+ static const int32_t PROCESSING_INSTRUCTION_QUESTION_MARK = 74;
+
+ static const int32_t COMMENT_LESSTHAN = 76;
+
+ static const int32_t COMMENT_LESSTHAN_BANG = 77;
+
+ static const int32_t COMMENT_LESSTHAN_BANG_DASH = 78;
+
+ static const int32_t COMMENT_LESSTHAN_BANG_DASH_DASH = 79;
+
+ private:
+ static const int32_t LEAD_OFFSET = (0xD800 - (0x10000 >> 10));
+
+ static char16_t LT_GT[];
+ static char16_t LT_SOLIDUS[];
+ static char16_t RSQB_RSQB[];
+ static char16_t REPLACEMENT_CHARACTER[];
+ static char16_t LF[];
+ static char16_t CDATA_LSQB[];
+ static char16_t OCTYPE[];
+ static char16_t UBLIC[];
+ static char16_t YSTEM[];
+ static staticJArray<char16_t, int32_t> TITLE_ARR;
+ static staticJArray<char16_t, int32_t> SCRIPT_ARR;
+ static staticJArray<char16_t, int32_t> STYLE_ARR;
+ static staticJArray<char16_t, int32_t> PLAINTEXT_ARR;
+ static staticJArray<char16_t, int32_t> XMP_ARR;
+ static staticJArray<char16_t, int32_t> TEXTAREA_ARR;
+ static staticJArray<char16_t, int32_t> IFRAME_ARR;
+ static staticJArray<char16_t, int32_t> NOEMBED_ARR;
+ static staticJArray<char16_t, int32_t> NOSCRIPT_ARR;
+ static staticJArray<char16_t, int32_t> NOFRAMES_ARR;
+
+ protected:
+ nsHtml5TreeBuilder* tokenHandler;
+ nsHtml5StreamParser* encodingDeclarationHandler;
+ bool lastCR;
+ int32_t stateSave;
+
+ private:
+ int32_t returnStateSave;
+
+ protected:
+ int32_t index;
+
+ private:
+ bool forceQuirks;
+ char16_t additional;
+ int32_t entCol;
+ int32_t firstCharKey;
+ int32_t lo;
+ int32_t hi;
+ int32_t candidate;
+ int32_t charRefBufMark;
+
+ protected:
+ int32_t value;
+
+ private:
+ bool seenDigits;
+ bool suspendAfterCurrentNonTextToken;
+
+ protected:
+ int32_t cstart;
+
+ private:
+ nsHtml5String publicId;
+ nsHtml5String systemId;
+ autoJArray<char16_t, int32_t> strBuf;
+ int32_t strBufLen;
+ autoJArray<char16_t, int32_t> charRefBuf;
+ int32_t charRefBufLen;
+ autoJArray<char16_t, int32_t> bmpChar;
+ autoJArray<char16_t, int32_t> astralChar;
+
+ protected:
+ nsHtml5ElementName* endTagExpectation;
+
+ private:
+ jArray<char16_t, int32_t> endTagExpectationAsArray;
+
+ protected:
+ bool endTag;
+
+ private:
+ bool containsHyphen;
+ nsHtml5ElementName* tagName;
+ nsHtml5ElementName* nonInternedTagName;
+
+ protected:
+ nsHtml5AttributeName* attributeName;
+
+ private:
+ nsHtml5AttributeName* nonInternedAttributeName;
+ RefPtr<nsAtom> doctypeName;
+ nsHtml5String publicIdentifier;
+ nsHtml5String systemIdentifier;
+ nsHtml5HtmlAttributes* attributes;
+ bool newAttributesEachTime;
+ bool shouldSuspend;
+
+ protected:
+ bool confident;
+
+ private:
+ int32_t line;
+ int32_t attributeLine;
+ nsHtml5AtomTable* interner;
+ bool viewingXmlSource;
+
+ public:
+ nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, bool viewingXmlSource);
+ void setInterner(nsHtml5AtomTable* interner);
+ void initLocation(nsHtml5String newPublicId, nsHtml5String newSystemId);
+ bool isViewingXmlSource();
+ void setState(int32_t specialTokenizerState);
+ void setStateAndEndTagExpectation(int32_t specialTokenizerState,
+ nsHtml5ElementName* endTagExpectation);
+
+ private:
+ void endTagExpectationToArray();
+
+ public:
+ void setLineNumber(int32_t line);
+ inline int32_t getLineNumber() { return line; }
+
+ nsHtml5HtmlAttributes* emptyAttributes();
+
+ private:
+ inline void appendCharRefBuf(char16_t c) {
+ MOZ_RELEASE_ASSERT(charRefBufLen < charRefBuf.length,
+ "Attempted to overrun charRefBuf!");
+ charRefBuf[charRefBufLen++] = c;
+ }
+
+ void emitOrAppendCharRefBuf(int32_t returnState);
+ inline void clearStrBufAfterUse() { strBufLen = 0; }
+
+ inline void clearStrBufBeforeUse() {
+ MOZ_ASSERT(!strBufLen, "strBufLen not reset after previous use!");
+ strBufLen = 0;
+ }
+
+ inline void clearStrBufAfterOneHyphen() {
+ MOZ_ASSERT(strBufLen == 1, "strBufLen length not one!");
+ MOZ_ASSERT(strBuf[0] == '-', "strBuf does not start with a hyphen!");
+ strBufLen = 0;
+ }
+
+ inline void appendStrBuf(char16_t c) {
+ MOZ_ASSERT(strBufLen < strBuf.length,
+ "Previous buffer length insufficient.");
+ if (MOZ_UNLIKELY(strBufLen == strBuf.length)) {
+ if (MOZ_UNLIKELY(!EnsureBufferSpace(1))) {
+ MOZ_CRASH("Unable to recover from buffer reallocation failure");
+ }
+ }
+ strBuf[strBufLen++] = c;
+ }
+
+ protected:
+ nsHtml5String strBufToString();
+
+ private:
+ void strBufToDoctypeName();
+ void emitStrBuf();
+ inline void appendSecondHyphenToBogusComment() { appendStrBuf('-'); }
+
+ inline void adjustDoubleHyphenAndAppendToStrBufAndErr(
+ char16_t c, bool reportedConsecutiveHyphens) {
+ appendStrBuf(c);
+ }
+
+ void appendStrBuf(char16_t* buffer, int32_t offset, int32_t length);
+ inline void appendCharRefBufToStrBuf() {
+ appendStrBuf(charRefBuf, 0, charRefBufLen);
+ charRefBufLen = 0;
+ }
+
+ void emitComment(int32_t provisionalHyphens, int32_t pos);
+
+ protected:
+ void flushChars(char16_t* buf, int32_t pos);
+
+ private:
+ void strBufToElementNameString();
+ int32_t emitCurrentTagToken(bool selfClosing, int32_t pos);
+ void attributeNameComplete();
+ void addAttributeWithoutValue();
+ void addAttributeWithValue();
+
+ public:
+ void start();
+ bool tokenizeBuffer(nsHtml5UTF16Buffer* buffer);
+
+ private:
+ template <class P>
+ int32_t stateLoop(int32_t state, char16_t c, int32_t pos, char16_t* buf,
+ bool reconsume, int32_t returnState, int32_t endPos);
+ void initDoctypeFields();
+ inline void adjustDoubleHyphenAndAppendToStrBufCarriageReturn() {
+ silentCarriageReturn();
+ adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false);
+ }
+
+ inline void adjustDoubleHyphenAndAppendToStrBufLineFeed() {
+ silentLineFeed();
+ adjustDoubleHyphenAndAppendToStrBufAndErr('\n', false);
+ }
+
+ inline void appendStrBufLineFeed() {
+ silentLineFeed();
+ appendStrBuf('\n');
+ }
+
+ inline void appendStrBufCarriageReturn() {
+ silentCarriageReturn();
+ appendStrBuf('\n');
+ }
+
+ void emitCarriageReturn(char16_t* buf, int32_t pos);
+ void emitReplacementCharacter(char16_t* buf, int32_t pos);
+ void maybeEmitReplacementCharacter(char16_t* buf, int32_t pos);
+ void emitPlaintextReplacementCharacter(char16_t* buf, int32_t pos);
+ void setAdditionalAndRememberAmpersandLocation(char16_t add);
+ void bogusDoctype();
+ void bogusDoctypeWithoutQuirks();
+ void handleNcrValue(int32_t returnState);
+
+ public:
+ void eof();
+
+ private:
+ void emitDoctypeToken(int32_t pos);
+ void suspendIfRequestedAfterCurrentNonTextToken();
+ void suspendAfterCurrentTokenIfNotInText();
+ bool suspensionAfterCurrentNonTextTokenPending();
+
+ public:
+ bool internalEncodingDeclaration(nsHtml5String internalCharset);
+
+ private:
+ void emitOrAppendTwo(const char16_t* val, int32_t returnState);
+ void emitOrAppendOne(const char16_t* val, int32_t returnState);
+
+ public:
+ void end();
+ void requestSuspension();
+ bool isInDataState();
+ void resetToDataState();
+ void loadState(nsHtml5Tokenizer* other);
+ void initializeWithoutStarting();
+ void setEncodingDeclarationHandler(
+ nsHtml5StreamParser* encodingDeclarationHandler);
+ ~nsHtml5Tokenizer();
+ static void initializeStatics();
+ static void releaseStatics();
+
+#include "nsHtml5TokenizerHSupplement.h"
+};
+
+#endif
diff --git a/parser/html/nsHtml5TokenizerCppSupplement.h b/parser/html/nsHtml5TokenizerCppSupplement.h
new file mode 100644
index 0000000000..b5bb2aec6b
--- /dev/null
+++ b/parser/html/nsHtml5TokenizerCppSupplement.h
@@ -0,0 +1,494 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/CheckedInt.h"
+#include "mozilla/Likely.h"
+
+// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
+// is 2^30. Note that this is counting char16_t units. The underlying
+// bytes will be twice that, but they fit even in 32-bit size_t even
+// if a contiguous chunk of memory of that size is pretty unlikely to
+// be available on a 32-bit system.
+#define MAX_POWER_OF_TWO_IN_INT32 0x40000000
+
+bool nsHtml5Tokenizer::EnsureBufferSpace(int32_t aLength) {
+ MOZ_RELEASE_ASSERT(aLength >= 0, "Negative length.");
+ if (aLength > MAX_POWER_OF_TWO_IN_INT32) {
+ // Can't happen when loading from network.
+ return false;
+ }
+ mozilla::CheckedInt<int32_t> worstCase(strBufLen);
+ worstCase += aLength;
+ worstCase += charRefBufLen;
+ // Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB.
+ // Adding to the general worst case instead of only the
+ // TreeBuilder-exposed worst case to avoid re-introducing a bug when
+ // unifying the tokenizer and tree builder buffers in the future.
+ worstCase += 2;
+ if (!worstCase.isValid()) {
+ return false;
+ }
+ if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) {
+ return false;
+ }
+ // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
+ // so that the call below becomes unnecessary.
+ if (!tokenHandler->EnsureBufferSpace(worstCase.value())) {
+ return false;
+ }
+ if (!strBuf) {
+ if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) {
+ // Add one to round to the next power of two to avoid immediate
+ // reallocation once there are a few characters in the buffer.
+ worstCase += 1;
+ }
+ strBuf = jArray<char16_t, int32_t>::newFallibleJArray(
+ mozilla::RoundUpPow2(worstCase.value()));
+ if (!strBuf) {
+ return false;
+ }
+ } else if (worstCase.value() > strBuf.length) {
+ jArray<char16_t, int32_t> newBuf =
+ jArray<char16_t, int32_t>::newFallibleJArray(
+ mozilla::RoundUpPow2(worstCase.value()));
+ if (!newBuf) {
+ return false;
+ }
+ memcpy(newBuf, strBuf, sizeof(char16_t) * size_t(strBufLen));
+ strBuf = newBuf;
+ }
+ return true;
+}
+
+bool nsHtml5Tokenizer::TemplatePushedOrHeadPopped() {
+ if (encodingDeclarationHandler) {
+ return encodingDeclarationHandler->TemplatePushedOrHeadPopped();
+ }
+ return false;
+}
+
+void nsHtml5Tokenizer::RememberGt(int32_t aPos) {
+ if (encodingDeclarationHandler) {
+ return encodingDeclarationHandler->RememberGt(aPos);
+ }
+}
+
+void nsHtml5Tokenizer::StartPlainText() {
+ stateSave = nsHtml5Tokenizer::PLAINTEXT;
+}
+
+void nsHtml5Tokenizer::EnableViewSource(nsHtml5Highlighter* aHighlighter) {
+ mViewSource = mozilla::WrapUnique(aHighlighter);
+}
+
+bool nsHtml5Tokenizer::ShouldFlushViewSource() {
+ return mViewSource->ShouldFlushOps();
+}
+
+mozilla::Result<bool, nsresult> nsHtml5Tokenizer::FlushViewSource() {
+ return mViewSource->FlushOps();
+}
+
+void nsHtml5Tokenizer::StartViewSource(const nsAutoString& aTitle) {
+ mViewSource->Start(aTitle);
+}
+
+void nsHtml5Tokenizer::StartViewSourceCharacters() {
+ mViewSource->StartCharacters();
+}
+
+[[nodiscard]] bool nsHtml5Tokenizer::EndViewSource() {
+ return mViewSource->End();
+}
+
+void nsHtml5Tokenizer::SetViewSourceOpSink(nsAHtml5TreeOpSink* aOpSink) {
+ mViewSource->SetOpSink(aOpSink);
+}
+
+void nsHtml5Tokenizer::RewindViewSource() { mViewSource->Rewind(); }
+
+void nsHtml5Tokenizer::errWarnLtSlashInRcdata() {}
+
+// The null checks below annotated MOZ_LIKELY are not actually necessary.
+
+void nsHtml5Tokenizer::errUnquotedAttributeValOrNull(char16_t c) {
+ if (MOZ_LIKELY(mViewSource)) {
+ switch (c) {
+ case '<':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeLt");
+ return;
+ case '`':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeGrave");
+ return;
+ case '\'':
+ case '"':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeQuote");
+ return;
+ case '=':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeEquals");
+ return;
+ }
+ }
+}
+
+void nsHtml5Tokenizer::errLtOrEqualsOrGraveInUnquotedAttributeOrNull(
+ char16_t c) {
+ if (MOZ_LIKELY(mViewSource)) {
+ switch (c) {
+ case '=':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartEquals");
+ return;
+ case '<':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartLt");
+ return;
+ case '`':
+ mViewSource->AddErrorToCurrentNode("errUnquotedAttributeStartGrave");
+ return;
+ }
+ }
+}
+
+void nsHtml5Tokenizer::errBadCharBeforeAttributeNameOrNull(char16_t c) {
+ if (MOZ_LIKELY(mViewSource)) {
+ if (c == '<') {
+ mViewSource->AddErrorToCurrentNode("errBadCharBeforeAttributeNameLt");
+ } else if (c == '=') {
+ errEqualsSignBeforeAttributeName();
+ } else if (c != 0xFFFD) {
+ errQuoteBeforeAttributeName(c);
+ }
+ }
+}
+
+void nsHtml5Tokenizer::errBadCharAfterLt(char16_t c) {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errBadCharAfterLt");
+ }
+}
+
+void nsHtml5Tokenizer::errQuoteOrLtInAttributeNameOrNull(char16_t c) {
+ if (MOZ_LIKELY(mViewSource)) {
+ if (c == '<') {
+ mViewSource->AddErrorToCurrentNode("errLtInAttributeName");
+ } else if (c != 0xFFFD) {
+ mViewSource->AddErrorToCurrentNode("errQuoteInAttributeName");
+ }
+ }
+}
+
+void nsHtml5Tokenizer::maybeErrAttributesOnEndTag(
+ nsHtml5HtmlAttributes* attrs) {
+ if (mViewSource && attrs->getLength() != 0) {
+ /*
+ * When an end tag token is emitted with attributes, that is a parse
+ * error.
+ */
+ mViewSource->AddErrorToCurrentRun("maybeErrAttributesOnEndTag");
+ }
+}
+
+void nsHtml5Tokenizer::maybeErrSlashInEndTag(bool selfClosing) {
+ if (mViewSource && selfClosing && endTag) {
+ mViewSource->AddErrorToCurrentSlash("maybeErrSlashInEndTag");
+ }
+}
+
+char16_t nsHtml5Tokenizer::errNcrNonCharacter(char16_t ch) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrNonCharacter");
+ }
+ return ch;
+}
+
+void nsHtml5Tokenizer::errAstralNonCharacter(int32_t ch) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrNonCharacter");
+ }
+}
+
+char16_t nsHtml5Tokenizer::errNcrControlChar(char16_t ch) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrControlChar");
+ }
+ return ch;
+}
+
+void nsHtml5Tokenizer::errGarbageAfterLtSlash() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errGarbageAfterLtSlash");
+ }
+}
+
+void nsHtml5Tokenizer::errLtSlashGt() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errLtSlashGt");
+ }
+}
+
+void nsHtml5Tokenizer::errCharRefLacksSemicolon() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errCharRefLacksSemicolon");
+ }
+}
+
+void nsHtml5Tokenizer::errNoDigitsInNCR() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNoDigitsInNCR");
+ }
+}
+
+void nsHtml5Tokenizer::errGtInSystemId() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errGtInSystemId");
+ }
+}
+
+void nsHtml5Tokenizer::errGtInPublicId() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errGtInPublicId");
+ }
+}
+
+void nsHtml5Tokenizer::errNamelessDoctype() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNamelessDoctype");
+ }
+}
+
+void nsHtml5Tokenizer::errConsecutiveHyphens() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errConsecutiveHyphens");
+ }
+}
+
+void nsHtml5Tokenizer::errPrematureEndOfComment() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errPrematureEndOfComment");
+ }
+}
+
+void nsHtml5Tokenizer::errBogusComment() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errBogusComment");
+ }
+}
+
+void nsHtml5Tokenizer::errSlashNotFollowedByGt() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentSlash("errSlashNotFollowedByGt");
+ }
+}
+
+void nsHtml5Tokenizer::errNoSpaceBetweenAttributes() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenAttributes");
+ }
+}
+
+void nsHtml5Tokenizer::errAttributeValueMissing() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errAttributeValueMissing");
+ }
+}
+
+void nsHtml5Tokenizer::errEqualsSignBeforeAttributeName() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errEqualsSignBeforeAttributeName");
+ }
+}
+
+void nsHtml5Tokenizer::errLtGt() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errLtGt");
+ }
+}
+
+void nsHtml5Tokenizer::errProcessingInstruction() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errProcessingInstruction");
+ }
+}
+
+void nsHtml5Tokenizer::errUnescapedAmpersandInterpretedAsCharacterReference() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentAmpersand(
+ "errUnescapedAmpersandInterpretedAsCharacterReference");
+ }
+}
+
+void nsHtml5Tokenizer::errNotSemicolonTerminated() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNotSemicolonTerminated");
+ }
+}
+
+void nsHtml5Tokenizer::errNoNamedCharacterMatch() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentAmpersand("errNoNamedCharacterMatch");
+ }
+}
+
+void nsHtml5Tokenizer::errQuoteBeforeAttributeName(char16_t c) {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errQuoteBeforeAttributeName");
+ }
+}
+
+void nsHtml5Tokenizer::errExpectedPublicId() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errExpectedPublicId");
+ }
+}
+
+void nsHtml5Tokenizer::errBogusDoctype() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errBogusDoctype");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrSurrogate() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrSurrogate");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrCr() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrCr");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrInC1Range() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrInC1Range");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInPublicId() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInPublicId");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInComment() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInComment");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInDoctype() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInDoctype");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInAttributeValue() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInAttributeValue");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInAttributeName() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInAttributeName");
+ }
+}
+
+void nsHtml5Tokenizer::errEofWithoutGt() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofWithoutGt");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInTagName() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInTagName");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInEndTag() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInEndTag");
+ }
+}
+
+void nsHtml5Tokenizer::errEofAfterLt() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofAfterLt");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrOutOfRange() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrOutOfRange");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrUnassigned() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrUnassigned");
+ }
+}
+
+void nsHtml5Tokenizer::errDuplicateAttribute() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errDuplicateAttribute");
+ }
+}
+
+void nsHtml5Tokenizer::errEofInSystemId() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEofInSystemId");
+ }
+}
+
+void nsHtml5Tokenizer::errExpectedSystemId() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errExpectedSystemId");
+ }
+}
+
+void nsHtml5Tokenizer::errMissingSpaceBeforeDoctypeName() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errMissingSpaceBeforeDoctypeName");
+ }
+}
+
+void nsHtml5Tokenizer::errNestedComment() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNestedComment");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrControlChar() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrControlChar");
+ }
+}
+
+void nsHtml5Tokenizer::errNcrZero() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNcrZero");
+ }
+}
+
+void nsHtml5Tokenizer::errNoSpaceBetweenDoctypeSystemKeywordAndQuote() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode(
+ "errNoSpaceBetweenDoctypeSystemKeywordAndQuote");
+ }
+}
+
+void nsHtml5Tokenizer::errNoSpaceBetweenPublicAndSystemIds() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode("errNoSpaceBetweenPublicAndSystemIds");
+ }
+}
+
+void nsHtml5Tokenizer::errNoSpaceBetweenDoctypePublicKeywordAndQuote() {
+ if (MOZ_LIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentNode(
+ "errNoSpaceBetweenDoctypePublicKeywordAndQuote");
+ }
+}
diff --git a/parser/html/nsHtml5TokenizerHSupplement.h b/parser/html/nsHtml5TokenizerHSupplement.h
new file mode 100644
index 0000000000..0e1930b93e
--- /dev/null
+++ b/parser/html/nsHtml5TokenizerHSupplement.h
@@ -0,0 +1,220 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+private:
+inline void silentCarriageReturn() {
+ nextCharOnNewLine = true;
+ lastCR = true;
+}
+
+inline void silentLineFeed() { nextCharOnNewLine = true; }
+
+inline char16_t checkChar(char16_t* buf, int32_t pos) {
+ // The name of this method comes from the validator.
+ // We aren't checking a char here. We read the next
+ // UTF-16 code unit and, before returning it, adjust
+ // the line and column numbers.
+ char16_t c = buf[pos];
+ if (MOZ_UNLIKELY(nextCharOnNewLine)) {
+ // By changing the line and column here instead
+ // of doing so eagerly when seeing the line break
+ // causes the line break itself to be considered
+ // column-wise at the end of a line.
+ line++;
+ col = 1;
+ nextCharOnNewLine = false;
+ } else if (MOZ_LIKELY(!NS_IS_LOW_SURROGATE(c))) {
+ // SpiderMonkey wants to count scalar values
+ // instead of UTF-16 code units. We omit low
+ // surrogates from the count so that only the
+ // high surrogate increments the count for
+ // two-code-unit scalar values.
+ //
+ // It's somewhat questionable from the performance
+ // perspective to make the human-perceivable column
+ // count correct for non-BMP characters in the case
+ // where there is a single scalar value per extended
+ // grapheme cluster when even on the BMP there are
+ // various cases where the scalar count doesn't make
+ // much sense as a human-perceived "column count" due
+ // to extended grapheme clusters consisting of more
+ // than one scalar value.
+ col++;
+ }
+ return c;
+}
+
+int32_t col;
+bool nextCharOnNewLine;
+
+public:
+inline int32_t getColumnNumber() { return col; }
+
+inline void setColumnNumberAndResetNextLine(int32_t aCol) {
+ col = aCol;
+ // The restored position only ever points to the position of
+ // script tag's > character, so we can unconditionally use
+ // `false` below.
+ nextCharOnNewLine = false;
+}
+
+inline nsHtml5HtmlAttributes* GetAttributes() { return attributes; }
+
+/**
+ * Makes sure the buffers are large enough to be able to tokenize aLength
+ * UTF-16 code units before having to make the buffers larger.
+ *
+ * @param aLength the number of UTF-16 code units to be tokenized before the
+ * next call to this method.
+ * @return true if successful; false if out of memory
+ */
+bool EnsureBufferSpace(int32_t aLength);
+
+bool TemplatePushedOrHeadPopped();
+
+void RememberGt(int32_t aPos);
+
+void AtKilobyteBoundary() { suspendAfterCurrentTokenIfNotInText(); }
+
+bool IsInTokenStartedAtKilobyteBoundary() {
+ return suspensionAfterCurrentNonTextTokenPending();
+}
+
+mozilla::UniquePtr<nsHtml5Highlighter> mViewSource;
+
+/**
+ * Starts handling text/plain. This is a one-way initialization. There is
+ * no corresponding EndPlainText() call.
+ */
+void StartPlainText();
+
+void EnableViewSource(nsHtml5Highlighter* aHighlighter);
+
+bool ShouldFlushViewSource();
+
+mozilla::Result<bool, nsresult> FlushViewSource();
+
+void StartViewSource(const nsAutoString& aTitle);
+
+void StartViewSourceCharacters();
+
+[[nodiscard]] bool EndViewSource();
+
+void RewindViewSource();
+
+void SetViewSourceOpSink(nsAHtml5TreeOpSink* aOpSink);
+
+void errGarbageAfterLtSlash();
+
+void errLtSlashGt();
+
+void errWarnLtSlashInRcdata();
+
+void errCharRefLacksSemicolon();
+
+void errNoDigitsInNCR();
+
+void errGtInSystemId();
+
+void errGtInPublicId();
+
+void errNamelessDoctype();
+
+void errConsecutiveHyphens();
+
+void errPrematureEndOfComment();
+
+void errBogusComment();
+
+void errUnquotedAttributeValOrNull(char16_t c);
+
+void errSlashNotFollowedByGt();
+
+void errNoSpaceBetweenAttributes();
+
+void errLtOrEqualsOrGraveInUnquotedAttributeOrNull(char16_t c);
+
+void errAttributeValueMissing();
+
+void errBadCharBeforeAttributeNameOrNull(char16_t c);
+
+void errEqualsSignBeforeAttributeName();
+
+void errBadCharAfterLt(char16_t c);
+
+void errLtGt();
+
+void errProcessingInstruction();
+
+void errUnescapedAmpersandInterpretedAsCharacterReference();
+
+void errNotSemicolonTerminated();
+
+void errNoNamedCharacterMatch();
+
+void errQuoteBeforeAttributeName(char16_t c);
+
+void errQuoteOrLtInAttributeNameOrNull(char16_t c);
+
+void errExpectedPublicId();
+
+void errBogusDoctype();
+
+void maybeErrAttributesOnEndTag(nsHtml5HtmlAttributes* attrs);
+
+void maybeErrSlashInEndTag(bool selfClosing);
+
+char16_t errNcrNonCharacter(char16_t ch);
+
+void errAstralNonCharacter(int32_t ch);
+
+void errNcrSurrogate();
+
+char16_t errNcrControlChar(char16_t ch);
+
+void errNcrCr();
+
+void errNcrInC1Range();
+
+void errEofInPublicId();
+
+void errEofInComment();
+
+void errEofInDoctype();
+
+void errEofInAttributeValue();
+
+void errEofInAttributeName();
+
+void errEofWithoutGt();
+
+void errEofInTagName();
+
+void errEofInEndTag();
+
+void errEofAfterLt();
+
+void errNcrOutOfRange();
+
+void errNcrUnassigned();
+
+void errDuplicateAttribute();
+
+void errEofInSystemId();
+
+void errExpectedSystemId();
+
+void errMissingSpaceBeforeDoctypeName();
+
+void errNestedComment();
+
+void errNcrControlChar();
+
+void errNcrZero();
+
+void errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
+
+void errNoSpaceBetweenPublicAndSystemIds();
+
+void errNoSpaceBetweenDoctypePublicKeywordAndQuote();
diff --git a/parser/html/nsHtml5TokenizerLoopPolicies.h b/parser/html/nsHtml5TokenizerLoopPolicies.h
new file mode 100644
index 0000000000..f1e547ca25
--- /dev/null
+++ b/parser/html/nsHtml5TokenizerLoopPolicies.h
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5TokenizerLoopPolicies_h
+#define nsHtml5TokenizerLoopPolicies_h
+
+/**
+ * This policy does not report tokenizer transitions anywhere. To be used
+ * when _not_ viewing source.
+ */
+struct nsHtml5SilentPolicy {
+ static const bool reportErrors = false;
+ static int32_t transition(nsHtml5Highlighter* aHighlighter, int32_t aState,
+ bool aReconsume, int32_t aPos) {
+ return aState;
+ }
+ static void completedNamedCharacterReference(
+ nsHtml5Highlighter* aHighlighter) {}
+};
+
+/**
+ * This policy reports the tokenizer transitions to a highlighter. To be used
+ * when viewing source.
+ */
+struct nsHtml5ViewSourcePolicy {
+ static const bool reportErrors = true;
+ static int32_t transition(nsHtml5Highlighter* aHighlighter, int32_t aState,
+ bool aReconsume, int32_t aPos) {
+ return aHighlighter->Transition(aState, aReconsume, aPos);
+ }
+ static void completedNamedCharacterReference(
+ nsHtml5Highlighter* aHighlighter) {
+ aHighlighter->CompletedNamedCharacterReference();
+ }
+};
+
+#endif // nsHtml5TokenizerLoopPolicies_h
diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp
new file mode 100644
index 0000000000..3c98c221ed
--- /dev/null
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -0,0 +1,4744 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2007-2017 Mozilla Foundation
+ * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
+ * Foundation, and Opera Software ASA.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit TreeBuilder.java instead and regenerate.
+ */
+
+#define nsHtml5TreeBuilder_cpp__
+
+#include "jArray.h"
+#include "mozilla/ImportScanner.h"
+#include "mozilla/Likely.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsAtom.h"
+#include "nsContentUtils.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5Highlighter.h"
+#include "nsHtml5OplessBuilder.h"
+#include "nsHtml5Parser.h"
+#include "nsHtml5PlainTextUtils.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5StreamParser.h"
+#include "nsHtml5String.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsHtml5TreeOpExecutor.h"
+#include "nsHtml5ViewSourceUtils.h"
+#include "nsIContent.h"
+#include "nsIContentHandle.h"
+#include "nsNameSpaceManager.h"
+#include "nsTraceRefcnt.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5UTF16Buffer.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5TreeBuilder.h"
+
+char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = {0xfffd};
+static const char* const QUIRKY_PUBLIC_IDS_DATA[] = {
+ "+//silmaril//dtd html pro v0r11 19970101//",
+ "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
+ "-//as//dtd html 3.0 aswedit + extensions//",
+ "-//ietf//dtd html 2.0 level 1//",
+ "-//ietf//dtd html 2.0 level 2//",
+ "-//ietf//dtd html 2.0 strict level 1//",
+ "-//ietf//dtd html 2.0 strict level 2//",
+ "-//ietf//dtd html 2.0 strict//",
+ "-//ietf//dtd html 2.0//",
+ "-//ietf//dtd html 2.1e//",
+ "-//ietf//dtd html 3.0//",
+ "-//ietf//dtd html 3.2 final//",
+ "-//ietf//dtd html 3.2//",
+ "-//ietf//dtd html 3//",
+ "-//ietf//dtd html level 0//",
+ "-//ietf//dtd html level 1//",
+ "-//ietf//dtd html level 2//",
+ "-//ietf//dtd html level 3//",
+ "-//ietf//dtd html strict level 0//",
+ "-//ietf//dtd html strict level 1//",
+ "-//ietf//dtd html strict level 2//",
+ "-//ietf//dtd html strict level 3//",
+ "-//ietf//dtd html strict//",
+ "-//ietf//dtd html//",
+ "-//metrius//dtd metrius presentational//",
+ "-//microsoft//dtd internet explorer 2.0 html strict//",
+ "-//microsoft//dtd internet explorer 2.0 html//",
+ "-//microsoft//dtd internet explorer 2.0 tables//",
+ "-//microsoft//dtd internet explorer 3.0 html strict//",
+ "-//microsoft//dtd internet explorer 3.0 html//",
+ "-//microsoft//dtd internet explorer 3.0 tables//",
+ "-//netscape comm. corp.//dtd html//",
+ "-//netscape comm. corp.//dtd strict html//",
+ "-//o'reilly and associates//dtd html 2.0//",
+ "-//o'reilly and associates//dtd html extended 1.0//",
+ "-//o'reilly and associates//dtd html extended relaxed 1.0//",
+ "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
+ "4.0//",
+ "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
+ "-//spyglass//dtd html 2.0 extended//",
+ "-//sq//dtd html 2.0 hotmetal + extensions//",
+ "-//sun microsystems corp.//dtd hotjava html//",
+ "-//sun microsystems corp.//dtd hotjava strict html//",
+ "-//w3c//dtd html 3 1995-03-24//",
+ "-//w3c//dtd html 3.2 draft//",
+ "-//w3c//dtd html 3.2 final//",
+ "-//w3c//dtd html 3.2//",
+ "-//w3c//dtd html 3.2s draft//",
+ "-//w3c//dtd html 4.0 frameset//",
+ "-//w3c//dtd html 4.0 transitional//",
+ "-//w3c//dtd html experimental 19960712//",
+ "-//w3c//dtd html experimental 970421//",
+ "-//w3c//dtd w3 html//",
+ "-//w3o//dtd w3 html 3.0//",
+ "-//webtechs//dtd mozilla html 2.0//",
+ "-//webtechs//dtd mozilla html//"};
+staticJArray<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = {
+ QUIRKY_PUBLIC_IDS_DATA, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA)};
+void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) {
+ tokenizer = self;
+ stackNodes = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
+ stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
+ templateModeStack = jArray<int32_t, int32_t>::newJArray(64);
+ listOfActiveFormattingElements =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
+ needToDropLF = false;
+ originalMode = INITIAL;
+ templateModePtr = -1;
+ stackNodesIdx = 0;
+ numStackNodes = 0;
+ currentPtr = -1;
+ listPtr = -1;
+ formPointer = nullptr;
+ headPointer = nullptr;
+ start(fragment);
+ charBufferLen = 0;
+ charBuffer = nullptr;
+ framesetOk = true;
+ if (fragment) {
+ nsIContentHandle* elt;
+ if (contextNode) {
+ elt = contextNode;
+ } else {
+ elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes());
+ }
+ if (contextNamespace == kNameSpaceID_SVG) {
+ nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG;
+ if (nsGkAtoms::title == contextName || nsGkAtoms::desc == contextName ||
+ nsGkAtoms::foreignObject == contextName) {
+ elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT;
+ }
+ nsHtml5StackNode* node =
+ createStackNode(elementName, elementName->getCamelCaseName(), elt);
+ currentPtr++;
+ stack[currentPtr] = node;
+ tokenizer->setState(nsHtml5Tokenizer::DATA);
+ mode = FRAMESET_OK;
+ } else if (contextNamespace == kNameSpaceID_MathML) {
+ nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH;
+ if (nsGkAtoms::mi_ == contextName || nsGkAtoms::mo_ == contextName ||
+ nsGkAtoms::mn_ == contextName || nsGkAtoms::ms_ == contextName ||
+ nsGkAtoms::mtext_ == contextName) {
+ elementName = nsHtml5ElementName::ELT_MTEXT;
+ } else if (nsGkAtoms::annotation_xml_ == contextName) {
+ elementName = nsHtml5ElementName::ELT_ANNOTATION_XML;
+ }
+ nsHtml5StackNode* node =
+ createStackNode(elementName, elt, elementName->getName(), false);
+ currentPtr++;
+ stack[currentPtr] = node;
+ tokenizer->setState(nsHtml5Tokenizer::DATA);
+ mode = FRAMESET_OK;
+ } else {
+ nsHtml5StackNode* node =
+ createStackNode(nsHtml5ElementName::ELT_HTML, elt);
+ currentPtr++;
+ stack[currentPtr] = node;
+ if (nsGkAtoms::_template == contextName) {
+ pushTemplateMode(IN_TEMPLATE);
+ }
+ resetTheInsertionMode();
+ formPointer = getFormPointerForContext(contextNode);
+ if (nsGkAtoms::title == contextName ||
+ nsGkAtoms::textarea == contextName) {
+ tokenizer->setState(nsHtml5Tokenizer::RCDATA);
+ } else if (nsGkAtoms::style == contextName ||
+ nsGkAtoms::xmp == contextName ||
+ nsGkAtoms::iframe == contextName ||
+ nsGkAtoms::noembed == contextName ||
+ nsGkAtoms::noframes == contextName ||
+ (scriptingEnabled && nsGkAtoms::noscript == contextName)) {
+ tokenizer->setState(nsHtml5Tokenizer::RAWTEXT);
+ } else if (nsGkAtoms::plaintext == contextName) {
+ tokenizer->setState(nsHtml5Tokenizer::PLAINTEXT);
+ } else if (nsGkAtoms::script == contextName) {
+ tokenizer->setState(nsHtml5Tokenizer::SCRIPT_DATA);
+ } else {
+ tokenizer->setState(nsHtml5Tokenizer::DATA);
+ }
+ }
+ } else {
+ mode = INITIAL;
+ if (tokenizer->isViewingXmlSource()) {
+ nsIContentHandle* elt = createElement(
+ kNameSpaceID_SVG, nsGkAtoms::svg, tokenizer->emptyAttributes(),
+ nullptr, svgCreator(NS_NewSVGSVGElement));
+ nsHtml5StackNode* node =
+ createStackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt);
+ currentPtr++;
+ stack[currentPtr] = node;
+ }
+ }
+}
+
+void nsHtml5TreeBuilder::doctype(nsAtom* name, nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier,
+ bool forceQuirks) {
+ needToDropLF = false;
+ if (!isInForeign() && mode == INITIAL) {
+ nsHtml5String emptyString = nsHtml5Portability::newEmptyString();
+ appendDoctypeToDocument(!name ? nsGkAtoms::_empty : name,
+ !publicIdentifier ? emptyString : publicIdentifier,
+ !systemIdentifier ? emptyString : systemIdentifier);
+ emptyString.Release();
+ if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) {
+ errQuirkyDoctype();
+ documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier);
+ } else if (isAlmostStandards(publicIdentifier, systemIdentifier)) {
+ errAlmostStandardsDoctype();
+ documentModeInternal(ALMOST_STANDARDS_MODE, publicIdentifier,
+ systemIdentifier);
+ } else {
+ documentModeInternal(STANDARDS_MODE, publicIdentifier, systemIdentifier);
+ }
+ mode = BEFORE_HTML;
+ return;
+ }
+ errStrayDoctype();
+ return;
+}
+
+void nsHtml5TreeBuilder::comment(char16_t* buf, int32_t start, int32_t length) {
+ needToDropLF = false;
+ if (!isInForeign()) {
+ switch (mode) {
+ case INITIAL:
+ case BEFORE_HTML:
+ case AFTER_AFTER_BODY:
+ case AFTER_AFTER_FRAMESET: {
+ appendCommentToDocument(buf, start, length);
+ return;
+ }
+ case AFTER_BODY: {
+ flushCharacters();
+ appendComment(stack[0]->node, buf, start, length);
+ return;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+ flushCharacters();
+ appendComment(stack[currentPtr]->node, buf, start, length);
+ return;
+}
+
+void nsHtml5TreeBuilder::characters(const char16_t* buf, int32_t start,
+ int32_t length) {
+ if (tokenizer->isViewingXmlSource()) {
+ return;
+ }
+ if (needToDropLF) {
+ needToDropLF = false;
+ if (buf[start] == '\n') {
+ start++;
+ length--;
+ if (!length) {
+ return;
+ }
+ }
+ }
+ switch (mode) {
+ case IN_BODY:
+ case IN_CELL:
+ case IN_CAPTION: {
+ if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
+ reconstructTheActiveFormattingElements();
+ }
+ [[fallthrough]];
+ }
+ case TEXT: {
+ accumulateCharacters(buf, start, length);
+ return;
+ }
+ case IN_TABLE:
+ case IN_TABLE_BODY:
+ case IN_ROW: {
+ accumulateCharactersForced(buf, start, length);
+ return;
+ }
+ default: {
+ int32_t end = start + length;
+ for (int32_t i = start; i < end; i++) {
+ switch (buf[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\f': {
+ switch (mode) {
+ case INITIAL:
+ case BEFORE_HTML:
+ case BEFORE_HEAD: {
+ start = i + 1;
+ continue;
+ }
+ case IN_HEAD:
+ case IN_HEAD_NOSCRIPT:
+ case AFTER_HEAD:
+ case IN_COLUMN_GROUP:
+ case IN_FRAMESET:
+ case AFTER_FRAMESET: {
+ continue;
+ }
+ case FRAMESET_OK:
+ case IN_TEMPLATE:
+ case IN_BODY:
+ case IN_CELL:
+ case IN_CAPTION: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
+ flushCharacters();
+ reconstructTheActiveFormattingElements();
+ }
+ NS_HTML5_BREAK(charactersloop);
+ }
+ case IN_SELECT:
+ case IN_SELECT_IN_TABLE: {
+ NS_HTML5_BREAK(charactersloop);
+ }
+ case IN_TABLE:
+ case IN_TABLE_BODY:
+ case IN_ROW: {
+ accumulateCharactersForced(buf, i, 1);
+ start = i + 1;
+ continue;
+ }
+ case AFTER_BODY:
+ case AFTER_AFTER_BODY:
+ case AFTER_AFTER_FRAMESET: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ flushCharacters();
+ reconstructTheActiveFormattingElements();
+ continue;
+ }
+ }
+ MOZ_FALLTHROUGH_ASSERT();
+ }
+ default: {
+ switch (mode) {
+ case INITIAL: {
+ documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
+ mode = BEFORE_HTML;
+ i--;
+ continue;
+ }
+ case BEFORE_HTML: {
+ appendHtmlElementToDocumentAndPush();
+ mode = BEFORE_HEAD;
+ i--;
+ continue;
+ }
+ case BEFORE_HEAD: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ flushCharacters();
+ appendToCurrentNodeAndPushHeadElement(
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ i--;
+ continue;
+ }
+ case IN_HEAD: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ flushCharacters();
+ pop();
+ mode = AFTER_HEAD;
+ i--;
+ continue;
+ }
+ case IN_HEAD_NOSCRIPT: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ errNonSpaceInNoscriptInHead();
+ flushCharacters();
+ pop();
+ mode = IN_HEAD;
+ i--;
+ continue;
+ }
+ case AFTER_HEAD: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ flushCharacters();
+ appendToCurrentNodeAndPushBodyElement();
+ mode = FRAMESET_OK;
+ i--;
+ continue;
+ }
+ case FRAMESET_OK: {
+ framesetOk = false;
+ mode = IN_BODY;
+ i--;
+ continue;
+ }
+ case IN_TEMPLATE:
+ case IN_BODY:
+ case IN_CELL:
+ case IN_CAPTION: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
+ flushCharacters();
+ reconstructTheActiveFormattingElements();
+ }
+ NS_HTML5_BREAK(charactersloop);
+ }
+ case IN_TABLE:
+ case IN_TABLE_BODY:
+ case IN_ROW: {
+ accumulateCharactersForced(buf, i, 1);
+ start = i + 1;
+ continue;
+ }
+ case IN_COLUMN_GROUP: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ start = i;
+ }
+ if (!currentPtr || stack[currentPtr]->getGroup() ==
+ nsHtml5TreeBuilder::TEMPLATE) {
+ errNonSpaceInColgroupInFragment();
+ start = i + 1;
+ continue;
+ }
+ flushCharacters();
+ pop();
+ mode = IN_TABLE;
+ i--;
+ continue;
+ }
+ case IN_SELECT:
+ case IN_SELECT_IN_TABLE: {
+ NS_HTML5_BREAK(charactersloop);
+ }
+ case AFTER_BODY: {
+ errNonSpaceAfterBody();
+
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ i--;
+ continue;
+ }
+ case IN_FRAMESET: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ }
+ errNonSpaceInFrameset();
+ start = i + 1;
+ continue;
+ }
+ case AFTER_FRAMESET: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ }
+ errNonSpaceAfterFrameset();
+ start = i + 1;
+ continue;
+ }
+ case AFTER_AFTER_BODY: {
+ errNonSpaceInTrailer();
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ i--;
+ continue;
+ }
+ case AFTER_AFTER_FRAMESET: {
+ if (start < i) {
+ accumulateCharacters(buf, start, i - start);
+ }
+ errNonSpaceInTrailer();
+ start = i + 1;
+ continue;
+ }
+ }
+ }
+ }
+ }
+ charactersloop_end:;
+ if (start < end) {
+ accumulateCharacters(buf, start, end - start);
+ }
+ }
+ }
+}
+
+void nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter() {
+ if (mode == TEXT) {
+ accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
+ return;
+ }
+ if (currentPtr >= 0) {
+ if (isSpecialParentInForeign(stack[currentPtr])) {
+ return;
+ }
+ accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
+ }
+}
+
+void nsHtml5TreeBuilder::zeroOrReplacementCharacter() {
+ zeroOriginatingReplacementCharacter();
+}
+
+void nsHtml5TreeBuilder::eof() {
+ flushCharacters();
+ for (;;) {
+ switch (mode) {
+ case INITIAL: {
+ documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
+ mode = BEFORE_HTML;
+ continue;
+ }
+ case BEFORE_HTML: {
+ appendHtmlElementToDocumentAndPush();
+ mode = BEFORE_HEAD;
+ continue;
+ }
+ case BEFORE_HEAD: {
+ appendToCurrentNodeAndPushHeadElement(
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ continue;
+ }
+ case IN_HEAD: {
+ while (currentPtr > 0) {
+ popOnEof();
+ }
+ mode = AFTER_HEAD;
+ continue;
+ }
+ case IN_HEAD_NOSCRIPT: {
+ while (currentPtr > 1) {
+ popOnEof();
+ }
+ mode = IN_HEAD;
+ continue;
+ }
+ case AFTER_HEAD: {
+ appendToCurrentNodeAndPushBodyElement();
+ mode = IN_BODY;
+ continue;
+ }
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ case IN_TABLE:
+ case IN_SELECT_IN_TABLE:
+ case IN_SELECT:
+ case IN_COLUMN_GROUP:
+ case FRAMESET_OK:
+ case IN_CAPTION:
+ case IN_CELL:
+ case IN_BODY: {
+ if (isTemplateModeStackEmpty()) {
+ NS_HTML5_BREAK(eofloop);
+ }
+ [[fallthrough]];
+ }
+ case IN_TEMPLATE: {
+ int32_t eltPos = findLast(nsGkAtoms::_template);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment);
+ NS_HTML5_BREAK(eofloop);
+ }
+ if (MOZ_UNLIKELY(mViewSource)) {
+ errListUnclosedStartTags(0);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ popTemplateMode();
+ resetTheInsertionMode();
+ continue;
+ }
+ case TEXT: {
+ if (originalMode == AFTER_HEAD) {
+ popOnEof();
+ }
+ popOnEof();
+ mode = originalMode;
+ continue;
+ }
+ case IN_FRAMESET: {
+ NS_HTML5_BREAK(eofloop);
+ }
+ case AFTER_BODY:
+ case AFTER_FRAMESET:
+ case AFTER_AFTER_BODY:
+ case AFTER_AFTER_FRAMESET:
+ default: {
+ NS_HTML5_BREAK(eofloop);
+ }
+ }
+ }
+eofloop_end:;
+ while (currentPtr > 0) {
+ popOnEof();
+ }
+ if (!fragment) {
+ popOnEof();
+ }
+}
+
+void nsHtml5TreeBuilder::endTokenization() {
+ formPointer = nullptr;
+ headPointer = nullptr;
+ contextName = nullptr;
+ contextNode = nullptr;
+ templateModeStack = nullptr;
+ if (stack) {
+ while (currentPtr > -1) {
+ stack[currentPtr]->release(this);
+ currentPtr--;
+ }
+ stack = nullptr;
+ }
+ if (listOfActiveFormattingElements) {
+ while (listPtr > -1) {
+ if (listOfActiveFormattingElements[listPtr]) {
+ listOfActiveFormattingElements[listPtr]->release(this);
+ }
+ listPtr--;
+ }
+ listOfActiveFormattingElements = nullptr;
+ }
+ if (stackNodes) {
+ for (int32_t i = 0; i < numStackNodes; i++) {
+ MOZ_ASSERT(stackNodes[i]->isUnused());
+ delete stackNodes[i];
+ }
+ numStackNodes = 0;
+ stackNodesIdx = 0;
+ stackNodes = nullptr;
+ }
+ charBuffer = nullptr;
+ end();
+}
+
+void nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes,
+ bool selfClosing) {
+ flushCharacters();
+ int32_t eltPos;
+ needToDropLF = false;
+starttagloop:
+ for (;;) {
+ int32_t group = elementName->getGroup();
+ nsAtom* name = elementName->getName();
+ if (isInForeign()) {
+ nsHtml5StackNode* currentNode = stack[currentPtr];
+ int32_t currNs = currentNode->ns;
+ if (!(currentNode->isHtmlIntegrationPoint() ||
+ (currNs == kNameSpaceID_MathML &&
+ ((currentNode->getGroup() == MI_MO_MN_MS_MTEXT &&
+ group != MGLYPH_OR_MALIGNMARK) ||
+ (currentNode->getGroup() == ANNOTATION_XML && group == SVG))))) {
+ switch (group) {
+ case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+ case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+ case BODY:
+ case BR:
+ case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
+ case DD_OR_DT:
+ case UL_OR_OL_OR_DL:
+ case EMBED:
+ case IMG:
+ case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
+ case HEAD:
+ case HR:
+ case LI:
+ case META:
+ case NOBR:
+ case P:
+ case PRE_OR_LISTING:
+ case TABLE:
+ case FONT: {
+ if (!(group == FONT &&
+ !(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) ||
+ attributes->contains(nsHtml5AttributeName::ATTR_FACE) ||
+ attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) {
+ errHtmlStartTagInForeignContext(name);
+ if (!fragment) {
+ while (!isSpecialParentInForeign(stack[currentPtr])) {
+ popForeign(-1, -1);
+ }
+ NS_HTML5_CONTINUE(starttagloop);
+ }
+ }
+ [[fallthrough]];
+ }
+ default: {
+ if (kNameSpaceID_SVG == currNs) {
+ attributes->adjustForSvg();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
+ attributes);
+ }
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ attributes->adjustForMath();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterMathML(elementName,
+ attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
+ attributes);
+ }
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ }
+ }
+ }
+ switch (mode) {
+ case IN_TEMPLATE: {
+ switch (group) {
+ case COL: {
+ popTemplateMode();
+ pushTemplateMode(IN_COLUMN_GROUP);
+ mode = IN_COLUMN_GROUP;
+ continue;
+ }
+ case CAPTION:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT: {
+ popTemplateMode();
+ pushTemplateMode(IN_TABLE);
+ mode = IN_TABLE;
+ continue;
+ }
+ case TR: {
+ popTemplateMode();
+ pushTemplateMode(IN_TABLE_BODY);
+ mode = IN_TABLE_BODY;
+ continue;
+ }
+ case TD_OR_TH: {
+ popTemplateMode();
+ pushTemplateMode(IN_ROW);
+ mode = IN_ROW;
+ continue;
+ }
+ case META: {
+ checkMetaCharset(attributes);
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TITLE: {
+ startTagTitleInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND: {
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case SCRIPT: {
+ startTagScriptInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOFRAMES:
+ case STYLE: {
+ startTagGenericRawText(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TEMPLATE: {
+ startTagTemplateInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ popTemplateMode();
+ pushTemplateMode(IN_BODY);
+ mode = IN_BODY;
+ continue;
+ }
+ }
+ }
+ case IN_ROW: {
+ switch (group) {
+ case TD_OR_TH: {
+ clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR));
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_CELL;
+ insertMarker();
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR: {
+ eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
+ if (!eltPos) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errNoTableRowToClose();
+ NS_HTML5_BREAK(starttagloop);
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ continue;
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_TABLE_BODY: {
+ switch (group) {
+ case TR: {
+ clearStackBackTo(
+ findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_ROW;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TD_OR_TH: {
+ errStartTagInTableBody(name);
+ clearStackBackTo(
+ findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
+ appendToCurrentNodeAndPushElement(
+ nsHtml5ElementName::ELT_TR,
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_ROW;
+ continue;
+ }
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT: {
+ eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
+ if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_TABLE: {
+ for (;;) {
+ switch (group) {
+ case CAPTION: {
+ clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
+ insertMarker();
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_CAPTION;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case COLGROUP: {
+ clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_COLUMN_GROUP;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case COL: {
+ clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
+ appendToCurrentNodeAndPushElement(
+ nsHtml5ElementName::ELT_COLGROUP,
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_COLUMN_GROUP;
+ NS_HTML5_CONTINUE(starttagloop);
+ }
+ case TBODY_OR_THEAD_OR_TFOOT: {
+ clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_TABLE_BODY;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TR:
+ case TD_OR_TH: {
+ clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
+ appendToCurrentNodeAndPushElement(
+ nsHtml5ElementName::ELT_TBODY,
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_TABLE_BODY;
+ NS_HTML5_CONTINUE(starttagloop);
+ }
+ case TEMPLATE: {
+ NS_HTML5_BREAK(intableloop);
+ }
+ case TABLE: {
+ errTableSeenWhileTableOpen();
+ eltPos = findLastInTableScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ NS_HTML5_BREAK(starttagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::table)) {
+ errNoCheckUnclosedElementsOnStack();
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ NS_HTML5_CONTINUE(starttagloop);
+ }
+ case SCRIPT: {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(
+ nsHtml5Tokenizer::SCRIPT_DATA, elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case STYLE: {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
+ elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case INPUT: {
+ errStartTagInTable(name);
+ if (!nsHtml5Portability::
+ lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "hidden", attributes->getValue(
+ nsHtml5AttributeName::ATTR_TYPE))) {
+ NS_HTML5_BREAK(intableloop);
+ }
+ appendVoidInputToCurrent(attributes, formPointer);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case FORM: {
+ if (!!formPointer || isTemplateContents()) {
+ errFormWhenFormOpen();
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ errStartTagInTable(name);
+ appendVoidFormToCurrent(attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ default: {
+ errStartTagInTable(name);
+ NS_HTML5_BREAK(intableloop);
+ }
+ }
+ }
+ intableloop_end:;
+ [[fallthrough]];
+ }
+ case IN_CAPTION: {
+ switch (group) {
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH: {
+ eltPos = findLastInTableScope(nsGkAtoms::caption);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
+ errNoCheckUnclosedElementsOnStack();
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_TABLE;
+ continue;
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_CELL: {
+ switch (group) {
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH: {
+ eltPos = findLastInTableScopeTdTh();
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errNoCellToClose();
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ closeTheCell(eltPos);
+ continue;
+ }
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case FRAMESET_OK: {
+ switch (group) {
+ case FRAMESET: {
+ if (mode == FRAMESET_OK) {
+ if (!currentPtr || stack[1]->getGroup() != BODY) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ errFramesetStart();
+ detachFromParent(stack[1]->node);
+ while (currentPtr > 0) {
+ pop();
+ }
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_FRAMESET;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ } else {
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ case PRE_OR_LISTING:
+ case LI:
+ case DD_OR_DT:
+ case BUTTON:
+ case MARQUEE_OR_APPLET:
+ case OBJECT:
+ case TABLE:
+ case AREA_OR_WBR:
+ case KEYGEN:
+ case BR:
+ case EMBED:
+ case IMG:
+ case INPUT:
+ case HR:
+ case TEXTAREA:
+ case XMP:
+ case IFRAME:
+ case SELECT: {
+ if (mode == FRAMESET_OK &&
+ !(group == INPUT &&
+ nsHtml5Portability::
+ lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "hidden", attributes->getValue(
+ nsHtml5AttributeName::ATTR_TYPE)))) {
+ framesetOk = false;
+ mode = IN_BODY;
+ }
+ [[fallthrough]];
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_BODY: {
+ for (;;) {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND:
+ case META:
+ case STYLE:
+ case SCRIPT:
+ case TITLE:
+ case TEMPLATE: {
+ NS_HTML5_BREAK(inbodyloop);
+ }
+ case BODY: {
+ if (!currentPtr || stack[1]->getGroup() != BODY ||
+ isTemplateContents()) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ errFooSeenWhenFooOpen(name);
+ framesetOk = false;
+ if (mode == FRAMESET_OK) {
+ mode = IN_BODY;
+ }
+ if (addAttributesToBody(attributes)) {
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case P:
+ case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+ case UL_OR_OL_OR_DL:
+ case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: {
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
+ implicitlyCloseP();
+ if (stack[currentPtr]->getGroup() ==
+ H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
+ errHeadingWhenHeadingOpen();
+ pop();
+ }
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case FIELDSET: {
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName, attributes, formPointer);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case PRE_OR_LISTING: {
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ needToDropLF = true;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case FORM: {
+ if (!!formPointer && !isTemplateContents()) {
+ errFormWhenFormOpen();
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushFormElementMayFoster(attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ case LI:
+ case DD_OR_DT: {
+ eltPos = currentPtr;
+ for (;;) {
+ nsHtml5StackNode* node = stack[eltPos];
+ if (node->getGroup() == group) {
+ generateImpliedEndTagsExceptFor(node->name);
+ if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
+ errUnclosedElementsImplied(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ break;
+ } else if (!eltPos || (node->isSpecial() &&
+ (node->ns != kNameSpaceID_XHTML ||
+ (node->name != nsGkAtoms::p &&
+ node->name != nsGkAtoms::address &&
+ node->name != nsGkAtoms::div)))) {
+ break;
+ }
+ eltPos--;
+ }
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case PLAINTEXT: {
+ implicitlyCloseP();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ tokenizer->setStateAndEndTagExpectation(
+ nsHtml5Tokenizer::PLAINTEXT, elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case A: {
+ int32_t activeAPos =
+ findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
+ nsGkAtoms::a);
+ if (activeAPos != -1) {
+ errFooSeenWhenFooOpen(name);
+ nsHtml5StackNode* activeA =
+ listOfActiveFormattingElements[activeAPos];
+ activeA->retain();
+ adoptionAgencyEndTag(nsGkAtoms::a);
+ removeFromStack(activeA);
+ activeAPos = findInListOfActiveFormattingElements(activeA);
+ if (activeAPos != -1) {
+ removeFromListOfActiveFormattingElements(activeAPos);
+ }
+ activeA->release(this);
+ }
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+ case FONT: {
+ reconstructTheActiveFormattingElements();
+ maybeForgetEarlierDuplicateFormattingElement(
+ elementName->getName(), attributes);
+ appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOBR: {
+ reconstructTheActiveFormattingElements();
+ if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
+ findLastInScope(nsGkAtoms::nobr)) {
+ errFooSeenWhenFooOpen(name);
+ adoptionAgencyEndTag(nsGkAtoms::nobr);
+ reconstructTheActiveFormattingElements();
+ }
+ appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BUTTON: {
+ eltPos = findLastInScope(name);
+ if (eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errFooSeenWhenFooOpen(name);
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElementsImplied(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ NS_HTML5_CONTINUE(starttagloop);
+ } else {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName, attributes, formPointer);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ case OBJECT: {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName, attributes, formPointer);
+ insertMarker();
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case MARQUEE_OR_APPLET: {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ insertMarker();
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TABLE: {
+ if (!quirks) {
+ implicitlyCloseP();
+ }
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ mode = IN_TABLE;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BR:
+ case EMBED:
+ case AREA_OR_WBR:
+ case KEYGEN: {
+ reconstructTheActiveFormattingElements();
+ [[fallthrough]];
+ }
+ case PARAM_OR_SOURCE_OR_TRACK: {
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case HR: {
+ implicitlyCloseP();
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case IMAGE: {
+ errImage();
+ elementName = nsHtml5ElementName::ELT_IMG;
+ NS_HTML5_CONTINUE(starttagloop);
+ }
+ case IMG:
+ case INPUT: {
+ reconstructTheActiveFormattingElements();
+ appendVoidElementToCurrentMayFoster(elementName, attributes,
+ formPointer);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TEXTAREA: {
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName, attributes, formPointer);
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
+ elementName);
+ originalMode = mode;
+ mode = TEXT;
+ needToDropLF = true;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case XMP: {
+ implicitlyCloseP();
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
+ elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOSCRIPT: {
+ if (!scriptingEnabled) {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ [[fallthrough]];
+ }
+ case NOFRAMES:
+ case IFRAME:
+ case NOEMBED: {
+ startTagGenericRawText(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case SELECT: {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName, attributes, formPointer);
+ switch (mode) {
+ case IN_TABLE:
+ case IN_CAPTION:
+ case IN_COLUMN_GROUP:
+ case IN_TABLE_BODY:
+ case IN_ROW:
+ case IN_CELL: {
+ mode = IN_SELECT_IN_TABLE;
+ break;
+ }
+ default: {
+ mode = IN_SELECT;
+ break;
+ }
+ }
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case OPTGROUP:
+ case OPTION: {
+ if (isCurrent(nsGkAtoms::option)) {
+ pop();
+ }
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case RB_OR_RTC: {
+ eltPos = findLastInScope(nsGkAtoms::ruby);
+ if (eltPos != NOT_FOUND_ON_STACK) {
+ generateImpliedEndTags();
+ }
+ if (eltPos != currentPtr) {
+ if (eltPos == NOT_FOUND_ON_STACK) {
+ errStartTagSeenWithoutRuby(name);
+ } else {
+ errUnclosedChildrenInRuby();
+ }
+ }
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case RT_OR_RP: {
+ eltPos = findLastInScope(nsGkAtoms::ruby);
+ if (eltPos != NOT_FOUND_ON_STACK) {
+ generateImpliedEndTagsExceptFor(nsGkAtoms::rtc);
+ }
+ if (eltPos != currentPtr) {
+ if (!isCurrent(nsGkAtoms::rtc)) {
+ if (eltPos == NOT_FOUND_ON_STACK) {
+ errStartTagSeenWithoutRuby(name);
+ } else {
+ errUnclosedChildrenInRuby();
+ }
+ }
+ }
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case MATH: {
+ reconstructTheActiveFormattingElements();
+ attributes->adjustForMath();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterMathML(elementName,
+ attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
+ attributes);
+ }
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case SVG: {
+ reconstructTheActiveFormattingElements();
+ attributes->adjustForSvg();
+ if (selfClosing) {
+ appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
+ selfClosing = false;
+ } else {
+ appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
+ attributes);
+ }
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ case FRAME:
+ case FRAMESET:
+ case HEAD: {
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case OUTPUT: {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(
+ elementName, attributes, formPointer);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ reconstructTheActiveFormattingElements();
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ }
+ inbodyloop_end:;
+ [[fallthrough]];
+ }
+ case IN_HEAD: {
+ for (;;) {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND: {
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case META: {
+ NS_HTML5_BREAK(inheadloop);
+ }
+ case TITLE: {
+ startTagTitleInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOSCRIPT: {
+ if (scriptingEnabled) {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(
+ nsHtml5Tokenizer::RAWTEXT, elementName);
+ } else {
+ appendToCurrentNodeAndPushElementMayFoster(elementName,
+ attributes);
+ mode = IN_HEAD_NOSCRIPT;
+ }
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case SCRIPT: {
+ startTagScriptInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case STYLE:
+ case NOFRAMES: {
+ startTagGenericRawText(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case HEAD: {
+ errFooSeenWhenFooOpen(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TEMPLATE: {
+ startTagTemplateInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ pop();
+ mode = AFTER_HEAD;
+ NS_HTML5_CONTINUE(starttagloop);
+ }
+ }
+ }
+ inheadloop_end:;
+ [[fallthrough]];
+ }
+ case IN_HEAD_NOSCRIPT: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case LINK_OR_BASEFONT_OR_BGSOUND: {
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case META: {
+ checkMetaCharset(attributes);
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case STYLE:
+ case NOFRAMES: {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
+ elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case HEAD: {
+ errFooSeenWhenFooOpen(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOSCRIPT: {
+ errFooSeenWhenFooOpen(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ errBadStartTagInNoscriptInHead(name);
+ pop();
+ mode = IN_HEAD;
+ continue;
+ }
+ }
+ }
+ case IN_COLUMN_GROUP: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case COL: {
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TEMPLATE: {
+ startTagTemplateInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ if (!currentPtr || stack[currentPtr]->getGroup() == TEMPLATE) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errGarbageInColgroup();
+ NS_HTML5_BREAK(starttagloop);
+ }
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ }
+ }
+ case IN_SELECT_IN_TABLE: {
+ switch (group) {
+ case CAPTION:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH:
+ case TABLE: {
+ errStartTagWithSelectOpen(name);
+ eltPos = findLastInTableScope(nsGkAtoms::select);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue;
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_SELECT: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case OPTION: {
+ if (isCurrent(nsGkAtoms::option)) {
+ pop();
+ }
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case OPTGROUP: {
+ if (isCurrent(nsGkAtoms::option)) {
+ pop();
+ }
+ if (isCurrent(nsGkAtoms::optgroup)) {
+ pop();
+ }
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case SELECT: {
+ errStartSelectWhereEndSelectExpected();
+ eltPos = findLastInTableScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment);
+ errNoSelectInTableScope();
+ NS_HTML5_BREAK(starttagloop);
+ } else {
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ case INPUT:
+ case TEXTAREA: {
+ errStartTagWithSelectOpen(name);
+ eltPos = findLastInTableScope(nsGkAtoms::select);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue;
+ }
+ case SCRIPT: {
+ startTagScriptInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TEMPLATE: {
+ startTagTemplateInHead(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ }
+ case AFTER_BODY: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ errStrayStartTag(name);
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ }
+ }
+ case IN_FRAMESET: {
+ switch (group) {
+ case FRAMESET: {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case FRAME: {
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case AFTER_FRAMESET: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOFRAMES: {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
+ elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ }
+ case INITIAL: {
+ errStartTagWithoutDoctype();
+ documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
+ mode = BEFORE_HTML;
+ continue;
+ }
+ case BEFORE_HTML: {
+ switch (group) {
+ case HTML: {
+ if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+ appendHtmlElementToDocumentAndPush();
+ } else {
+ appendHtmlElementToDocumentAndPush(attributes);
+ }
+ mode = BEFORE_HEAD;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ appendHtmlElementToDocumentAndPush();
+ mode = BEFORE_HEAD;
+ continue;
+ }
+ }
+ }
+ case BEFORE_HEAD: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case HEAD: {
+ appendToCurrentNodeAndPushHeadElement(attributes);
+ mode = IN_HEAD;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ appendToCurrentNodeAndPushHeadElement(
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ continue;
+ }
+ }
+ }
+ case AFTER_HEAD: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BODY: {
+ if (!attributes->getLength()) {
+ appendToCurrentNodeAndPushBodyElement();
+ } else {
+ appendToCurrentNodeAndPushBodyElement(attributes);
+ }
+ framesetOk = false;
+ mode = IN_BODY;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case FRAMESET: {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ mode = IN_FRAMESET;
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TEMPLATE: {
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ nsHtml5StackNode* headOnStack = stack[currentPtr];
+ startTagTemplateInHead(elementName, attributes);
+ removeFromStack(headOnStack);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case BASE:
+ case LINK_OR_BASEFONT_OR_BGSOUND: {
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ pop();
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case META: {
+ errFooBetweenHeadAndBody(name);
+ checkMetaCharset(attributes);
+ pushHeadPointerOntoStack();
+ appendVoidElementToCurrentMayFoster(elementName, attributes);
+ selfClosing = false;
+ pop();
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case SCRIPT: {
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(
+ nsHtml5Tokenizer::SCRIPT_DATA, elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case STYLE:
+ case NOFRAMES: {
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
+ elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case TITLE: {
+ errFooBetweenHeadAndBody(name);
+ pushHeadPointerOntoStack();
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
+ elementName);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case HEAD: {
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ appendToCurrentNodeAndPushBodyElement();
+ mode = FRAMESET_OK;
+ continue;
+ }
+ }
+ }
+ case AFTER_AFTER_BODY: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ errStrayStartTag(name);
+
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ }
+ }
+ case AFTER_AFTER_FRAMESET: {
+ switch (group) {
+ case HTML: {
+ errStrayStartTag(name);
+ if (!fragment && !isTemplateContents()) {
+ addAttributesToHtml(attributes);
+ attributes = nullptr;
+ }
+ NS_HTML5_BREAK(starttagloop);
+ }
+ case NOFRAMES: {
+ startTagGenericRawText(elementName, attributes);
+ attributes = nullptr;
+ NS_HTML5_BREAK(starttagloop);
+ }
+ default: {
+ errStrayStartTag(name);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ }
+ case TEXT: {
+ MOZ_ASSERT(false);
+ NS_HTML5_BREAK(starttagloop);
+ }
+ }
+ }
+starttagloop_end:;
+ if (selfClosing) {
+ errSelfClosing();
+ }
+ if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+ delete attributes;
+ }
+}
+
+void nsHtml5TreeBuilder::startTagTitleInHead(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
+ elementName);
+}
+
+void nsHtml5TreeBuilder::startTagGenericRawText(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
+ elementName);
+}
+
+void nsHtml5TreeBuilder::startTagScriptInHead(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
+ originalMode = mode;
+ mode = TEXT;
+ tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA,
+ elementName);
+}
+
+void nsHtml5TreeBuilder::startTagTemplateInHead(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ appendToCurrentNodeAndPushElement(elementName, attributes);
+ insertMarker();
+ framesetOk = false;
+ originalMode = mode;
+ mode = IN_TEMPLATE;
+ pushTemplateMode(IN_TEMPLATE);
+}
+
+bool nsHtml5TreeBuilder::isTemplateContents() {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
+ findLast(nsGkAtoms::_template);
+}
+
+bool nsHtml5TreeBuilder::isTemplateModeStackEmpty() {
+ return templateModePtr == -1;
+}
+
+bool nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode) {
+ int32_t ns = stackNode->ns;
+ return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) ||
+ ((kNameSpaceID_MathML == ns) &&
+ (stackNode->getGroup() == MI_MO_MN_MS_MTEXT));
+}
+
+nsHtml5String nsHtml5TreeBuilder::extractCharsetFromContent(
+ nsHtml5String attributeValue, nsHtml5TreeBuilder* tb) {
+ int32_t charsetState = CHARSET_INITIAL;
+ int32_t start = -1;
+ int32_t end = -1;
+ autoJArray<char16_t, int32_t> buffer =
+ nsHtml5Portability::newCharArrayFromString(attributeValue);
+ for (int32_t i = 0; i < buffer.length; i++) {
+ char16_t c = buffer[i];
+ switch (charsetState) {
+ case CHARSET_INITIAL: {
+ switch (c) {
+ case 'c':
+ case 'C': {
+ charsetState = CHARSET_C;
+ continue;
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ case CHARSET_C: {
+ switch (c) {
+ case 'h':
+ case 'H': {
+ charsetState = CHARSET_H;
+ continue;
+ }
+ default: {
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ }
+ }
+ case CHARSET_H: {
+ switch (c) {
+ case 'a':
+ case 'A': {
+ charsetState = CHARSET_A;
+ continue;
+ }
+ default: {
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ }
+ }
+ case CHARSET_A: {
+ switch (c) {
+ case 'r':
+ case 'R': {
+ charsetState = CHARSET_R;
+ continue;
+ }
+ default: {
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ }
+ }
+ case CHARSET_R: {
+ switch (c) {
+ case 's':
+ case 'S': {
+ charsetState = CHARSET_S;
+ continue;
+ }
+ default: {
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ }
+ }
+ case CHARSET_S: {
+ switch (c) {
+ case 'e':
+ case 'E': {
+ charsetState = CHARSET_E;
+ continue;
+ }
+ default: {
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ }
+ }
+ case CHARSET_E: {
+ switch (c) {
+ case 't':
+ case 'T': {
+ charsetState = CHARSET_T;
+ continue;
+ }
+ default: {
+ charsetState = CHARSET_INITIAL;
+ continue;
+ }
+ }
+ }
+ case CHARSET_T: {
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case ' ': {
+ continue;
+ }
+ case '=': {
+ charsetState = CHARSET_EQUALS;
+ continue;
+ }
+ default: {
+ return nullptr;
+ }
+ }
+ }
+ case CHARSET_EQUALS: {
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case ' ': {
+ continue;
+ }
+ case '\'': {
+ start = i + 1;
+ charsetState = CHARSET_SINGLE_QUOTED;
+ continue;
+ }
+ case '\"': {
+ start = i + 1;
+ charsetState = CHARSET_DOUBLE_QUOTED;
+ continue;
+ }
+ default: {
+ start = i;
+ charsetState = CHARSET_UNQUOTED;
+ continue;
+ }
+ }
+ }
+ case CHARSET_SINGLE_QUOTED: {
+ switch (c) {
+ case '\'': {
+ end = i;
+ NS_HTML5_BREAK(charsetloop);
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ case CHARSET_DOUBLE_QUOTED: {
+ switch (c) {
+ case '\"': {
+ end = i;
+ NS_HTML5_BREAK(charsetloop);
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ case CHARSET_UNQUOTED: {
+ switch (c) {
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case ' ':
+ case ';': {
+ end = i;
+ NS_HTML5_BREAK(charsetloop);
+ }
+ default: {
+ continue;
+ }
+ }
+ }
+ }
+ }
+charsetloop_end:;
+ if (start != -1) {
+ if (end == -1) {
+ if (charsetState == CHARSET_UNQUOTED) {
+ end = buffer.length;
+ } else {
+ return nullptr;
+ }
+ }
+ return nsHtml5Portability::newStringFromBuffer(buffer, start, end - start,
+ tb, false);
+ }
+ return nullptr;
+}
+
+void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) {
+ nsHtml5String charset =
+ attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
+ if (charset) {
+ if (tokenizer->internalEncodingDeclaration(charset)) {
+ requestSuspension();
+ return;
+ }
+ return;
+ }
+ if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "content-type",
+ attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
+ return;
+ }
+ nsHtml5String content =
+ attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
+ if (content) {
+ nsHtml5String extract =
+ nsHtml5TreeBuilder::extractCharsetFromContent(content, this);
+ if (extract) {
+ if (tokenizer->internalEncodingDeclaration(extract)) {
+ requestSuspension();
+ }
+ }
+ extract.Release();
+ }
+}
+
+void nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) {
+ flushCharacters();
+ needToDropLF = false;
+ int32_t eltPos;
+ int32_t group = elementName->getGroup();
+ nsAtom* name = elementName->getName();
+ for (;;) {
+ if (isInForeign()) {
+ if (stack[currentPtr]->name != name) {
+ if (!currentPtr) {
+ errStrayEndTag(name);
+ } else {
+ errEndTagDidNotMatchCurrentOpenElement(name,
+ stack[currentPtr]->popName);
+ }
+ }
+ eltPos = currentPtr;
+ int32_t origPos = currentPtr;
+ for (;;) {
+ if (!eltPos) {
+ MOZ_ASSERT(fragment,
+ "We can get this close to the root of the stack in "
+ "foreign content only in the fragment case.");
+ NS_HTML5_BREAK(endtagloop);
+ }
+ if (stack[eltPos]->name == name) {
+ while (currentPtr >= eltPos) {
+ popForeign(origPos, eltPos);
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ if (stack[--eltPos]->ns == kNameSpaceID_XHTML) {
+ break;
+ }
+ }
+ }
+ switch (mode) {
+ case IN_TEMPLATE: {
+ switch (group) {
+ case TEMPLATE: {
+ break;
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ [[fallthrough]];
+ }
+ case IN_ROW: {
+ switch (group) {
+ case TR: {
+ eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
+ if (!eltPos) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errNoTableRowToClose();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TABLE: {
+ eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
+ if (!eltPos) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errNoTableRowToClose();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ continue;
+ }
+ case TBODY_OR_THEAD_OR_TFOOT: {
+ if (findLastInTableScope(name) ==
+ nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
+ if (!eltPos) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errNoTableRowToClose();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE_BODY;
+ continue;
+ }
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TD_OR_TH: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_TABLE_BODY: {
+ switch (group) {
+ case TBODY_OR_THEAD_OR_TFOOT: {
+ eltPos = findLastOrRoot(name);
+ if (!eltPos) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TABLE: {
+ eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
+ if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ clearStackBackTo(eltPos);
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TD_OR_TH:
+ case TR: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_TABLE: {
+ switch (group) {
+ case TABLE: {
+ eltPos = findLast(nsGkAtoms::table);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case TR: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TEMPLATE: {
+ break;
+ }
+ default: {
+ errStrayEndTag(name);
+ }
+ }
+ [[fallthrough]];
+ }
+ case IN_CAPTION: {
+ switch (group) {
+ case CAPTION: {
+ eltPos = findLastInTableScope(nsGkAtoms::caption);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ NS_HTML5_BREAK(endtagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_TABLE;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TABLE: {
+ eltPos = findLastInTableScope(nsGkAtoms::caption);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_TABLE;
+ continue;
+ }
+ case BODY:
+ case COL:
+ case COLGROUP:
+ case HTML:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case TR: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_CELL: {
+ switch (group) {
+ case TD_OR_TH: {
+ eltPos = findLastInTableScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_ROW;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TABLE:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR: {
+ if (findLastInTableScope(name) ==
+ nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(name == nsGkAtoms::tbody || name == nsGkAtoms::tfoot ||
+ name == nsGkAtoms::thead || fragment ||
+ isTemplateContents());
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ closeTheCell(findLastInTableScopeTdTh());
+ continue;
+ }
+ case BODY:
+ case CAPTION:
+ case COL:
+ case COLGROUP:
+ case HTML: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case FRAMESET_OK:
+ case IN_BODY: {
+ switch (group) {
+ case BODY: {
+ if (!isSecondOnStackBody()) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ MOZ_ASSERT(currentPtr >= 1);
+ if (MOZ_UNLIKELY(mViewSource)) {
+ for (int32_t i = 2; i <= currentPtr; i++) {
+ switch (stack[i]->getGroup()) {
+ case DD_OR_DT:
+ case LI:
+ case OPTGROUP:
+ case OPTION:
+ case P:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ case TD_OR_TH:
+ case TBODY_OR_THEAD_OR_TFOOT: {
+ break;
+ }
+ default: {
+ errEndWithUnclosedElements(name);
+ NS_HTML5_BREAK(uncloseloop1);
+ }
+ }
+ }
+ uncloseloop1_end:;
+ }
+ mode = AFTER_BODY;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case HTML: {
+ if (!isSecondOnStackBody()) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ if (MOZ_UNLIKELY(mViewSource)) {
+ for (int32_t i = 0; i <= currentPtr; i++) {
+ switch (stack[i]->getGroup()) {
+ case DD_OR_DT:
+ case LI:
+ case P:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case BODY:
+ case HTML: {
+ break;
+ }
+ default: {
+ errEndWithUnclosedElements(name);
+ NS_HTML5_BREAK(uncloseloop2);
+ }
+ }
+ }
+ uncloseloop2_end:;
+ }
+ mode = AFTER_BODY;
+ continue;
+ }
+ case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
+ case UL_OR_OL_OR_DL:
+ case PRE_OR_LISTING:
+ case FIELDSET:
+ case BUTTON:
+ case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: {
+ eltPos = findLastInScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ } else {
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case FORM: {
+ if (!isTemplateContents()) {
+ if (!formPointer) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ formPointer = nullptr;
+ eltPos = findLastInScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ removeFromStack(eltPos);
+ NS_HTML5_BREAK(endtagloop);
+ } else {
+ eltPos = findLastInScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ case P: {
+ eltPos = findLastInButtonScope(nsGkAtoms::p);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errNoElementToCloseButEndTagSeen(nsGkAtoms::p);
+ if (isInForeign()) {
+ errHtmlStartTagInForeignContext(name);
+ while (currentPtr >= 0 &&
+ stack[currentPtr]->ns != kNameSpaceID_XHTML) {
+ pop();
+ }
+ }
+ appendVoidElementToCurrentMayFoster(
+ elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ generateImpliedEndTagsExceptFor(nsGkAtoms::p);
+ MOZ_ASSERT(eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK);
+ if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case LI: {
+ eltPos = findLastInListScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errNoElementToCloseButEndTagSeen(name);
+ } else {
+ generateImpliedEndTagsExceptFor(name);
+ if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case DD_OR_DT: {
+ eltPos = findLastInScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errNoElementToCloseButEndTagSeen(name);
+ } else {
+ generateImpliedEndTagsExceptFor(name);
+ if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
+ eltPos = findLastInScopeHn();
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ } else {
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case OBJECT:
+ case MARQUEE_OR_APPLET: {
+ eltPos = findLastInScope(name);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(name);
+ } else {
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case BR: {
+ errEndTagBr();
+ if (isInForeign()) {
+ errHtmlStartTagInForeignContext(name);
+ while (currentPtr >= 0 &&
+ stack[currentPtr]->ns != kNameSpaceID_XHTML) {
+ pop();
+ }
+ }
+ reconstructTheActiveFormattingElements();
+ appendVoidElementToCurrentMayFoster(
+ elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TEMPLATE: {
+ break;
+ }
+ case AREA_OR_WBR:
+ case KEYGEN:
+ case PARAM_OR_SOURCE_OR_TRACK:
+ case EMBED:
+ case IMG:
+ case IMAGE:
+ case INPUT:
+ case HR:
+ case IFRAME:
+ case NOEMBED:
+ case NOFRAMES:
+ case SELECT:
+ case TABLE:
+ case TEXTAREA: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case NOSCRIPT: {
+ if (scriptingEnabled) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ [[fallthrough]];
+ }
+ case A:
+ case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
+ case FONT:
+ case NOBR: {
+ if (adoptionAgencyEndTag(name)) {
+ NS_HTML5_BREAK(endtagloop);
+ }
+ [[fallthrough]];
+ }
+ default: {
+ if (isCurrent(name)) {
+ pop();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ eltPos = currentPtr;
+ for (;;) {
+ nsHtml5StackNode* node = stack[eltPos];
+ if (node->ns == kNameSpaceID_XHTML && node->name == name) {
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
+ errUnclosedElements(eltPos, name);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ NS_HTML5_BREAK(endtagloop);
+ } else if (!eltPos || node->isSpecial()) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ eltPos--;
+ }
+ }
+ }
+ [[fallthrough]];
+ }
+ case IN_HEAD: {
+ switch (group) {
+ case HEAD: {
+ pop();
+ mode = AFTER_HEAD;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case BR:
+ case HTML:
+ case BODY: {
+ pop();
+ mode = AFTER_HEAD;
+ continue;
+ }
+ case TEMPLATE: {
+ endTagTemplateInHead();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case IN_HEAD_NOSCRIPT: {
+ switch (group) {
+ case NOSCRIPT: {
+ pop();
+ mode = IN_HEAD;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case BR: {
+ errStrayEndTag(name);
+ pop();
+ mode = IN_HEAD;
+ continue;
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case IN_COLUMN_GROUP: {
+ switch (group) {
+ case COLGROUP: {
+ if (!currentPtr ||
+ stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errGarbageInColgroup();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ pop();
+ mode = IN_TABLE;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case COL: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TEMPLATE: {
+ endTagTemplateInHead();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default: {
+ if (!currentPtr ||
+ stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
+ MOZ_ASSERT(fragment || isTemplateContents());
+ errGarbageInColgroup();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ pop();
+ mode = IN_TABLE;
+ continue;
+ }
+ }
+ }
+ case IN_SELECT_IN_TABLE: {
+ switch (group) {
+ case CAPTION:
+ case TABLE:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TR:
+ case TD_OR_TH: {
+ errEndTagSeenWithSelectOpen(name);
+ if (findLastInTableScope(name) !=
+ nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ eltPos = findLastInTableScope(nsGkAtoms::select);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ continue;
+ } else {
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ default:; // fall through
+ }
+ [[fallthrough]];
+ }
+ case IN_SELECT: {
+ switch (group) {
+ case OPTION: {
+ if (isCurrent(nsGkAtoms::option)) {
+ pop();
+ NS_HTML5_BREAK(endtagloop);
+ } else {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ case OPTGROUP: {
+ if (isCurrent(nsGkAtoms::option) &&
+ nsGkAtoms::optgroup == stack[currentPtr - 1]->name) {
+ pop();
+ }
+ if (isCurrent(nsGkAtoms::optgroup)) {
+ pop();
+ } else {
+ errStrayEndTag(name);
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case SELECT: {
+ eltPos = findLastInTableScope(nsGkAtoms::select);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ MOZ_ASSERT(fragment);
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ resetTheInsertionMode();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TEMPLATE: {
+ endTagTemplateInHead();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case AFTER_BODY: {
+ switch (group) {
+ case HTML: {
+ if (fragment) {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ } else {
+ mode = AFTER_AFTER_BODY;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ default: {
+ errEndTagAfterBody();
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ }
+ }
+ case IN_FRAMESET: {
+ switch (group) {
+ case FRAMESET: {
+ if (!currentPtr) {
+ MOZ_ASSERT(fragment);
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ pop();
+ if ((!fragment) && !isCurrent(nsGkAtoms::frameset)) {
+ mode = AFTER_FRAMESET;
+ }
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case AFTER_FRAMESET: {
+ switch (group) {
+ case HTML: {
+ mode = AFTER_AFTER_FRAMESET;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case INITIAL: {
+ errEndTagSeenWithoutDoctype();
+ documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
+ mode = BEFORE_HTML;
+ continue;
+ }
+ case BEFORE_HTML: {
+ switch (group) {
+ case HEAD:
+ case BR:
+ case HTML:
+ case BODY: {
+ appendHtmlElementToDocumentAndPush();
+ mode = BEFORE_HEAD;
+ continue;
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case BEFORE_HEAD: {
+ switch (group) {
+ case HEAD:
+ case BR:
+ case HTML:
+ case BODY: {
+ appendToCurrentNodeAndPushHeadElement(
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
+ mode = IN_HEAD;
+ continue;
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case AFTER_HEAD: {
+ switch (group) {
+ case TEMPLATE: {
+ endTagTemplateInHead();
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case HTML:
+ case BODY:
+ case BR: {
+ appendToCurrentNodeAndPushBodyElement();
+ mode = FRAMESET_OK;
+ continue;
+ }
+ default: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+ case AFTER_AFTER_BODY: {
+ errStrayEndTag(name);
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ continue;
+ }
+ case AFTER_AFTER_FRAMESET: {
+ errStrayEndTag(name);
+ NS_HTML5_BREAK(endtagloop);
+ }
+ case TEXT: {
+ pop();
+ if (originalMode == AFTER_HEAD) {
+ silentPop();
+ }
+ mode = originalMode;
+ NS_HTML5_BREAK(endtagloop);
+ }
+ }
+ }
+endtagloop_end:;
+}
+
+void nsHtml5TreeBuilder::endTagTemplateInHead() {
+ int32_t eltPos = findLast(nsGkAtoms::_template);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ errStrayEndTag(nsGkAtoms::_template);
+ return;
+ }
+ generateImpliedEndTagsThoroughly();
+ if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::_template)) {
+ errUnclosedElements(eltPos, nsGkAtoms::_template);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ popTemplateMode();
+ resetTheInsertionMode();
+}
+
+int32_t
+nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML &&
+ (stack[i]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT ||
+ stack[i]->getGroup() == nsHtml5TreeBuilder::TEMPLATE)) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+int32_t nsHtml5TreeBuilder::findLast(nsAtom* name) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
+ return i;
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+int32_t nsHtml5TreeBuilder::findLastInTableScope(nsAtom* name) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML) {
+ if (stack[i]->name == name) {
+ return i;
+ } else if (stack[i]->name == nsGkAtoms::table ||
+ stack[i]->name == nsGkAtoms::_template) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+int32_t nsHtml5TreeBuilder::findLastInButtonScope(nsAtom* name) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML) {
+ if (stack[i]->name == name) {
+ return i;
+ } else if (stack[i]->name == nsGkAtoms::button) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ if (stack[i]->isScoping()) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+int32_t nsHtml5TreeBuilder::findLastInScope(nsAtom* name) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
+ return i;
+ } else if (stack[i]->isScoping()) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+int32_t nsHtml5TreeBuilder::findLastInListScope(nsAtom* name) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML) {
+ if (stack[i]->name == name) {
+ return i;
+ } else if (stack[i]->name == nsGkAtoms::ul ||
+ stack[i]->name == nsGkAtoms::ol) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ if (stack[i]->isScoping()) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+int32_t nsHtml5TreeBuilder::findLastInScopeHn() {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->getGroup() ==
+ nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
+ return i;
+ } else if (stack[i]->isScoping()) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+void nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom* name) {
+ for (;;) {
+ nsHtml5StackNode* node = stack[currentPtr];
+ switch (node->getGroup()) {
+ case P:
+ case LI:
+ case DD_OR_DT:
+ case OPTION:
+ case OPTGROUP:
+ case RB_OR_RTC:
+ case RT_OR_RP: {
+ if (node->ns == kNameSpaceID_XHTML && node->name == name) {
+ return;
+ }
+ pop();
+ continue;
+ }
+ default: {
+ return;
+ }
+ }
+ }
+}
+
+void nsHtml5TreeBuilder::generateImpliedEndTags() {
+ for (;;) {
+ switch (stack[currentPtr]->getGroup()) {
+ case P:
+ case LI:
+ case DD_OR_DT:
+ case OPTION:
+ case OPTGROUP:
+ case RB_OR_RTC:
+ case RT_OR_RP: {
+ pop();
+ continue;
+ }
+ default: {
+ return;
+ }
+ }
+ }
+}
+
+void nsHtml5TreeBuilder::generateImpliedEndTagsThoroughly() {
+ for (;;) {
+ switch (stack[currentPtr]->getGroup()) {
+ case CAPTION:
+ case COLGROUP:
+ case DD_OR_DT:
+ case LI:
+ case OPTGROUP:
+ case OPTION:
+ case P:
+ case RB_OR_RTC:
+ case RT_OR_RP:
+ case TBODY_OR_THEAD_OR_TFOOT:
+ case TD_OR_TH:
+ case TR: {
+ pop();
+ continue;
+ }
+ default: {
+ return;
+ }
+ }
+ }
+}
+
+bool nsHtml5TreeBuilder::isSecondOnStackBody() {
+ return currentPtr >= 1 && stack[1]->getGroup() == nsHtml5TreeBuilder::BODY;
+}
+
+void nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m,
+ nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier) {
+ if (forceNoQuirks) {
+ quirks = false;
+ this->documentMode(STANDARDS_MODE);
+ return;
+ }
+ quirks = (m == QUIRKS_MODE);
+ this->documentMode(m);
+}
+
+bool nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier) {
+ if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier)) {
+ return true;
+ }
+ if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier)) {
+ return true;
+ }
+ if (systemIdentifier) {
+ if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
+ return true;
+ }
+ if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool nsHtml5TreeBuilder::isQuirky(nsAtom* name, nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier,
+ bool forceQuirks) {
+ if (forceQuirks) {
+ return true;
+ }
+ if (name != nsGkAtoms::html) {
+ return true;
+ }
+ if (publicIdentifier) {
+ for (int32_t i = 0; i < nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS.length; i++) {
+ if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
+ return true;
+ }
+ }
+ if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) ||
+ nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "-/w3c/dtd html 4.0 transitional/en", publicIdentifier) ||
+ nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "html", publicIdentifier)) {
+ return true;
+ }
+ }
+ if (!systemIdentifier) {
+ if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
+ return true;
+ } else if (nsHtml5Portability::
+ lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
+ "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
+ return true;
+ }
+ } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
+ systemIdentifier)) {
+ return true;
+ }
+ return false;
+}
+
+void nsHtml5TreeBuilder::closeTheCell(int32_t eltPos) {
+ generateImpliedEndTags();
+ if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
+ errUnclosedElementsCell(eltPos);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ mode = IN_ROW;
+ return;
+}
+
+int32_t nsHtml5TreeBuilder::findLastInTableScopeTdTh() {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ nsAtom* name = stack[i]->name;
+ if (stack[i]->ns == kNameSpaceID_XHTML) {
+ if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
+ return i;
+ } else if (name == nsGkAtoms::table || name == nsGkAtoms::_template) {
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+ }
+ }
+ }
+ return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
+}
+
+void nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos) {
+ int32_t eltGroup = stack[eltPos]->getGroup();
+ while (currentPtr > eltPos) {
+ if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
+ stack[currentPtr]->getGroup() == TEMPLATE &&
+ (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT ||
+ eltGroup == TR || !eltPos)) {
+ return;
+ }
+ pop();
+ }
+}
+
+void nsHtml5TreeBuilder::resetTheInsertionMode() {
+ nsHtml5StackNode* node;
+ nsAtom* name;
+ int32_t ns;
+ for (int32_t i = currentPtr; i >= 0; i--) {
+ node = stack[i];
+ name = node->name;
+ ns = node->ns;
+ if (!i) {
+ if (!(contextNamespace == kNameSpaceID_XHTML &&
+ (contextName == nsGkAtoms::td || contextName == nsGkAtoms::th))) {
+ if (fragment) {
+ name = contextName;
+ ns = contextNamespace;
+ }
+ } else {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ }
+ }
+ if (nsGkAtoms::select == name) {
+ int32_t ancestorIndex = i;
+ while (ancestorIndex > 0) {
+ nsHtml5StackNode* ancestor = stack[ancestorIndex--];
+ if (kNameSpaceID_XHTML == ancestor->ns) {
+ if (nsGkAtoms::_template == ancestor->name) {
+ break;
+ }
+ if (nsGkAtoms::table == ancestor->name) {
+ mode = IN_SELECT_IN_TABLE;
+ return;
+ }
+ }
+ }
+ mode = IN_SELECT;
+ return;
+ } else if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
+ mode = IN_CELL;
+ return;
+ } else if (nsGkAtoms::tr == name) {
+ mode = IN_ROW;
+ return;
+ } else if (nsGkAtoms::tbody == name || nsGkAtoms::thead == name ||
+ nsGkAtoms::tfoot == name) {
+ mode = IN_TABLE_BODY;
+ return;
+ } else if (nsGkAtoms::caption == name) {
+ mode = IN_CAPTION;
+ return;
+ } else if (nsGkAtoms::colgroup == name) {
+ mode = IN_COLUMN_GROUP;
+ return;
+ } else if (nsGkAtoms::table == name) {
+ mode = IN_TABLE;
+ return;
+ } else if (kNameSpaceID_XHTML != ns) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ } else if (nsGkAtoms::_template == name) {
+ MOZ_ASSERT(templateModePtr >= 0);
+ mode = templateModeStack[templateModePtr];
+ return;
+ } else if (nsGkAtoms::head == name) {
+ if (name == contextName) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ } else {
+ mode = IN_HEAD;
+ }
+ return;
+ } else if (nsGkAtoms::body == name) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ } else if (nsGkAtoms::frameset == name) {
+ mode = IN_FRAMESET;
+ return;
+ } else if (nsGkAtoms::html == name) {
+ if (!headPointer) {
+ mode = BEFORE_HEAD;
+ } else {
+ mode = AFTER_HEAD;
+ }
+ return;
+ } else if (!i) {
+ mode = framesetOk ? FRAMESET_OK : IN_BODY;
+ return;
+ }
+ }
+}
+
+void nsHtml5TreeBuilder::implicitlyCloseP() {
+ int32_t eltPos = findLastInButtonScope(nsGkAtoms::p);
+ if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
+ return;
+ }
+ generateImpliedEndTagsExceptFor(nsGkAtoms::p);
+ if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
+ errUnclosedElementsImplied(eltPos, nsGkAtoms::p);
+ }
+ while (currentPtr >= eltPos) {
+ pop();
+ }
+}
+
+bool nsHtml5TreeBuilder::debugOnlyClearLastStackSlot() {
+ stack[currentPtr] = nullptr;
+ return true;
+}
+
+bool nsHtml5TreeBuilder::debugOnlyClearLastListSlot() {
+ listOfActiveFormattingElements[listPtr] = nullptr;
+ return true;
+}
+
+void nsHtml5TreeBuilder::pushTemplateMode(int32_t mode) {
+ templateModePtr++;
+ if (templateModePtr == templateModeStack.length) {
+ jArray<int32_t, int32_t> newStack =
+ jArray<int32_t, int32_t>::newJArray(templateModeStack.length + 64);
+ nsHtml5ArrayCopy::arraycopy(templateModeStack, newStack,
+ templateModeStack.length);
+ templateModeStack = newStack;
+ }
+ templateModeStack[templateModePtr] = mode;
+}
+
+void nsHtml5TreeBuilder::push(nsHtml5StackNode* node) {
+ currentPtr++;
+ if (currentPtr == stack.length) {
+ jArray<nsHtml5StackNode*, int32_t> newStack =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
+ nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
+ stack = newStack;
+ }
+ stack[currentPtr] = node;
+ elementPushed(node->ns, node->popName, node->node);
+}
+
+void nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node) {
+ currentPtr++;
+ if (currentPtr == stack.length) {
+ jArray<nsHtml5StackNode*, int32_t> newStack =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
+ nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
+ stack = newStack;
+ }
+ stack[currentPtr] = node;
+}
+
+void nsHtml5TreeBuilder::append(nsHtml5StackNode* node) {
+ listPtr++;
+ if (listPtr == listOfActiveFormattingElements.length) {
+ jArray<nsHtml5StackNode*, int32_t> newList =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(
+ listOfActiveFormattingElements.length + 64);
+ nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, newList,
+ listOfActiveFormattingElements.length);
+ listOfActiveFormattingElements = newList;
+ }
+ listOfActiveFormattingElements[listPtr] = node;
+}
+
+void nsHtml5TreeBuilder::
+ clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
+ while (listPtr > -1) {
+ if (!listOfActiveFormattingElements[listPtr]) {
+ --listPtr;
+ return;
+ }
+ listOfActiveFormattingElements[listPtr]->release(this);
+ --listPtr;
+ }
+}
+
+void nsHtml5TreeBuilder::removeFromStack(int32_t pos) {
+ if (currentPtr == pos) {
+ pop();
+ } else {
+ stack[pos]->release(this);
+ nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
+ MOZ_ASSERT(debugOnlyClearLastStackSlot());
+ currentPtr--;
+ }
+}
+
+void nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node) {
+ if (stack[currentPtr] == node) {
+ pop();
+ } else {
+ int32_t pos = currentPtr - 1;
+ while (pos >= 0 && stack[pos] != node) {
+ pos--;
+ }
+ if (pos == -1) {
+ return;
+ }
+
+ node->release(this);
+ nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
+ currentPtr--;
+ }
+}
+
+void nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos) {
+ MOZ_ASSERT(!!listOfActiveFormattingElements[pos]);
+ listOfActiveFormattingElements[pos]->release(this);
+ if (pos == listPtr) {
+ MOZ_ASSERT(debugOnlyClearLastListSlot());
+ listPtr--;
+ return;
+ }
+ MOZ_ASSERT(pos < listPtr);
+ nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, pos + 1, pos,
+ listPtr - pos);
+ MOZ_ASSERT(debugOnlyClearLastListSlot());
+ listPtr--;
+}
+
+bool nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom* name) {
+ if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
+ stack[currentPtr]->name == name &&
+ findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
+ pop();
+ return true;
+ }
+ for (int32_t i = 0; i < 8; ++i) {
+ int32_t formattingEltListPos = listPtr;
+ while (formattingEltListPos > -1) {
+ nsHtml5StackNode* listNode =
+ listOfActiveFormattingElements[formattingEltListPos];
+ if (!listNode) {
+ formattingEltListPos = -1;
+ break;
+ } else if (listNode->name == name) {
+ break;
+ }
+ formattingEltListPos--;
+ }
+ if (formattingEltListPos == -1) {
+ return false;
+ }
+ nsHtml5StackNode* formattingElt =
+ listOfActiveFormattingElements[formattingEltListPos];
+ int32_t formattingEltStackPos = currentPtr;
+ bool inScope = true;
+ while (formattingEltStackPos > -1) {
+ nsHtml5StackNode* node = stack[formattingEltStackPos];
+ if (node == formattingElt) {
+ break;
+ } else if (node->isScoping()) {
+ inScope = false;
+ }
+ formattingEltStackPos--;
+ }
+ if (formattingEltStackPos == -1) {
+ errNoElementToCloseButEndTagSeen(name);
+ removeFromListOfActiveFormattingElements(formattingEltListPos);
+ return true;
+ }
+ if (!inScope) {
+ errNoElementToCloseButEndTagSeen(name);
+ return true;
+ }
+ if (formattingEltStackPos != currentPtr) {
+ errEndTagViolatesNestingRules(name);
+ }
+ int32_t furthestBlockPos = formattingEltStackPos + 1;
+ while (furthestBlockPos <= currentPtr) {
+ nsHtml5StackNode* node = stack[furthestBlockPos];
+ MOZ_ASSERT(furthestBlockPos > 0,
+ "How is formattingEltStackPos + 1 not > 0?");
+ if (node->isSpecial()) {
+ break;
+ }
+ furthestBlockPos++;
+ }
+ if (furthestBlockPos > currentPtr) {
+ while (currentPtr >= formattingEltStackPos) {
+ pop();
+ }
+ removeFromListOfActiveFormattingElements(formattingEltListPos);
+ return true;
+ }
+ nsHtml5StackNode* commonAncestor = stack[formattingEltStackPos - 1];
+ nsIContentHandle* insertionCommonAncestor =
+ nodeFromStackWithBlinkCompat(formattingEltStackPos - 1);
+ nsHtml5StackNode* furthestBlock = stack[furthestBlockPos];
+ int32_t bookmark = formattingEltListPos;
+ int32_t nodePos = furthestBlockPos;
+ nsHtml5StackNode* lastNode = furthestBlock;
+ int32_t j = 0;
+ for (;;) {
+ ++j;
+ nodePos--;
+ if (nodePos == formattingEltStackPos) {
+ break;
+ }
+ nsHtml5StackNode* node = stack[nodePos];
+ int32_t nodeListPos = findInListOfActiveFormattingElements(node);
+ if (j > 3 && nodeListPos != -1) {
+ removeFromListOfActiveFormattingElements(nodeListPos);
+ if (nodeListPos <= formattingEltListPos) {
+ formattingEltListPos--;
+ }
+ if (nodeListPos <= bookmark) {
+ bookmark--;
+ }
+ nodeListPos = -1;
+ }
+ if (nodeListPos == -1) {
+ MOZ_ASSERT(formattingEltStackPos < nodePos);
+ MOZ_ASSERT(bookmark < nodePos);
+ MOZ_ASSERT(furthestBlockPos > nodePos);
+ removeFromStack(nodePos);
+ furthestBlockPos--;
+ continue;
+ }
+ if (nodePos == furthestBlockPos) {
+ bookmark = nodeListPos + 1;
+ }
+ MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
+ MOZ_ASSERT(node == stack[nodePos]);
+ nsIContentHandle* clone = createElement(
+ kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(),
+ insertionCommonAncestor, htmlCreator(node->getHtmlCreator()));
+ nsHtml5StackNode* newNode = createStackNode(
+ node->getFlags(), node->ns, node->name, clone, node->popName,
+ node->attributes, node->getHtmlCreator());
+ node->dropAttributes();
+ stack[nodePos] = newNode;
+ newNode->retain();
+ listOfActiveFormattingElements[nodeListPos] = newNode;
+ node->release(this);
+ node->release(this);
+ node = newNode;
+ detachFromParent(lastNode->node);
+ appendElement(lastNode->node, nodeFromStackWithBlinkCompat(nodePos));
+ lastNode = node;
+ }
+ if (commonAncestor->isFosterParenting()) {
+ detachFromParent(lastNode->node);
+ insertIntoFosterParent(lastNode->node);
+ } else {
+ detachFromParent(lastNode->node);
+ appendElement(lastNode->node, insertionCommonAncestor);
+ }
+ nsIContentHandle* clone = createElement(
+ kNameSpaceID_XHTML, formattingElt->name,
+ formattingElt->attributes->cloneAttributes(), furthestBlock->node,
+ htmlCreator(formattingElt->getHtmlCreator()));
+ nsHtml5StackNode* formattingClone = createStackNode(
+ formattingElt->getFlags(), formattingElt->ns, formattingElt->name,
+ clone, formattingElt->popName, formattingElt->attributes,
+ formattingElt->getHtmlCreator());
+ formattingElt->dropAttributes();
+ appendChildrenToNewParent(furthestBlock->node, clone);
+ appendElement(clone, furthestBlock->node);
+ removeFromListOfActiveFormattingElements(formattingEltListPos);
+ insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
+ MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
+ removeFromStack(formattingEltStackPos);
+ insertIntoStack(formattingClone, furthestBlockPos);
+ }
+ return true;
+}
+
+void nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode* node,
+ int32_t position) {
+ MOZ_ASSERT(currentPtr + 1 < stack.length);
+ MOZ_ASSERT(position <= currentPtr + 1);
+ if (position == currentPtr + 1) {
+ push(node);
+ } else {
+ nsHtml5ArrayCopy::arraycopy(stack, position, position + 1,
+ (currentPtr - position) + 1);
+ currentPtr++;
+ stack[position] = node;
+ }
+}
+
+void nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
+ nsHtml5StackNode* formattingClone, int32_t bookmark) {
+ formattingClone->retain();
+ MOZ_ASSERT(listPtr + 1 < listOfActiveFormattingElements.length);
+ if (bookmark <= listPtr) {
+ nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, bookmark,
+ bookmark + 1, (listPtr - bookmark) + 1);
+ }
+ listPtr++;
+ listOfActiveFormattingElements[bookmark] = formattingClone;
+}
+
+int32_t nsHtml5TreeBuilder::findInListOfActiveFormattingElements(
+ nsHtml5StackNode* node) {
+ for (int32_t i = listPtr; i >= 0; i--) {
+ if (node == listOfActiveFormattingElements[i]) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int32_t nsHtml5TreeBuilder::
+ findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
+ nsAtom* name) {
+ for (int32_t i = listPtr; i >= 0; i--) {
+ nsHtml5StackNode* node = listOfActiveFormattingElements[i];
+ if (!node) {
+ return -1;
+ } else if (node->name == name) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
+ nsAtom* name, nsHtml5HtmlAttributes* attributes) {
+ int32_t candidate = -1;
+ int32_t count = 0;
+ for (int32_t i = listPtr; i >= 0; i--) {
+ nsHtml5StackNode* node = listOfActiveFormattingElements[i];
+ if (!node) {
+ break;
+ }
+ if (node->name == name && node->attributes->equalsAnother(attributes)) {
+ candidate = i;
+ ++count;
+ }
+ }
+ if (count >= 3) {
+ removeFromListOfActiveFormattingElements(candidate);
+ }
+}
+
+int32_t nsHtml5TreeBuilder::findLastOrRoot(nsAtom* name) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+int32_t nsHtml5TreeBuilder::findLastOrRoot(int32_t group) {
+ for (int32_t i = currentPtr; i > 0; i--) {
+ if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->getGroup() == group) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+bool nsHtml5TreeBuilder::addAttributesToBody(
+ nsHtml5HtmlAttributes* attributes) {
+ if (currentPtr >= 1) {
+ nsHtml5StackNode* body = stack[1];
+ if (body->getGroup() == nsHtml5TreeBuilder::BODY) {
+ addAttributesToElement(body->node, attributes);
+ return true;
+ }
+ }
+ return false;
+}
+
+void nsHtml5TreeBuilder::addAttributesToHtml(
+ nsHtml5HtmlAttributes* attributes) {
+ addAttributesToElement(stack[0]->node, attributes);
+}
+
+void nsHtml5TreeBuilder::pushHeadPointerOntoStack() {
+ MOZ_ASSERT(!!headPointer);
+ MOZ_ASSERT(mode == AFTER_HEAD);
+
+ silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
+}
+
+void nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() {
+ if (listPtr == -1) {
+ return;
+ }
+ nsHtml5StackNode* mostRecent = listOfActiveFormattingElements[listPtr];
+ if (!mostRecent || isInStack(mostRecent)) {
+ return;
+ }
+ int32_t entryPos = listPtr;
+ for (;;) {
+ entryPos--;
+ if (entryPos == -1) {
+ break;
+ }
+ if (!listOfActiveFormattingElements[entryPos]) {
+ break;
+ }
+ if (isInStack(listOfActiveFormattingElements[entryPos])) {
+ break;
+ }
+ }
+ while (entryPos < listPtr) {
+ entryPos++;
+ nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
+ nsHtml5StackNode* current = stack[currentPtr];
+ nsIContentHandle* clone;
+ if (current->isFosterParenting()) {
+ clone = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(),
+ htmlCreator(entry->getHtmlCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ clone = createElement(kNameSpaceID_XHTML, entry->name,
+ entry->attributes->cloneAttributes(), currentNode,
+ htmlCreator(entry->getHtmlCreator()));
+ appendElement(clone, currentNode);
+ }
+ nsHtml5StackNode* entryClone = createStackNode(
+ entry->getFlags(), entry->ns, entry->name, clone, entry->popName,
+ entry->attributes, entry->getHtmlCreator());
+ entry->dropAttributes();
+ push(entryClone);
+ listOfActiveFormattingElements[entryPos] = entryClone;
+ entry->release(this);
+ entryClone->retain();
+ }
+}
+
+void nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes) {
+ if (idxInStackNodes < stackNodesIdx) {
+ stackNodesIdx = idxInStackNodes;
+ }
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::getUnusedStackNode() {
+ while (stackNodesIdx < numStackNodes) {
+ if (stackNodes[stackNodesIdx]->isUnused()) {
+ return stackNodes[stackNodesIdx++];
+ }
+ stackNodesIdx++;
+ }
+ if (stackNodesIdx < stackNodes.length) {
+ stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
+ numStackNodes++;
+ return stackNodes[stackNodesIdx++];
+ }
+ jArray<nsHtml5StackNode*, int32_t> newStack =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(stackNodes.length + 64);
+ nsHtml5ArrayCopy::arraycopy(stackNodes, newStack, stackNodes.length);
+ stackNodes = newStack;
+ stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
+ numStackNodes++;
+ return stackNodes[stackNodesIdx++];
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
+ int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node,
+ nsAtom* popName, nsHtml5HtmlAttributes* attributes,
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator) {
+ nsHtml5StackNode* instance = getUnusedStackNode();
+ instance->setValues(flags, ns, name, node, popName, attributes, htmlCreator);
+ return instance;
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
+ nsHtml5ElementName* elementName, nsIContentHandle* node) {
+ nsHtml5StackNode* instance = getUnusedStackNode();
+ instance->setValues(elementName, node);
+ return instance;
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
+ nsHtml5ElementName* elementName, nsIContentHandle* node,
+ nsHtml5HtmlAttributes* attributes) {
+ nsHtml5StackNode* instance = getUnusedStackNode();
+ instance->setValues(elementName, node, attributes);
+ return instance;
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
+ nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName) {
+ nsHtml5StackNode* instance = getUnusedStackNode();
+ instance->setValues(elementName, node, popName);
+ return instance;
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
+ nsHtml5ElementName* elementName, nsAtom* popName, nsIContentHandle* node) {
+ nsHtml5StackNode* instance = getUnusedStackNode();
+ instance->setValues(elementName, popName, node);
+ return instance;
+}
+
+nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
+ nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName,
+ bool markAsIntegrationPoint) {
+ nsHtml5StackNode* instance = getUnusedStackNode();
+ instance->setValues(elementName, node, popName, markAsIntegrationPoint);
+ return instance;
+}
+
+void nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child) {
+ int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
+ int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
+ if (templatePos >= tablePos) {
+ appendElement(child, stack[templatePos]->node);
+ return;
+ }
+ nsHtml5StackNode* node = stack[tablePos];
+ insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
+ int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
+ nsHtml5ContentCreatorFunction creator) {
+ return createAndInsertFosterParentedElement(ns, name, attributes, nullptr,
+ creator);
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
+ int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form, nsHtml5ContentCreatorFunction creator) {
+ int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
+ int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
+ if (templatePos >= tablePos) {
+ nsIContentHandle* child = createElement(ns, name, attributes, form,
+ stack[templatePos]->node, creator);
+ appendElement(child, stack[templatePos]->node);
+ return child;
+ }
+ nsHtml5StackNode* node = stack[tablePos];
+ return createAndInsertFosterParentedElement(
+ ns, name, attributes, form, node->node, stack[tablePos - 1]->node,
+ creator);
+}
+
+bool nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node) {
+ for (int32_t i = currentPtr; i >= 0; i--) {
+ if (stack[i] == node) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void nsHtml5TreeBuilder::popTemplateMode() { templateModePtr--; }
+
+void nsHtml5TreeBuilder::pop() {
+ nsHtml5StackNode* node = stack[currentPtr];
+ MOZ_ASSERT(debugOnlyClearLastStackSlot());
+ currentPtr--;
+ elementPopped(node->ns, node->popName, node->node);
+ node->release(this);
+}
+
+void nsHtml5TreeBuilder::popForeign(int32_t origPos, int32_t eltPos) {
+ nsHtml5StackNode* node = stack[currentPtr];
+ if (origPos != currentPtr || eltPos != currentPtr) {
+ markMalformedIfScript(node->node);
+ }
+ MOZ_ASSERT(debugOnlyClearLastStackSlot());
+ currentPtr--;
+ elementPopped(node->ns, node->popName, node->node);
+ node->release(this);
+}
+
+void nsHtml5TreeBuilder::silentPop() {
+ nsHtml5StackNode* node = stack[currentPtr];
+ MOZ_ASSERT(debugOnlyClearLastStackSlot());
+ currentPtr--;
+ node->release(this);
+}
+
+void nsHtml5TreeBuilder::popOnEof() {
+ nsHtml5StackNode* node = stack[currentPtr];
+ MOZ_ASSERT(debugOnlyClearLastStackSlot());
+ currentPtr--;
+ markMalformedIfScript(node->node);
+ elementPopped(node->ns, node->popName, node->node);
+ node->release(this);
+}
+
+void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
+ nsHtml5HtmlAttributes* attributes) {
+ nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
+ nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush() {
+ appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
+ nsHtml5HtmlAttributes* attributes) {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ nsIContentHandle* elt =
+ createElement(kNameSpaceID_XHTML, nsGkAtoms::head, attributes,
+ currentNode, htmlCreator(NS_NewHTMLSharedElement));
+ appendElement(elt, currentNode);
+ headPointer = elt;
+ nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HEAD, elt);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
+ nsHtml5HtmlAttributes* attributes) {
+ appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement() {
+ appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
+ nsHtml5HtmlAttributes* attributes) {
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
+ htmlCreator(NS_NewHTMLFormElement));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
+ currentNode, htmlCreator(NS_NewHTMLFormElement));
+ appendElement(elt, currentNode);
+ }
+ if (!isTemplateContents()) {
+ formPointer = elt;
+ }
+ nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_FORM, elt);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsHtml5HtmlAttributes* clone = attributes->cloneAttributes();
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, elementName->getName(), attributes,
+ htmlCreator(elementName->getHtmlCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt =
+ createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
+ currentNode, htmlCreator(elementName->getHtmlCreator()));
+ appendElement(elt, currentNode);
+ }
+ nsHtml5StackNode* node = createStackNode(elementName, elt, clone);
+ push(node);
+ append(node);
+ node->retain();
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ nsIContentHandle* elt =
+ createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
+ currentNode, htmlCreator(elementName->getHtmlCreator()));
+ appendElement(elt, currentNode);
+ if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
+ elt = getDocumentFragmentForTemplate(elt);
+ }
+ nsHtml5StackNode* node = createStackNode(elementName, elt);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsAtom* popName = elementName->getName();
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, popName, attributes,
+ htmlCreator(elementName->getHtmlCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
+ htmlCreator(elementName->getHtmlCreator()));
+ appendElement(elt, currentNode);
+ }
+ nsHtml5StackNode* node = createStackNode(elementName, elt, popName);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsAtom* popName = elementName->getName();
+ bool markAsHtmlIntegrationPoint = false;
+ if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName &&
+ annotationXmlEncodingPermitsHtml(attributes)) {
+ markAsHtmlIntegrationPoint = true;
+ }
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode,
+ htmlCreator(nullptr));
+ appendElement(elt, currentNode);
+ }
+ nsHtml5StackNode* node =
+ createStackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
+ push(node);
+}
+
+bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
+ nsHtml5HtmlAttributes* attributes) {
+ nsHtml5String encoding =
+ attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
+ if (!encoding) {
+ return false;
+ }
+ return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "application/xhtml+xml", encoding) ||
+ nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "text/html", encoding);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsAtom* popName = elementName->getCamelCaseName();
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_SVG, popName, attributes,
+ svgCreator(elementName->getSvgCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode,
+ svgCreator(elementName->getSvgCreator()));
+ appendElement(elt, currentNode);
+ }
+ nsHtml5StackNode* node = createStackNode(elementName, popName, elt);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form) {
+ nsIContentHandle* elt;
+ nsIContentHandle* formOwner =
+ !form || fragment || isTemplateContents() ? nullptr : form;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, elementName->getName(), attributes, formOwner,
+ htmlCreator(elementName->getHtmlCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
+ formOwner, currentNode,
+ htmlCreator(elementName->getHtmlCreator()));
+ appendElement(elt, currentNode);
+ }
+ nsHtml5StackNode* node = createStackNode(elementName, elt);
+ push(node);
+}
+
+void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form) {
+ nsAtom* name = elementName->getName();
+ nsIContentHandle* elt;
+ nsIContentHandle* formOwner =
+ !form || fragment || isTemplateContents() ? nullptr : form;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, name, attributes, formOwner,
+ htmlCreator(elementName->getHtmlCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt =
+ createElement(kNameSpaceID_XHTML, name, attributes, formOwner,
+ currentNode, htmlCreator(elementName->getHtmlCreator()));
+ appendElement(elt, currentNode);
+ }
+ elementPushed(kNameSpaceID_XHTML, name, elt);
+ elementPopped(kNameSpaceID_XHTML, name, elt);
+}
+
+void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsAtom* popName = elementName->getName();
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_XHTML, popName, attributes,
+ htmlCreator(elementName->getHtmlCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
+ htmlCreator(elementName->getHtmlCreator()));
+ appendElement(elt, currentNode);
+ }
+ elementPushed(kNameSpaceID_XHTML, popName, elt);
+ elementPopped(kNameSpaceID_XHTML, popName, elt);
+}
+
+void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsAtom* popName = elementName->getCamelCaseName();
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_SVG, popName, attributes,
+ svgCreator(elementName->getSvgCreator()));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode,
+ svgCreator(elementName->getSvgCreator()));
+ appendElement(elt, currentNode);
+ }
+ elementPushed(kNameSpaceID_SVG, popName, elt);
+ elementPopped(kNameSpaceID_SVG, popName, elt);
+}
+
+void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
+ nsAtom* popName = elementName->getName();
+ nsIContentHandle* elt;
+ nsHtml5StackNode* current = stack[currentPtr];
+ if (current->isFosterParenting()) {
+ elt = createAndInsertFosterParentedElement(
+ kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
+ } else {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode,
+ htmlCreator(nullptr));
+ appendElement(elt, currentNode);
+ }
+ elementPushed(kNameSpaceID_MathML, popName, elt);
+ elementPopped(kNameSpaceID_MathML, popName, elt);
+}
+
+void nsHtml5TreeBuilder::appendVoidInputToCurrent(
+ nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ nsIContentHandle* elt =
+ createElement(kNameSpaceID_XHTML, nsGkAtoms::input, attributes,
+ !form || fragment || isTemplateContents() ? nullptr : form,
+ currentNode, htmlCreator(NS_NewHTMLInputElement));
+ appendElement(elt, currentNode);
+ elementPushed(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
+ elementPopped(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
+}
+
+void nsHtml5TreeBuilder::appendVoidFormToCurrent(
+ nsHtml5HtmlAttributes* attributes) {
+ nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
+ nsIContentHandle* elt =
+ createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
+ currentNode, htmlCreator(NS_NewHTMLFormElement));
+ formPointer = elt;
+ appendElement(elt, currentNode);
+ elementPushed(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
+ elementPopped(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
+}
+
+void nsHtml5TreeBuilder::requestSuspension() {
+ tokenizer->requestSuspension();
+}
+
+;
+bool nsHtml5TreeBuilder::isInForeign() {
+ return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
+}
+
+bool nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint() {
+ if (currentPtr < 0) {
+ return false;
+ }
+ return !isSpecialParentInForeign(stack[currentPtr]);
+}
+
+void nsHtml5TreeBuilder::setFragmentContext(nsAtom* context, int32_t ns,
+ nsIContentHandle* node,
+ bool quirks) {
+ this->contextName = context;
+ this->contextNamespace = ns;
+ this->contextNode = node;
+ this->fragment = (!!contextName);
+ this->quirks = quirks;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::currentNode() {
+ return stack[currentPtr]->node;
+}
+
+bool nsHtml5TreeBuilder::isScriptingEnabled() { return scriptingEnabled; }
+
+void nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled) {
+ this->scriptingEnabled = scriptingEnabled;
+}
+
+void nsHtml5TreeBuilder::setForceNoQuirks(bool forceNoQuirks) {
+ this->forceNoQuirks = forceNoQuirks;
+}
+
+void nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument) {
+ this->setForceNoQuirks(isSrcdocDocument);
+}
+
+void nsHtml5TreeBuilder::flushCharacters() {
+ if (charBufferLen > 0) {
+ if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) &&
+ charBufferContainsNonWhitespace()) {
+ errNonSpaceInTable();
+ reconstructTheActiveFormattingElements();
+ if (!stack[currentPtr]->isFosterParenting()) {
+ appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
+ charBufferLen = 0;
+ return;
+ }
+ int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
+ int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
+ if (templatePos >= tablePos) {
+ appendCharacters(stack[templatePos]->node, charBuffer, 0,
+ charBufferLen);
+ charBufferLen = 0;
+ return;
+ }
+ nsHtml5StackNode* tableElt = stack[tablePos];
+ insertFosterParentedCharacters(charBuffer, 0, charBufferLen,
+ tableElt->node, stack[tablePos - 1]->node);
+ charBufferLen = 0;
+ return;
+ }
+ appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
+ charBufferLen = 0;
+ }
+}
+
+bool nsHtml5TreeBuilder::charBufferContainsNonWhitespace() {
+ for (int32_t i = 0; i < charBufferLen; i++) {
+ switch (charBuffer[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\f': {
+ continue;
+ }
+ default: {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+nsAHtml5TreeBuilderState* nsHtml5TreeBuilder::newSnapshot() {
+ jArray<nsHtml5StackNode*, int32_t> listCopy =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(listPtr + 1);
+ for (int32_t i = 0; i < listCopy.length; i++) {
+ nsHtml5StackNode* node = listOfActiveFormattingElements[i];
+ if (node) {
+ nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
+ newNode->setValues(node->getFlags(), node->ns, node->name, node->node,
+ node->popName, node->attributes->cloneAttributes(),
+ node->getHtmlCreator());
+ listCopy[i] = newNode;
+ } else {
+ listCopy[i] = nullptr;
+ }
+ }
+ jArray<nsHtml5StackNode*, int32_t> stackCopy =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(currentPtr + 1);
+ for (int32_t i = 0; i < stackCopy.length; i++) {
+ nsHtml5StackNode* node = stack[i];
+ int32_t listIndex = findInListOfActiveFormattingElements(node);
+ if (listIndex == -1) {
+ nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
+ newNode->setValues(node->getFlags(), node->ns, node->name, node->node,
+ node->popName, nullptr, node->getHtmlCreator());
+ stackCopy[i] = newNode;
+ } else {
+ stackCopy[i] = listCopy[listIndex];
+ stackCopy[i]->retain();
+ }
+ }
+ jArray<int32_t, int32_t> templateModeStackCopy =
+ jArray<int32_t, int32_t>::newJArray(templateModePtr + 1);
+ nsHtml5ArrayCopy::arraycopy(templateModeStack, templateModeStackCopy,
+ templateModeStackCopy.length);
+ return new nsHtml5StateSnapshot(stackCopy, listCopy, templateModeStackCopy,
+ formPointer, headPointer, mode, originalMode,
+ framesetOk, needToDropLF, quirks);
+}
+
+bool nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot) {
+ jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
+ int32_t stackLen = snapshot->getStackLength();
+ jArray<nsHtml5StackNode*, int32_t> listCopy =
+ snapshot->getListOfActiveFormattingElements();
+ int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
+ jArray<int32_t, int32_t> templateModeStackCopy =
+ snapshot->getTemplateModeStack();
+ int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
+ if (stackLen != currentPtr + 1 || listLen != listPtr + 1 ||
+ templateModeStackLen != templateModePtr + 1 ||
+ formPointer != snapshot->getFormPointer() ||
+ headPointer != snapshot->getHeadPointer() ||
+ mode != snapshot->getMode() ||
+ originalMode != snapshot->getOriginalMode() ||
+ framesetOk != snapshot->isFramesetOk() ||
+ needToDropLF != snapshot->isNeedToDropLF() ||
+ quirks != snapshot->isQuirks()) {
+ return false;
+ }
+ for (int32_t i = listLen - 1; i >= 0; i--) {
+ if (!listCopy[i] && !listOfActiveFormattingElements[i]) {
+ continue;
+ } else if (!listCopy[i] || !listOfActiveFormattingElements[i]) {
+ return false;
+ }
+ if (listCopy[i]->node != listOfActiveFormattingElements[i]->node) {
+ return false;
+ }
+ }
+ for (int32_t i = stackLen - 1; i >= 0; i--) {
+ if (stackCopy[i]->node != stack[i]->node) {
+ return false;
+ }
+ }
+ for (int32_t i = templateModeStackLen - 1; i >= 0; i--) {
+ if (templateModeStackCopy[i] != templateModeStack[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState* snapshot) {
+ mCurrentHtmlScriptIsAsyncOrDefer = false;
+ jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
+ int32_t stackLen = snapshot->getStackLength();
+ jArray<nsHtml5StackNode*, int32_t> listCopy =
+ snapshot->getListOfActiveFormattingElements();
+ int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
+ jArray<int32_t, int32_t> templateModeStackCopy =
+ snapshot->getTemplateModeStack();
+ int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
+ for (int32_t i = 0; i <= listPtr; i++) {
+ if (listOfActiveFormattingElements[i]) {
+ listOfActiveFormattingElements[i]->release(this);
+ }
+ }
+ if (listOfActiveFormattingElements.length < listLen) {
+ listOfActiveFormattingElements =
+ jArray<nsHtml5StackNode*, int32_t>::newJArray(listLen);
+ }
+ listPtr = listLen - 1;
+ for (int32_t i = 0; i <= currentPtr; i++) {
+ stack[i]->release(this);
+ }
+ if (stack.length < stackLen) {
+ stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(stackLen);
+ }
+ currentPtr = stackLen - 1;
+ if (templateModeStack.length < templateModeStackLen) {
+ templateModeStack =
+ jArray<int32_t, int32_t>::newJArray(templateModeStackLen);
+ }
+ templateModePtr = templateModeStackLen - 1;
+ for (int32_t i = 0; i < listLen; i++) {
+ nsHtml5StackNode* node = listCopy[i];
+ if (node) {
+ nsHtml5StackNode* newNode = createStackNode(
+ node->getFlags(), node->ns, node->name, node->node, node->popName,
+ node->attributes->cloneAttributes(), node->getHtmlCreator());
+ listOfActiveFormattingElements[i] = newNode;
+ } else {
+ listOfActiveFormattingElements[i] = nullptr;
+ }
+ }
+ for (int32_t i = 0; i < stackLen; i++) {
+ nsHtml5StackNode* node = stackCopy[i];
+ int32_t listIndex = findInArray(node, listCopy);
+ if (listIndex == -1) {
+ nsHtml5StackNode* newNode =
+ createStackNode(node->getFlags(), node->ns, node->name, node->node,
+ node->popName, nullptr, node->getHtmlCreator());
+ stack[i] = newNode;
+ } else {
+ stack[i] = listOfActiveFormattingElements[listIndex];
+ stack[i]->retain();
+ }
+ }
+ nsHtml5ArrayCopy::arraycopy(templateModeStackCopy, templateModeStack,
+ templateModeStackLen);
+ formPointer = snapshot->getFormPointer();
+ headPointer = snapshot->getHeadPointer();
+ mode = snapshot->getMode();
+ originalMode = snapshot->getOriginalMode();
+ framesetOk = snapshot->isFramesetOk();
+ needToDropLF = snapshot->isNeedToDropLF();
+ quirks = snapshot->isQuirks();
+}
+
+int32_t nsHtml5TreeBuilder::findInArray(
+ nsHtml5StackNode* node, jArray<nsHtml5StackNode*, int32_t> arr) {
+ for (int32_t i = listPtr; i >= 0; i--) {
+ if (node == arr[i]) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::nodeFromStackWithBlinkCompat(
+ int32_t stackPos) {
+ if (stackPos > 511) {
+ errDeepTree();
+ return stack[511]->node;
+ }
+ return stack[stackPos]->node;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::getFormPointer() { return formPointer; }
+
+nsIContentHandle* nsHtml5TreeBuilder::getHeadPointer() { return headPointer; }
+
+jArray<nsHtml5StackNode*, int32_t>
+nsHtml5TreeBuilder::getListOfActiveFormattingElements() {
+ return listOfActiveFormattingElements;
+}
+
+jArray<nsHtml5StackNode*, int32_t> nsHtml5TreeBuilder::getStack() {
+ return stack;
+}
+
+jArray<int32_t, int32_t> nsHtml5TreeBuilder::getTemplateModeStack() {
+ return templateModeStack;
+}
+
+int32_t nsHtml5TreeBuilder::getMode() { return mode; }
+
+int32_t nsHtml5TreeBuilder::getOriginalMode() { return originalMode; }
+
+bool nsHtml5TreeBuilder::isFramesetOk() { return framesetOk; }
+
+bool nsHtml5TreeBuilder::isNeedToDropLF() { return needToDropLF; }
+
+bool nsHtml5TreeBuilder::isQuirks() { return quirks; }
+
+int32_t nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength() {
+ return listPtr + 1;
+}
+
+int32_t nsHtml5TreeBuilder::getStackLength() { return currentPtr + 1; }
+
+int32_t nsHtml5TreeBuilder::getTemplateModeStackLength() {
+ return templateModePtr + 1;
+}
+
+void nsHtml5TreeBuilder::initializeStatics() {}
+
+void nsHtml5TreeBuilder::releaseStatics() {}
+
+#include "nsHtml5TreeBuilderCppSupplement.h"
diff --git a/parser/html/nsHtml5TreeBuilder.h b/parser/html/nsHtml5TreeBuilder.h
new file mode 100644
index 0000000000..97b0876601
--- /dev/null
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2007 Henri Sivonen
+ * Copyright (c) 2007-2017 Mozilla Foundation
+ * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
+ * Foundation, and Opera Software ASA.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit TreeBuilder.java instead and regenerate.
+ */
+
+#ifndef nsHtml5TreeBuilder_h
+#define nsHtml5TreeBuilder_h
+
+#include "jArray.h"
+#include "mozilla/ImportScanner.h"
+#include "mozilla/Likely.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsAtom.h"
+#include "nsContentUtils.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5Highlighter.h"
+#include "nsHtml5OplessBuilder.h"
+#include "nsHtml5Parser.h"
+#include "nsHtml5PlainTextUtils.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5StreamParser.h"
+#include "nsHtml5String.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsHtml5TreeOpExecutor.h"
+#include "nsHtml5ViewSourceUtils.h"
+#include "nsIContent.h"
+#include "nsIContentHandle.h"
+#include "nsNameSpaceManager.h"
+#include "nsTraceRefcnt.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5Tokenizer;
+class nsHtml5UTF16Buffer;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState {
+ private:
+ static char16_t REPLACEMENT_CHARACTER[];
+
+ public:
+ static const int32_t OTHER = 0;
+
+ static const int32_t A = 1;
+
+ static const int32_t BASE = 2;
+
+ static const int32_t BODY = 3;
+
+ static const int32_t BR = 4;
+
+ static const int32_t BUTTON = 5;
+
+ static const int32_t CAPTION = 6;
+
+ static const int32_t COL = 7;
+
+ static const int32_t COLGROUP = 8;
+
+ static const int32_t FORM = 9;
+
+ static const int32_t FRAME = 10;
+
+ static const int32_t FRAMESET = 11;
+
+ static const int32_t IMAGE = 12;
+
+ static const int32_t INPUT = 13;
+
+ static const int32_t RT_OR_RP = 14;
+
+ static const int32_t LI = 15;
+
+ static const int32_t LINK_OR_BASEFONT_OR_BGSOUND = 16;
+
+ static const int32_t MATH = 17;
+
+ static const int32_t META = 18;
+
+ static const int32_t SVG = 19;
+
+ static const int32_t HEAD = 20;
+
+ static const int32_t HR = 22;
+
+ static const int32_t HTML = 23;
+
+ static const int32_t NOBR = 24;
+
+ static const int32_t NOFRAMES = 25;
+
+ static const int32_t NOSCRIPT = 26;
+
+ static const int32_t OPTGROUP = 27;
+
+ static const int32_t OPTION = 28;
+
+ static const int32_t P = 29;
+
+ static const int32_t PLAINTEXT = 30;
+
+ static const int32_t SCRIPT = 31;
+
+ static const int32_t SELECT = 32;
+
+ static const int32_t STYLE = 33;
+
+ static const int32_t TABLE = 34;
+
+ static const int32_t TEXTAREA = 35;
+
+ static const int32_t TITLE = 36;
+
+ static const int32_t TR = 37;
+
+ static const int32_t XMP = 38;
+
+ static const int32_t TBODY_OR_THEAD_OR_TFOOT = 39;
+
+ static const int32_t TD_OR_TH = 40;
+
+ static const int32_t DD_OR_DT = 41;
+
+ static const int32_t H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6 = 42;
+
+ static const int32_t MARQUEE_OR_APPLET = 43;
+
+ static const int32_t PRE_OR_LISTING = 44;
+
+ static const int32_t
+ B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U =
+ 45;
+
+ static const int32_t UL_OR_OL_OR_DL = 46;
+
+ static const int32_t IFRAME = 47;
+
+ static const int32_t EMBED = 48;
+
+ static const int32_t AREA_OR_WBR = 49;
+
+ static const int32_t DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU = 50;
+
+ static const int32_t
+ ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY =
+ 51;
+
+ static const int32_t RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR = 52;
+
+ static const int32_t RB_OR_RTC = 53;
+
+ static const int32_t PARAM_OR_SOURCE_OR_TRACK = 55;
+
+ static const int32_t MGLYPH_OR_MALIGNMARK = 56;
+
+ static const int32_t MI_MO_MN_MS_MTEXT = 57;
+
+ static const int32_t ANNOTATION_XML = 58;
+
+ static const int32_t FOREIGNOBJECT_OR_DESC = 59;
+
+ static const int32_t NOEMBED = 60;
+
+ static const int32_t FIELDSET = 61;
+
+ static const int32_t OUTPUT = 62;
+
+ static const int32_t OBJECT = 63;
+
+ static const int32_t FONT = 64;
+
+ static const int32_t KEYGEN = 65;
+
+ static const int32_t TEMPLATE = 66;
+
+ static const int32_t IMG = 67;
+
+ private:
+ static const int32_t IN_ROW = 0;
+
+ static const int32_t IN_TABLE_BODY = 1;
+
+ static const int32_t IN_TABLE = 2;
+
+ static const int32_t IN_CAPTION = 3;
+
+ static const int32_t IN_CELL = 4;
+
+ static const int32_t FRAMESET_OK = 5;
+
+ static const int32_t IN_BODY = 6;
+
+ static const int32_t IN_HEAD = 7;
+
+ static const int32_t IN_HEAD_NOSCRIPT = 8;
+
+ static const int32_t IN_COLUMN_GROUP = 9;
+
+ static const int32_t IN_SELECT_IN_TABLE = 10;
+
+ static const int32_t IN_SELECT = 11;
+
+ static const int32_t AFTER_BODY = 12;
+
+ static const int32_t IN_FRAMESET = 13;
+
+ static const int32_t AFTER_FRAMESET = 14;
+
+ static const int32_t INITIAL = 15;
+
+ static const int32_t BEFORE_HTML = 16;
+
+ static const int32_t BEFORE_HEAD = 17;
+
+ static const int32_t AFTER_HEAD = 18;
+
+ static const int32_t AFTER_AFTER_BODY = 19;
+
+ static const int32_t AFTER_AFTER_FRAMESET = 20;
+
+ static const int32_t TEXT = 21;
+
+ static const int32_t IN_TEMPLATE = 22;
+
+ static const int32_t CHARSET_INITIAL = 0;
+
+ static const int32_t CHARSET_C = 1;
+
+ static const int32_t CHARSET_H = 2;
+
+ static const int32_t CHARSET_A = 3;
+
+ static const int32_t CHARSET_R = 4;
+
+ static const int32_t CHARSET_S = 5;
+
+ static const int32_t CHARSET_E = 6;
+
+ static const int32_t CHARSET_T = 7;
+
+ static const int32_t CHARSET_EQUALS = 8;
+
+ static const int32_t CHARSET_SINGLE_QUOTED = 9;
+
+ static const int32_t CHARSET_DOUBLE_QUOTED = 10;
+
+ static const int32_t CHARSET_UNQUOTED = 11;
+
+ static staticJArray<const char*, int32_t> QUIRKY_PUBLIC_IDS;
+ static const int32_t NOT_FOUND_ON_STACK = INT32_MAX;
+
+ int32_t mode;
+ int32_t originalMode;
+ bool framesetOk;
+
+ protected:
+ nsHtml5Tokenizer* tokenizer;
+
+ private:
+ bool scriptingEnabled;
+ bool needToDropLF;
+ bool fragment;
+ RefPtr<nsAtom> contextName;
+ int32_t contextNamespace;
+ nsIContentHandle* contextNode;
+ autoJArray<int32_t, int32_t> templateModeStack;
+ int32_t templateModePtr;
+ autoJArray<nsHtml5StackNode*, int32_t> stackNodes;
+ int32_t stackNodesIdx;
+ int32_t numStackNodes;
+ autoJArray<nsHtml5StackNode*, int32_t> stack;
+ int32_t currentPtr;
+ autoJArray<nsHtml5StackNode*, int32_t> listOfActiveFormattingElements;
+ int32_t listPtr;
+ nsIContentHandle* formPointer;
+ nsIContentHandle* headPointer;
+
+ protected:
+ autoJArray<char16_t, int32_t> charBuffer;
+ int32_t charBufferLen;
+
+ private:
+ bool quirks;
+ bool forceNoQuirks;
+ inline nsHtml5ContentCreatorFunction htmlCreator(
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator) {
+ nsHtml5ContentCreatorFunction creator;
+ creator.html = htmlCreator;
+ return creator;
+ }
+
+ inline nsHtml5ContentCreatorFunction svgCreator(
+ mozilla::dom::SVGContentCreatorFunction svgCreator) {
+ nsHtml5ContentCreatorFunction creator;
+ creator.svg = svgCreator;
+ return creator;
+ }
+
+ public:
+ void startTokenization(nsHtml5Tokenizer* self);
+ void doctype(nsAtom* name, nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier, bool forceQuirks);
+ void comment(char16_t* buf, int32_t start, int32_t length);
+ void characters(const char16_t* buf, int32_t start, int32_t length);
+ void zeroOriginatingReplacementCharacter();
+ void zeroOrReplacementCharacter();
+ void eof();
+ void endTokenization();
+ void startTag(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes, bool selfClosing);
+
+ private:
+ void startTagTitleInHead(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes);
+ void startTagGenericRawText(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes);
+ void startTagScriptInHead(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes);
+ void startTagTemplateInHead(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes);
+ bool isTemplateContents();
+ bool isTemplateModeStackEmpty();
+ bool isSpecialParentInForeign(nsHtml5StackNode* stackNode);
+
+ public:
+ static nsHtml5String extractCharsetFromContent(nsHtml5String attributeValue,
+ nsHtml5TreeBuilder* tb);
+
+ private:
+ void checkMetaCharset(nsHtml5HtmlAttributes* attributes);
+
+ public:
+ void endTag(nsHtml5ElementName* elementName);
+
+ private:
+ void endTagTemplateInHead();
+ int32_t findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
+ int32_t findLast(nsAtom* name);
+ int32_t findLastInTableScope(nsAtom* name);
+ int32_t findLastInButtonScope(nsAtom* name);
+ int32_t findLastInScope(nsAtom* name);
+ int32_t findLastInListScope(nsAtom* name);
+ int32_t findLastInScopeHn();
+ void generateImpliedEndTagsExceptFor(nsAtom* name);
+ void generateImpliedEndTags();
+ void generateImpliedEndTagsThoroughly();
+ bool isSecondOnStackBody();
+ void documentModeInternal(nsHtml5DocumentMode m,
+ nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier);
+ bool isAlmostStandards(nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier);
+ bool isQuirky(nsAtom* name, nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier, bool forceQuirks);
+ void closeTheCell(int32_t eltPos);
+ int32_t findLastInTableScopeTdTh();
+ void clearStackBackTo(int32_t eltPos);
+ void resetTheInsertionMode();
+ void implicitlyCloseP();
+ bool debugOnlyClearLastStackSlot();
+ bool debugOnlyClearLastListSlot();
+ void pushTemplateMode(int32_t mode);
+ void push(nsHtml5StackNode* node);
+ void silentPush(nsHtml5StackNode* node);
+ void append(nsHtml5StackNode* node);
+ inline void insertMarker() { append(nullptr); }
+
+ void clearTheListOfActiveFormattingElementsUpToTheLastMarker();
+ inline bool isCurrent(nsAtom* name) {
+ return stack[currentPtr]->ns == kNameSpaceID_XHTML &&
+ name == stack[currentPtr]->name;
+ }
+
+ void removeFromStack(int32_t pos);
+ void removeFromStack(nsHtml5StackNode* node);
+ void removeFromListOfActiveFormattingElements(int32_t pos);
+ bool adoptionAgencyEndTag(nsAtom* name);
+ void insertIntoStack(nsHtml5StackNode* node, int32_t position);
+ void insertIntoListOfActiveFormattingElements(
+ nsHtml5StackNode* formattingClone, int32_t bookmark);
+ int32_t findInListOfActiveFormattingElements(nsHtml5StackNode* node);
+ int32_t findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
+ nsAtom* name);
+ void maybeForgetEarlierDuplicateFormattingElement(
+ nsAtom* name, nsHtml5HtmlAttributes* attributes);
+ int32_t findLastOrRoot(nsAtom* name);
+ int32_t findLastOrRoot(int32_t group);
+ bool addAttributesToBody(nsHtml5HtmlAttributes* attributes);
+ void addAttributesToHtml(nsHtml5HtmlAttributes* attributes);
+ void pushHeadPointerOntoStack();
+ void reconstructTheActiveFormattingElements();
+
+ public:
+ void notifyUnusedStackNode(int32_t idxInStackNodes);
+
+ private:
+ nsHtml5StackNode* getUnusedStackNode();
+ nsHtml5StackNode* createStackNode(
+ int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node,
+ nsAtom* popName, nsHtml5HtmlAttributes* attributes,
+ mozilla::dom::HTMLContentCreatorFunction htmlCreator);
+ nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName,
+ nsIContentHandle* node);
+ nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName,
+ nsIContentHandle* node,
+ nsHtml5HtmlAttributes* attributes);
+ nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName,
+ nsIContentHandle* node, nsAtom* popName);
+ nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName,
+ nsAtom* popName, nsIContentHandle* node);
+ nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName,
+ nsIContentHandle* node, nsAtom* popName,
+ bool markAsIntegrationPoint);
+ void insertIntoFosterParent(nsIContentHandle* child);
+ nsIContentHandle* createAndInsertFosterParentedElement(
+ int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
+ nsHtml5ContentCreatorFunction creator);
+ nsIContentHandle* createAndInsertFosterParentedElement(
+ int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form, nsHtml5ContentCreatorFunction creator);
+ bool isInStack(nsHtml5StackNode* node);
+ void popTemplateMode();
+ void pop();
+ void popForeign(int32_t origPos, int32_t eltPos);
+ void silentPop();
+ void popOnEof();
+ void appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes);
+ void appendHtmlElementToDocumentAndPush();
+ void appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushBodyElement();
+ void appendToCurrentNodeAndPushFormElementMayFoster(
+ nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushFormattingElementMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushElementMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushElementMayFosterMathML(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
+ bool annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushElementMayFosterSVG(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
+ void appendToCurrentNodeAndPushElementMayFoster(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form);
+ void appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form);
+ void appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName,
+ nsHtml5HtmlAttributes* attributes);
+ void appendVoidElementToCurrentMayFosterSVG(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
+ void appendVoidElementToCurrentMayFosterMathML(
+ nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes);
+ void appendVoidInputToCurrent(nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form);
+ void appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes);
+
+ protected:
+ void accumulateCharacters(const char16_t* buf, int32_t start, int32_t length);
+ void requestSuspension();
+ nsIContentHandle* createElement(int32_t ns, nsAtom* name,
+ nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* intendedParent,
+ nsHtml5ContentCreatorFunction creator);
+ nsIContentHandle* createElement(int32_t ns, nsAtom* name,
+ nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form,
+ nsIContentHandle* intendedParent,
+ nsHtml5ContentCreatorFunction creator);
+ nsIContentHandle* createHtmlElementSetAsRoot(
+ nsHtml5HtmlAttributes* attributes);
+ void detachFromParent(nsIContentHandle* element);
+ bool hasChildren(nsIContentHandle* element);
+ void appendElement(nsIContentHandle* child, nsIContentHandle* newParent);
+ void appendChildrenToNewParent(nsIContentHandle* oldParent,
+ nsIContentHandle* newParent);
+ void insertFosterParentedChild(nsIContentHandle* child,
+ nsIContentHandle* table,
+ nsIContentHandle* stackParent);
+ nsIContentHandle* createAndInsertFosterParentedElement(
+ int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
+ nsIContentHandle* form, nsIContentHandle* table,
+ nsIContentHandle* stackParent, nsHtml5ContentCreatorFunction creator);
+ ;
+ void insertFosterParentedCharacters(char16_t* buf, int32_t start,
+ int32_t length, nsIContentHandle* table,
+ nsIContentHandle* stackParent);
+ void appendCharacters(nsIContentHandle* parent, char16_t* buf, int32_t start,
+ int32_t length);
+ void appendComment(nsIContentHandle* parent, char16_t* buf, int32_t start,
+ int32_t length);
+ void appendCommentToDocument(char16_t* buf, int32_t start, int32_t length);
+ void addAttributesToElement(nsIContentHandle* element,
+ nsHtml5HtmlAttributes* attributes);
+ void markMalformedIfScript(nsIContentHandle* elt);
+ void start(bool fragmentMode);
+ void end();
+ void appendDoctypeToDocument(nsAtom* name, nsHtml5String publicIdentifier,
+ nsHtml5String systemIdentifier);
+ void elementPushed(int32_t ns, nsAtom* name, nsIContentHandle* node);
+ void elementPopped(int32_t ns, nsAtom* name, nsIContentHandle* node);
+
+ public:
+ inline bool cdataSectionAllowed() { return isInForeign(); }
+
+ private:
+ bool isInForeign();
+ bool isInForeignButNotHtmlOrMathTextIntegrationPoint();
+
+ public:
+ void setFragmentContext(nsAtom* context, int32_t ns, nsIContentHandle* node,
+ bool quirks);
+
+ protected:
+ nsIContentHandle* currentNode();
+
+ public:
+ bool isScriptingEnabled();
+ void setScriptingEnabled(bool scriptingEnabled);
+ void setForceNoQuirks(bool forceNoQuirks);
+ void setIsSrcdocDocument(bool isSrcdocDocument);
+ void flushCharacters();
+
+ private:
+ bool charBufferContainsNonWhitespace();
+
+ public:
+ nsAHtml5TreeBuilderState* newSnapshot();
+ bool snapshotMatches(nsAHtml5TreeBuilderState* snapshot);
+ void loadState(nsAHtml5TreeBuilderState* snapshot);
+
+ private:
+ int32_t findInArray(nsHtml5StackNode* node,
+ jArray<nsHtml5StackNode*, int32_t> arr);
+ nsIContentHandle* nodeFromStackWithBlinkCompat(int32_t stackPos);
+
+ public:
+ nsIContentHandle* getFormPointer() override;
+ nsIContentHandle* getHeadPointer() override;
+ jArray<nsHtml5StackNode*, int32_t> getListOfActiveFormattingElements()
+ override;
+ jArray<nsHtml5StackNode*, int32_t> getStack() override;
+ jArray<int32_t, int32_t> getTemplateModeStack() override;
+ int32_t getMode() override;
+ int32_t getOriginalMode() override;
+ bool isFramesetOk() override;
+ bool isNeedToDropLF() override;
+ bool isQuirks() override;
+ int32_t getListOfActiveFormattingElementsLength() override;
+ int32_t getStackLength() override;
+ int32_t getTemplateModeStackLength() override;
+ static void initializeStatics();
+ static void releaseStatics();
+
+#include "nsHtml5TreeBuilderHSupplement.h"
+};
+
+#endif
diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h
new file mode 100644
index 0000000000..d32c137071
--- /dev/null
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -0,0 +1,1830 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ErrorList.h"
+#include "nsError.h"
+#include "nsNetUtil.h"
+#include "mozilla/CheckedInt.h"
+#include "mozilla/Likely.h"
+#include "mozilla/StaticPrefs_dom.h"
+#include "mozilla/StaticPrefs_network.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/UniquePtrExtensions.h"
+
+nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
+ : mode(0),
+ originalMode(0),
+ framesetOk(false),
+ tokenizer(nullptr),
+ scriptingEnabled(false),
+ needToDropLF(false),
+ fragment(false),
+ contextName(nullptr),
+ contextNamespace(kNameSpaceID_None),
+ contextNode(nullptr),
+ templateModePtr(0),
+ stackNodesIdx(0),
+ numStackNodes(0),
+ currentPtr(0),
+ listPtr(0),
+ formPointer(nullptr),
+ headPointer(nullptr),
+ charBufferLen(0),
+ quirks(false),
+ forceNoQuirks(false),
+ mBuilder(aBuilder),
+ mViewSource(nullptr),
+ mOpSink(nullptr),
+ mHandles(nullptr),
+ mHandlesUsed(0),
+ mSpeculativeLoadStage(nullptr),
+ mBroken(NS_OK),
+ mCurrentHtmlScriptIsAsyncOrDefer(false),
+ mPreventScriptExecution(false),
+ mGenerateSpeculativeLoads(false),
+ mHasSeenImportMap(false)
+#ifdef DEBUG
+ ,
+ mActive(false)
+#endif
+{
+ MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
+}
+
+nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
+ nsHtml5TreeOpStage* aStage,
+ bool aGenerateSpeculativeLoads)
+ : mode(0),
+ originalMode(0),
+ framesetOk(false),
+ tokenizer(nullptr),
+ scriptingEnabled(false),
+ needToDropLF(false),
+ fragment(false),
+ contextName(nullptr),
+ contextNamespace(kNameSpaceID_None),
+ contextNode(nullptr),
+ templateModePtr(0),
+ stackNodesIdx(0),
+ numStackNodes(0),
+ currentPtr(0),
+ listPtr(0),
+ formPointer(nullptr),
+ headPointer(nullptr),
+ charBufferLen(0),
+ quirks(false),
+ forceNoQuirks(false),
+ mBuilder(nullptr),
+ mViewSource(nullptr),
+ mOpSink(aOpSink),
+ mHandles(new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH]),
+ mHandlesUsed(0),
+ mSpeculativeLoadStage(aStage),
+ mBroken(NS_OK),
+ mCurrentHtmlScriptIsAsyncOrDefer(false),
+ mPreventScriptExecution(false),
+ mGenerateSpeculativeLoads(aGenerateSpeculativeLoads),
+ mHasSeenImportMap(false)
+#ifdef DEBUG
+ ,
+ mActive(false)
+#endif
+{
+ MOZ_ASSERT(!(!aStage && aGenerateSpeculativeLoads),
+ "Must not generate speculative loads without a stage");
+ MOZ_COUNT_CTOR(nsHtml5TreeBuilder);
+}
+
+nsHtml5TreeBuilder::~nsHtml5TreeBuilder() {
+ MOZ_COUNT_DTOR(nsHtml5TreeBuilder);
+ NS_ASSERTION(!mActive,
+ "nsHtml5TreeBuilder deleted without ever calling end() on it!");
+ mOpQueue.Clear();
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::createElement(
+ int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ nsIContentHandle* aIntendedParent, nsHtml5ContentCreatorFunction aCreator) {
+ MOZ_ASSERT(aAttributes, "Got null attributes.");
+ MOZ_ASSERT(aName, "Got null name.");
+ MOZ_ASSERT(aNamespace == kNameSpaceID_XHTML ||
+ aNamespace == kNameSpaceID_SVG ||
+ aNamespace == kNameSpaceID_MathML,
+ "Bogus namespace.");
+
+ if (mBuilder) {
+ nsIContent* intendedParent =
+ aIntendedParent ? static_cast<nsIContent*>(aIntendedParent) : nullptr;
+
+ // intendedParent == nullptr is a special case where the
+ // intended parent is the document.
+ nsNodeInfoManager* nodeInfoManager =
+ intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
+ : mBuilder->GetNodeInfoManager();
+
+ nsIContent* elem;
+ if (aNamespace == kNameSpaceID_XHTML) {
+ elem = nsHtml5TreeOperation::CreateHTMLElement(
+ aName, aAttributes, mozilla::dom::FROM_PARSER_FRAGMENT,
+ nodeInfoManager, mBuilder, aCreator.html);
+ } else if (aNamespace == kNameSpaceID_SVG) {
+ elem = nsHtml5TreeOperation::CreateSVGElement(
+ aName, aAttributes, mozilla::dom::FROM_PARSER_FRAGMENT,
+ nodeInfoManager, mBuilder, aCreator.svg);
+ } else {
+ MOZ_ASSERT(aNamespace == kNameSpaceID_MathML);
+ elem = nsHtml5TreeOperation::CreateMathMLElement(
+ aName, aAttributes, nodeInfoManager, mBuilder);
+ }
+ if (MOZ_UNLIKELY(aAttributes != tokenizer->GetAttributes() &&
+ aAttributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES)) {
+ delete aAttributes;
+ }
+ return elem;
+ }
+
+ nsIContentHandle* content = AllocateContentHandle();
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+
+ if (aNamespace == kNameSpaceID_XHTML) {
+ opCreateHTMLElement opeation(
+ content, aName, aAttributes, aCreator.html, aIntendedParent,
+ (!!mSpeculativeLoadStage) ? mozilla::dom::FROM_PARSER_NETWORK
+ : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
+ treeOp->Init(mozilla::AsVariant(opeation));
+ } else if (aNamespace == kNameSpaceID_SVG) {
+ opCreateSVGElement operation(
+ content, aName, aAttributes, aCreator.svg, aIntendedParent,
+ (!!mSpeculativeLoadStage) ? mozilla::dom::FROM_PARSER_NETWORK
+ : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
+ treeOp->Init(mozilla::AsVariant(operation));
+ } else {
+ // kNameSpaceID_MathML
+ opCreateMathMLElement operation(content, aName, aAttributes,
+ aIntendedParent);
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+
+ // mSpeculativeLoadStage is non-null only in the off-the-main-thread
+ // tree builder, which handles the network stream
+
+ // Start wall of code for speculative loading and line numbers
+
+ if (mGenerateSpeculativeLoads && mode != IN_TEMPLATE) {
+ switch (aNamespace) {
+ case kNameSpaceID_XHTML:
+ if (nsGkAtoms::img == aName) {
+ nsHtml5String loading =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_LOADING);
+ if (!mozilla::StaticPrefs::dom_image_lazy_loading_enabled() ||
+ !loading.LowerCaseEqualsASCII("lazy")) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
+ nsHtml5String srcset =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
+ nsHtml5String crossOrigin =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ nsHtml5String sizes =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
+ mSpeculativeLoadQueue.AppendElement()->InitImage(
+ url, crossOrigin, /* aMedia = */ nullptr, referrerPolicy,
+ srcset, sizes, false);
+ }
+ } else if (nsGkAtoms::source == aName) {
+ nsHtml5String srcset =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET);
+ // Sources without srcset cannot be selected. The source could also be
+ // for a media element, but in that context doesn't use srcset. See
+ // comments in nsHtml5SpeculativeLoad.h about <picture> preloading
+ if (srcset) {
+ nsHtml5String sizes =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
+ nsHtml5String type =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
+ nsHtml5String media =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
+ mSpeculativeLoadQueue.AppendElement()->InitPictureSource(
+ srcset, sizes, type, media);
+ }
+ } else if (nsGkAtoms::script == aName) {
+ nsHtml5TreeOperation* treeOp =
+ mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(
+ NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetScriptLineAndColumnNumberAndFreeze operation(
+ content, tokenizer->getLineNumber(),
+ tokenizer->getColumnNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+
+ nsHtml5String type =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
+ if (!mHasSeenImportMap) {
+ // If we see an importmap, we don't want to later start
+ // speculative loads for modulepreloads, since such load might
+ // finish before the importmap is created.
+ nsAutoString typeString;
+ type.ToString(typeString);
+ mHasSeenImportMap =
+ typeString.LowerCaseFindASCII("importmap") != kNotFound;
+ }
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC);
+ if (url) {
+ nsHtml5String charset =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
+ nsHtml5String crossOrigin =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String integrity =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ bool async =
+ aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC);
+ bool defer =
+ aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
+ bool noModule =
+ aAttributes->contains(nsHtml5AttributeName::ATTR_NOMODULE);
+ mSpeculativeLoadQueue.AppendElement()->InitScript(
+ url, charset, type, crossOrigin, /* aMedia = */ nullptr,
+ integrity, referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
+ async, defer, noModule, false);
+ mCurrentHtmlScriptIsAsyncOrDefer = async || defer;
+ }
+ } else if (nsGkAtoms::link == aName) {
+ nsHtml5String rel =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_REL);
+ // Not splitting on space here is bogus but the old parser didn't even
+ // do a case-insensitive check.
+ if (rel) {
+ if (rel.LowerCaseEqualsASCII("stylesheet")) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (url) {
+ nsHtml5String charset =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
+ nsHtml5String crossOrigin = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String integrity =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ nsHtml5String media =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
+ mSpeculativeLoadQueue.AppendElement()->InitStyle(
+ url, charset, crossOrigin, media, referrerPolicy, integrity,
+ false);
+ }
+ } else if (rel.LowerCaseEqualsASCII("preconnect")) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (url) {
+ nsHtml5String crossOrigin = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ mSpeculativeLoadQueue.AppendElement()->InitPreconnect(
+ url, crossOrigin);
+ }
+ } else if (mozilla::StaticPrefs::network_preload() &&
+ rel.LowerCaseEqualsASCII("preload")) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (url) {
+ nsHtml5String as =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_AS);
+ nsHtml5String charset =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
+ nsHtml5String crossOrigin = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String integrity =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ nsHtml5String media =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
+
+ // Note that respective speculative loaders for scripts and
+ // styles check all additional attributes to be equal to use the
+ // speculative load. So, if any of them is specified and the
+ // preload has to take the expected effect, those attributes
+ // must also be specified on the actual tag to use the preload.
+ // Omitting an attribute on both will make the values equal
+ // (empty) and thus use the preload.
+ if (as.LowerCaseEqualsASCII("script")) {
+ nsHtml5String type =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
+ mSpeculativeLoadQueue.AppendElement()->InitScript(
+ url, charset, type, crossOrigin, media, integrity,
+ referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
+ false, false, false, true);
+ } else if (as.LowerCaseEqualsASCII("style")) {
+ mSpeculativeLoadQueue.AppendElement()->InitStyle(
+ url, charset, crossOrigin, media, referrerPolicy,
+ integrity, true);
+ } else if (as.LowerCaseEqualsASCII("image")) {
+ nsHtml5String srcset = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_IMAGESRCSET);
+ nsHtml5String sizes = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_IMAGESIZES);
+ mSpeculativeLoadQueue.AppendElement()->InitImage(
+ url, crossOrigin, media, referrerPolicy, srcset, sizes,
+ true);
+ } else if (as.LowerCaseEqualsASCII("font")) {
+ mSpeculativeLoadQueue.AppendElement()->InitFont(
+ url, crossOrigin, media, referrerPolicy);
+ } else if (as.LowerCaseEqualsASCII("fetch")) {
+ mSpeculativeLoadQueue.AppendElement()->InitFetch(
+ url, crossOrigin, media, referrerPolicy);
+ }
+ // Other "as" values will be supported later.
+ }
+ } else if (mozilla::StaticPrefs::network_modulepreload() &&
+ rel.LowerCaseEqualsASCII("modulepreload") &&
+ !mHasSeenImportMap) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (url && url.Length() != 0) {
+ nsHtml5String as =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_AS);
+ nsAutoString asString;
+ as.ToString(asString);
+ if (mozilla::net::IsScriptLikeOrInvalid(asString)) {
+ nsHtml5String charset =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
+ RefPtr<nsAtom> moduleType = nsGkAtoms::_module;
+ nsHtml5String type =
+ nsHtml5String::FromAtom(moduleType.forget());
+ nsHtml5String crossOrigin = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String media =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA);
+ nsHtml5String integrity = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_INTEGRITY);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ mSpeculativeLoadQueue.AppendElement()->InitScript(
+ url, charset, type, crossOrigin, media, integrity,
+ referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
+ false, false, false, true);
+ }
+ }
+ }
+ }
+ } else if (nsGkAtoms::video == aName) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
+ if (url) {
+ mSpeculativeLoadQueue.AppendElement()->InitImage(
+ url, nullptr, nullptr, nullptr, nullptr, nullptr, false);
+ }
+ } else if (nsGkAtoms::style == aName) {
+ mImportScanner.Start();
+ nsHtml5TreeOperation* treeOp =
+ mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(
+ NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetStyleLineNumber operation(content, tokenizer->getLineNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+ } else if (nsGkAtoms::html == aName) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
+ mSpeculativeLoadQueue.AppendElement()->InitManifest(url);
+ } else if (nsGkAtoms::base == aName) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (url) {
+ mSpeculativeLoadQueue.AppendElement()->InitBase(url);
+ }
+ } else if (nsGkAtoms::meta == aName) {
+ if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "content-security-policy",
+ aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
+ nsHtml5String csp =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
+ if (csp) {
+ mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(csp);
+ }
+ } else if (nsHtml5Portability::
+ lowerCaseLiteralEqualsIgnoreAsciiCaseString(
+ "referrer",
+ aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_NAME))) {
+ nsHtml5String referrerPolicy =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
+ if (referrerPolicy) {
+ mSpeculativeLoadQueue.AppendElement()->InitMetaReferrerPolicy(
+ referrerPolicy);
+ }
+ }
+ }
+ break;
+ case kNameSpaceID_SVG:
+ if (nsGkAtoms::image == aName) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (!url) {
+ url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
+ }
+ if (url) {
+ mSpeculativeLoadQueue.AppendElement()->InitImage(
+ url, nullptr, nullptr, nullptr, nullptr, nullptr, false);
+ }
+ } else if (nsGkAtoms::script == aName) {
+ nsHtml5TreeOperation* treeOp =
+ mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(
+ NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetScriptLineAndColumnNumberAndFreeze operation(
+ content, tokenizer->getLineNumber(),
+ tokenizer->getColumnNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (!url) {
+ url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
+ }
+ if (url) {
+ nsHtml5String type =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
+ nsHtml5String crossOrigin =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
+ nsHtml5String integrity =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
+ nsHtml5String referrerPolicy = aAttributes->getValue(
+ nsHtml5AttributeName::ATTR_REFERRERPOLICY);
+ mSpeculativeLoadQueue.AppendElement()->InitScript(
+ url, nullptr, type, crossOrigin, /* aMedia = */ nullptr,
+ integrity, referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
+ false, false, false, false);
+ }
+ } else if (nsGkAtoms::style == aName) {
+ mImportScanner.Start();
+ nsHtml5TreeOperation* treeOp =
+ mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(
+ NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetStyleLineNumber operation(content, tokenizer->getLineNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+ break;
+ }
+ } else if (aNamespace != kNameSpaceID_MathML) {
+ // No speculative loader--just line numbers and defer/async check
+ if (nsGkAtoms::style == aName) {
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetStyleLineNumber operation(content, tokenizer->getLineNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+ } else if (nsGkAtoms::script == aName) {
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetScriptLineAndColumnNumberAndFreeze operation(
+ content, tokenizer->getLineNumber(), tokenizer->getColumnNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+ if (aNamespace == kNameSpaceID_XHTML) {
+ mCurrentHtmlScriptIsAsyncOrDefer =
+ aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) &&
+ (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
+ aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER));
+ }
+ } else if (aNamespace == kNameSpaceID_XHTML) {
+ if (nsGkAtoms::html == aName) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
+ nsHtml5TreeOperation* treeOp =
+ mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(
+ NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ if (url) {
+ nsString
+ urlString; // Not Auto, because using it to hold nsStringBuffer*
+ url.ToString(urlString);
+ opProcessOfflineManifest operation(ToNewUnicode(urlString));
+ treeOp->Init(mozilla::AsVariant(operation));
+ } else {
+ opProcessOfflineManifest operation(ToNewUnicode(u""_ns));
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+ } else if (nsGkAtoms::base == aName && mViewSource) {
+ nsHtml5String url =
+ aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
+ if (url) {
+ mViewSource->AddBase(url);
+ }
+ }
+ }
+ }
+
+ // End wall of code for speculative loading
+
+ return content;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::createElement(
+ int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ nsIContentHandle* aFormElement, nsIContentHandle* aIntendedParent,
+ nsHtml5ContentCreatorFunction aCreator) {
+ nsIContentHandle* content =
+ createElement(aNamespace, aName, aAttributes, aIntendedParent, aCreator);
+ if (aFormElement) {
+ if (mBuilder) {
+ nsHtml5TreeOperation::SetFormElement(
+ static_cast<nsIContent*>(content),
+ static_cast<nsIContent*>(aFormElement));
+ } else {
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opSetFormElement operation(content, aFormElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+ }
+ return content;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::createHtmlElementSetAsRoot(
+ nsHtml5HtmlAttributes* aAttributes) {
+ nsHtml5ContentCreatorFunction creator;
+ // <html> uses NS_NewHTMLSharedElement creator
+ creator.html = NS_NewHTMLSharedElement;
+ nsIContentHandle* content = createElement(kNameSpaceID_XHTML, nsGkAtoms::html,
+ aAttributes, nullptr, creator);
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::AppendToDocument(
+ static_cast<nsIContent*>(content), mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ } else {
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ opAppendToDocument operation(content);
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+ return content;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
+ int32_t aNamespace, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ nsIContentHandle* aFormElement, nsIContentHandle* aTable,
+ nsIContentHandle* aStackParent, nsHtml5ContentCreatorFunction aCreator) {
+ MOZ_ASSERT(aTable, "Null table");
+ MOZ_ASSERT(aStackParent, "Null stack parent");
+
+ if (mBuilder) {
+ // Get the foster parent to use as the intended parent when creating
+ // the child element.
+ nsIContent* fosterParent = nsHtml5TreeOperation::GetFosterParent(
+ static_cast<nsIContent*>(aTable),
+ static_cast<nsIContent*>(aStackParent));
+
+ nsIContentHandle* child = createElement(
+ aNamespace, aName, aAttributes, aFormElement, fosterParent, aCreator);
+
+ insertFosterParentedChild(child, aTable, aStackParent);
+
+ return child;
+ }
+
+ // Tree op to get the foster parent that we use as the intended parent
+ // when creating the child element.
+ nsHtml5TreeOperation* fosterParentTreeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(fosterParentTreeOp, "Tree op allocation failed.");
+ nsIContentHandle* fosterParentHandle = AllocateContentHandle();
+ opGetFosterParent operation(aTable, aStackParent, fosterParentHandle);
+ fosterParentTreeOp->Init(mozilla::AsVariant(operation));
+
+ // Create the element with the correct intended parent.
+ nsIContentHandle* child =
+ createElement(aNamespace, aName, aAttributes, aFormElement,
+ fosterParentHandle, aCreator);
+
+ // Insert the child into the foster parent.
+ insertFosterParentedChild(child, aTable, aStackParent);
+
+ return child;
+}
+
+void nsHtml5TreeBuilder::detachFromParent(nsIContentHandle* aElement) {
+ MOZ_ASSERT(aElement, "Null element");
+
+ if (mBuilder) {
+ nsHtml5TreeOperation::Detach(static_cast<nsIContent*>(aElement), mBuilder);
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opDetach operation(aElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::appendElement(nsIContentHandle* aChild,
+ nsIContentHandle* aParent) {
+ MOZ_ASSERT(aChild, "Null child");
+ MOZ_ASSERT(aParent, "Null parent");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::Append(
+ static_cast<nsIContent*>(aChild), static_cast<nsIContent*>(aParent),
+ mozilla::dom::FROM_PARSER_FRAGMENT, mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+
+ opAppend operation(aChild, aParent,
+ (!!mSpeculativeLoadStage)
+ ? mozilla::dom::FROM_PARSER_NETWORK
+ : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::appendChildrenToNewParent(
+ nsIContentHandle* aOldParent, nsIContentHandle* aNewParent) {
+ MOZ_ASSERT(aOldParent, "Null old parent");
+ MOZ_ASSERT(aNewParent, "Null new parent");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::AppendChildrenToNewParent(
+ static_cast<nsIContent*>(aOldParent),
+ static_cast<nsIContent*>(aNewParent), mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opAppendChildrenToNewParent operation(aOldParent, aNewParent);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::insertFosterParentedCharacters(
+ char16_t* aBuffer, int32_t aStart, int32_t aLength,
+ nsIContentHandle* aTable, nsIContentHandle* aStackParent) {
+ MOZ_ASSERT(aBuffer, "Null buffer");
+ MOZ_ASSERT(aTable, "Null table");
+ MOZ_ASSERT(aStackParent, "Null stack parent");
+ MOZ_ASSERT(!aStart, "aStart must always be zero.");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::FosterParentText(
+ static_cast<nsIContent*>(aStackParent),
+ aBuffer, // XXX aStart always ignored???
+ aLength, static_cast<nsIContent*>(aTable), mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
+ if (!bufferCopy) {
+ // Just assigning mBroken instead of generating tree op. The caller
+ // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
+ mBroken = NS_ERROR_OUT_OF_MEMORY;
+ requestSuspension();
+ return;
+ }
+
+ memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opFosterParentText operation(aStackParent, bufferCopy.release(), aTable,
+ aLength);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::insertFosterParentedChild(
+ nsIContentHandle* aChild, nsIContentHandle* aTable,
+ nsIContentHandle* aStackParent) {
+ MOZ_ASSERT(aChild, "Null child");
+ MOZ_ASSERT(aTable, "Null table");
+ MOZ_ASSERT(aStackParent, "Null stack parent");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::FosterParent(
+ static_cast<nsIContent*>(aChild),
+ static_cast<nsIContent*>(aStackParent),
+ static_cast<nsIContent*>(aTable), mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opFosterParent operation(aChild, aStackParent, aTable);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent,
+ char16_t* aBuffer, int32_t aStart,
+ int32_t aLength) {
+ MOZ_ASSERT(aBuffer, "Null buffer");
+ MOZ_ASSERT(aParent, "Null parent");
+ MOZ_ASSERT(!aStart, "aStart must always be zero.");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::AppendText(
+ aBuffer, // XXX aStart always ignored???
+ aLength, static_cast<nsIContent*>(aParent), mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
+ if (!bufferCopy) {
+ // Just assigning mBroken instead of generating tree op. The caller
+ // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
+ mBroken = NS_ERROR_OUT_OF_MEMORY;
+ requestSuspension();
+ return;
+ }
+
+ memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
+
+ if (mImportScanner.ShouldScan()) {
+ nsTArray<nsString> imports =
+ mImportScanner.Scan(mozilla::Span(aBuffer, aLength));
+ for (nsString& url : imports) {
+ mSpeculativeLoadQueue.AppendElement()->InitImportStyle(std::move(url));
+ }
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opAppendText operation(aParent, bufferCopy.release(), aLength);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent,
+ char16_t* aBuffer, int32_t aStart,
+ int32_t aLength) {
+ MOZ_ASSERT(aBuffer, "Null buffer");
+ MOZ_ASSERT(aParent, "Null parent");
+ MOZ_ASSERT(!aStart, "aStart must always be zero.");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::AppendComment(
+ static_cast<nsIContent*>(aParent),
+ aBuffer, // XXX aStart always ignored???
+ aLength, mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
+ if (!bufferCopy) {
+ // Just assigning mBroken instead of generating tree op. The caller
+ // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
+ mBroken = NS_ERROR_OUT_OF_MEMORY;
+ requestSuspension();
+ return;
+ }
+
+ memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opAppendComment operation(aParent, bufferCopy.release(), aLength);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer,
+ int32_t aStart,
+ int32_t aLength) {
+ MOZ_ASSERT(aBuffer, "Null buffer");
+ MOZ_ASSERT(!aStart, "aStart must always be zero.");
+
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::AppendCommentToDocument(
+ aBuffer, // XXX aStart always ignored???
+ aLength, mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ auto bufferCopy = mozilla::MakeUniqueFallible<char16_t[]>(aLength);
+ if (!bufferCopy) {
+ // Just assigning mBroken instead of generating tree op. The caller
+ // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
+ mBroken = NS_ERROR_OUT_OF_MEMORY;
+ requestSuspension();
+ return;
+ }
+
+ memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opAppendCommentToDocument data(bufferCopy.release(), aLength);
+ treeOp->Init(mozilla::AsVariant(data));
+}
+
+void nsHtml5TreeBuilder::addAttributesToElement(
+ nsIContentHandle* aElement, nsHtml5HtmlAttributes* aAttributes) {
+ MOZ_ASSERT(aElement, "Null element");
+ MOZ_ASSERT(aAttributes, "Null attributes");
+
+ if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+ return;
+ }
+
+ if (mBuilder) {
+ MOZ_ASSERT(
+ aAttributes == tokenizer->GetAttributes(),
+ "Using attribute other than the tokenizer's to add to body or html.");
+ nsresult rv = nsHtml5TreeOperation::AddAttributes(
+ static_cast<nsIContent*>(aElement), aAttributes, mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opAddAttributes opeation(aElement, aAttributes);
+ treeOp->Init(mozilla::AsVariant(opeation));
+}
+
+void nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle* aElement) {
+ MOZ_ASSERT(aElement, "Null element");
+
+ if (mBuilder) {
+ nsHtml5TreeOperation::MarkMalformedIfScript(
+ static_cast<nsIContent*>(aElement));
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opMarkMalformedIfScript operation(aElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::start(bool fragment) {
+ mCurrentHtmlScriptIsAsyncOrDefer = false;
+#ifdef DEBUG
+ mActive = true;
+#endif
+}
+
+void nsHtml5TreeBuilder::end() {
+ mOpQueue.Clear();
+#ifdef DEBUG
+ mActive = false;
+#endif
+}
+
+void nsHtml5TreeBuilder::appendDoctypeToDocument(nsAtom* aName,
+ nsHtml5String aPublicId,
+ nsHtml5String aSystemId) {
+ MOZ_ASSERT(aName, "Null name");
+ nsString publicId; // Not Auto, because using it to hold nsStringBuffer*
+ nsString systemId; // Not Auto, because using it to hold nsStringBuffer*
+ aPublicId.ToString(publicId);
+ aSystemId.ToString(systemId);
+ if (mBuilder) {
+ nsresult rv = nsHtml5TreeOperation::AppendDoctypeToDocument(
+ aName, publicId, systemId, mBuilder);
+ if (NS_FAILED(rv)) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
+ }
+ return;
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opAppendDoctypeToDocument operation(aName, publicId, systemId);
+ treeOp->Init(mozilla::AsVariant(operation));
+ // nsXMLContentSink can flush here, but what's the point?
+ // It can also interrupt here, but we can't.
+}
+
+void nsHtml5TreeBuilder::elementPushed(int32_t aNamespace, nsAtom* aName,
+ nsIContentHandle* aElement) {
+ NS_ASSERTION(aNamespace == kNameSpaceID_XHTML ||
+ aNamespace == kNameSpaceID_SVG ||
+ aNamespace == kNameSpaceID_MathML,
+ "Element isn't HTML, SVG or MathML!");
+ NS_ASSERTION(aName, "Element doesn't have local name!");
+ NS_ASSERTION(aElement, "No element!");
+ /*
+ * The frame constructor uses recursive algorithms, so it can't deal with
+ * arbitrarily deep trees. This is especially a problem on Windows where
+ * the permitted depth of the runtime stack is rather small.
+ *
+ * The following is a protection against author incompetence--not against
+ * malice. There are other ways to make the DOM deep anyway.
+ *
+ * The basic idea is that when the tree builder stack gets too deep,
+ * append operations no longer append to the node that the HTML parsing
+ * algorithm says they should but instead text nodes are append to the last
+ * element that was seen before a magic tree builder stack threshold was
+ * reached and element and comment nodes aren't appended to the DOM at all.
+ *
+ * However, for security reasons, non-child descendant text nodes inside an
+ * SVG script or style element should not become children. Also, non-cell
+ * table elements shouldn't be used as surrogate parents for user experience
+ * reasons.
+ */
+ if (aNamespace != kNameSpaceID_XHTML) {
+ return;
+ }
+ if (aName == nsGkAtoms::body || aName == nsGkAtoms::frameset) {
+ if (mBuilder) {
+ // InnerHTML and DOMParser shouldn't start layout anyway
+ return;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ treeOp->Init(mozilla::AsVariant(opStartLayout()));
+ return;
+ }
+ if (nsIContent::RequiresDoneCreatingElement(kNameSpaceID_XHTML, aName)) {
+ if (mBuilder) {
+ nsHtml5TreeOperation::DoneCreatingElement(
+ static_cast<nsIContent*>(aElement));
+ } else {
+ opDoneCreatingElement operation(aElement);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+ }
+ return;
+ }
+ if (mGenerateSpeculativeLoads && aName == nsGkAtoms::picture) {
+ // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
+ mSpeculativeLoadQueue.AppendElement()->InitOpenPicture();
+ return;
+ }
+ if (aName == nsGkAtoms::_template) {
+ if (tokenizer->TemplatePushedOrHeadPopped()) {
+ requestSuspension();
+ }
+ }
+}
+
+void nsHtml5TreeBuilder::elementPopped(int32_t aNamespace, nsAtom* aName,
+ nsIContentHandle* aElement) {
+ NS_ASSERTION(aNamespace == kNameSpaceID_XHTML ||
+ aNamespace == kNameSpaceID_SVG ||
+ aNamespace == kNameSpaceID_MathML,
+ "Element isn't HTML, SVG or MathML!");
+ NS_ASSERTION(aName, "Element doesn't have local name!");
+ NS_ASSERTION(aElement, "No element!");
+ if (aNamespace == kNameSpaceID_MathML) {
+ return;
+ }
+ // we now have only SVG and HTML
+ if (aName == nsGkAtoms::script) {
+ if (mPreventScriptExecution) {
+ if (mBuilder) {
+ nsHtml5TreeOperation::PreventScriptExecution(
+ static_cast<nsIContent*>(aElement));
+ return;
+ }
+ opPreventScriptExecution operation(aElement);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+ return;
+ }
+ if (mBuilder) {
+ return;
+ }
+ if (mCurrentHtmlScriptIsAsyncOrDefer) {
+ NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
+ "Only HTML scripts may be async/defer.");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opRunScriptAsyncDefer operation(aElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+ mCurrentHtmlScriptIsAsyncOrDefer = false;
+ return;
+ }
+ requestSuspension();
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opRunScript operation(aElement, nullptr);
+ treeOp->Init(mozilla::AsVariant(operation));
+ return;
+ }
+ // Some nodes need DoneAddingChildren() called to initialize
+ // properly (e.g. form state restoration).
+ if (nsIContent::RequiresDoneAddingChildren(aNamespace, aName)) {
+ if (mBuilder) {
+ nsHtml5TreeOperation::DoneAddingChildren(
+ static_cast<nsIContent*>(aElement));
+ return;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opDoneAddingChildren operation(aElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+ if (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::head) {
+ if (tokenizer->TemplatePushedOrHeadPopped()) {
+ requestSuspension();
+ }
+ }
+ return;
+ }
+ if (aName == nsGkAtoms::style ||
+ (aNamespace == kNameSpaceID_XHTML && aName == nsGkAtoms::link)) {
+ if (mBuilder) {
+ MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
+ "Scripts must be blocked.");
+ mBuilder->UpdateStyleSheet(static_cast<nsIContent*>(aElement));
+ return;
+ }
+
+ if (aName == nsGkAtoms::style) {
+ nsTArray<nsString> imports = mImportScanner.Stop();
+ for (nsString& url : imports) {
+ mSpeculativeLoadQueue.AppendElement()->InitImportStyle(std::move(url));
+ }
+ }
+
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opUpdateStyleSheet operation(aElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+ return;
+ }
+ if (aNamespace == kNameSpaceID_SVG) {
+ if (aName == nsGkAtoms::svg) {
+ if (!scriptingEnabled || mPreventScriptExecution) {
+ return;
+ }
+ if (mBuilder) {
+ nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent*>(aElement));
+ return;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opSvgLoad operation(aElement);
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+ return;
+ }
+
+ if (mGenerateSpeculativeLoads && aName == nsGkAtoms::picture) {
+ // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
+ mSpeculativeLoadQueue.AppendElement()->InitEndPicture();
+ return;
+ }
+}
+
+void nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf,
+ int32_t aStart, int32_t aLength) {
+ MOZ_RELEASE_ASSERT(charBufferLen + aLength <= charBuffer.length,
+ "About to memcpy past the end of the buffer!");
+ memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength);
+ charBufferLen += aLength;
+}
+
+// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
+// is 2^30. Note that this is counting char16_t units. The underlying
+// bytes will be twice that, but they fit even in 32-bit size_t even
+// if a contiguous chunk of memory of that size is pretty unlikely to
+// be available on a 32-bit system.
+#define MAX_POWER_OF_TWO_IN_INT32 0x40000000
+
+bool nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength) {
+ // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
+ // so that this method becomes unnecessary.
+ mozilla::CheckedInt<int32_t> worstCase(charBufferLen);
+ worstCase += aLength;
+ if (!worstCase.isValid()) {
+ return false;
+ }
+ if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) {
+ return false;
+ }
+ if (!charBuffer) {
+ if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) {
+ // Add one to round to the next power of two to avoid immediate
+ // reallocation once there are a few characters in the buffer.
+ worstCase += 1;
+ }
+ charBuffer = jArray<char16_t, int32_t>::newFallibleJArray(
+ mozilla::RoundUpPow2(worstCase.value()));
+ if (!charBuffer) {
+ return false;
+ }
+ } else if (worstCase.value() > charBuffer.length) {
+ jArray<char16_t, int32_t> newBuf =
+ jArray<char16_t, int32_t>::newFallibleJArray(
+ mozilla::RoundUpPow2(worstCase.value()));
+ if (!newBuf) {
+ return false;
+ }
+ memcpy(newBuf, charBuffer, sizeof(char16_t) * size_t(charBufferLen));
+ charBuffer = newBuf;
+ }
+ return true;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::AllocateContentHandle() {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never allocate a handle with builder.");
+ return nullptr;
+ }
+ if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
+ mOldHandles.AppendElement(std::move(mHandles));
+ mHandles = mozilla::MakeUnique<nsIContent*[]>(
+ NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH);
+ mHandlesUsed = 0;
+ }
+#ifdef DEBUG
+ mHandles[mHandlesUsed] = reinterpret_cast<nsIContent*>(uintptr_t(0xC0DEDBAD));
+#endif
+ return &mHandles[mHandlesUsed++];
+}
+
+bool nsHtml5TreeBuilder::HasScript() {
+ uint32_t len = mOpQueue.Length();
+ if (!len) {
+ return false;
+ }
+ return mOpQueue.ElementAt(len - 1).IsRunScript();
+}
+
+mozilla::Result<bool, nsresult> nsHtml5TreeBuilder::Flush(bool aDiscretionary) {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never flush with builder.");
+ return false;
+ }
+ if (NS_SUCCEEDED(mBroken)) {
+ if (!aDiscretionary || !(charBufferLen && currentPtr >= 0 &&
+ stack[currentPtr]->isFosterParenting())) {
+ // Don't flush text on discretionary flushes if the current element on
+ // the stack is a foster-parenting element and there's pending text,
+ // because flushing in that case would make the tree shape dependent on
+ // where the flush points fall.
+ flushCharacters();
+ }
+ FlushLoads();
+ }
+ if (mOpSink) {
+ bool hasOps = !mOpQueue.IsEmpty();
+ if (hasOps) {
+ // If the builder is broken and mOpQueue is not empty, there must be
+ // one op and it must be eTreeOpMarkAsBroken.
+ if (NS_FAILED(mBroken)) {
+ MOZ_ASSERT(mOpQueue.Length() == 1,
+ "Tree builder is broken with a non-empty op queue whose "
+ "length isn't 1.");
+ MOZ_ASSERT(mOpQueue[0].IsMarkAsBroken(),
+ "Tree builder is broken but the op in queue is not marked "
+ "as broken.");
+ }
+ if (!mOpSink->MoveOpsFrom(mOpQueue)) {
+ return mozilla::Err(NS_ERROR_OUT_OF_MEMORY);
+ }
+ }
+ return hasOps;
+ }
+ // no op sink: throw away ops
+ mOpQueue.Clear();
+ return false;
+}
+
+void nsHtml5TreeBuilder::FlushLoads() {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never flush loads with builder.");
+ return;
+ }
+ if (!mSpeculativeLoadQueue.IsEmpty()) {
+ mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
+ }
+}
+
+void nsHtml5TreeBuilder::SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ nsCharsetSource aCharsetSource,
+ bool aCommitEncodingSpeculation) {
+ MOZ_ASSERT(!mBuilder, "How did we call this with builder?");
+ MOZ_ASSERT(mSpeculativeLoadStage,
+ "How did we call this without a speculative load stage?");
+ mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(
+ aEncoding, aCharsetSource, aCommitEncodingSpeculation);
+}
+
+void nsHtml5TreeBuilder::UpdateCharsetSource(nsCharsetSource aCharsetSource) {
+ MOZ_ASSERT(!mBuilder, "How did we call this with builder?");
+ MOZ_ASSERT(mSpeculativeLoadStage,
+ "How did we call this without a speculative load stage (even "
+ "though we don't need it right here)?");
+ if (mViewSource) {
+ mViewSource->UpdateCharsetSource(aCharsetSource);
+ return;
+ }
+ opUpdateCharsetSource operation(aCharsetSource);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::StreamEnded() {
+ MOZ_ASSERT(!mBuilder, "Must not call StreamEnded with builder.");
+ MOZ_ASSERT(!fragment, "Must not parse fragments off the main thread.");
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ treeOp->Init(mozilla::AsVariant(opStreamEnded()));
+}
+
+void nsHtml5TreeBuilder::NeedsCharsetSwitchTo(
+ NotNull<const Encoding*> aEncoding, int32_t aCharsetSource,
+ int32_t aLineNumber) {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never switch charset with builder.");
+ return;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ opCharsetSwitchTo opeation(aEncoding, aCharsetSource, aLineNumber);
+ treeOp->Init(mozilla::AsVariant(opeation));
+}
+
+void nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId,
+ bool aError,
+ int32_t aLineNumber) {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never complain about charset with builder.");
+ return;
+ }
+
+ if (mSpeculativeLoadStage) {
+ mSpeculativeLoadQueue.AppendElement()->InitMaybeComplainAboutCharset(
+ aMsgId, aError, aLineNumber);
+ } else {
+ opMaybeComplainAboutCharset opeartion(const_cast<char*>(aMsgId), aError,
+ aLineNumber);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(opeartion));
+ }
+}
+
+void nsHtml5TreeBuilder::TryToEnableEncodingMenu() {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never disable encoding menu with builder.");
+ return;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ NS_ASSERTION(treeOp, "Tree op allocation failed.");
+ treeOp->Init(mozilla::AsVariant(opEnableEncodingMenu()));
+}
+
+void nsHtml5TreeBuilder::AddSnapshotToScript(
+ nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must never use snapshots with builder.");
+ return;
+ }
+ MOZ_ASSERT(HasScript(), "No script to add a snapshot to!");
+ MOZ_ASSERT(aSnapshot, "Got null snapshot.");
+ mOpQueue.ElementAt(mOpQueue.Length() - 1).SetSnapshot(aSnapshot, aLine);
+}
+
+void nsHtml5TreeBuilder::DropHandles() {
+ MOZ_ASSERT(!mBuilder, "Must not drop handles with builder.");
+ mOldHandles.Clear();
+ mHandlesUsed = 0;
+}
+
+void nsHtml5TreeBuilder::MarkAsBroken(nsresult aRv) {
+ if (MOZ_UNLIKELY(mBuilder)) {
+ MOZ_ASSERT_UNREACHABLE("Must not call this with builder.");
+ return;
+ }
+ mBroken = aRv;
+ mOpQueue.Clear(); // Previous ops don't matter anymore
+ opMarkAsBroken operation(aRv);
+ mOpQueue.AppendElement()->Init(mozilla::AsVariant(operation));
+}
+
+void nsHtml5TreeBuilder::MarkAsBrokenFromPortability(nsresult aRv) {
+ if (mBuilder) {
+ MarkAsBrokenAndRequestSuspensionWithBuilder(aRv);
+ return;
+ }
+ mBroken = aRv;
+ requestSuspension();
+}
+
+void nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString& aTitle) {
+ MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
+
+ startTag(nsHtml5ElementName::ELT_META,
+ nsHtml5ViewSourceUtils::NewMetaViewportAttributes(), false);
+
+ startTag(nsHtml5ElementName::ELT_TITLE,
+ nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES, false);
+
+ // XUL will add the "Source of: " prefix.
+ uint32_t length = aTitle.Length();
+ if (length > INT32_MAX) {
+ length = INT32_MAX;
+ }
+ characters(aTitle.get(), 0, (int32_t)length);
+ endTag(nsHtml5ElementName::ELT_TITLE);
+
+ startTag(nsHtml5ElementName::ELT_LINK,
+ nsHtml5ViewSourceUtils::NewLinkAttributes(), false);
+
+ startTag(nsHtml5ElementName::ELT_BODY,
+ nsHtml5ViewSourceUtils::NewBodyAttributes(), false);
+
+ StartPlainTextBody();
+}
+
+void nsHtml5TreeBuilder::StartPlainText() {
+ MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
+ setForceNoQuirks(true);
+ startTag(nsHtml5ElementName::ELT_LINK,
+ nsHtml5PlainTextUtils::NewLinkAttributes(), false);
+
+ startTag(nsHtml5ElementName::ELT_BODY,
+ nsHtml5PlainTextUtils::NewBodyAttributes(), false);
+
+ StartPlainTextBody();
+}
+
+void nsHtml5TreeBuilder::StartPlainTextBody() {
+ MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
+ startTag(nsHtml5ElementName::ELT_PRE, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES,
+ false);
+ needToDropLF = false;
+}
+
+// DocumentModeHandler
+void nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m) {
+ if (mBuilder) {
+ mBuilder->SetDocumentMode(m);
+ return;
+ }
+ if (mSpeculativeLoadStage) {
+ mSpeculativeLoadQueue.AppendElement()->InitSetDocumentMode(m);
+ return;
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ treeOp->Init(mozilla::AsVariant(m));
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::getDocumentFragmentForTemplate(
+ nsIContentHandle* aTemplate) {
+ if (mBuilder) {
+ return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
+ static_cast<nsIContent*>(aTemplate));
+ }
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
+ if (MOZ_UNLIKELY(!treeOp)) {
+ MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ nsIContentHandle* fragHandle = AllocateContentHandle();
+ opGetDocumentFragmentForTemplate operation(aTemplate, fragHandle);
+ treeOp->Init(mozilla::AsVariant(operation));
+ return fragHandle;
+}
+
+nsIContentHandle* nsHtml5TreeBuilder::getFormPointerForContext(
+ nsIContentHandle* aContext) {
+ MOZ_ASSERT(mBuilder, "Must have builder.");
+ if (!aContext) {
+ return nullptr;
+ }
+
+ MOZ_ASSERT(NS_IsMainThread());
+
+ // aContext must always be an element that already exists
+ // in the document.
+ nsIContent* contextNode = static_cast<nsIContent*>(aContext);
+ nsIContent* currentAncestor = contextNode;
+
+ // We traverse the ancestors of the context node to find the nearest
+ // form pointer. This traversal is why aContext must not be an emtpy handle.
+ nsIContent* nearestForm = nullptr;
+ while (currentAncestor) {
+ if (currentAncestor->IsHTMLElement(nsGkAtoms::form)) {
+ nearestForm = currentAncestor;
+ break;
+ }
+ currentAncestor = currentAncestor->GetParent();
+ }
+
+ if (!nearestForm) {
+ return nullptr;
+ }
+
+ return nearestForm;
+}
+
+// Error reporting
+
+void nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter* aHighlighter) {
+ MOZ_ASSERT(!mBuilder, "Must not view source with builder.");
+ mViewSource = aHighlighter;
+}
+
+void nsHtml5TreeBuilder::errDeepTree() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errDeepTree");
+ } else if (!mBuilder) {
+ nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
+ MOZ_ASSERT(treeOp, "Tree op allocation failed.");
+ opMaybeComplainAboutDeepTree operation(tokenizer->getLineNumber());
+ treeOp->Init(mozilla::AsVariant(operation));
+ }
+}
+
+void nsHtml5TreeBuilder::errStrayStartTag(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStrayStartTag2", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errStrayEndTag(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStrayEndTag", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errUnclosedElements(int32_t aIndex, nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errUnclosedElements", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errUnclosedElementsImplied(int32_t aIndex,
+ nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errUnclosedElementsImplied", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errUnclosedElementsCell(int32_t aIndex) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errUnclosedElementsCell");
+ }
+}
+
+void nsHtml5TreeBuilder::errStrayDoctype() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStrayDoctype");
+ }
+}
+
+void nsHtml5TreeBuilder::errAlmostStandardsDoctype() {
+ if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
+ mViewSource->AddErrorToCurrentRun("errAlmostStandardsDoctype");
+ }
+}
+
+void nsHtml5TreeBuilder::errQuirkyDoctype() {
+ if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
+ mViewSource->AddErrorToCurrentRun("errQuirkyDoctype");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceInTrailer() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceInTrailer");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceAfterFrameset() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceAfterFrameset");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceInFrameset() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceInFrameset");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceAfterBody() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceAfterBody");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead");
+ }
+}
+
+void nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errStartTagWithoutDoctype() {
+ if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
+ mViewSource->AddErrorToCurrentRun("errStartTagWithoutDoctype");
+ }
+}
+
+void nsHtml5TreeBuilder::errNoSelectInTableScope() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNoSelectInTableScope");
+ }
+}
+
+void nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStartSelectWhereEndSelectExpected");
+ }
+}
+
+void nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errBadStartTagInNoscriptInHead(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errBadStartTagInNoscriptInHead", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errImage() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errImage");
+ }
+}
+
+void nsHtml5TreeBuilder::errIsindex() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errIsindex");
+ }
+}
+
+void nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errFooSeenWhenFooOpen2", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errHeadingWhenHeadingOpen() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errHeadingWhenHeadingOpen");
+ }
+}
+
+void nsHtml5TreeBuilder::errFramesetStart() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errFramesetStart");
+ }
+}
+
+void nsHtml5TreeBuilder::errNoCellToClose() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNoCellToClose");
+ }
+}
+
+void nsHtml5TreeBuilder::errStartTagInTable(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStartTagInTable", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errFormWhenFormOpen() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errFormWhenFormOpen");
+ }
+}
+
+void nsHtml5TreeBuilder::errTableSeenWhileTableOpen() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errTableSeenWhileTableOpen");
+ }
+}
+
+void nsHtml5TreeBuilder::errStartTagInTableBody(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStartTagInTableBody", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype() {
+ if (MOZ_UNLIKELY(mViewSource) && !forceNoQuirks) {
+ mViewSource->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype");
+ }
+}
+
+void nsHtml5TreeBuilder::errEndTagAfterBody() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEndTagAfterBody");
+ }
+}
+
+void nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errGarbageInColgroup() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errGarbageInColgroup");
+ }
+}
+
+void nsHtml5TreeBuilder::errEndTagBr() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEndTagBr");
+ }
+}
+
+void nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNoElementToCloseButEndTagSeen",
+ aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errHtmlStartTagInForeignContext", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errNoTableRowToClose() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNoTableRowToClose");
+ }
+}
+
+void nsHtml5TreeBuilder::errNonSpaceInTable() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNonSpaceInTable");
+ }
+}
+
+void nsHtml5TreeBuilder::errUnclosedChildrenInRuby() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errUnclosedChildrenInRuby");
+ }
+}
+
+void nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errStartTagSeenWithoutRuby", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errSelfClosing() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentSlash("errSelfClosing");
+ }
+}
+
+void nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack() {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errNoCheckUnclosedElementsOnStack");
+ }
+}
+
+void nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement(
+ nsAtom* aName, nsAtom* aOther) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEndTagDidNotMatchCurrentOpenElement",
+ aName, aOther);
+ }
+}
+
+void nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errEndWithUnclosedElements(nsAtom* aName) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errEndWithUnclosedElements", aName);
+ }
+}
+
+void nsHtml5TreeBuilder::errListUnclosedStartTags(int32_t aIgnored) {
+ if (MOZ_UNLIKELY(mViewSource)) {
+ mViewSource->AddErrorToCurrentRun("errListUnclosedStartTags");
+ }
+}
diff --git a/parser/html/nsHtml5TreeBuilderHSupplement.h b/parser/html/nsHtml5TreeBuilderHSupplement.h
new file mode 100644
index 0000000000..2439818d74
--- /dev/null
+++ b/parser/html/nsHtml5TreeBuilderHSupplement.h
@@ -0,0 +1,274 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512
+private:
+using Encoding = mozilla::Encoding;
+template <typename T>
+using NotNull = mozilla::NotNull<T>;
+
+nsHtml5OplessBuilder* mBuilder;
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// If mBuilder is not null, the tree op machinery is not in use and
+// the fields below aren't in use, either.
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+nsHtml5Highlighter* mViewSource;
+mozilla::ImportScanner mImportScanner;
+nsTArray<nsHtml5TreeOperation> mOpQueue;
+nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue;
+nsAHtml5TreeOpSink* mOpSink;
+mozilla::UniquePtr<nsIContent*[]> mHandles;
+int32_t mHandlesUsed;
+nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles;
+nsHtml5TreeOpStage* mSpeculativeLoadStage;
+nsresult mBroken;
+bool mCurrentHtmlScriptIsAsyncOrDefer;
+bool mPreventScriptExecution;
+/**
+ * Whether to actually generate speculative load operations that actually
+ * represent speculative loads as opposed to other operations traveling
+ * in the same queue. True for normal loads and false for XHR, plain text,
+ * and View Source. Needed, because we can't just null-check
+ * mSpeculativeLoadStage, since it is used for transferring encoding
+ * information even in the XHR/plain text/View Source cases.
+ */
+bool mGenerateSpeculativeLoads;
+
+bool mHasSeenImportMap;
+#ifdef DEBUG
+bool mActive;
+#endif
+
+// DocumentModeHandler
+/**
+ * Tree builder uses this to report quirkiness of the document
+ */
+void documentMode(nsHtml5DocumentMode m);
+
+nsIContentHandle* getDocumentFragmentForTemplate(nsIContentHandle* aTemplate);
+
+nsIContentHandle* getFormPointerForContext(nsIContentHandle* aContext);
+
+/**
+ * Using nsIContent** instead of nsIContent* is the parser deals with DOM
+ * nodes in a way that works off the main thread. Non-main-thread code
+ * can't refcount or otherwise touch nsIContent objects in any way.
+ * Yet, the off-the-main-thread code needs to have a way to hold onto a
+ * particular node and repeatedly operate on the same node.
+ *
+ * The way this works is that the off-the-main-thread code has an
+ * nsIContent** for each DOM node and a given nsIContent** is only ever
+ * actually dereferenced into an actual nsIContent* on the main thread.
+ * When the off-the-main-thread code requests a new node, it gets an
+ * nsIContent** immediately and a tree op is enqueued for later allocating
+ * an actual nsIContent object and writing a pointer to it into the memory
+ * location pointed to by the nsIContent**.
+ *
+ * Since tree ops are in a queue, the node creating tree op will always
+ * run before tree ops that try to further operate on the node that the
+ * nsIContent** is a handle to.
+ *
+ * On-the-main-thread parts of the parser use nsIContent* instead of
+ * nsIContent**. Since both cases share the same parser core, the parser
+ * core casts both to nsIContentHandle*.
+ */
+nsIContentHandle* AllocateContentHandle();
+
+void accumulateCharactersForced(const char16_t* aBuf, int32_t aStart,
+ int32_t aLength) {
+ accumulateCharacters(aBuf, aStart, aLength);
+}
+
+void MarkAsBrokenAndRequestSuspensionWithBuilder(nsresult aRv) {
+ mBuilder->MarkAsBroken(aRv);
+ requestSuspension();
+}
+
+void MarkAsBrokenAndRequestSuspensionWithoutBuilder(nsresult aRv) {
+ MarkAsBroken(aRv);
+ requestSuspension();
+}
+
+void MarkAsBrokenFromPortability(nsresult aRv);
+
+public:
+explicit nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder);
+
+nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink, nsHtml5TreeOpStage* aStage,
+ bool aGenerateSpeculativeLoads);
+
+~nsHtml5TreeBuilder();
+
+void StartPlainTextViewSource(const nsAutoString& aTitle);
+
+void StartPlainText();
+
+void StartPlainTextBody();
+
+bool HasScript();
+
+void SetOpSink(nsAHtml5TreeOpSink* aOpSink) { mOpSink = aOpSink; }
+
+void ClearOps() { mOpQueue.Clear(); }
+
+/**
+ * Flushes tree ops.
+ * @return Ok(true) if there were ops to flush, Ok(false)
+ * if there were no ops to flush and Err() on OOM.
+ */
+mozilla::Result<bool, nsresult> Flush(bool aDiscretionary = false);
+
+void FlushLoads();
+
+/**
+ * Sets the document charset via the speculation queue.
+ *
+ * @param aCommitEncodingSpeculation true iff the main thread should
+ * treat the first speculation as an
+ * encoding speculation.
+ */
+void SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ nsCharsetSource aCharsetSource,
+ bool aCommitEncodingSpeculation);
+
+/**
+ * Updates the charset source via the op queue.
+ */
+void UpdateCharsetSource(nsCharsetSource aCharsetSource);
+
+void StreamEnded();
+
+void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding, int32_t aSource,
+ int32_t aLineNumber);
+
+void MaybeComplainAboutCharset(const char* aMsgId, bool aError,
+ int32_t aLineNumber);
+
+void TryToEnableEncodingMenu();
+
+void AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine);
+
+void DropHandles();
+
+void SetPreventScriptExecution(bool aPrevent) {
+ mPreventScriptExecution = aPrevent;
+}
+
+bool HasBuilder() { return mBuilder; }
+
+/**
+ * Makes sure the buffers are large enough to be able to tokenize aLength
+ * UTF-16 code units before having to make the buffers larger.
+ *
+ * @param aLength the number of UTF-16 code units to be tokenized before the
+ * next call to this method.
+ * @return true if successful; false if out of memory
+ */
+bool EnsureBufferSpace(int32_t aLength);
+
+void EnableViewSource(nsHtml5Highlighter* aHighlighter);
+
+void errDeepTree();
+
+void errStrayStartTag(nsAtom* aName);
+
+void errStrayEndTag(nsAtom* aName);
+
+void errUnclosedElements(int32_t aIndex, nsAtom* aName);
+
+void errUnclosedElementsImplied(int32_t aIndex, nsAtom* aName);
+
+void errUnclosedElementsCell(int32_t aIndex);
+
+void errStrayDoctype();
+
+void errAlmostStandardsDoctype();
+
+void errQuirkyDoctype();
+
+void errNonSpaceInTrailer();
+
+void errNonSpaceAfterFrameset();
+
+void errNonSpaceInFrameset();
+
+void errNonSpaceAfterBody();
+
+void errNonSpaceInColgroupInFragment();
+
+void errNonSpaceInNoscriptInHead();
+
+void errFooBetweenHeadAndBody(nsAtom* aName);
+
+void errStartTagWithoutDoctype();
+
+void errNoSelectInTableScope();
+
+void errStartSelectWhereEndSelectExpected();
+
+void errStartTagWithSelectOpen(nsAtom* aName);
+
+void errBadStartTagInNoscriptInHead(nsAtom* aName);
+
+void errImage();
+
+void errIsindex();
+
+void errFooSeenWhenFooOpen(nsAtom* aName);
+
+void errHeadingWhenHeadingOpen();
+
+void errFramesetStart();
+
+void errNoCellToClose();
+
+void errStartTagInTable(nsAtom* aName);
+
+void errFormWhenFormOpen();
+
+void errTableSeenWhileTableOpen();
+
+void errStartTagInTableBody(nsAtom* aName);
+
+void errEndTagSeenWithoutDoctype();
+
+void errEndTagAfterBody();
+
+void errEndTagSeenWithSelectOpen(nsAtom* aName);
+
+void errGarbageInColgroup();
+
+void errEndTagBr();
+
+void errNoElementToCloseButEndTagSeen(nsAtom* aName);
+
+void errHtmlStartTagInForeignContext(nsAtom* aName);
+
+void errNoTableRowToClose();
+
+void errNonSpaceInTable();
+
+void errUnclosedChildrenInRuby();
+
+void errStartTagSeenWithoutRuby(nsAtom* aName);
+
+void errSelfClosing();
+
+void errNoCheckUnclosedElementsOnStack();
+
+void errEndTagDidNotMatchCurrentOpenElement(nsAtom* aName, nsAtom* aOther);
+
+void errEndTagViolatesNestingRules(nsAtom* aName);
+
+void errEndWithUnclosedElements(nsAtom* aName);
+
+void errListUnclosedStartTags(int32_t aIgnored);
+
+void MarkAsBroken(nsresult aRv);
+
+/**
+ * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
+ * value if broken.
+ */
+nsresult IsBroken() { return mBroken; }
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
new file mode 100644
index 0000000000..b74246fdca
--- /dev/null
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -0,0 +1,1405 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Likely.h"
+#include "mozilla/dom/BrowsingContext.h"
+#include "mozilla/dom/MediaList.h"
+#include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/dom/nsCSPContext.h"
+#include "mozilla/dom/nsCSPService.h"
+
+#include "mozAutoDocUpdate.h"
+#include "mozilla/IdleTaskRunner.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/ProfilerLabels.h"
+#include "mozilla/ProfilerMarkers.h"
+#include "mozilla/StaticPrefs_content.h"
+#include "mozilla/StaticPrefs_security.h"
+#include "mozilla/StaticPrefs_view_source.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/css/Loader.h"
+#include "mozilla/fallible.h"
+#include "nsContentUtils.h"
+#include "nsDocShell.h"
+#include "nsError.h"
+#include "nsHTMLDocument.h"
+#include "nsHtml5AutoPauseUpdate.h"
+#include "nsHtml5Parser.h"
+#include "nsHtml5StreamParser.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5TreeOpExecutor.h"
+#include "nsIContentSecurityPolicy.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsINestedURI.h"
+#include "nsIHttpChannel.h"
+#include "nsIScriptContext.h"
+#include "nsIScriptError.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIViewSourceChannel.h"
+#include "nsNetUtil.h"
+#include "xpcpublic.h"
+
+using namespace mozilla;
+
+static LazyLogModule gCharsetMenuLog("Chardetng");
+
+#define LOGCHARDETNG(args) MOZ_LOG(gCharsetMenuLog, LogLevel::Debug, args)
+
+NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsHtml5TreeOpExecutor,
+ nsHtml5DocumentBuilder,
+ nsIContentSink)
+
+class nsHtml5ExecutorReflusher : public Runnable {
+ private:
+ RefPtr<nsHtml5TreeOpExecutor> mExecutor;
+
+ public:
+ explicit nsHtml5ExecutorReflusher(nsHtml5TreeOpExecutor* aExecutor)
+ : Runnable("nsHtml5ExecutorReflusher"), mExecutor(aExecutor) {}
+ NS_IMETHOD Run() override {
+ dom::Document* doc = mExecutor->GetDocument();
+ if (XRE_IsContentProcess() &&
+ nsContentUtils::
+ HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
+ doc)) {
+ // Possible early paint pending, reuse the runnable and try to
+ // call RunFlushLoop later.
+ nsCOMPtr<nsIRunnable> flusher = this;
+ if (NS_SUCCEEDED(
+ doc->Dispatch(TaskCategory::Network, flusher.forget()))) {
+ PROFILER_MARKER_UNTYPED("HighPrio blocking parser flushing(2)", DOM);
+ return NS_OK;
+ }
+ }
+ mExecutor->RunFlushLoop();
+ return NS_OK;
+ }
+};
+
+class MOZ_RAII nsHtml5AutoFlush final {
+ private:
+ RefPtr<nsHtml5TreeOpExecutor> mExecutor;
+ size_t mOpsToRemove;
+
+ public:
+ explicit nsHtml5AutoFlush(nsHtml5TreeOpExecutor* aExecutor)
+ : mExecutor(aExecutor), mOpsToRemove(aExecutor->OpQueueLength()) {
+ mExecutor->BeginFlush();
+ mExecutor->BeginDocUpdate();
+ }
+ ~nsHtml5AutoFlush() {
+ if (mExecutor->IsInDocUpdate()) {
+ mExecutor->EndDocUpdate();
+ } else {
+ // We aren't in an update if nsHtml5AutoPauseUpdate
+ // caused something to terminate the parser.
+ MOZ_RELEASE_ASSERT(
+ mExecutor->IsComplete(),
+ "How do we have mParser but the doc update isn't open?");
+ }
+ mExecutor->EndFlush();
+ mExecutor->RemoveFromStartOfOpQueue(mOpsToRemove);
+ }
+ void SetNumberOfOpsToRemove(size_t aOpsToRemove) {
+ MOZ_ASSERT(aOpsToRemove < mOpsToRemove,
+ "Requested partial clearing of op queue but the number to clear "
+ "wasn't less than the length of the queue.");
+ mOpsToRemove = aOpsToRemove;
+ }
+};
+
+static LinkedList<nsHtml5TreeOpExecutor>* gBackgroundFlushList = nullptr;
+StaticRefPtr<IdleTaskRunner> gBackgroundFlushRunner;
+
+nsHtml5TreeOpExecutor::nsHtml5TreeOpExecutor()
+ : nsHtml5DocumentBuilder(false),
+ mSuppressEOF(false),
+ mReadingFromStage(false),
+ mStreamParser(nullptr),
+ mPreloadedURLs(23), // Mean # of preloadable resources per page on dmoz
+ mStarted(false),
+ mRunFlushLoopOnStack(false),
+ mCallContinueInterruptedParsingIfEnabled(false),
+ mAlreadyComplainedAboutCharset(false),
+ mAlreadyComplainedAboutDeepTree(false) {}
+
+nsHtml5TreeOpExecutor::~nsHtml5TreeOpExecutor() {
+ if (gBackgroundFlushList && isInList()) {
+ ClearOpQueue();
+ removeFrom(*gBackgroundFlushList);
+ if (gBackgroundFlushList->isEmpty()) {
+ delete gBackgroundFlushList;
+ gBackgroundFlushList = nullptr;
+ if (gBackgroundFlushRunner) {
+ gBackgroundFlushRunner->Cancel();
+ gBackgroundFlushRunner = nullptr;
+ }
+ }
+ }
+ MOZ_ASSERT(NS_FAILED(mBroken) || mOpQueue.IsEmpty(),
+ "Somehow there's stuff in the op queue.");
+}
+
+// nsIContentSink
+NS_IMETHODIMP
+nsHtml5TreeOpExecutor::WillParse() {
+ MOZ_ASSERT_UNREACHABLE("No one should call this");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult nsHtml5TreeOpExecutor::WillBuildModel() {
+ mDocument->AddObserver(this);
+ WillBuildModelImpl();
+ GetDocument()->BeginLoad();
+ if (mDocShell && !GetDocument()->GetWindow() && !IsExternalViewSource()) {
+ // Not loading as data but script global object not ready
+ return MarkAsBroken(NS_ERROR_DOM_INVALID_STATE_ERR);
+ }
+ return NS_OK;
+}
+
+// This is called when the tree construction has ended
+NS_IMETHODIMP
+nsHtml5TreeOpExecutor::DidBuildModel(bool aTerminated) {
+ if (mRunsToCompletion) {
+ return NS_OK;
+ }
+
+ MOZ_RELEASE_ASSERT(!IsInDocUpdate(),
+ "DidBuildModel from inside a doc update.");
+
+ RefPtr<nsHtml5TreeOpExecutor> pin(this);
+ auto queueClearer = MakeScopeExit([&] {
+ if (aTerminated && (mFlushState == eNotFlushing)) {
+ ClearOpQueue(); // clear in order to be able to assert in destructor
+ }
+ });
+
+ // This comes from nsXMLContentSink and nsHTMLContentSink
+ // If this parser has been marked as broken, treat the end of parse as
+ // forced termination.
+ DidBuildModelImpl(aTerminated || NS_FAILED(IsBroken()));
+
+ bool destroying = true;
+ if (mDocShell) {
+ mDocShell->IsBeingDestroyed(&destroying);
+ }
+
+ if (!destroying) {
+ mDocument->OnParsingCompleted();
+
+ if (!mLayoutStarted) {
+ // We never saw the body, and layout never got started. Force
+ // layout *now*, to get an initial reflow.
+
+ // NOTE: only force the layout if we are NOT destroying the
+ // docshell. If we are destroying it, then starting layout will
+ // likely cause us to crash, or at best waste a lot of time as we
+ // are just going to tear it down anyway.
+ nsContentSink::StartLayout(false);
+ }
+ }
+
+ ScrollToRef();
+ mDocument->RemoveObserver(this);
+ if (!mParser) {
+ // DidBuildModelImpl may cause mParser to be nulled out
+ // Return early to avoid unblocking the onload event too many times.
+ return NS_OK;
+ }
+
+ // We may not have called BeginLoad() if loading is terminated before
+ // OnStartRequest call.
+ if (mStarted) {
+ mDocument->EndLoad();
+
+ // Gather telemetry only for top-level content navigations in order to
+ // avoid noise from ad iframes.
+ bool topLevel = false;
+ if (mozilla::dom::BrowsingContext* bc = mDocument->GetBrowsingContext()) {
+ topLevel = bc->IsTopContent();
+ }
+
+ // Gather telemetry only for text/html and text/plain (excluding CSS, JS,
+ // etc. being viewed as text.)
+ nsAutoString contentType;
+ mDocument->GetContentType(contentType);
+ bool htmlOrPlain = contentType.EqualsLiteral(u"text/html") ||
+ contentType.EqualsLiteral(u"text/plain");
+
+ // Gather telemetry only for HTTP status code 200 in order to exclude
+ // error pages.
+ bool httpOk = false;
+ nsCOMPtr<nsIChannel> channel;
+ nsresult rv = GetParser()->GetChannel(getter_AddRefs(channel));
+ if (NS_SUCCEEDED(rv) && channel) {
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
+ if (httpChannel) {
+ uint32_t httpStatus;
+ rv = httpChannel->GetResponseStatus(&httpStatus);
+ if (NS_SUCCEEDED(rv) && httpStatus == 200) {
+ httpOk = true;
+ }
+ }
+ }
+
+ // Gather chardetng telemetry
+ MOZ_ASSERT(mDocument->IsHTMLDocument());
+ if (httpOk && htmlOrPlain && topLevel && !aTerminated &&
+ !mDocument->AsHTMLDocument()->IsViewSource()) {
+ // We deliberately measure only normally-completed (non-aborted) loads
+ // that are not View Source loads. This seems like a better place for
+ // checking normal completion than anything in nsHtml5StreamParser.
+ bool plain = mDocument->AsHTMLDocument()->IsPlainText();
+ int32_t charsetSource = mDocument->GetDocumentCharacterSetSource();
+ switch (charsetSource) {
+ case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::UtfInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::UtfInitial);
+ } else {
+ LOGCHARDETNG(("HTML::UtfInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::UtfInitial);
+ }
+ break;
+ case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::GenericInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::
+ GenericInitial);
+ } else {
+ LOGCHARDETNG(("HTML::GenericInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::
+ GenericInitial);
+ }
+ break;
+ case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::ContentInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::
+ ContentInitial);
+ } else {
+ LOGCHARDETNG(("HTML::ContentInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::
+ ContentInitial);
+ }
+ break;
+ case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::TldInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::TldInitial);
+ } else {
+ LOGCHARDETNG(("HTML::TldInitial"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::TldInitial);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::UtfFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::UtfFinal);
+ } else {
+ LOGCHARDETNG(("HTML::UtfFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::UtfFinal);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::GenericFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::
+ GenericFinal);
+ } else {
+ LOGCHARDETNG(("HTML::GenericFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::
+ GenericFinal);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::GenericFinalA"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::
+ GenericFinalA);
+ } else {
+ LOGCHARDETNG(("HTML::GenericFinalA"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::
+ GenericFinalA);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::ContentFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::
+ ContentFinal);
+ } else {
+ LOGCHARDETNG(("HTML::ContentFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::
+ ContentFinal);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::ContentFinalA"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::
+ ContentFinalA);
+ } else {
+ LOGCHARDETNG(("HTML::ContentFinalA"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::
+ ContentFinalA);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::TldFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::TldFinal);
+ } else {
+ LOGCHARDETNG(("HTML::TldFinal"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::TldFinal);
+ }
+ break;
+ case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
+ if (plain) {
+ LOGCHARDETNG(("TEXT::TldFinalA"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_TEXT::TldFinalA);
+ } else {
+ LOGCHARDETNG(("HTML::TldFinalA"));
+ Telemetry::AccumulateCategorical(
+ Telemetry::LABELS_ENCODING_DETECTION_OUTCOME_HTML::TldFinalA);
+ }
+ break;
+ default:
+ // Chardetng didn't run automatically or the input was all ASCII.
+ break;
+ }
+ }
+ }
+
+ // Dropping the stream parser changes the parser's apparent
+ // script-createdness, which is why the stream parser must not be dropped
+ // before this executor's nsHtml5Parser has been made unreachable from its
+ // nsHTMLDocument. (mDocument->EndLoad() above drops the parser from the
+ // document.)
+ GetParser()->DropStreamParser();
+ DropParserAndPerfHint();
+#ifdef GATHER_DOCWRITE_STATISTICS
+ printf("UNSAFE SCRIPTS: %d\n", sUnsafeDocWrites);
+ printf("TOKENIZER-SAFE SCRIPTS: %d\n", sTokenSafeDocWrites);
+ printf("TREEBUILDER-SAFE SCRIPTS: %d\n", sTreeSafeDocWrites);
+#endif
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+ printf("MAX NOTIFICATION BATCH LEN: %d\n", sAppendBatchMaxSize);
+ if (sAppendBatchExaminations != 0) {
+ printf("AVERAGE SLOTS EXAMINED: %d\n",
+ sAppendBatchSlotsExamined / sAppendBatchExaminations);
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHtml5TreeOpExecutor::WillInterrupt() {
+ MOZ_ASSERT_UNREACHABLE("Don't call. For interface compat only.");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void nsHtml5TreeOpExecutor::WillResume() {
+ MOZ_ASSERT_UNREACHABLE("Don't call. For interface compat only.");
+}
+
+NS_IMETHODIMP
+nsHtml5TreeOpExecutor::SetParser(nsParserBase* aParser) {
+ mParser = aParser;
+ return NS_OK;
+}
+
+void nsHtml5TreeOpExecutor::InitialTranslationCompleted() {
+ nsContentSink::StartLayout(false);
+}
+
+void nsHtml5TreeOpExecutor::FlushPendingNotifications(FlushType aType) {
+ if (aType >= FlushType::EnsurePresShellInitAndFrames) {
+ // Bug 577508 / 253951
+ nsContentSink::StartLayout(true);
+ }
+}
+
+nsISupports* nsHtml5TreeOpExecutor::GetTarget() {
+ return ToSupports(mDocument);
+}
+
+nsresult nsHtml5TreeOpExecutor::MarkAsBroken(nsresult aReason) {
+ MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+ mBroken = aReason;
+ if (mStreamParser) {
+ mStreamParser->Terminate();
+ }
+ // We are under memory pressure, but let's hope the following allocation
+ // works out so that we get to terminate and clean up the parser from
+ // a safer point.
+ if (mParser && mDocument) { // can mParser ever be null here?
+ nsCOMPtr<nsIRunnable> terminator = NewRunnableMethod(
+ "nsHtml5Parser::Terminate", GetParser(), &nsHtml5Parser::Terminate);
+ if (NS_FAILED(
+ mDocument->Dispatch(TaskCategory::Network, terminator.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+ }
+ return aReason;
+}
+
+static bool BackgroundFlushCallback(TimeStamp /*aDeadline*/) {
+ RefPtr<nsHtml5TreeOpExecutor> ex = gBackgroundFlushList->popFirst();
+ if (ex) {
+ ex->RunFlushLoop();
+ }
+ if (gBackgroundFlushList && gBackgroundFlushList->isEmpty()) {
+ delete gBackgroundFlushList;
+ gBackgroundFlushList = nullptr;
+ gBackgroundFlushRunner->Cancel();
+ gBackgroundFlushRunner = nullptr;
+ return true;
+ }
+ return true;
+}
+
+void nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync() {
+ if (mDocument && !mDocument->IsInBackgroundWindow()) {
+ nsCOMPtr<nsIRunnable> flusher = new nsHtml5ExecutorReflusher(this);
+ if (NS_FAILED(
+ mDocument->Dispatch(TaskCategory::Network, flusher.forget()))) {
+ NS_WARNING("failed to dispatch executor flush event");
+ }
+ } else {
+ if (!gBackgroundFlushList) {
+ gBackgroundFlushList = new LinkedList<nsHtml5TreeOpExecutor>();
+ }
+ if (!isInList()) {
+ gBackgroundFlushList->insertBack(this);
+ }
+ if (gBackgroundFlushRunner) {
+ return;
+ }
+ // Now we set up a repetitive idle scheduler for flushing background list.
+ gBackgroundFlushRunner = IdleTaskRunner::Create(
+ &BackgroundFlushCallback,
+ "nsHtml5TreeOpExecutor::BackgroundFlushCallback",
+ 0, // Start looking for idle time immediately.
+ TimeDuration::FromMilliseconds(250), // The hard deadline.
+ TimeDuration::FromMicroseconds(
+ StaticPrefs::content_sink_interactive_parse_time()), // Required
+ // budget.
+ true, // repeating
+ [] { return false; }); // MayStopProcessing
+ }
+}
+
+void nsHtml5TreeOpExecutor::FlushSpeculativeLoads() {
+ nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue;
+ mStage.MoveSpeculativeLoadsTo(speculativeLoadQueue);
+ nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
+ nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
+ for (nsHtml5SpeculativeLoad* iter = start; iter < end; ++iter) {
+ if (MOZ_UNLIKELY(!mParser)) {
+ // An extension terminated the parser from a HTTP observer.
+ return;
+ }
+ iter->Perform(this);
+ }
+}
+
+class nsHtml5FlushLoopGuard {
+ private:
+ RefPtr<nsHtml5TreeOpExecutor> mExecutor;
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+ uint32_t mStartTime;
+#endif
+ public:
+ explicit nsHtml5FlushLoopGuard(nsHtml5TreeOpExecutor* aExecutor)
+ : mExecutor(aExecutor)
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+ ,
+ mStartTime(PR_IntervalToMilliseconds(PR_IntervalNow()))
+#endif
+ {
+ mExecutor->mRunFlushLoopOnStack = true;
+ }
+ ~nsHtml5FlushLoopGuard() {
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+ uint32_t timeOffTheEventLoop =
+ PR_IntervalToMilliseconds(PR_IntervalNow()) - mStartTime;
+ if (timeOffTheEventLoop >
+ nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop) {
+ nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop = timeOffTheEventLoop;
+ }
+ printf("Longest time off the event loop: %d\n",
+ nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop);
+#endif
+
+ mExecutor->mRunFlushLoopOnStack = false;
+ }
+};
+
+/**
+ * The purpose of the loop here is to avoid returning to the main event loop
+ */
+void nsHtml5TreeOpExecutor::RunFlushLoop() {
+ AUTO_PROFILER_LABEL("nsHtml5TreeOpExecutor::RunFlushLoop", OTHER);
+
+ if (mRunFlushLoopOnStack) {
+ // There's already a RunFlushLoop() on the call stack.
+ return;
+ }
+
+ nsHtml5FlushLoopGuard guard(this); // this is also the self-kungfu!
+
+ RefPtr<nsParserBase> parserKungFuDeathGrip(mParser);
+ RefPtr<nsHtml5StreamParser> streamParserGrip;
+ if (mParser) {
+ streamParserGrip = GetParser()->GetStreamParser();
+ }
+ Unused << streamParserGrip; // Intentionally not used within function
+
+ // Remember the entry time
+ (void)nsContentSink::WillParseImpl();
+
+ for (;;) {
+ if (!mParser) {
+ // Parse has terminated.
+ ClearOpQueue(); // clear in order to be able to assert in destructor
+ return;
+ }
+
+ if (NS_FAILED(IsBroken())) {
+ return;
+ }
+
+ if (!parserKungFuDeathGrip->IsParserEnabled()) {
+ // The parser is blocked.
+ return;
+ }
+
+ if (mFlushState != eNotFlushing) {
+ // XXX Can this happen? In case it can, let's avoid crashing.
+ return;
+ }
+
+ // If there are scripts executing, then the content sink is jumping the gun
+ // (probably due to a synchronous XMLHttpRequest) and will re-enable us
+ // later, see bug 460706.
+ if (IsScriptExecuting()) {
+ return;
+ }
+
+ if (mReadingFromStage) {
+ nsTArray<nsHtml5SpeculativeLoad> speculativeLoadQueue;
+ MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
+ "mOpQueue modified during flush.");
+ if (!mStage.MoveOpsAndSpeculativeLoadsTo(mOpQueue,
+ speculativeLoadQueue)) {
+ MarkAsBroken(nsresult::NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+
+ // Make sure speculative loads never start after the corresponding
+ // normal loads for the same URLs.
+ nsHtml5SpeculativeLoad* start = speculativeLoadQueue.Elements();
+ nsHtml5SpeculativeLoad* end = start + speculativeLoadQueue.Length();
+ for (nsHtml5SpeculativeLoad* iter = start; iter < end; ++iter) {
+ iter->Perform(this);
+ if (MOZ_UNLIKELY(!mParser)) {
+ // An extension terminated the parser from a HTTP observer.
+ ClearOpQueue(); // clear in order to be able to assert in destructor
+ return;
+ }
+ }
+ } else {
+ FlushSpeculativeLoads(); // Make sure speculative loads never start after
+ // the corresponding normal loads for the same
+ // URLs.
+ if (MOZ_UNLIKELY(!mParser)) {
+ // An extension terminated the parser from a HTTP observer.
+ ClearOpQueue(); // clear in order to be able to assert in destructor
+ return;
+ }
+ // Now parse content left in the document.write() buffer queue if any.
+ // This may generate tree ops on its own or dequeue a speculation.
+ nsresult rv = GetParser()->ParseUntilBlocked();
+
+ // ParseUntilBlocked flushes operations from the stage to the OpQueue.
+ // Those operations may have accompanying speculative operations.
+ // If so, we have to flush those speculative loads so that we maintain
+ // the invariant that no speculative load starts after the corresponding
+ // normal load for the same URL. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1513292#c80
+ // for a more detailed explanation of why this is necessary.
+ FlushSpeculativeLoads();
+
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ return;
+ }
+ }
+
+ if (mOpQueue.IsEmpty()) {
+ // Avoid bothering the rest of the engine with a doc update if there's
+ // nothing to do.
+ return;
+ }
+
+ nsIContent* scriptElement = nullptr;
+ bool interrupted = false;
+ bool streamEnded = false;
+
+ {
+ // autoFlush clears mOpQueue in its destructor unless
+ // SetNumberOfOpsToRemove is called first, in which case only
+ // some ops from the start of the queue are cleared.
+ nsHtml5AutoFlush autoFlush(this);
+
+ nsHtml5TreeOperation* first = mOpQueue.Elements();
+ nsHtml5TreeOperation* last = first + mOpQueue.Length() - 1;
+ for (nsHtml5TreeOperation* iter = first;; ++iter) {
+ if (MOZ_UNLIKELY(!mParser)) {
+ // The previous tree op caused a call to nsIParser::Terminate().
+ return;
+ }
+ MOZ_ASSERT(IsInDocUpdate(),
+ "Tried to perform tree op outside update batch.");
+ nsresult rv =
+ iter->Perform(this, &scriptElement, &interrupted, &streamEnded);
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ break;
+ }
+
+ // Be sure not to check the deadline if the last op was just performed.
+ if (MOZ_UNLIKELY(iter == last)) {
+ break;
+ } else if (MOZ_UNLIKELY(interrupted) ||
+ MOZ_UNLIKELY(nsContentSink::DidProcessATokenImpl() ==
+ NS_ERROR_HTMLPARSER_INTERRUPTED)) {
+ autoFlush.SetNumberOfOpsToRemove((iter - first) + 1);
+
+ nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync();
+ return;
+ }
+ }
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // The parse ended during an update pause.
+ return;
+ }
+ if (streamEnded) {
+ GetParser()->PermanentlyUndefineInsertionPoint();
+ }
+ } // end autoFlush
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // Ending the doc update caused a call to nsIParser::Terminate().
+ return;
+ }
+
+ if (streamEnded) {
+ DidBuildModel(false);
+#ifdef DEBUG
+ if (scriptElement) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(scriptElement);
+ if (!sele) {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ }
+ MOZ_ASSERT(sele->IsMalformed(), "Script wasn't marked as malformed.");
+ }
+#endif
+ } else if (scriptElement) {
+ // must be tail call when mFlushState is eNotFlushing
+ RunScript(scriptElement);
+
+ // Always check the clock in nsContentSink right after a script
+ StopDeflecting();
+ if (nsContentSink::DidProcessATokenImpl() ==
+ NS_ERROR_HTMLPARSER_INTERRUPTED) {
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+ printf("REFLUSH SCHEDULED (after script): %d\n",
+ ++sTimesFlushLoopInterrupted);
+#endif
+ nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync();
+ return;
+ }
+ }
+ }
+}
+
+nsresult nsHtml5TreeOpExecutor::FlushDocumentWrite() {
+ nsresult rv = IsBroken();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ FlushSpeculativeLoads(); // Make sure speculative loads never start after the
+ // corresponding normal loads for the same URLs.
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // The parse has ended.
+ ClearOpQueue(); // clear in order to be able to assert in destructor
+ return rv;
+ }
+
+ if (mFlushState != eNotFlushing) {
+ // XXX Can this happen? In case it can, let's avoid crashing.
+ return rv;
+ }
+
+ // avoid crashing near EOF
+ RefPtr<nsHtml5TreeOpExecutor> kungFuDeathGrip(this);
+ RefPtr<nsParserBase> parserKungFuDeathGrip(mParser);
+ Unused << parserKungFuDeathGrip; // Intentionally not used within function
+ RefPtr<nsHtml5StreamParser> streamParserGrip;
+ if (mParser) {
+ streamParserGrip = GetParser()->GetStreamParser();
+ }
+ Unused << streamParserGrip; // Intentionally not used within function
+
+ MOZ_RELEASE_ASSERT(!mReadingFromStage,
+ "Got doc write flush when reading from stage");
+
+#ifdef DEBUG
+ mStage.AssertEmpty();
+#endif
+
+ nsIContent* scriptElement = nullptr;
+ bool interrupted = false;
+ bool streamEnded = false;
+
+ {
+ // autoFlush clears mOpQueue in its destructor.
+ nsHtml5AutoFlush autoFlush(this);
+
+ nsHtml5TreeOperation* start = mOpQueue.Elements();
+ nsHtml5TreeOperation* end = start + mOpQueue.Length();
+ for (nsHtml5TreeOperation* iter = start; iter < end; ++iter) {
+ if (MOZ_UNLIKELY(!mParser)) {
+ // The previous tree op caused a call to nsIParser::Terminate().
+ return rv;
+ }
+ NS_ASSERTION(IsInDocUpdate(),
+ "Tried to perform tree op outside update batch.");
+ rv = iter->Perform(this, &scriptElement, &interrupted, &streamEnded);
+ if (NS_FAILED(rv)) {
+ MarkAsBroken(rv);
+ break;
+ }
+ }
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // The parse ended during an update pause.
+ return rv;
+ }
+ if (streamEnded) {
+ // This should be redundant but let's do it just in case.
+ GetParser()->PermanentlyUndefineInsertionPoint();
+ }
+ } // autoFlush
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // Ending the doc update caused a call to nsIParser::Terminate().
+ return rv;
+ }
+
+ if (streamEnded) {
+ DidBuildModel(false);
+#ifdef DEBUG
+ if (scriptElement) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(scriptElement);
+ if (!sele) {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ }
+ MOZ_ASSERT(sele->IsMalformed(), "Script wasn't marked as malformed.");
+ }
+#endif
+ } else if (scriptElement) {
+ // must be tail call when mFlushState is eNotFlushing
+ RunScript(scriptElement);
+ }
+ return rv;
+}
+
+void nsHtml5TreeOpExecutor::CommitToInternalEncoding() {
+ if (MOZ_UNLIKELY(!mParser || !mStreamParser)) {
+ // An extension terminated the parser from a HTTP observer.
+ ClearOpQueue(); // clear in order to be able to assert in destructor
+ return;
+ }
+ mStreamParser->ContinueAfterScriptsOrEncodingCommitment(nullptr, nullptr,
+ false);
+}
+
+[[nodiscard]] bool nsHtml5TreeOpExecutor::TakeOpsFromStage() {
+ return mStage.MoveOpsTo(mOpQueue);
+}
+
+// copied from HTML content sink
+bool nsHtml5TreeOpExecutor::IsScriptEnabled() {
+ // Note that if we have no document or no docshell or no global or whatnot we
+ // want to claim script _is_ enabled, so we don't parse the contents of
+ // <noscript> tags!
+ if (!mDocument || !mDocShell) {
+ return true;
+ }
+
+ return mDocument->IsScriptEnabled();
+}
+
+void nsHtml5TreeOpExecutor::StartLayout(bool* aInterrupted) {
+ if (mLayoutStarted || !mDocument) {
+ return;
+ }
+
+ nsHtml5AutoPauseUpdate autoPause(this);
+
+ if (MOZ_UNLIKELY(!mParser)) {
+ // got terminate
+ return;
+ }
+
+ nsContentSink::StartLayout(false);
+
+ if (mParser) {
+ *aInterrupted = !GetParser()->IsParserEnabled();
+ }
+}
+
+void nsHtml5TreeOpExecutor::PauseDocUpdate(bool* aInterrupted) {
+ // Pausing the document update allows JS to run, and potentially block
+ // further parsing.
+ nsHtml5AutoPauseUpdate autoPause(this);
+
+ if (MOZ_LIKELY(mParser)) {
+ *aInterrupted = !GetParser()->IsParserEnabled();
+ }
+}
+
+/**
+ * The reason why this code is here and not in the tree builder even in the
+ * main-thread case is to allow the control to return from the tokenizer
+ * before scripts run. This way, the tokenizer is not invoked re-entrantly
+ * although the parser is.
+ *
+ * The reason why this is called as a tail call when mFlushState is set to
+ * eNotFlushing is to allow re-entry to Flush() but only after the current
+ * Flush() has cleared the op queue and is otherwise done cleaning up after
+ * itself.
+ */
+void nsHtml5TreeOpExecutor::RunScript(nsIContent* aScriptElement) {
+ if (mRunsToCompletion) {
+ // We are in createContextualFragment() or in the upcoming document.parse().
+ // Do nothing. Let's not even mark scripts malformed here, because that
+ // could cause serialization weirdness later.
+ return;
+ }
+
+ MOZ_ASSERT(mParser, "Trying to run script with a terminated parser.");
+ MOZ_ASSERT(aScriptElement, "No script to run");
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aScriptElement);
+ if (!sele) {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ return;
+ }
+
+ if (sele->GetScriptDeferred() || sele->GetScriptAsync()) {
+ DebugOnly<bool> block = sele->AttemptToExecute();
+ NS_ASSERTION(!block, "Defer or async script tried to block.");
+ return;
+ }
+
+ MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
+ "Tried to run script while flushing.");
+
+ mReadingFromStage = false;
+
+ sele->SetCreatorParser(GetParser());
+
+ // Copied from nsXMLContentSink
+ // Now tell the script that it's ready to go. This may execute the script
+ // or return true, or neither if the script doesn't need executing.
+ bool block = sele->AttemptToExecute();
+
+ // If the act of insertion evaluated the script, we're fine.
+ // Else, block the parser till the script has loaded.
+ if (block) {
+ if (mParser) {
+ GetParser()->BlockParser();
+ }
+ } else {
+ // mParser may have been nulled out by now, but the flusher deals
+
+ // If this event isn't needed, it doesn't do anything. It is sometimes
+ // necessary for the parse to continue after complex situations.
+ nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync();
+ }
+}
+
+void nsHtml5TreeOpExecutor::Start() {
+ MOZ_ASSERT(!mStarted, "Tried to start when already started.");
+ mStarted = true;
+}
+
+void nsHtml5TreeOpExecutor::UpdateCharsetSource(
+ nsCharsetSource aCharsetSource) {
+ if (mDocument) {
+ mDocument->SetDocumentCharacterSetSource(aCharsetSource);
+ }
+}
+
+void nsHtml5TreeOpExecutor::SetDocumentCharsetAndSource(
+ NotNull<const Encoding*> aEncoding, nsCharsetSource aCharsetSource) {
+ if (mDocument) {
+ mDocument->SetDocumentCharacterSetSource(aCharsetSource);
+ mDocument->SetDocumentCharacterSet(aEncoding);
+ }
+}
+
+void nsHtml5TreeOpExecutor::NeedsCharsetSwitchTo(
+ NotNull<const Encoding*> aEncoding, int32_t aSource, uint32_t aLineNumber) {
+ nsHtml5AutoPauseUpdate autoPause(this);
+ if (MOZ_UNLIKELY(!mParser)) {
+ // got terminate
+ return;
+ }
+
+ if (!mDocShell) {
+ return;
+ }
+
+ RefPtr<nsDocShell> docShell = static_cast<nsDocShell*>(mDocShell.get());
+
+ if (NS_SUCCEEDED(docShell->CharsetChangeStopDocumentLoad())) {
+ docShell->CharsetChangeReloadDocument(aEncoding, aSource);
+ }
+ // if the charset switch was accepted, mDocShell has called Terminate() on the
+ // parser by now
+ if (!mParser) {
+ return;
+ }
+
+ GetParser()->ContinueAfterFailedCharsetSwitch();
+}
+
+void nsHtml5TreeOpExecutor::MaybeComplainAboutCharset(const char* aMsgId,
+ bool aError,
+ uint32_t aLineNumber) {
+ // Encoding errors don't count towards already complaining
+ if (!(!strcmp(aMsgId, "EncError") || !strcmp(aMsgId, "EncErrorFrame") ||
+ !strcmp(aMsgId, "EncErrorFramePlain"))) {
+ if (mAlreadyComplainedAboutCharset) {
+ return;
+ }
+ mAlreadyComplainedAboutCharset = true;
+ }
+ nsContentUtils::ReportToConsole(
+ aError ? nsIScriptError::errorFlag : nsIScriptError::warningFlag,
+ "HTML parser"_ns, mDocument, nsContentUtils::eHTMLPARSER_PROPERTIES,
+ aMsgId, nsTArray<nsString>(), nullptr, u""_ns, aLineNumber);
+}
+
+void nsHtml5TreeOpExecutor::ComplainAboutBogusProtocolCharset(
+ Document* aDoc, bool aUnrecognized) {
+ NS_ASSERTION(!mAlreadyComplainedAboutCharset,
+ "How come we already managed to complain?");
+ mAlreadyComplainedAboutCharset = true;
+ nsContentUtils::ReportToConsole(
+ nsIScriptError::errorFlag, "HTML parser"_ns, aDoc,
+ nsContentUtils::eHTMLPARSER_PROPERTIES,
+ aUnrecognized ? "EncProtocolUnsupported" : "EncProtocolReplacement");
+}
+
+void nsHtml5TreeOpExecutor::MaybeComplainAboutDeepTree(uint32_t aLineNumber) {
+ if (mAlreadyComplainedAboutDeepTree) {
+ return;
+ }
+ mAlreadyComplainedAboutDeepTree = true;
+ nsContentUtils::ReportToConsole(
+ nsIScriptError::errorFlag, "HTML parser"_ns, mDocument,
+ nsContentUtils::eHTMLPARSER_PROPERTIES, "errDeepTree",
+ nsTArray<nsString>(), nullptr, u""_ns, aLineNumber);
+}
+
+nsHtml5Parser* nsHtml5TreeOpExecutor::GetParser() {
+ MOZ_ASSERT(!mRunsToCompletion);
+ return static_cast<nsHtml5Parser*>(mParser.get());
+}
+
+[[nodiscard]] bool nsHtml5TreeOpExecutor::MoveOpsFrom(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) {
+ MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
+ "Ops added to mOpQueue during tree op execution.");
+ return !!mOpQueue.AppendElements(std::move(aOpQueue), mozilla::fallible_t());
+}
+
+void nsHtml5TreeOpExecutor::ClearOpQueue() {
+ MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
+ "mOpQueue cleared during tree op execution.");
+ mOpQueue.Clear();
+}
+
+void nsHtml5TreeOpExecutor::RemoveFromStartOfOpQueue(
+ size_t aNumberOfOpsToRemove) {
+ MOZ_RELEASE_ASSERT(mFlushState == eNotFlushing,
+ "Ops removed from mOpQueue during tree op execution.");
+ mOpQueue.RemoveElementsAt(0, aNumberOfOpsToRemove);
+}
+
+void nsHtml5TreeOpExecutor::InitializeDocWriteParserState(
+ nsAHtml5TreeBuilderState* aState, int32_t aLine) {
+ GetParser()->InitializeDocWriteParserState(aState, aLine);
+}
+
+nsIURI* nsHtml5TreeOpExecutor::GetViewSourceBaseURI() {
+ if (!mViewSourceBaseURI) {
+ // We query the channel for the baseURI because in certain situations it
+ // cannot otherwise be determined. If this process fails, fall back to the
+ // standard method.
+ nsCOMPtr<nsIViewSourceChannel> vsc =
+ do_QueryInterface(mDocument->GetChannel());
+ if (vsc) {
+ nsresult rv = vsc->GetBaseURI(getter_AddRefs(mViewSourceBaseURI));
+ if (NS_SUCCEEDED(rv) && mViewSourceBaseURI) {
+ return mViewSourceBaseURI;
+ }
+ }
+
+ nsCOMPtr<nsIURI> orig = mDocument->GetOriginalURI();
+ if (orig->SchemeIs("view-source")) {
+ nsCOMPtr<nsINestedURI> nested = do_QueryInterface(orig);
+ NS_ASSERTION(nested, "URI with scheme view-source didn't QI to nested!");
+ nested->GetInnerURI(getter_AddRefs(mViewSourceBaseURI));
+ } else {
+ // Fail gracefully if the base URL isn't a view-source: URL.
+ // Not sure if this can ever happen.
+ mViewSourceBaseURI = orig;
+ }
+ }
+ return mViewSourceBaseURI;
+}
+
+bool nsHtml5TreeOpExecutor::IsExternalViewSource() {
+ if (!StaticPrefs::view_source_editor_external()) {
+ return false;
+ }
+ if (mDocumentURI) {
+ return mDocumentURI->SchemeIs("view-source");
+ }
+ return false;
+}
+
+// Speculative loading
+
+nsIURI* nsHtml5TreeOpExecutor::BaseURIForPreload() {
+ // The URL of the document without <base>
+ nsIURI* documentURI = mDocument->GetDocumentURI();
+ // The URL of the document with non-speculative <base>
+ nsIURI* documentBaseURI = mDocument->GetDocBaseURI();
+
+ // If the two above are different, use documentBaseURI. If they are the same,
+ // the document object isn't aware of a <base>, so attempt to use the
+ // mSpeculationBaseURI or, failing, that, documentURI.
+ return (documentURI == documentBaseURI)
+ ? (mSpeculationBaseURI ? mSpeculationBaseURI.get() : documentURI)
+ : documentBaseURI;
+}
+
+already_AddRefed<nsIURI>
+nsHtml5TreeOpExecutor::ConvertIfNotPreloadedYetAndMediaApplies(
+ const nsAString& aURL, const nsAString& aMedia) {
+ nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
+ if (!uri) {
+ return nullptr;
+ }
+
+ if (!MediaApplies(aMedia)) {
+ return nullptr;
+ }
+ return uri.forget();
+}
+
+bool nsHtml5TreeOpExecutor::MediaApplies(const nsAString& aMedia) {
+ using dom::MediaList;
+
+ if (aMedia.IsEmpty()) {
+ return true;
+ }
+ RefPtr<MediaList> media = MediaList::Create(NS_ConvertUTF16toUTF8(aMedia));
+ return media->Matches(*mDocument);
+}
+
+already_AddRefed<nsIURI> nsHtml5TreeOpExecutor::ConvertIfNotPreloadedYet(
+ const nsAString& aURL) {
+ if (aURL.IsEmpty()) {
+ return nullptr;
+ }
+
+ nsIURI* base = BaseURIForPreload();
+ auto encoding = mDocument->GetDocumentCharacterSet();
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, encoding, base);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to create a URI");
+ return nullptr;
+ }
+
+ if (ShouldPreloadURI(uri)) {
+ return uri.forget();
+ }
+
+ return nullptr;
+}
+
+bool nsHtml5TreeOpExecutor::ShouldPreloadURI(nsIURI* aURI) {
+ nsAutoCString spec;
+ nsresult rv = aURI->GetSpec(spec);
+ NS_ENSURE_SUCCESS(rv, false);
+ return mPreloadedURLs.EnsureInserted(spec);
+}
+
+dom::ReferrerPolicy nsHtml5TreeOpExecutor::GetPreloadReferrerPolicy(
+ const nsAString& aReferrerPolicy) {
+ dom::ReferrerPolicy referrerPolicy =
+ dom::ReferrerInfo::ReferrerPolicyAttributeFromString(aReferrerPolicy);
+ return GetPreloadReferrerPolicy(referrerPolicy);
+}
+
+dom::ReferrerPolicy nsHtml5TreeOpExecutor::GetPreloadReferrerPolicy(
+ ReferrerPolicy aReferrerPolicy) {
+ if (aReferrerPolicy != dom::ReferrerPolicy::_empty) {
+ return aReferrerPolicy;
+ }
+
+ return mDocument->GetPreloadReferrerInfo()->ReferrerPolicy();
+}
+
+void nsHtml5TreeOpExecutor::PreloadScript(
+ const nsAString& aURL, const nsAString& aCharset, const nsAString& aType,
+ const nsAString& aCrossOrigin, const nsAString& aMedia,
+ const nsAString& aIntegrity, dom::ReferrerPolicy aReferrerPolicy,
+ bool aScriptFromHead, bool aAsync, bool aDefer, bool aNoModule,
+ bool aLinkPreload) {
+ nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia);
+ if (!uri) {
+ return;
+ }
+ auto key = PreloadHashKey::CreateAsScript(uri, aCrossOrigin, aType);
+ if (mDocument->Preloads().PreloadExists(key)) {
+ return;
+ }
+ mDocument->ScriptLoader()->PreloadURI(
+ uri, aCharset, aType, aCrossOrigin, aIntegrity, aScriptFromHead, aAsync,
+ aDefer, aNoModule, aLinkPreload,
+ GetPreloadReferrerPolicy(aReferrerPolicy), 0);
+}
+
+void nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
+ const nsAString& aCharset,
+ const nsAString& aCrossOrigin,
+ const nsAString& aMedia,
+ const nsAString& aReferrerPolicy,
+ const nsAString& aIntegrity,
+ bool aLinkPreload) {
+ nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia);
+ if (!uri) {
+ return;
+ }
+
+ if (aLinkPreload) {
+ auto hashKey = PreloadHashKey::CreateAsStyle(
+ uri, mDocument->NodePrincipal(),
+ dom::Element::StringToCORSMode(aCrossOrigin),
+ css::eAuthorSheetFeatures);
+ if (mDocument->Preloads().PreloadExists(hashKey)) {
+ return;
+ }
+ }
+
+ mDocument->PreloadStyle(uri, Encoding::ForLabel(aCharset), aCrossOrigin,
+ GetPreloadReferrerPolicy(aReferrerPolicy), aIntegrity,
+ aLinkPreload
+ ? css::StylePreloadKind::FromLinkRelPreloadElement
+ : css::StylePreloadKind::FromParser,
+ 0);
+}
+
+void nsHtml5TreeOpExecutor::PreloadImage(
+ const nsAString& aURL, const nsAString& aCrossOrigin,
+ const nsAString& aMedia, const nsAString& aSrcset, const nsAString& aSizes,
+ const nsAString& aImageReferrerPolicy, bool aLinkPreload,
+ const TimeStamp& aInitTimestamp) {
+ nsCOMPtr<nsIURI> baseURI = BaseURIForPreload();
+ bool isImgSet = false;
+ nsCOMPtr<nsIURI> uri =
+ mDocument->ResolvePreloadImage(baseURI, aURL, aSrcset, aSizes, &isImgSet);
+ if (uri && ShouldPreloadURI(uri) && MediaApplies(aMedia)) {
+ // use document wide referrer policy
+ mDocument->MaybePreLoadImage(uri, aCrossOrigin,
+ GetPreloadReferrerPolicy(aImageReferrerPolicy),
+ isImgSet, aLinkPreload, aInitTimestamp);
+ }
+}
+
+// These calls inform the document of picture state and seen sources, such that
+// it can use them to inform ResolvePreLoadImage as necessary
+void nsHtml5TreeOpExecutor::PreloadPictureSource(const nsAString& aSrcset,
+ const nsAString& aSizes,
+ const nsAString& aType,
+ const nsAString& aMedia) {
+ mDocument->PreloadPictureImageSource(aSrcset, aSizes, aType, aMedia);
+}
+
+void nsHtml5TreeOpExecutor::PreloadFont(const nsAString& aURL,
+ const nsAString& aCrossOrigin,
+ const nsAString& aMedia,
+ const nsAString& aReferrerPolicy) {
+ nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia);
+ if (!uri) {
+ return;
+ }
+
+ mDocument->Preloads().PreloadFont(uri, aCrossOrigin, aReferrerPolicy, 0);
+}
+
+void nsHtml5TreeOpExecutor::PreloadFetch(const nsAString& aURL,
+ const nsAString& aCrossOrigin,
+ const nsAString& aMedia,
+ const nsAString& aReferrerPolicy) {
+ nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia);
+ if (!uri) {
+ return;
+ }
+
+ mDocument->Preloads().PreloadFetch(uri, aCrossOrigin, aReferrerPolicy, 0);
+}
+
+void nsHtml5TreeOpExecutor::PreloadOpenPicture() {
+ mDocument->PreloadPictureOpened();
+}
+
+void nsHtml5TreeOpExecutor::PreloadEndPicture() {
+ mDocument->PreloadPictureClosed();
+}
+
+void nsHtml5TreeOpExecutor::AddBase(const nsAString& aURL) {
+ auto encoding = mDocument->GetDocumentCharacterSet();
+ nsresult rv = NS_NewURI(getter_AddRefs(mViewSourceBaseURI), aURL, encoding,
+ GetViewSourceBaseURI());
+ if (NS_FAILED(rv)) {
+ mViewSourceBaseURI = nullptr;
+ }
+}
+void nsHtml5TreeOpExecutor::SetSpeculationBase(const nsAString& aURL) {
+ if (mSpeculationBaseURI) {
+ // the first one wins
+ return;
+ }
+
+ auto encoding = mDocument->GetDocumentCharacterSet();
+ nsCOMPtr<nsIURI> newBaseURI;
+ DebugOnly<nsresult> rv = NS_NewURI(getter_AddRefs(newBaseURI), aURL, encoding,
+ mDocument->GetDocumentURI());
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to create a URI");
+ if (!newBaseURI) {
+ return;
+ }
+
+ // Check the document's CSP usually delivered via the CSP header.
+ if (nsCOMPtr<nsIContentSecurityPolicy> csp = mDocument->GetCsp()) {
+ // base-uri should not fallback to the default-src and preloads should not
+ // trigger violation reports.
+ bool cspPermitsBaseURI = true;
+ nsresult rv = csp->Permits(
+ nullptr, nullptr, newBaseURI,
+ nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */,
+ false /* aSendViolationReports */, &cspPermitsBaseURI);
+ if (NS_FAILED(rv) || !cspPermitsBaseURI) {
+ return;
+ }
+ }
+
+ // Also check the CSP discovered from the <meta> tag during speculative
+ // parsing.
+ if (nsCOMPtr<nsIContentSecurityPolicy> csp = mDocument->GetPreloadCsp()) {
+ bool cspPermitsBaseURI = true;
+ nsresult rv = csp->Permits(
+ nullptr, nullptr, newBaseURI,
+ nsIContentSecurityPolicy::BASE_URI_DIRECTIVE, true /* aSpecific */,
+ false /* aSendViolationReports */, &cspPermitsBaseURI);
+ if (NS_FAILED(rv) || !cspPermitsBaseURI) {
+ return;
+ }
+ }
+
+ mSpeculationBaseURI = newBaseURI;
+ mDocument->Preloads().SetSpeculationBase(mSpeculationBaseURI);
+}
+
+void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta(
+ const nsAString& aMetaReferrer) {
+ mDocument->UpdateReferrerInfoFromMeta(aMetaReferrer, true);
+}
+
+void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
+ NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = mDocument->GetPreloadCsp();
+ if (!preloadCsp) {
+ RefPtr<nsCSPContext> csp = new nsCSPContext();
+ csp->SuppressParserLogMessages();
+ preloadCsp = csp;
+ rv = preloadCsp->SetRequestContextWithDocument(mDocument);
+ NS_ENSURE_SUCCESS_VOID(rv);
+ }
+
+ // Please note that multiple meta CSPs need to be joined together.
+ rv = preloadCsp->AppendPolicy(
+ aCSP,
+ false, // csp via meta tag can not be report only
+ true); // delivered through the meta tag
+ NS_ENSURE_SUCCESS_VOID(rv);
+
+ nsPIDOMWindowInner* inner = mDocument->GetInnerWindow();
+ if (inner) {
+ inner->SetPreloadCsp(preloadCsp);
+ }
+ mDocument->ApplySettingsFromCSP(true);
+}
+
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+uint32_t nsHtml5TreeOpExecutor::sAppendBatchMaxSize = 0;
+uint32_t nsHtml5TreeOpExecutor::sAppendBatchSlotsExamined = 0;
+uint32_t nsHtml5TreeOpExecutor::sAppendBatchExaminations = 0;
+uint32_t nsHtml5TreeOpExecutor::sLongestTimeOffTheEventLoop = 0;
+uint32_t nsHtml5TreeOpExecutor::sTimesFlushLoopInterrupted = 0;
+#endif
diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h
new file mode 100644
index 0000000000..e47d99a1b2
--- /dev/null
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -0,0 +1,320 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5TreeOpExecutor_h
+#define nsHtml5TreeOpExecutor_h
+
+#include "nsAtom.h"
+#include "nsTraceRefcnt.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsHtml5SpeculativeLoad.h"
+#include "nsTArray.h"
+#include "nsContentSink.h"
+#include "nsNodeInfoManager.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsIScriptElement.h"
+#include "nsIParser.h"
+#include "nsAHtml5TreeOpSink.h"
+#include "nsHtml5TreeOpStage.h"
+#include "nsIURI.h"
+#include "nsTHashSet.h"
+#include "nsHashKeys.h"
+#include "mozilla/LinkedList.h"
+#include "nsHtml5DocumentBuilder.h"
+#include "nsCharsetSource.h"
+
+class nsHtml5Parser;
+class nsHtml5StreamParser;
+class nsIContent;
+namespace mozilla {
+namespace dom {
+class Document;
+}
+} // namespace mozilla
+
+class nsHtml5TreeOpExecutor final
+ : public nsHtml5DocumentBuilder,
+ public nsIContentSink,
+ public nsAHtml5TreeOpSink,
+ public mozilla::LinkedListElement<nsHtml5TreeOpExecutor> {
+ friend class nsHtml5FlushLoopGuard;
+ typedef mozilla::dom::ReferrerPolicy ReferrerPolicy;
+ using Encoding = mozilla::Encoding;
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+
+ public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ private:
+#ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH
+ static uint32_t sAppendBatchMaxSize;
+ static uint32_t sAppendBatchSlotsExamined;
+ static uint32_t sAppendBatchExaminations;
+ static uint32_t sLongestTimeOffTheEventLoop;
+ static uint32_t sTimesFlushLoopInterrupted;
+#endif
+
+ /**
+ * Whether EOF needs to be suppressed
+ */
+ bool mSuppressEOF;
+
+ bool mReadingFromStage;
+ nsTArray<nsHtml5TreeOperation> mOpQueue;
+ nsHtml5StreamParser* mStreamParser;
+
+ /**
+ * URLs already preloaded/preloading.
+ */
+ nsTHashSet<nsCString> mPreloadedURLs;
+
+ nsCOMPtr<nsIURI> mSpeculationBaseURI;
+
+ nsCOMPtr<nsIURI> mViewSourceBaseURI;
+
+ /**
+ * Whether the parser has started
+ */
+ bool mStarted;
+
+ nsHtml5TreeOpStage mStage;
+
+ bool mRunFlushLoopOnStack;
+
+ bool mCallContinueInterruptedParsingIfEnabled;
+
+ /**
+ * Whether this executor has already complained about matters related
+ * to character encoding declarations.
+ */
+ bool mAlreadyComplainedAboutCharset;
+
+ /**
+ * Whether this executor has already complained about the tree being too
+ * deep.
+ */
+ bool mAlreadyComplainedAboutDeepTree;
+
+ public:
+ nsHtml5TreeOpExecutor();
+
+ protected:
+ virtual ~nsHtml5TreeOpExecutor();
+
+ public:
+ // nsIContentSink
+
+ /**
+ * Unimplemented. For interface compat only.
+ */
+ NS_IMETHOD WillParse() override;
+
+ NS_IMETHOD WillBuildModel(nsDTDMode /* unused */) override {
+ return WillBuildModel();
+ }
+ nsresult WillBuildModel();
+
+ /**
+ * Emits EOF.
+ */
+ NS_IMETHOD DidBuildModel(bool aTerminated) override;
+
+ /**
+ * Forwards to nsContentSink
+ */
+ NS_IMETHOD WillInterrupt() override;
+
+ /**
+ * Unimplemented. For interface compat only.
+ */
+ void WillResume() override;
+
+ virtual nsIContentSink* AsExecutor() override { return this; }
+
+ virtual void InitialTranslationCompleted() override;
+
+ /**
+ * Sets the parser.
+ */
+ NS_IMETHOD SetParser(nsParserBase* aParser) override;
+
+ /**
+ * No-op for backwards compat.
+ */
+ virtual void FlushPendingNotifications(mozilla::FlushType aType) override;
+
+ /**
+ * Don't call. For interface compat only.
+ */
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override {
+ MOZ_ASSERT_UNREACHABLE("No one should call this.");
+ }
+
+ /**
+ * Returns the document.
+ */
+ virtual nsISupports* GetTarget() override;
+
+ virtual void ContinueInterruptedParsingAsync() override;
+
+ bool IsScriptExecuting() override { return IsScriptExecutingImpl(); }
+
+ // Not from interface
+
+ void SetStreamParser(nsHtml5StreamParser* aStreamParser) {
+ mStreamParser = aStreamParser;
+ }
+
+ void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState,
+ int32_t aLine);
+
+ bool IsScriptEnabled();
+
+ virtual nsresult MarkAsBroken(nsresult aReason) override;
+
+ void StartLayout(bool* aInterrupted);
+
+ void PauseDocUpdate(bool* aInterrupted);
+
+ void FlushSpeculativeLoads();
+
+ void RunFlushLoop();
+
+ nsresult FlushDocumentWrite();
+
+ void CommitToInternalEncoding();
+
+ [[nodiscard]] bool TakeOpsFromStage();
+
+ void MaybeSuspend();
+
+ void Start();
+
+ void SetDocumentCharsetAndSource(NotNull<const Encoding*> aEncoding,
+ nsCharsetSource aCharsetSource);
+
+ void UpdateCharsetSource(nsCharsetSource aCharsetSource);
+
+ void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding, int32_t aSource,
+ uint32_t aLineNumber);
+
+ void MaybeComplainAboutCharset(const char* aMsgId, bool aError,
+ uint32_t aLineNumber);
+
+ void ComplainAboutBogusProtocolCharset(mozilla::dom::Document* aDoc,
+ bool aUnrecognized);
+
+ void MaybeComplainAboutDeepTree(uint32_t aLineNumber);
+
+ bool HasStarted() { return mStarted; }
+
+ bool IsFlushing() { return mFlushState >= eInFlush; }
+
+#ifdef DEBUG
+ bool IsInFlushLoop() { return mRunFlushLoopOnStack; }
+#endif
+
+ void RunScript(nsIContent* aScriptElement);
+
+ /**
+ * Flush the operations from the tree operations from the argument
+ * queue unconditionally. (This is for the main thread case.)
+ */
+ [[nodiscard]] virtual bool MoveOpsFrom(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) override;
+
+ void ClearOpQueue();
+
+ void RemoveFromStartOfOpQueue(size_t aNumberOfOpsToRemove);
+
+ inline size_t OpQueueLength() { return mOpQueue.Length(); }
+
+ nsHtml5TreeOpStage* GetStage() { return &mStage; }
+
+ void StartReadingFromStage() { mReadingFromStage = true; }
+
+ void StreamEnded();
+
+#ifdef DEBUG
+ void AssertStageEmpty() { mStage.AssertEmpty(); }
+#endif
+
+ nsIURI* GetViewSourceBaseURI();
+
+ void PreloadScript(const nsAString& aURL, const nsAString& aCharset,
+ const nsAString& aType, const nsAString& aCrossOrigin,
+ const nsAString& aMedia, const nsAString& aIntegrity,
+ ReferrerPolicy aReferrerPolicy, bool aScriptFromHead,
+ bool aAsync, bool aDefer, bool aNoModule,
+ bool aLinkPreload);
+
+ void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
+ const nsAString& aCrossOrigin, const nsAString& aMedia,
+ const nsAString& aReferrerPolicy,
+ const nsAString& aIntegrity, bool aLinkPreload);
+
+ void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin,
+ const nsAString& aMedia, const nsAString& aSrcset,
+ const nsAString& aSizes,
+ const nsAString& aImageReferrerPolicy, bool aLinkPreload,
+ const mozilla::TimeStamp& aInitTimestamp);
+
+ void PreloadOpenPicture();
+
+ void PreloadEndPicture();
+
+ void PreloadPictureSource(const nsAString& aSrcset, const nsAString& aSizes,
+ const nsAString& aType, const nsAString& aMedia);
+
+ void PreloadFont(const nsAString& aURL, const nsAString& aCrossOrigin,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy);
+
+ void PreloadFetch(const nsAString& aURL, const nsAString& aCrossOrigin,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy);
+
+ void SetSpeculationBase(const nsAString& aURL);
+
+ void UpdateReferrerInfoFromMeta(const nsAString& aMetaReferrer);
+
+ void AddSpeculationCSP(const nsAString& aCSP);
+
+ void AddBase(const nsAString& aURL);
+
+ private:
+ nsHtml5Parser* GetParser();
+
+ bool IsExternalViewSource();
+
+ /**
+ * Get a nsIURI for an nsString if the URL hasn't been preloaded yet.
+ */
+ already_AddRefed<nsIURI> ConvertIfNotPreloadedYet(const nsAString& aURL);
+
+ /**
+ * The above, plus also checks that the media attribute applies.
+ */
+ already_AddRefed<nsIURI> ConvertIfNotPreloadedYetAndMediaApplies(
+ const nsAString& aURL, const nsAString& aMedia);
+
+ /** Returns whether the given media attribute applies to mDocument */
+ bool MediaApplies(const nsAString& aMedia);
+
+ /**
+ * The base URI we would use for current preload operations
+ */
+ nsIURI* BaseURIForPreload();
+
+ /**
+ * Returns true if we haven't preloaded this URI yet, and adds it to the
+ * list of preloaded URIs
+ */
+ bool ShouldPreloadURI(nsIURI* aURI);
+
+ ReferrerPolicy GetPreloadReferrerPolicy(const nsAString& aReferrerPolicy);
+
+ ReferrerPolicy GetPreloadReferrerPolicy(ReferrerPolicy aReferrerPolicy);
+};
+
+#endif // nsHtml5TreeOpExecutor_h
diff --git a/parser/html/nsHtml5TreeOpStage.cpp b/parser/html/nsHtml5TreeOpStage.cpp
new file mode 100644
index 0000000000..6f7cb5f608
--- /dev/null
+++ b/parser/html/nsHtml5TreeOpStage.cpp
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5TreeOpStage.h"
+
+using namespace mozilla;
+
+nsHtml5TreeOpStage::nsHtml5TreeOpStage() : mMutex("nsHtml5TreeOpStage mutex") {}
+
+nsHtml5TreeOpStage::~nsHtml5TreeOpStage() {}
+
+bool nsHtml5TreeOpStage::MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue) {
+ mozilla::MutexAutoLock autoLock(mMutex);
+ return !!mOpQueue.AppendElements(std::move(aOpQueue), mozilla::fallible_t());
+}
+
+[[nodiscard]] bool nsHtml5TreeOpStage::MoveOpsAndSpeculativeLoadsTo(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue,
+ nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue) {
+ mozilla::MutexAutoLock autoLock(mMutex);
+ if (!aOpQueue.AppendElements(std::move(mOpQueue), mozilla::fallible_t())) {
+ return false;
+ };
+ aSpeculativeLoadQueue.AppendElements(std::move(mSpeculativeLoadQueue));
+ return true;
+}
+
+[[nodiscard]] bool nsHtml5TreeOpStage::MoveOpsTo(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) {
+ mozilla::MutexAutoLock autoLock(mMutex);
+ return !!aOpQueue.AppendElements(std::move(mOpQueue), mozilla::fallible_t());
+}
+
+void nsHtml5TreeOpStage::MoveSpeculativeLoadsFrom(
+ nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue) {
+ mozilla::MutexAutoLock autoLock(mMutex);
+ mSpeculativeLoadQueue.AppendElements(std::move(aSpeculativeLoadQueue));
+}
+
+void nsHtml5TreeOpStage::MoveSpeculativeLoadsTo(
+ nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue) {
+ mozilla::MutexAutoLock autoLock(mMutex);
+ aSpeculativeLoadQueue.AppendElements(std::move(mSpeculativeLoadQueue));
+}
+
+#ifdef DEBUG
+void nsHtml5TreeOpStage::AssertEmpty() {
+ mozilla::MutexAutoLock autoLock(mMutex);
+ MOZ_ASSERT(mOpQueue.IsEmpty(), "The stage was supposed to be empty.");
+}
+#endif
diff --git a/parser/html/nsHtml5TreeOpStage.h b/parser/html/nsHtml5TreeOpStage.h
new file mode 100644
index 0000000000..967ccfd008
--- /dev/null
+++ b/parser/html/nsHtml5TreeOpStage.h
@@ -0,0 +1,61 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5TreeOpStage_h
+#define nsHtml5TreeOpStage_h
+
+#include "mozilla/Mutex.h"
+#include "nsHtml5TreeOperation.h"
+#include "nsTArray.h"
+#include "nsAHtml5TreeOpSink.h"
+#include "nsHtml5SpeculativeLoad.h"
+
+class nsHtml5TreeOpStage : public nsAHtml5TreeOpSink {
+ public:
+ nsHtml5TreeOpStage();
+
+ virtual ~nsHtml5TreeOpStage();
+
+ /**
+ * Flush the operations from the tree operations from the argument
+ * queue unconditionally.
+ */
+ [[nodiscard]] virtual bool MoveOpsFrom(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue) override;
+
+ /**
+ * Retrieve the staged operations into the argument.
+ */
+ [[nodiscard]] bool MoveOpsTo(nsTArray<nsHtml5TreeOperation>& aOpQueue);
+
+ /**
+ * Retrieve the staged operations and speculative loads into the arguments.
+ */
+ [[nodiscard]] bool MoveOpsAndSpeculativeLoadsTo(
+ nsTArray<nsHtml5TreeOperation>& aOpQueue,
+ nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue);
+
+ /**
+ * Move the speculative loads from the argument into the staging queue.
+ */
+ void MoveSpeculativeLoadsFrom(
+ nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue);
+
+ /**
+ * Retrieve the staged speculative loads into the argument.
+ */
+ void MoveSpeculativeLoadsTo(
+ nsTArray<nsHtml5SpeculativeLoad>& aSpeculativeLoadQueue);
+
+#ifdef DEBUG
+ void AssertEmpty();
+#endif
+
+ private:
+ nsTArray<nsHtml5TreeOperation> mOpQueue;
+ nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue;
+ mozilla::Mutex mMutex MOZ_UNANNOTATED;
+};
+
+#endif /* nsHtml5TreeOpStage_h */
diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp
new file mode 100644
index 0000000000..a6e0298420
--- /dev/null
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -0,0 +1,1208 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5TreeOperation.h"
+#include "mozAutoDocUpdate.h"
+#include "mozilla/CycleCollectedJSContext.h"
+#include "mozilla/Likely.h"
+#include "mozilla/dom/Comment.h"
+#include "mozilla/dom/CustomElementRegistry.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/DocumentType.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/LinkStyle.h"
+#include "mozilla/dom/HTMLFormElement.h"
+#include "mozilla/dom/HTMLImageElement.h"
+#include "mozilla/dom/HTMLTemplateElement.h"
+#include "mozilla/dom/MutationObservers.h"
+#include "mozilla/dom/Text.h"
+#include "nsAttrName.h"
+#include "nsContentCreatorFunctions.h"
+#include "nsContentUtils.h"
+#include "nsDocElementCreatedNotificationRunner.h"
+#include "nsEscape.h"
+#include "nsHtml5AutoPauseUpdate.h"
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5HtmlAttributes.h"
+#include "nsHtml5SVGLoadDispatcher.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsIDTD.h"
+#include "nsIFormControl.h"
+#include "nsIMutationObserver.h"
+#include "nsINode.h"
+#include "nsIProtocolHandler.h"
+#include "nsIScriptElement.h"
+#include "nsISupportsImpl.h"
+#include "nsIURI.h"
+#include "nsNetUtil.h"
+#include "nsTextNode.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+using mozilla::dom::Document;
+
+/**
+ * Helper class that opens a notification batch if the current doc
+ * is different from the executor doc.
+ */
+class MOZ_STACK_CLASS nsHtml5OtherDocUpdate {
+ public:
+ nsHtml5OtherDocUpdate(Document* aCurrentDoc, Document* aExecutorDoc) {
+ MOZ_ASSERT(aCurrentDoc, "Node has no doc?");
+ MOZ_ASSERT(aExecutorDoc, "Executor has no doc?");
+ if (MOZ_LIKELY(aCurrentDoc == aExecutorDoc)) {
+ mDocument = nullptr;
+ } else {
+ mDocument = aCurrentDoc;
+ aCurrentDoc->BeginUpdate();
+ }
+ }
+
+ ~nsHtml5OtherDocUpdate() {
+ if (MOZ_UNLIKELY(mDocument)) {
+ mDocument->EndUpdate();
+ }
+ }
+
+ private:
+ RefPtr<Document> mDocument;
+};
+
+nsHtml5TreeOperation::nsHtml5TreeOperation() : mOperation(uninitialized()) {
+ MOZ_COUNT_CTOR(nsHtml5TreeOperation);
+}
+
+nsHtml5TreeOperation::~nsHtml5TreeOperation() {
+ MOZ_COUNT_DTOR(nsHtml5TreeOperation);
+
+ struct TreeOperationMatcher {
+ void operator()(const opAppend& aOperation) {}
+
+ void operator()(const opDetach& aOperation) {}
+
+ void operator()(const opAppendChildrenToNewParent& aOperation) {}
+
+ void operator()(const opFosterParent& aOperation) {}
+
+ void operator()(const opAppendToDocument& aOperation) {}
+
+ void operator()(const opAddAttributes& aOperation) {
+ delete aOperation.mAttributes;
+ }
+
+ void operator()(const nsHtml5DocumentMode& aMode) {}
+
+ void operator()(const opCreateHTMLElement& aOperation) {
+ aOperation.mName->Release();
+ delete aOperation.mAttributes;
+ }
+
+ void operator()(const opCreateSVGElement& aOperation) {
+ aOperation.mName->Release();
+ delete aOperation.mAttributes;
+ }
+
+ void operator()(const opCreateMathMLElement& aOperation) {
+ aOperation.mName->Release();
+ delete aOperation.mAttributes;
+ }
+
+ void operator()(const opSetFormElement& aOperation) {}
+
+ void operator()(const opAppendText& aOperation) {
+ delete[] aOperation.mBuffer;
+ }
+
+ void operator()(const opFosterParentText& aOperation) {
+ delete[] aOperation.mBuffer;
+ }
+
+ void operator()(const opAppendComment& aOperation) {
+ delete[] aOperation.mBuffer;
+ }
+
+ void operator()(const opAppendCommentToDocument& aOperation) {
+ delete[] aOperation.mBuffer;
+ }
+
+ void operator()(const opAppendDoctypeToDocument& aOperation) {
+ aOperation.mName->Release();
+ delete aOperation.mStringPair;
+ }
+
+ void operator()(const opGetDocumentFragmentForTemplate& aOperation) {}
+
+ void operator()(const opGetFosterParent& aOperation) {}
+
+ void operator()(const opMarkAsBroken& aOperation) {}
+
+ void operator()(const opRunScript& aOperation) {}
+
+ void operator()(const opRunScriptAsyncDefer& aOperation) {}
+
+ void operator()(const opPreventScriptExecution& aOperation) {}
+
+ void operator()(const opDoneAddingChildren& aOperation) {}
+
+ void operator()(const opDoneCreatingElement& aOperation) {}
+
+ void operator()(const opUpdateCharsetSource& aOperation) {}
+
+ void operator()(const opCharsetSwitchTo& aOperation) {}
+
+ void operator()(const opUpdateStyleSheet& aOperation) {}
+
+ void operator()(const opProcessOfflineManifest& aOperation) {
+ free(aOperation.mUrl);
+ }
+
+ void operator()(const opMarkMalformedIfScript& aOperation) {}
+
+ void operator()(const opStreamEnded& aOperation) {}
+
+ void operator()(const opSetStyleLineNumber& aOperation) {}
+
+ void operator()(const opSetScriptLineAndColumnNumberAndFreeze& aOperation) {
+ }
+
+ void operator()(const opSvgLoad& aOperation) {}
+
+ void operator()(const opMaybeComplainAboutCharset& aOperation) {}
+
+ void operator()(const opMaybeComplainAboutDeepTree& aOperation) {}
+
+ void operator()(const opAddClass& aOperation) {}
+
+ void operator()(const opAddViewSourceHref& aOperation) {
+ delete[] aOperation.mBuffer;
+ }
+
+ void operator()(const opAddViewSourceBase& aOperation) {
+ delete[] aOperation.mBuffer;
+ }
+
+ void operator()(const opAddErrorType& aOperation) {
+ if (aOperation.mName) {
+ aOperation.mName->Release();
+ }
+ if (aOperation.mOther) {
+ aOperation.mOther->Release();
+ }
+ }
+
+ void operator()(const opAddLineNumberId& aOperation) {}
+
+ void operator()(const opStartLayout& aOperation) {}
+
+ void operator()(const opEnableEncodingMenu& aOperation) {}
+
+ void operator()(const uninitialized& aOperation) {
+ NS_WARNING("Uninitialized tree op.");
+ }
+ };
+
+ mOperation.match(TreeOperationMatcher());
+}
+
+nsresult nsHtml5TreeOperation::AppendTextToTextNode(
+ const char16_t* aBuffer, uint32_t aLength, dom::Text* aTextNode,
+ nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aTextNode, "Got null text node.");
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+ uint32_t oldLength = aTextNode->TextLength();
+ CharacterDataChangeInfo info = {true, oldLength, oldLength, aLength};
+ MutationObservers::NotifyCharacterDataWillChange(aTextNode, info);
+
+ nsresult rv = aTextNode->AppendText(aBuffer, aLength, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ MutationObservers::NotifyCharacterDataChanged(aTextNode, info);
+ return rv;
+}
+
+nsresult nsHtml5TreeOperation::AppendText(const char16_t* aBuffer,
+ uint32_t aLength, nsIContent* aParent,
+ nsHtml5DocumentBuilder* aBuilder) {
+ nsresult rv = NS_OK;
+ nsIContent* lastChild = aParent->GetLastChild();
+ if (lastChild && lastChild->IsText()) {
+ nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
+ return AppendTextToTextNode(aBuffer, aLength, lastChild->GetAsText(),
+ aBuilder);
+ }
+
+ nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
+ RefPtr<nsTextNode> text = new (nodeInfoManager) nsTextNode(nodeInfoManager);
+ NS_ASSERTION(text, "Infallible malloc failed?");
+ rv = text->SetText(aBuffer, aLength, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return Append(text, aParent, aBuilder);
+}
+
+nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent,
+ nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+ ErrorResult rv;
+ nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
+ aParent->AppendChildTo(aNode, false, rv);
+ if (!rv.Failed()) {
+ aNode->SetParserHasNotified();
+ MutationObservers::NotifyContentAppended(aParent, aNode);
+ }
+ return rv.StealNSResult();
+}
+
+nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent,
+ mozilla::dom::FromParser aFromParser,
+ nsHtml5DocumentBuilder* aBuilder) {
+ Maybe<nsHtml5AutoPauseUpdate> autoPause;
+ Maybe<dom::AutoCEReaction> autoCEReaction;
+ dom::DocGroup* docGroup = aParent->OwnerDoc()->GetDocGroup();
+ if (docGroup && aFromParser != mozilla::dom::FROM_PARSER_FRAGMENT) {
+ autoCEReaction.emplace(docGroup->CustomElementReactionsStack(), nullptr);
+ }
+ nsresult rv = Append(aNode, aParent, aBuilder);
+ // Pause the parser only when there are reactions to be invoked to avoid
+ // pausing parsing too aggressive.
+ if (autoCEReaction.isSome() && docGroup &&
+ docGroup->CustomElementReactionsStack()
+ ->IsElementQueuePushedForCurrentRecursionDepth()) {
+ autoPause.emplace(aBuilder);
+ }
+ return rv;
+}
+
+nsresult nsHtml5TreeOperation::AppendToDocument(
+ nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->GetDocument() == aNode->OwnerDoc());
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+
+ ErrorResult rv;
+ Document* doc = aBuilder->GetDocument();
+ doc->AppendChildTo(aNode, false, rv);
+ if (rv.ErrorCodeIs(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR)) {
+ aNode->SetParserHasNotified();
+ return NS_OK;
+ }
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+
+ aNode->SetParserHasNotified();
+ MutationObservers::NotifyContentInserted(doc, aNode);
+
+ NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
+ "Someone forgot to block scripts");
+ if (aNode->IsElement()) {
+ nsContentUtils::AddScriptRunner(
+ new nsDocElementCreatedNotificationRunner(doc));
+ }
+ return NS_OK;
+}
+
+static bool IsElementOrTemplateContent(nsINode* aNode) {
+ if (aNode) {
+ if (aNode->IsElement()) {
+ return true;
+ }
+ if (aNode->IsDocumentFragment()) {
+ // Check if the node is a template content.
+ nsIContent* fragHost = aNode->AsDocumentFragment()->GetHost();
+ if (fragHost && fragHost->IsTemplateElement()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void nsHtml5TreeOperation::Detach(nsIContent* aNode,
+ nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+ nsCOMPtr<nsINode> parent = aNode->GetParentNode();
+ if (parent) {
+ nsHtml5OtherDocUpdate update(parent->OwnerDoc(), aBuilder->GetDocument());
+ parent->RemoveChildNode(aNode, true);
+ }
+}
+
+nsresult nsHtml5TreeOperation::AppendChildrenToNewParent(
+ nsIContent* aNode, nsIContent* aParent, nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+ nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
+
+ bool didAppend = false;
+ while (aNode->HasChildren()) {
+ nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
+ aNode->RemoveChildNode(child, true);
+
+ ErrorResult rv;
+ aParent->AppendChildTo(child, false, rv);
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+ didAppend = true;
+ }
+ if (didAppend) {
+ MutationObservers::NotifyContentAppended(aParent, aParent->GetLastChild());
+ }
+ return NS_OK;
+}
+
+nsresult nsHtml5TreeOperation::FosterParent(nsIContent* aNode,
+ nsIContent* aParent,
+ nsIContent* aTable,
+ nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+ nsIContent* foster = aTable->GetParent();
+
+ if (IsElementOrTemplateContent(foster)) {
+ nsHtml5OtherDocUpdate update(foster->OwnerDoc(), aBuilder->GetDocument());
+
+ ErrorResult rv;
+ foster->InsertChildBefore(aNode, aTable, false, rv);
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+
+ MutationObservers::NotifyContentInserted(foster, aNode);
+ return NS_OK;
+ }
+
+ return Append(aNode, aParent, aBuilder);
+}
+
+nsresult nsHtml5TreeOperation::AddAttributes(nsIContent* aNode,
+ nsHtml5HtmlAttributes* aAttributes,
+ nsHtml5DocumentBuilder* aBuilder) {
+ dom::Element* node = aNode->AsElement();
+ nsHtml5OtherDocUpdate update(node->OwnerDoc(), aBuilder->GetDocument());
+
+ int32_t len = aAttributes->getLength();
+ for (int32_t i = len; i > 0;) {
+ --i;
+ nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
+ int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
+ if (!node->HasAttr(nsuri, localName)) {
+ nsString value; // Not Auto, because using it to hold nsStringBuffer*
+ aAttributes->getValueNoBoundsCheck(i).ToString(value);
+ node->SetAttr(nsuri, localName, aAttributes->getPrefixNoBoundsCheck(i),
+ value, true);
+ // XXX what to do with nsresult?
+ }
+ }
+ return NS_OK;
+}
+
+void nsHtml5TreeOperation::SetHTMLElementAttributes(
+ dom::Element* aElement, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes) {
+ int32_t len = aAttributes->getLength();
+ for (int32_t i = 0; i < len; i++) {
+ nsHtml5String val = aAttributes->getValueNoBoundsCheck(i);
+ nsAtom* klass = val.MaybeAsAtom();
+ if (klass) {
+ aElement->SetSingleClassFromParser(klass);
+ } else {
+ nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
+ nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i);
+ int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
+
+ nsString value; // Not Auto, because using it to hold nsStringBuffer*
+ val.ToString(value);
+ if (nsGkAtoms::a == aName && nsGkAtoms::name == localName) {
+ // This is an HTML5-incompliant Geckoism.
+ // Remove when fixing bug 582361
+ NS_ConvertUTF16toUTF8 cname(value);
+ NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
+ aElement->SetAttr(nsuri, localName, prefix, uv, false);
+ } else {
+ aElement->SetAttr(nsuri, localName, prefix, value, false);
+ }
+ }
+ }
+}
+
+nsIContent* nsHtml5TreeOperation::CreateHTMLElement(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder,
+ mozilla::dom::HTMLContentCreatorFunction aCreator) {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE);
+ NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
+
+ dom::Element* newContent = nullptr;
+ Document* document = nodeInfo->GetDocument();
+ bool willExecuteScript = false;
+ bool isCustomElement = false;
+ RefPtr<nsAtom> isAtom;
+ dom::CustomElementDefinition* definition = nullptr;
+
+ if (aAttributes) {
+ nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS);
+ if (is) {
+ nsAutoString isValue;
+ is.ToString(isValue);
+ isAtom = NS_Atomize(isValue);
+ }
+ }
+
+ isCustomElement = (aCreator == NS_NewCustomElement || isAtom);
+ if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) {
+ RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom();
+ RefPtr<nsAtom> typeAtom =
+ (aCreator == NS_NewCustomElement) ? tagAtom : isAtom;
+
+ MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()));
+ definition = nsContentUtils::LookupCustomElementDefinition(
+ document, nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
+
+ if (definition) {
+ willExecuteScript = true;
+ }
+ }
+
+ if (willExecuteScript) { // This will cause custom element constructors to
+ // run
+ mozilla::dom::AutoSetThrowOnDynamicMarkupInsertionCounter
+ throwOnDynamicMarkupInsertionCounter(document);
+ nsHtml5AutoPauseUpdate autoPauseContentUpdate(aBuilder);
+ { nsAutoMicroTask mt; }
+ dom::AutoCEReaction autoCEReaction(
+ document->GetDocGroup()->CustomElementReactionsStack(), nullptr);
+
+ nsCOMPtr<dom::Element> newElement;
+ NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
+ aFromParser, isAtom, definition);
+
+ MOZ_ASSERT(newElement, "Element creation created null pointer.");
+ newContent = newElement;
+ aBuilder->HoldElement(newElement.forget());
+
+ if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) {
+ if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) {
+ linkStyle->SetEnableUpdates(false);
+ }
+ }
+
+ if (!aAttributes) {
+ return newContent;
+ }
+
+ SetHTMLElementAttributes(newContent, aName, aAttributes);
+ } else {
+ nsCOMPtr<dom::Element> newElement;
+
+ if (isCustomElement) {
+ NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
+ aFromParser, isAtom, definition);
+ } else {
+ newElement = aCreator(nodeInfo.forget(), aFromParser);
+ }
+
+ MOZ_ASSERT(newElement, "Element creation created null pointer.");
+
+ newContent = newElement;
+ aBuilder->HoldElement(newElement.forget());
+
+ if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) {
+ if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) {
+ linkStyle->SetEnableUpdates(false);
+ }
+ }
+
+ if (!aAttributes) {
+ return newContent;
+ }
+
+ SetHTMLElementAttributes(newContent, aName, aAttributes);
+ }
+
+ return newContent;
+}
+
+nsIContent* nsHtml5TreeOperation::CreateSVGElement(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder,
+ mozilla::dom::SVGContentCreatorFunction aCreator) {
+ nsCOMPtr<nsIContent> newElement;
+ if (MOZ_LIKELY(aNodeInfoManager->SVGEnabled())) {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_SVG, nsINode::ELEMENT_NODE);
+ MOZ_ASSERT(nodeInfo, "Got null nodeinfo.");
+
+ mozilla::DebugOnly<nsresult> rv =
+ aCreator(getter_AddRefs(newElement), nodeInfo.forget(), aFromParser);
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
+ } else {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_disabled_SVG, nsINode::ELEMENT_NODE);
+ MOZ_ASSERT(nodeInfo, "Got null nodeinfo.");
+
+ // The mismatch between NS_NewXMLElement and SVGContentCreatorFunction
+ // argument types is annoying.
+ nsCOMPtr<dom::Element> xmlElement;
+ mozilla::DebugOnly<nsresult> rv =
+ NS_NewXMLElement(getter_AddRefs(xmlElement), nodeInfo.forget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && xmlElement);
+ newElement = xmlElement;
+ }
+
+ dom::Element* newContent = newElement->AsElement();
+ aBuilder->HoldElement(newElement.forget());
+
+ if (MOZ_UNLIKELY(aName == nsGkAtoms::style)) {
+ if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) {
+ linkStyle->SetEnableUpdates(false);
+ }
+ }
+
+ if (!aAttributes) {
+ return newContent;
+ }
+
+ int32_t len = aAttributes->getLength();
+ for (int32_t i = 0; i < len; i++) {
+ nsHtml5String val = aAttributes->getValueNoBoundsCheck(i);
+ nsAtom* klass = val.MaybeAsAtom();
+ if (klass) {
+ newContent->SetSingleClassFromParser(klass);
+ } else {
+ nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
+ nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i);
+ int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
+
+ nsString value; // Not Auto, because using it to hold nsStringBuffer*
+ val.ToString(value);
+ newContent->SetAttr(nsuri, localName, prefix, value, false);
+ }
+ }
+ return newContent;
+}
+
+nsIContent* nsHtml5TreeOperation::CreateMathMLElement(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ nsNodeInfoManager* aNodeInfoManager, nsHtml5DocumentBuilder* aBuilder) {
+ nsCOMPtr<dom::Element> newElement;
+ if (MOZ_LIKELY(aNodeInfoManager->MathMLEnabled())) {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_MathML, nsINode::ELEMENT_NODE);
+ NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
+
+ mozilla::DebugOnly<nsresult> rv =
+ NS_NewMathMLElement(getter_AddRefs(newElement), nodeInfo.forget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
+ } else {
+ RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
+ aName, nullptr, kNameSpaceID_disabled_MathML, nsINode::ELEMENT_NODE);
+ NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
+
+ mozilla::DebugOnly<nsresult> rv =
+ NS_NewXMLElement(getter_AddRefs(newElement), nodeInfo.forget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
+ }
+
+ dom::Element* newContent = newElement;
+ aBuilder->HoldElement(newElement.forget());
+
+ if (!aAttributes) {
+ return newContent;
+ }
+
+ int32_t len = aAttributes->getLength();
+ for (int32_t i = 0; i < len; i++) {
+ nsHtml5String val = aAttributes->getValueNoBoundsCheck(i);
+ nsAtom* klass = val.MaybeAsAtom();
+ if (klass) {
+ newContent->SetSingleClassFromParser(klass);
+ } else {
+ nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
+ nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i);
+ int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
+
+ nsString value; // Not Auto, because using it to hold nsStringBuffer*
+ val.ToString(value);
+ newContent->SetAttr(nsuri, localName, prefix, value, false);
+ }
+ }
+ return newContent;
+}
+
+void nsHtml5TreeOperation::SetFormElement(nsIContent* aNode,
+ nsIContent* aParent) {
+ RefPtr<dom::HTMLFormElement> formElement =
+ dom::HTMLFormElement::FromNodeOrNull(aParent);
+ NS_ASSERTION(formElement,
+ "The form element doesn't implement HTMLFormElement.");
+ nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
+ if (formControl &&
+ formControl->ControlType() !=
+ FormControlType::FormAssociatedCustomElement &&
+ !aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
+ formControl->SetForm(formElement);
+ } else if (HTMLImageElement* domImageElement =
+ dom::HTMLImageElement::FromNodeOrNull(aNode)) {
+ domImageElement->SetForm(formElement);
+ }
+}
+
+nsresult nsHtml5TreeOperation::FosterParentText(
+ nsIContent* aStackParent, char16_t* aBuffer, uint32_t aLength,
+ nsIContent* aTable, nsHtml5DocumentBuilder* aBuilder) {
+ MOZ_ASSERT(aBuilder);
+ MOZ_ASSERT(aBuilder->IsInDocUpdate());
+ nsresult rv = NS_OK;
+ nsIContent* foster = aTable->GetParent();
+
+ if (IsElementOrTemplateContent(foster)) {
+ nsHtml5OtherDocUpdate update(foster->OwnerDoc(), aBuilder->GetDocument());
+
+ nsIContent* previousSibling = aTable->GetPreviousSibling();
+ if (previousSibling && previousSibling->IsText()) {
+ return AppendTextToTextNode(aBuffer, aLength,
+ previousSibling->GetAsText(), aBuilder);
+ }
+
+ nsNodeInfoManager* nodeInfoManager =
+ aStackParent->OwnerDoc()->NodeInfoManager();
+ RefPtr<nsTextNode> text = new (nodeInfoManager) nsTextNode(nodeInfoManager);
+ NS_ASSERTION(text, "Infallible malloc failed?");
+ rv = text->SetText(aBuffer, aLength, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ErrorResult error;
+ foster->InsertChildBefore(text, aTable, false, error);
+ if (error.Failed()) {
+ return error.StealNSResult();
+ }
+
+ MutationObservers::NotifyContentInserted(foster, text);
+ return rv;
+ }
+
+ return AppendText(aBuffer, aLength, aStackParent, aBuilder);
+}
+
+nsresult nsHtml5TreeOperation::AppendComment(nsIContent* aParent,
+ char16_t* aBuffer, int32_t aLength,
+ nsHtml5DocumentBuilder* aBuilder) {
+ nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
+ RefPtr<dom::Comment> comment =
+ new (nodeInfoManager) dom::Comment(nodeInfoManager);
+ NS_ASSERTION(comment, "Infallible malloc failed?");
+ nsresult rv = comment->SetText(aBuffer, aLength, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return Append(comment, aParent, aBuilder);
+}
+
+nsresult nsHtml5TreeOperation::AppendCommentToDocument(
+ char16_t* aBuffer, int32_t aLength, nsHtml5DocumentBuilder* aBuilder) {
+ RefPtr<dom::Comment> comment = new (aBuilder->GetNodeInfoManager())
+ dom::Comment(aBuilder->GetNodeInfoManager());
+ NS_ASSERTION(comment, "Infallible malloc failed?");
+ nsresult rv = comment->SetText(aBuffer, aLength, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return AppendToDocument(comment, aBuilder);
+}
+
+nsresult nsHtml5TreeOperation::AppendDoctypeToDocument(
+ nsAtom* aName, const nsAString& aPublicId, const nsAString& aSystemId,
+ nsHtml5DocumentBuilder* aBuilder) {
+ // Adapted from nsXMLContentSink
+ // Create a new doctype node
+ RefPtr<dom::DocumentType> docType =
+ NS_NewDOMDocumentType(aBuilder->GetNodeInfoManager(), aName, aPublicId,
+ aSystemId, VoidString());
+ return AppendToDocument(docType, aBuilder);
+}
+
+nsIContent* nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
+ nsIContent* aNode) {
+ dom::HTMLTemplateElement* tempElem =
+ static_cast<dom::HTMLTemplateElement*>(aNode);
+ RefPtr<dom::DocumentFragment> frag = tempElem->Content();
+ return frag;
+}
+
+nsIContent* nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable,
+ nsIContent* aStackParent) {
+ nsIContent* tableParent = aTable->GetParent();
+ return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent;
+}
+
+void nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
+ if (sele) {
+ sele->PreventExecution();
+ } else {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ }
+}
+
+void nsHtml5TreeOperation::DoneAddingChildren(nsIContent* aNode) {
+ aNode->DoneAddingChildren(aNode->HasParserNotified());
+}
+
+void nsHtml5TreeOperation::DoneCreatingElement(nsIContent* aNode) {
+ aNode->DoneCreatingElement();
+}
+
+void nsHtml5TreeOperation::SvgLoad(nsIContent* aNode) {
+ nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(aNode);
+ if (NS_FAILED(
+ aNode->OwnerDoc()->Dispatch(TaskCategory::Network, event.forget()))) {
+ NS_WARNING("failed to dispatch svg load dispatcher");
+ }
+}
+
+void nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent* aNode) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
+ if (sele) {
+ // Make sure to serialize this script correctly, for nice round tripping.
+ sele->SetIsMalformed();
+ }
+}
+
+nsresult nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
+ nsIContent** aScriptElement,
+ bool* aInterrupted, bool* aStreamEnded) {
+ struct TreeOperationMatcher {
+ TreeOperationMatcher(nsHtml5TreeOpExecutor* aBuilder,
+ nsIContent** aScriptElement, bool* aInterrupted,
+ bool* aStreamEnded)
+ : mBuilder(aBuilder),
+ mScriptElement(aScriptElement),
+ mInterrupted(aInterrupted),
+ mStreamEnded(aStreamEnded) {}
+
+ nsHtml5TreeOpExecutor* mBuilder;
+ nsIContent** mScriptElement;
+ bool* mInterrupted;
+ bool* mStreamEnded;
+
+ nsresult operator()(const opAppend& aOperation) {
+ return Append(*(aOperation.mChild), *(aOperation.mParent),
+ aOperation.mFromNetwork, mBuilder);
+ }
+
+ nsresult operator()(const opDetach& aOperation) {
+ Detach(*(aOperation.mElement), mBuilder);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opAppendChildrenToNewParent& aOperation) {
+ nsCOMPtr<nsIContent> node = *(aOperation.mOldParent);
+ nsIContent* parent = *(aOperation.mNewParent);
+ return AppendChildrenToNewParent(node, parent, mBuilder);
+ }
+
+ nsresult operator()(const opFosterParent& aOperation) {
+ nsIContent* node = *(aOperation.mChild);
+ nsIContent* parent = *(aOperation.mStackParent);
+ nsIContent* table = *(aOperation.mTable);
+ return FosterParent(node, parent, table, mBuilder);
+ }
+
+ nsresult operator()(const opAppendToDocument& aOperation) {
+ nsresult rv = AppendToDocument(*(aOperation.mContent), mBuilder);
+ mBuilder->PauseDocUpdate(mInterrupted);
+ return rv;
+ }
+
+ nsresult operator()(const opAddAttributes& aOperation) {
+ nsIContent* node = *(aOperation.mElement);
+ nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
+ return AddAttributes(node, attributes, mBuilder);
+ }
+
+ nsresult operator()(const nsHtml5DocumentMode& aMode) {
+ mBuilder->SetDocumentMode(aMode);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opCreateHTMLElement& aOperation) {
+ nsIContent** target = aOperation.mContent;
+ mozilla::dom::HTMLContentCreatorFunction creator = aOperation.mCreator;
+ nsAtom* name = aOperation.mName;
+ nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
+ nsIContent* intendedParent =
+ aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr;
+
+ // intendedParent == nullptr is a special case where the
+ // intended parent is the document.
+ nsNodeInfoManager* nodeInfoManager =
+ intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
+ : mBuilder->GetNodeInfoManager();
+
+ *target = CreateHTMLElement(name, attributes, aOperation.mFromNetwork,
+ nodeInfoManager, mBuilder, creator);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opCreateSVGElement& aOperation) {
+ nsIContent** target = aOperation.mContent;
+ mozilla::dom::SVGContentCreatorFunction creator = aOperation.mCreator;
+ nsAtom* name = aOperation.mName;
+ nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
+ nsIContent* intendedParent =
+ aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr;
+
+ // intendedParent == nullptr is a special case where the
+ // intended parent is the document.
+ nsNodeInfoManager* nodeInfoManager =
+ intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
+ : mBuilder->GetNodeInfoManager();
+
+ *target = CreateSVGElement(name, attributes, aOperation.mFromNetwork,
+ nodeInfoManager, mBuilder, creator);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opCreateMathMLElement& aOperation) {
+ nsIContent** target = aOperation.mContent;
+ nsAtom* name = aOperation.mName;
+ nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
+ nsIContent* intendedParent =
+ aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr;
+
+ // intendedParent == nullptr is a special case where the
+ // intended parent is the document.
+ nsNodeInfoManager* nodeInfoManager =
+ intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
+ : mBuilder->GetNodeInfoManager();
+
+ *target =
+ CreateMathMLElement(name, attributes, nodeInfoManager, mBuilder);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opSetFormElement& aOperation) {
+ SetFormElement(*(aOperation.mContent), *(aOperation.mFormElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opAppendText& aOperation) {
+ nsIContent* parent = *aOperation.mParent;
+ char16_t* buffer = aOperation.mBuffer;
+ uint32_t length = aOperation.mLength;
+ return AppendText(buffer, length, parent, mBuilder);
+ }
+
+ nsresult operator()(const opFosterParentText& aOperation) {
+ nsIContent* stackParent = *aOperation.mStackParent;
+ char16_t* buffer = aOperation.mBuffer;
+ uint32_t length = aOperation.mLength;
+ nsIContent* table = *aOperation.mTable;
+ return FosterParentText(stackParent, buffer, length, table, mBuilder);
+ }
+
+ nsresult operator()(const opAppendComment& aOperation) {
+ nsIContent* parent = *aOperation.mParent;
+ char16_t* buffer = aOperation.mBuffer;
+ uint32_t length = aOperation.mLength;
+ return AppendComment(parent, buffer, length, mBuilder);
+ }
+
+ nsresult operator()(const opAppendCommentToDocument& aOperation) {
+ char16_t* buffer = aOperation.mBuffer;
+ int32_t length = aOperation.mLength;
+ return AppendCommentToDocument(buffer, length, mBuilder);
+ }
+
+ nsresult operator()(const opAppendDoctypeToDocument& aOperation) {
+ nsAtom* name = aOperation.mName;
+ nsHtml5TreeOperationStringPair* pair = aOperation.mStringPair;
+ nsString publicId;
+ nsString systemId;
+ pair->Get(publicId, systemId);
+ return AppendDoctypeToDocument(name, publicId, systemId, mBuilder);
+ }
+
+ nsresult operator()(const opGetDocumentFragmentForTemplate& aOperation) {
+ nsIContent* node = *(aOperation.mTemplate);
+ *(aOperation.mFragHandle) = GetDocumentFragmentForTemplate(node);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opGetFosterParent& aOperation) {
+ nsIContent* table = *(aOperation.mTable);
+ nsIContent* stackParent = *(aOperation.mStackParent);
+ nsIContent* fosterParent = GetFosterParent(table, stackParent);
+ *aOperation.mParentHandle = fosterParent;
+ return NS_OK;
+ }
+
+ nsresult operator()(const opMarkAsBroken& aOperation) {
+ return aOperation.mResult;
+ }
+
+ nsresult operator()(const opRunScript& aOperation) {
+ nsIContent* node = *(aOperation.mElement);
+ nsAHtml5TreeBuilderState* snapshot = aOperation.mBuilderState;
+ if (snapshot) {
+ mBuilder->InitializeDocWriteParserState(snapshot,
+ aOperation.mLineNumber);
+ }
+ *mScriptElement = node;
+ return NS_OK;
+ }
+
+ nsresult operator()(const opRunScriptAsyncDefer& aOperation) {
+ mBuilder->RunScript(*(aOperation.mElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opPreventScriptExecution& aOperation) {
+ PreventScriptExecution(*(aOperation.mElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opDoneAddingChildren& aOperation) {
+ nsIContent* node = *(aOperation.mElement);
+ node->DoneAddingChildren(node->HasParserNotified());
+ return NS_OK;
+ }
+
+ nsresult operator()(const opDoneCreatingElement& aOperation) {
+ DoneCreatingElement(*(aOperation.mElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opUpdateCharsetSource& aOperation) {
+ mBuilder->UpdateCharsetSource(aOperation.mCharsetSource);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opCharsetSwitchTo& aOperation) {
+ auto encoding = WrapNotNull(aOperation.mEncoding);
+ mBuilder->NeedsCharsetSwitchTo(encoding, aOperation.mCharsetSource,
+ (uint32_t)aOperation.mLineNumber);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opUpdateStyleSheet& aOperation) {
+ mBuilder->UpdateStyleSheet(*(aOperation.mElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opProcessOfflineManifest& aOperation) {
+ // TODO: remove this
+ return NS_OK;
+ }
+
+ nsresult operator()(const opMarkMalformedIfScript& aOperation) {
+ MarkMalformedIfScript(*(aOperation.mElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opStreamEnded& aOperation) {
+ *mStreamEnded = true;
+ return NS_OK;
+ }
+
+ nsresult operator()(const opSetStyleLineNumber& aOperation) {
+ nsIContent* node = *(aOperation.mContent);
+ if (auto* linkStyle = dom::LinkStyle::FromNode(*node)) {
+ linkStyle->SetLineNumber(aOperation.mLineNumber);
+ } else {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to style, but SVG wasn't disabled.");
+ }
+ return NS_OK;
+ }
+
+ nsresult operator()(
+ const opSetScriptLineAndColumnNumberAndFreeze& aOperation) {
+ nsIContent* node = *(aOperation.mContent);
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
+ if (sele) {
+ sele->SetScriptLineNumber(aOperation.mLineNumber);
+ sele->SetScriptColumnNumber(aOperation.mColumnNumber);
+ sele->FreezeExecutionAttrs(node->OwnerDoc());
+ } else {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ }
+ return NS_OK;
+ }
+
+ nsresult operator()(const opSvgLoad& aOperation) {
+ SvgLoad(*(aOperation.mElement));
+ return NS_OK;
+ }
+
+ nsresult operator()(const opMaybeComplainAboutCharset& aOperation) {
+ char* msgId = aOperation.mMsgId;
+ bool error = aOperation.mError;
+ int32_t lineNumber = aOperation.mLineNumber;
+ mBuilder->MaybeComplainAboutCharset(msgId, error, (uint32_t)lineNumber);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opMaybeComplainAboutDeepTree& aOperation) {
+ mBuilder->MaybeComplainAboutDeepTree((uint32_t)aOperation.mLineNumber);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opAddClass& aOperation) {
+ Element* element = (*(aOperation.mElement))->AsElement();
+ char16_t* str = aOperation.mClass;
+ nsDependentString depStr(str);
+ // See viewsource.css for the possible classes
+ nsAutoString klass;
+ element->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
+ if (!klass.IsEmpty()) {
+ klass.Append(' ');
+ klass.Append(depStr);
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
+ } else {
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
+ }
+ return NS_OK;
+ }
+
+ nsresult operator()(const opAddViewSourceHref& aOperation) {
+ Element* element = (*aOperation.mElement)->AsElement();
+ char16_t* buffer = aOperation.mBuffer;
+ int32_t length = aOperation.mLength;
+ nsDependentString relative(buffer, length);
+
+ Document* doc = mBuilder->GetDocument();
+
+ auto encoding = doc->GetDocumentCharacterSet();
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_NewURI(getter_AddRefs(uri), relative, encoding,
+ mBuilder->GetViewSourceBaseURI());
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+
+ // Reuse the fix for bug 467852
+ // URLs that execute script (e.g. "javascript:" URLs) should just be
+ // ignored. There's nothing reasonable we can do with them, and allowing
+ // them to execute in the context of the view-source window presents a
+ // security risk. Just return the empty string in this case.
+ bool openingExecutesScript = false;
+ rv = NS_URIChainHasFlags(uri,
+ nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT,
+ &openingExecutesScript);
+ if (NS_FAILED(rv) || openingExecutesScript) {
+ return NS_OK;
+ }
+
+ nsAutoCString viewSourceUrl;
+
+ // URLs that return data (e.g. "http:" URLs) should be prefixed with
+ // "view-source:". URLs that don't return data should just be returned
+ // undecorated.
+ if (!nsContentUtils::IsExternalProtocol(uri)) {
+ viewSourceUrl.AssignLiteral("view-source:");
+ }
+
+ nsAutoCString spec;
+ rv = uri->GetSpec(spec);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ viewSourceUrl.Append(spec);
+
+ nsAutoString utf16;
+ CopyUTF8toUTF16(viewSourceUrl, utf16);
+
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opAddViewSourceBase& aOperation) {
+ nsDependentString baseUrl(aOperation.mBuffer, aOperation.mLength);
+ mBuilder->AddBase(baseUrl);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opAddErrorType& aOperation) {
+ Element* element = (*(aOperation.mElement))->AsElement();
+ char* msgId = aOperation.mMsgId;
+ nsAtom* atom = aOperation.mName;
+ nsAtom* otherAtom = aOperation.mOther;
+ // See viewsource.css for the possible classes in addition to "error".
+ nsAutoString klass;
+ element->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
+ if (!klass.IsEmpty()) {
+ klass.AppendLiteral(" error");
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
+ } else {
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, u"error"_ns,
+ true);
+ }
+
+ nsresult rv;
+ nsAutoString message;
+ if (otherAtom) {
+ rv = nsContentUtils::FormatLocalizedString(
+ message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId,
+ nsDependentAtomString(atom), nsDependentAtomString(otherAtom));
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+ } else if (atom) {
+ rv = nsContentUtils::FormatLocalizedString(
+ message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId,
+ nsDependentAtomString(atom));
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+ } else {
+ rv = nsContentUtils::GetLocalizedString(
+ nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+ }
+
+ nsAutoString title;
+ element->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
+ if (!title.IsEmpty()) {
+ title.Append('\n');
+ title.Append(message);
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true);
+ } else {
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
+ }
+ return rv;
+ }
+
+ nsresult operator()(const opAddLineNumberId& aOperation) {
+ Element* element = (*(aOperation.mElement))->AsElement();
+ int32_t lineNumber = aOperation.mLineNumber;
+ nsAutoString val(u"line"_ns);
+ val.AppendInt(lineNumber);
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true);
+ return NS_OK;
+ }
+
+ nsresult operator()(const opStartLayout& aOperation) {
+ mBuilder->StartLayout(
+ mInterrupted); // this causes a notification flush anyway
+ return NS_OK;
+ }
+
+ nsresult operator()(const opEnableEncodingMenu& aOperation) {
+ Document* doc = mBuilder->GetDocument();
+ doc->EnableEncodingMenu();
+ return NS_OK;
+ }
+
+ nsresult operator()(const uninitialized& aOperation) {
+ MOZ_CRASH("uninitialized");
+ return NS_OK;
+ }
+ };
+
+ return mOperation.match(TreeOperationMatcher(aBuilder, aScriptElement,
+ aInterrupted, aStreamEnded));
+}
diff --git a/parser/html/nsHtml5TreeOperation.h b/parser/html/nsHtml5TreeOperation.h
new file mode 100644
index 0000000000..dd5d1e8c4a
--- /dev/null
+++ b/parser/html/nsHtml5TreeOperation.h
@@ -0,0 +1,637 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5TreeOperation_h
+#define nsHtml5TreeOperation_h
+
+#include "nsHtml5DocumentMode.h"
+#include "nsHtml5HtmlAttributes.h"
+#include "mozilla/dom/FromParser.h"
+#include "mozilla/NotNull.h"
+#include "mozilla/Variant.h"
+#include "nsCharsetSource.h"
+
+class nsIContent;
+class nsHtml5TreeOpExecutor;
+class nsHtml5DocumentBuilder;
+namespace mozilla {
+class Encoding;
+
+namespace dom {
+class Text;
+} // namespace dom
+} // namespace mozilla
+
+struct uninitialized {};
+
+// main HTML5 ops
+struct opDetach {
+ nsIContent** mElement;
+
+ explicit opDetach(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opAppend {
+ nsIContent** mChild;
+ nsIContent** mParent;
+ mozilla::dom::FromParser mFromNetwork;
+
+ explicit opAppend(nsIContentHandle* aChild, nsIContentHandle* aParent,
+ mozilla::dom::FromParser aFromNetwork)
+ : mFromNetwork(aFromNetwork) {
+ mChild = static_cast<nsIContent**>(aChild);
+ mParent = static_cast<nsIContent**>(aParent);
+ };
+};
+
+struct opAppendChildrenToNewParent {
+ nsIContent** mOldParent;
+ nsIContent** mNewParent;
+
+ explicit opAppendChildrenToNewParent(nsIContentHandle* aOldParent,
+ nsIContentHandle* aNewParent) {
+ mOldParent = static_cast<nsIContent**>(aOldParent);
+ mNewParent = static_cast<nsIContent**>(aNewParent);
+ };
+};
+
+struct opFosterParent {
+ nsIContent** mChild;
+ nsIContent** mStackParent;
+ nsIContent** mTable;
+
+ explicit opFosterParent(nsIContentHandle* aChild,
+ nsIContentHandle* aStackParent,
+ nsIContentHandle* aTable) {
+ mChild = static_cast<nsIContent**>(aChild);
+ mStackParent = static_cast<nsIContent**>(aStackParent);
+ mTable = static_cast<nsIContent**>(aTable);
+ };
+};
+
+struct opAppendToDocument {
+ nsIContent** mContent;
+
+ explicit opAppendToDocument(nsIContentHandle* aContent) {
+ mContent = static_cast<nsIContent**>(aContent);
+ };
+};
+
+struct opAddAttributes {
+ nsIContent** mElement;
+ nsHtml5HtmlAttributes* mAttributes;
+
+ explicit opAddAttributes(nsIContentHandle* aElement,
+ nsHtml5HtmlAttributes* aAttributes)
+ : mAttributes(aAttributes) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opCreateHTMLElement {
+ nsIContent** mContent;
+ nsAtom* mName;
+ nsHtml5HtmlAttributes* mAttributes;
+ mozilla::dom::HTMLContentCreatorFunction mCreator;
+ nsIContent** mIntendedParent;
+ mozilla::dom::FromParser mFromNetwork;
+
+ explicit opCreateHTMLElement(
+ nsIContentHandle* aContent, nsAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::HTMLContentCreatorFunction aCreator,
+ nsIContentHandle* aIntendedParent, mozilla::dom::FromParser mFromNetwork)
+ : mName(aName),
+ mAttributes(aAttributes),
+ mCreator(aCreator),
+ mFromNetwork(mFromNetwork) {
+ mContent = static_cast<nsIContent**>(aContent);
+ mIntendedParent = static_cast<nsIContent**>(aIntendedParent);
+ aName->AddRef();
+ if (mAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+ mAttributes = nullptr;
+ }
+ };
+};
+
+struct opCreateSVGElement {
+ nsIContent** mContent;
+ nsAtom* mName;
+ nsHtml5HtmlAttributes* mAttributes;
+ mozilla::dom::SVGContentCreatorFunction mCreator;
+ nsIContent** mIntendedParent;
+ mozilla::dom::FromParser mFromNetwork;
+
+ explicit opCreateSVGElement(nsIContentHandle* aContent, nsAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::SVGContentCreatorFunction aCreator,
+ nsIContentHandle* aIntendedParent,
+ mozilla::dom::FromParser mFromNetwork)
+ : mName(aName),
+ mAttributes(aAttributes),
+ mCreator(aCreator),
+ mFromNetwork(mFromNetwork) {
+ mContent = static_cast<nsIContent**>(aContent);
+ mIntendedParent = static_cast<nsIContent**>(aIntendedParent);
+ aName->AddRef();
+ if (mAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+ mAttributes = nullptr;
+ }
+ };
+};
+
+struct opCreateMathMLElement {
+ nsIContent** mContent;
+ nsAtom* mName;
+ nsHtml5HtmlAttributes* mAttributes;
+ nsIContent** mIntendedParent;
+
+ explicit opCreateMathMLElement(nsIContentHandle* aContent, nsAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ nsIContentHandle* aIntendedParent)
+ : mName(aName), mAttributes(aAttributes) {
+ mContent = static_cast<nsIContent**>(aContent);
+ mIntendedParent = static_cast<nsIContent**>(aIntendedParent);
+ aName->AddRef();
+ if (mAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
+ mAttributes = nullptr;
+ }
+ };
+};
+
+struct opSetFormElement {
+ nsIContent** mContent;
+ nsIContent** mFormElement;
+
+ explicit opSetFormElement(nsIContentHandle* aContent,
+ nsIContentHandle* aFormElement) {
+ mContent = static_cast<nsIContent**>(aContent);
+ mFormElement = static_cast<nsIContent**>(aFormElement);
+ };
+};
+
+struct opAppendText {
+ nsIContent** mParent;
+ char16_t* mBuffer;
+ int32_t mLength;
+
+ explicit opAppendText(nsIContentHandle* aParent, char16_t* aBuffer,
+ int32_t aLength)
+ : mBuffer(aBuffer), mLength(aLength) {
+ mParent = static_cast<nsIContent**>(aParent);
+ };
+};
+
+struct opFosterParentText {
+ nsIContent** mStackParent;
+ char16_t* mBuffer;
+ nsIContent** mTable;
+ int32_t mLength;
+
+ explicit opFosterParentText(nsIContentHandle* aStackParent, char16_t* aBuffer,
+ nsIContentHandle* aTable, int32_t aLength)
+ : mBuffer(aBuffer), mLength(aLength) {
+ mStackParent = static_cast<nsIContent**>(aStackParent);
+ mTable = static_cast<nsIContent**>(aTable);
+ };
+};
+
+struct opAppendComment {
+ nsIContent** mParent;
+ char16_t* mBuffer;
+ int32_t mLength;
+
+ explicit opAppendComment(nsIContentHandle* aParent, char16_t* aBuffer,
+ int32_t aLength)
+ : mBuffer(aBuffer), mLength(aLength) {
+ mParent = static_cast<nsIContent**>(aParent);
+ };
+};
+
+struct opAppendCommentToDocument {
+ char16_t* mBuffer;
+ int32_t mLength;
+
+ explicit opAppendCommentToDocument(char16_t* aBuffer, int32_t aLength)
+ : mBuffer(aBuffer), mLength(aLength){};
+};
+
+class nsHtml5TreeOperationStringPair {
+ private:
+ nsString mPublicId;
+ nsString mSystemId;
+
+ public:
+ nsHtml5TreeOperationStringPair(const nsAString& aPublicId,
+ const nsAString& aSystemId)
+ : mPublicId(aPublicId), mSystemId(aSystemId) {
+ MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair);
+ }
+
+ ~nsHtml5TreeOperationStringPair() {
+ MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair);
+ }
+
+ inline void Get(nsAString& aPublicId, nsAString& aSystemId) {
+ aPublicId.Assign(mPublicId);
+ aSystemId.Assign(mSystemId);
+ }
+};
+
+struct opAppendDoctypeToDocument {
+ nsAtom* mName;
+ nsHtml5TreeOperationStringPair* mStringPair;
+
+ explicit opAppendDoctypeToDocument(nsAtom* aName, const nsAString& aPublicId,
+ const nsAString& aSystemId) {
+ mName = aName;
+ aName->AddRef();
+ mStringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId);
+ }
+};
+
+struct opGetDocumentFragmentForTemplate {
+ nsIContent** mTemplate;
+ nsIContent** mFragHandle;
+
+ explicit opGetDocumentFragmentForTemplate(nsIContentHandle* aTemplate,
+ nsIContentHandle* aFragHandle) {
+ mTemplate = static_cast<nsIContent**>(aTemplate);
+ mFragHandle = static_cast<nsIContent**>(aFragHandle);
+ }
+};
+
+struct opGetFosterParent {
+ nsIContent** mTable;
+ nsIContent** mStackParent;
+ nsIContent** mParentHandle;
+
+ explicit opGetFosterParent(nsIContentHandle* aTable,
+ nsIContentHandle* aStackParent,
+ nsIContentHandle* aParentHandle) {
+ mTable = static_cast<nsIContent**>(aTable);
+ mStackParent = static_cast<nsIContent**>(aStackParent);
+ mParentHandle = static_cast<nsIContent**>(aParentHandle);
+ };
+};
+
+// Gecko-specific on-pop ops
+struct opMarkAsBroken {
+ nsresult mResult;
+
+ explicit opMarkAsBroken(nsresult aResult) : mResult(aResult){};
+};
+
+struct opRunScript {
+ nsIContent** mElement;
+ nsAHtml5TreeBuilderState* mBuilderState;
+ int32_t mLineNumber;
+
+ explicit opRunScript(nsIContentHandle* aElement,
+ nsAHtml5TreeBuilderState* aBuilderState)
+ : mBuilderState(aBuilderState), mLineNumber(0) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opRunScriptAsyncDefer {
+ nsIContent** mElement;
+
+ explicit opRunScriptAsyncDefer(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opPreventScriptExecution {
+ nsIContent** mElement;
+
+ explicit opPreventScriptExecution(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opDoneAddingChildren {
+ nsIContent** mElement;
+
+ explicit opDoneAddingChildren(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opDoneCreatingElement {
+ nsIContent** mElement;
+
+ explicit opDoneCreatingElement(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opUpdateCharsetSource {
+ nsCharsetSource mCharsetSource;
+
+ explicit opUpdateCharsetSource(nsCharsetSource aCharsetSource)
+ : mCharsetSource(aCharsetSource){};
+};
+
+struct opCharsetSwitchTo {
+ const mozilla::Encoding* mEncoding;
+ int32_t mCharsetSource;
+ int32_t mLineNumber;
+
+ explicit opCharsetSwitchTo(const mozilla::Encoding* aEncoding,
+ int32_t aCharsetSource, int32_t aLineNumber)
+ : mEncoding(aEncoding),
+ mCharsetSource(aCharsetSource),
+ mLineNumber(aLineNumber){};
+};
+
+struct opUpdateStyleSheet {
+ nsIContent** mElement;
+
+ explicit opUpdateStyleSheet(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opProcessOfflineManifest {
+ char16_t* mUrl;
+
+ explicit opProcessOfflineManifest(char16_t* aUrl) : mUrl(aUrl){};
+};
+
+struct opMarkMalformedIfScript {
+ nsIContent** mElement;
+
+ explicit opMarkMalformedIfScript(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ }
+};
+
+struct opStreamEnded {};
+
+struct opSetStyleLineNumber {
+ nsIContent** mContent;
+ int32_t mLineNumber;
+
+ explicit opSetStyleLineNumber(nsIContentHandle* aContent, int32_t aLineNumber)
+ : mLineNumber(aLineNumber) {
+ mContent = static_cast<nsIContent**>(aContent);
+ };
+};
+
+struct opSetScriptLineAndColumnNumberAndFreeze {
+ nsIContent** mContent;
+ int32_t mLineNumber;
+ int32_t mColumnNumber;
+
+ explicit opSetScriptLineAndColumnNumberAndFreeze(nsIContentHandle* aContent,
+ int32_t aLineNumber,
+ int32_t aColumnNumber)
+ : mLineNumber(aLineNumber), mColumnNumber(aColumnNumber) {
+ mContent = static_cast<nsIContent**>(aContent);
+ };
+};
+
+struct opSvgLoad {
+ nsIContent** mElement;
+
+ explicit opSvgLoad(nsIContentHandle* aElement) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opMaybeComplainAboutCharset {
+ char* mMsgId;
+ bool mError;
+ int32_t mLineNumber;
+
+ explicit opMaybeComplainAboutCharset(char* aMsgId, bool aError,
+ int32_t aLineNumber)
+ : mMsgId(aMsgId), mError(aError), mLineNumber(aLineNumber){};
+};
+
+struct opMaybeComplainAboutDeepTree {
+ int32_t mLineNumber;
+
+ explicit opMaybeComplainAboutDeepTree(int32_t aLineNumber)
+ : mLineNumber(aLineNumber){};
+};
+
+struct opAddClass {
+ nsIContent** mElement;
+ char16_t* mClass;
+
+ explicit opAddClass(nsIContentHandle* aElement, char16_t* aClass)
+ : mClass(aClass) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opAddViewSourceHref {
+ nsIContent** mElement;
+ char16_t* mBuffer;
+ int32_t mLength;
+
+ explicit opAddViewSourceHref(nsIContentHandle* aElement, char16_t* aBuffer,
+ int32_t aLength)
+ : mBuffer(aBuffer), mLength(aLength) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opAddViewSourceBase {
+ char16_t* mBuffer;
+ int32_t mLength;
+
+ explicit opAddViewSourceBase(char16_t* aBuffer, int32_t aLength)
+ : mBuffer(aBuffer), mLength(aLength){};
+};
+
+struct opAddErrorType {
+ nsIContent** mElement;
+ char* mMsgId;
+ nsAtom* mName;
+ nsAtom* mOther;
+
+ explicit opAddErrorType(nsIContentHandle* aElement, char* aMsgId,
+ nsAtom* aName = nullptr, nsAtom* aOther = nullptr)
+ : mMsgId(aMsgId), mName(aName), mOther(aOther) {
+ mElement = static_cast<nsIContent**>(aElement);
+ if (aName) {
+ aName->AddRef();
+ }
+ if (aOther) {
+ aOther->AddRef();
+ }
+ };
+};
+
+struct opAddLineNumberId {
+ nsIContent** mElement;
+ int32_t mLineNumber;
+
+ explicit opAddLineNumberId(nsIContentHandle* aElement, int32_t aLineNumber)
+ : mLineNumber(aLineNumber) {
+ mElement = static_cast<nsIContent**>(aElement);
+ };
+};
+
+struct opStartLayout {};
+
+struct opEnableEncodingMenu {};
+
+typedef mozilla::Variant<
+ uninitialized,
+ // main HTML5 ops
+ opAppend, opDetach, opAppendChildrenToNewParent, opFosterParent,
+ opAppendToDocument, opAddAttributes, nsHtml5DocumentMode,
+ opCreateHTMLElement, opCreateSVGElement, opCreateMathMLElement,
+ opSetFormElement, opAppendText, opFosterParentText, opAppendComment,
+ opAppendCommentToDocument, opAppendDoctypeToDocument,
+ opGetDocumentFragmentForTemplate, opGetFosterParent,
+ // Gecko-specific on-pop ops
+ opMarkAsBroken, opRunScript, opRunScriptAsyncDefer,
+ opPreventScriptExecution, opDoneAddingChildren, opDoneCreatingElement,
+ opUpdateCharsetSource, opCharsetSwitchTo, opUpdateStyleSheet,
+ opProcessOfflineManifest, opMarkMalformedIfScript, opStreamEnded,
+ opSetStyleLineNumber, opSetScriptLineAndColumnNumberAndFreeze, opSvgLoad,
+ opMaybeComplainAboutCharset, opMaybeComplainAboutDeepTree, opAddClass,
+ opAddViewSourceHref, opAddViewSourceBase, opAddErrorType, opAddLineNumberId,
+ opStartLayout, opEnableEncodingMenu>
+ treeOperation;
+
+class nsHtml5TreeOperation final {
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+ using Encoding = mozilla::Encoding;
+
+ public:
+ static nsresult AppendTextToTextNode(const char16_t* aBuffer,
+ uint32_t aLength,
+ mozilla::dom::Text* aTextNode,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AppendText(const char16_t* aBuffer, uint32_t aLength,
+ nsIContent* aParent,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult Append(nsIContent* aNode, nsIContent* aParent,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult Append(nsIContent* aNode, nsIContent* aParent,
+ mozilla::dom::FromParser aFromParser,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AppendToDocument(nsIContent* aNode,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static void Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AppendChildrenToNewParent(nsIContent* aNode,
+ nsIContent* aParent,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult FosterParent(nsIContent* aNode, nsIContent* aParent,
+ nsIContent* aTable,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AddAttributes(nsIContent* aNode,
+ nsHtml5HtmlAttributes* aAttributes,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static void SetHTMLElementAttributes(mozilla::dom::Element* aElement,
+ nsAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes);
+
+ static nsIContent* CreateHTMLElement(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder,
+ mozilla::dom::HTMLContentCreatorFunction aCreator);
+
+ static nsIContent* CreateSVGElement(
+ nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
+ mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder,
+ mozilla::dom::SVGContentCreatorFunction aCreator);
+
+ static nsIContent* CreateMathMLElement(nsAtom* aName,
+ nsHtml5HtmlAttributes* aAttributes,
+ nsNodeInfoManager* aNodeInfoManager,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
+
+ static nsresult AppendIsindexPrompt(nsIContent* parent,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult FosterParentText(nsIContent* aStackParent, char16_t* aBuffer,
+ uint32_t aLength, nsIContent* aTable,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AppendComment(nsIContent* aParent, char16_t* aBuffer,
+ int32_t aLength,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AppendCommentToDocument(char16_t* aBuffer, int32_t aLength,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsresult AppendDoctypeToDocument(nsAtom* aName,
+ const nsAString& aPublicId,
+ const nsAString& aSystemId,
+ nsHtml5DocumentBuilder* aBuilder);
+
+ static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode);
+
+ static nsIContent* GetFosterParent(nsIContent* aTable,
+ nsIContent* aStackParent);
+
+ static void PreventScriptExecution(nsIContent* aNode);
+
+ static void DoneAddingChildren(nsIContent* aNode);
+
+ static void DoneCreatingElement(nsIContent* aNode);
+
+ static void SvgLoad(nsIContent* aNode);
+
+ static void MarkMalformedIfScript(nsIContent* aNode);
+
+ nsHtml5TreeOperation();
+
+ ~nsHtml5TreeOperation();
+
+ inline void Init(const treeOperation& aOperation) {
+ NS_ASSERTION(mOperation.is<uninitialized>(),
+ "Op code must be uninitialized when initializing.");
+ mOperation = aOperation;
+ }
+
+ inline bool IsRunScript() { return mOperation.is<opRunScript>(); }
+
+ inline bool IsMarkAsBroken() { return mOperation.is<opMarkAsBroken>(); }
+
+ inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine) {
+ NS_ASSERTION(
+ IsRunScript(),
+ "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
+ MOZ_ASSERT(aSnapshot, "Initialized tree op with null snapshot.");
+ opRunScript data = mOperation.as<opRunScript>();
+ data.mBuilderState = aSnapshot;
+ data.mLineNumber = aLine;
+ mOperation = mozilla::AsVariant(data);
+ }
+
+ nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent** aScriptElement,
+ bool* aInterrupted, bool* aStreamEnded);
+
+ private:
+ nsHtml5TreeOperation(const nsHtml5TreeOperation&) = delete;
+ nsHtml5TreeOperation& operator=(const nsHtml5TreeOperation&) = delete;
+
+ treeOperation mOperation;
+};
+
+#endif // nsHtml5TreeOperation_h
diff --git a/parser/html/nsHtml5UTF16Buffer.cpp b/parser/html/nsHtml5UTF16Buffer.cpp
new file mode 100644
index 0000000000..146f06ac69
--- /dev/null
+++ b/parser/html/nsHtml5UTF16Buffer.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit UTF16Buffer.java instead and regenerate.
+ */
+
+#define nsHtml5UTF16Buffer_cpp__
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5ElementName.h"
+#include "nsHtml5Tokenizer.h"
+#include "nsHtml5TreeBuilder.h"
+#include "nsHtml5StackNode.h"
+#include "nsHtml5StateSnapshot.h"
+#include "nsHtml5Portability.h"
+
+#include "nsHtml5UTF16Buffer.h"
+
+int32_t nsHtml5UTF16Buffer::getStart() { return start; }
+
+void nsHtml5UTF16Buffer::setStart(int32_t start) { this->start = start; }
+
+char16_t* nsHtml5UTF16Buffer::getBuffer() { return buffer; }
+
+int32_t nsHtml5UTF16Buffer::getEnd() { return end; }
+
+bool nsHtml5UTF16Buffer::hasMore() { return start < end; }
+
+int32_t nsHtml5UTF16Buffer::getLength() { return end - start; }
+
+void nsHtml5UTF16Buffer::adjust(bool lastWasCR) {
+ if (lastWasCR && buffer[start] == '\n') {
+ start++;
+ }
+}
+
+void nsHtml5UTF16Buffer::setEnd(int32_t end) { this->end = end; }
+
+void nsHtml5UTF16Buffer::initializeStatics() {}
+
+void nsHtml5UTF16Buffer::releaseStatics() {}
+
+#include "nsHtml5UTF16BufferCppSupplement.h"
diff --git a/parser/html/nsHtml5UTF16Buffer.h b/parser/html/nsHtml5UTF16Buffer.h
new file mode 100644
index 0000000000..e5867df3f9
--- /dev/null
+++ b/parser/html/nsHtml5UTF16Buffer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2008-2010 Mozilla Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
+ * Please edit UTF16Buffer.java instead and regenerate.
+ */
+
+#ifndef nsHtml5UTF16Buffer_h
+#define nsHtml5UTF16Buffer_h
+
+#include "nsAtom.h"
+#include "nsHtml5AtomTable.h"
+#include "nsHtml5String.h"
+#include "nsNameSpaceManager.h"
+#include "nsIContent.h"
+#include "nsTraceRefcnt.h"
+#include "jArray.h"
+#include "nsHtml5ArrayCopy.h"
+#include "nsAHtml5TreeBuilderState.h"
+#include "nsGkAtoms.h"
+#include "nsHtml5ByteReadable.h"
+#include "nsHtml5Macros.h"
+#include "nsIContentHandle.h"
+#include "nsHtml5Portability.h"
+#include "nsHtml5ContentCreatorFunction.h"
+
+class nsHtml5StreamParser;
+
+class nsHtml5AttributeName;
+class nsHtml5ElementName;
+class nsHtml5Tokenizer;
+class nsHtml5TreeBuilder;
+class nsHtml5StateSnapshot;
+class nsHtml5Portability;
+
+class nsHtml5UTF16Buffer {
+ private:
+ char16_t* buffer;
+ int32_t start;
+ int32_t end;
+
+ public:
+ int32_t getStart();
+ void setStart(int32_t start);
+ char16_t* getBuffer();
+ int32_t getEnd();
+ bool hasMore();
+ int32_t getLength();
+ void adjust(bool lastWasCR);
+ void setEnd(int32_t end);
+ static void initializeStatics();
+ static void releaseStatics();
+
+#include "nsHtml5UTF16BufferHSupplement.h"
+};
+
+#endif
diff --git a/parser/html/nsHtml5UTF16BufferCppSupplement.h b/parser/html/nsHtml5UTF16BufferCppSupplement.h
new file mode 100644
index 0000000000..79f2658a45
--- /dev/null
+++ b/parser/html/nsHtml5UTF16BufferCppSupplement.h
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+nsHtml5UTF16Buffer::nsHtml5UTF16Buffer(char16_t* aBuffer, int32_t aEnd)
+ : buffer(aBuffer), start(0), end(aEnd) {
+ MOZ_COUNT_CTOR(nsHtml5UTF16Buffer);
+}
+
+nsHtml5UTF16Buffer::~nsHtml5UTF16Buffer() {
+ MOZ_COUNT_DTOR(nsHtml5UTF16Buffer);
+}
+
+void nsHtml5UTF16Buffer::DeleteBuffer() { delete[] buffer; }
+
+void nsHtml5UTF16Buffer::Swap(nsHtml5UTF16Buffer* aOther) {
+ char16_t* tempBuffer = buffer;
+ int32_t tempStart = start;
+ int32_t tempEnd = end;
+ buffer = aOther->buffer;
+ start = aOther->start;
+ end = aOther->end;
+ aOther->buffer = tempBuffer;
+ aOther->start = tempStart;
+ aOther->end = tempEnd;
+}
diff --git a/parser/html/nsHtml5UTF16BufferHSupplement.h b/parser/html/nsHtml5UTF16BufferHSupplement.h
new file mode 100644
index 0000000000..ef7b662cbe
--- /dev/null
+++ b/parser/html/nsHtml5UTF16BufferHSupplement.h
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+protected:
+nsHtml5UTF16Buffer(char16_t* aBuffer, int32_t aEnd);
+~nsHtml5UTF16Buffer();
+
+/**
+ * For working around the privacy of |buffer| in the generated code.
+ */
+void DeleteBuffer();
+
+/**
+ * For working around the privacy of |buffer| in the generated code.
+ */
+void Swap(nsHtml5UTF16Buffer* aOther);
diff --git a/parser/html/nsHtml5ViewSourceUtils.cpp b/parser/html/nsHtml5ViewSourceUtils.cpp
new file mode 100644
index 0000000000..3fb46e8bd2
--- /dev/null
+++ b/parser/html/nsHtml5ViewSourceUtils.cpp
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHtml5ViewSourceUtils.h"
+#include "mozilla/Preferences.h"
+#include "nsHtml5AttributeName.h"
+#include "nsHtml5String.h"
+#include "mozilla/StaticPrefs_view_source.h"
+
+// static
+nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewBodyAttributes() {
+ nsHtml5HtmlAttributes* bodyAttrs = new nsHtml5HtmlAttributes(0);
+ nsHtml5String id = nsHtml5Portability::newStringFromLiteral("viewsource");
+ bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, id, -1);
+
+ nsString klass;
+ if (mozilla::StaticPrefs::view_source_wrap_long_lines()) {
+ klass.AppendLiteral(u"wrap ");
+ }
+ if (mozilla::StaticPrefs::view_source_syntax_highlight()) {
+ klass.AppendLiteral(u"highlight");
+ }
+ if (!klass.IsEmpty()) {
+ bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_CLASS,
+ nsHtml5String::FromString(klass), -1);
+ }
+
+ int32_t tabSize = mozilla::StaticPrefs::view_source_tab_size();
+ if (tabSize > 0) {
+ nsString style;
+ style.AssignLiteral("tab-size: ");
+ style.AppendInt(tabSize);
+ bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_STYLE,
+ nsHtml5String::FromString(style), -1);
+ }
+
+ return bodyAttrs;
+}
+
+// static
+nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewLinkAttributes() {
+ nsHtml5HtmlAttributes* linkAttrs = new nsHtml5HtmlAttributes(0);
+ nsHtml5String rel = nsHtml5Portability::newStringFromLiteral("stylesheet");
+ linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_REL, rel, -1);
+ nsHtml5String type = nsHtml5Portability::newStringFromLiteral("text/css");
+ linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TYPE, type, -1);
+ nsHtml5String href = nsHtml5Portability::newStringFromLiteral(
+ "resource://content-accessible/viewsource.css");
+ linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1);
+ return linkAttrs;
+}
+
+// static
+nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewMetaViewportAttributes() {
+ nsHtml5HtmlAttributes* metaVpAttrs = new nsHtml5HtmlAttributes(0);
+ nsHtml5String name = nsHtml5Portability::newStringFromLiteral("viewport");
+ metaVpAttrs->addAttribute(nsHtml5AttributeName::ATTR_NAME, name, -1);
+ nsHtml5String content =
+ nsHtml5Portability::newStringFromLiteral("width=device-width");
+ metaVpAttrs->addAttribute(nsHtml5AttributeName::ATTR_CONTENT, content, -1);
+ return metaVpAttrs;
+}
diff --git a/parser/html/nsHtml5ViewSourceUtils.h b/parser/html/nsHtml5ViewSourceUtils.h
new file mode 100644
index 0000000000..e5ba30f8d5
--- /dev/null
+++ b/parser/html/nsHtml5ViewSourceUtils.h
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHtml5ViewSourceUtils_h
+#define nsHtml5ViewSourceUtils_h
+
+#include "nsHtml5HtmlAttributes.h"
+
+class nsHtml5ViewSourceUtils {
+ public:
+ static nsHtml5HtmlAttributes* NewBodyAttributes();
+ static nsHtml5HtmlAttributes* NewLinkAttributes();
+ static nsHtml5HtmlAttributes* NewMetaViewportAttributes();
+};
+
+#endif // nsHtml5ViewSourceUtils_h
diff --git a/parser/html/nsIContentHandle.h b/parser/html/nsIContentHandle.h
new file mode 100644
index 0000000000..b1cd6475f8
--- /dev/null
+++ b/parser/html/nsIContentHandle.h
@@ -0,0 +1,5 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+typedef void nsIContentHandle;
diff --git a/parser/html/nsIParserUtils.idl b/parser/html/nsIParserUtils.idl
new file mode 100644
index 0000000000..a8027a83fb
--- /dev/null
+++ b/parser/html/nsIParserUtils.idl
@@ -0,0 +1,141 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIURI;
+
+webidl DocumentFragment;
+webidl Element;
+
+/**
+ * Non-Web HTML parser functionality to Firefox extensions and XULRunner apps.
+ * Don't use this from within Gecko--use nsContentUtils, nsTreeSanitizer, etc.
+ * directly instead.
+ */
+[builtinclass, scriptable, uuid(a1101145-0025-411e-8873-fdf57bf28128)]
+interface nsIParserUtils : nsISupports
+{
+ /**
+ * Flag for sanitizer: Allow comment nodes.
+ */
+ const unsigned long SanitizerAllowComments = (1 << 0);
+
+ /**
+ * Flag for sanitizer: Allow <style> and style="" (with contents sanitized
+ * in case of -moz-binding). Note! If -moz-binding is absent, properties
+ * that might be XSS risks in other Web engines are preserved!
+ */
+ const unsigned long SanitizerAllowStyle = (1 << 1);
+
+ /**
+ * Flag for sanitizer: Only allow cid: URLs for embedded content.
+ *
+ * At present, sanitizing CSS backgrounds, etc., is not supported, so setting
+ * this together with SanitizerAllowStyle doesn't make sense.
+ *
+ * At present, sanitizing CSS syntax in SVG presentational attributes is not
+ * supported, so this option flattens out SVG.
+ */
+ const unsigned long SanitizerCidEmbedsOnly = (1 << 2);
+
+ /**
+ * Flag for sanitizer: Drop non-CSS presentational HTML elements and
+ * attributes, such as <font>, <center> and bgcolor="".
+ */
+ const unsigned long SanitizerDropNonCSSPresentation = (1 << 3);
+
+ /**
+ * Flag for sanitizer: Drop forms and form controls (excluding
+ * fieldset/legend).
+ */
+ const unsigned long SanitizerDropForms = (1 << 4);
+
+ /**
+ * Flag for sanitizer: Drop <img>, <video>, <audio> and <source> and flatten
+ * out SVG.
+ */
+ const unsigned long SanitizerDropMedia = (1 << 5);
+
+ /**
+ * Flag for sanitizer: Log messages to the console for everything that gets
+ * sanitized
+ */
+ const unsigned long SanitizerLogRemovals = (1 << 6);
+
+ /**
+ * Parses a string into an HTML document, sanitizes the document and
+ * returns the result serialized to a string.
+ *
+ * The sanitizer is designed to protect against XSS when sanitized content
+ * is inserted into a different-origin context without an iframe-equivalent
+ * sandboxing mechanism.
+ *
+ * By default, the sanitizer doesn't try to avoid leaking information that
+ * the content was viewed to third parties. That is, by default, e.g.
+ * <img src> pointing to an HTTP server potentially controlled by a third
+ * party is not removed. To avoid ambient information leakage upon loading
+ * the sanitized content, use the SanitizerInternalEmbedsOnly flag. In that
+ * case, <a href> links (and similar) to other content are preserved, so an
+ * explicit user action (following a link) after the content has been loaded
+ * can still leak information.
+ *
+ * By default, non-dangerous non-CSS presentational HTML elements and
+ * attributes or forms are not removed. To remove these, use
+ * SanitizerDropNonCSSPresentation and/or SanitizerDropForms.
+ *
+ * By default, comments and CSS is removed. To preserve comments, use
+ * SanitizerAllowComments. To preserve <style> and style="", use
+ * SanitizerAllowStyle. -moz-binding is removed from <style> and style="" if
+ * present. In this case, properties that Gecko doesn't recognize can get
+ * removed as a side effect. Note! If -moz-binding is not present, <style>
+ * and style="" and SanitizerAllowStyle is specified, the sanitized content
+ * may still be XSS dangerous if loaded into a non-Gecko Web engine!
+ *
+ * @param src the HTML source to parse (C++ callers are allowed but not
+ * required to use the same string for the return value.)
+ * @param flags sanitization option flags defined above
+ */
+ AString sanitize(in AString src, in unsigned long flags);
+
+ /**
+ * Removes conditional CSS (@media / etc) from the input string.
+ */
+ AString removeConditionalCSS(in AString src);
+
+ /**
+ * Convert HTML to plain text.
+ *
+ * @param src the HTML source to parse (C++ callers are allowed but not
+ * required to use the same string for the return value.)
+ * @param flags conversion option flags defined in nsIDocumentEncoder
+ * @param wrapCol number of characters per line; 0 for no auto-wrapping
+ */
+ AString convertToPlainText(in AString src,
+ in unsigned long flags,
+ in unsigned long wrapCol);
+
+ /**
+ * Parses markup into a sanitized document fragment.
+ *
+ * @param fragment the input markup
+ * @param flags sanitization option flags defined above
+ * @param isXML true if |fragment| is XML and false if HTML
+ * @param baseURI the base URL for this fragment
+ * @param element the context node for the fragment parsing algorithm
+ */
+ DocumentFragment parseFragment(in AString fragment,
+ in unsigned long flags,
+ in boolean isXML,
+ in nsIURI baseURI,
+ in Element element);
+
+};
+
+%{ C++
+#define NS_PARSERUTILS_CONTRACTID \
+ "@mozilla.org/parserutils;1"
+#define NS_PARSERUTILS_CID \
+{ 0xaf7b24cb, 0x893f, 0x41bb, { 0x96, 0x1f, 0x5a, 0x69, 0x38, 0x8e, 0x27, 0xc3 } }
+%}
diff --git a/parser/html/nsParserUtils.cpp b/parser/html/nsParserUtils.cpp
new file mode 100644
index 0000000000..74b86febe8
--- /dev/null
+++ b/parser/html/nsParserUtils.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsParserUtils.h"
+#include "mozilla/NullPrincipal.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/dom/DocumentFragment.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ScriptLoader.h"
+#include "nsAttrName.h"
+#include "nsCOMPtr.h"
+#include "nsContentCID.h"
+#include "nsContentUtils.h"
+#include "nsEscape.h"
+#include "nsHTMLParts.h"
+#include "nsHtml5Module.h"
+#include "nsIContent.h"
+#include "nsIContentSink.h"
+#include "nsIDTD.h"
+#include "mozilla/dom/Document.h"
+#include "nsIDocumentEncoder.h"
+#include "nsIFragmentContentSink.h"
+#include "nsIParser.h"
+#include "nsNetCID.h"
+#include "nsNetUtil.h"
+#include "nsString.h"
+#include "nsTreeSanitizer.h"
+#include "nsXPCOM.h"
+
+#define XHTML_DIV_TAG u"div xmlns=\"http://www.w3.org/1999/xhtml\""
+
+using namespace mozilla::dom;
+
+NS_IMPL_ISUPPORTS(nsParserUtils, nsIParserUtils)
+
+NS_IMETHODIMP
+nsParserUtils::ConvertToPlainText(const nsAString& aFromStr, uint32_t aFlags,
+ uint32_t aWrapCol, nsAString& aToStr) {
+ return nsContentUtils::ConvertToPlainText(aFromStr, aToStr, aFlags, aWrapCol);
+}
+
+template <typename Callable>
+static nsresult SanitizeWith(const nsAString& aInput, nsAString& aOutput,
+ Callable aDoSanitize) {
+ RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr);
+ if (!document) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv = nsContentUtils::ParseDocumentHTML(aInput, document, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aDoSanitize(document.get());
+
+ nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/html");
+ encoder->NativeInit(document, u"text/html"_ns,
+ nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration |
+ nsIDocumentEncoder::OutputNoScriptContent |
+ nsIDocumentEncoder::OutputEncodeBasicEntities |
+ nsIDocumentEncoder::OutputLFLineBreak |
+ nsIDocumentEncoder::OutputRaw);
+ return encoder->EncodeToString(aOutput);
+}
+
+NS_IMETHODIMP
+nsParserUtils::Sanitize(const nsAString& aFromStr, uint32_t aFlags,
+ nsAString& aToStr) {
+ return SanitizeWith(aFromStr, aToStr, [&](Document* aDocument) {
+ nsTreeSanitizer sanitizer(aFlags);
+ sanitizer.Sanitize(aDocument);
+ });
+}
+
+NS_IMETHODIMP
+nsParserUtils::RemoveConditionalCSS(const nsAString& aFromStr,
+ nsAString& aToStr) {
+ return SanitizeWith(aFromStr, aToStr, [](Document* aDocument) {
+ nsTreeSanitizer::RemoveConditionalCSSFromSubtree(aDocument);
+ });
+}
+
+NS_IMETHODIMP
+nsParserUtils::ParseFragment(const nsAString& aFragment, uint32_t aFlags,
+ bool aIsXML, nsIURI* aBaseURI,
+ Element* aContextElement,
+ DocumentFragment** aReturn) {
+ NS_ENSURE_ARG(aContextElement);
+ *aReturn = nullptr;
+
+ RefPtr<Document> document = aContextElement->OwnerDoc();
+
+ nsAutoScriptBlockerSuppressNodeRemoved autoBlocker;
+
+ // stop scripts
+ RefPtr<ScriptLoader> loader = document->ScriptLoader();
+ bool scripts_enabled = loader->GetEnabled();
+ if (scripts_enabled) {
+ loader->SetEnabled(false);
+ }
+
+ // Wrap things in a div or body for parsing, but it won't show up in
+ // the fragment.
+ nsresult rv = NS_OK;
+ AutoTArray<nsString, 2> tagStack;
+ RefPtr<DocumentFragment> fragment;
+ if (aIsXML) {
+ // XHTML
+ tagStack.AppendElement(nsLiteralString(XHTML_DIV_TAG));
+ rv = nsContentUtils::ParseFragmentXML(aFragment, document, tagStack, true,
+ aFlags, getter_AddRefs(fragment));
+ } else {
+ fragment = new (document->NodeInfoManager())
+ DocumentFragment(document->NodeInfoManager());
+ rv = nsContentUtils::ParseFragmentHTML(aFragment, fragment, nsGkAtoms::body,
+ kNameSpaceID_XHTML, false, true,
+ aFlags);
+ }
+
+ if (scripts_enabled) {
+ loader->SetEnabled(true);
+ }
+
+ fragment.forget(aReturn);
+ return rv;
+}
diff --git a/parser/html/nsParserUtils.h b/parser/html/nsParserUtils.h
new file mode 100644
index 0000000000..cd92d6add9
--- /dev/null
+++ b/parser/html/nsParserUtils.h
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsParserUtils_h
+#define nsParserUtils_h
+
+#include "nsIParserUtils.h"
+#include "mozilla/Attributes.h"
+
+class nsParserUtils final : public nsIParserUtils {
+ ~nsParserUtils() {}
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPARSERUTILS
+};
+
+#endif // nsParserUtils_h
diff --git a/parser/htmlparser/CNavDTD.cpp b/parser/htmlparser/CNavDTD.cpp
new file mode 100644
index 0000000000..d18aacfcb2
--- /dev/null
+++ b/parser/htmlparser/CNavDTD.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.h"
+#include "nsISupportsImpl.h"
+#include "nsIParser.h"
+#include "CNavDTD.h"
+#include "nsIHTMLContentSink.h"
+
+NS_IMPL_ISUPPORTS(CNavDTD, nsIDTD);
+
+CNavDTD::CNavDTD() {}
+
+CNavDTD::~CNavDTD() {}
+
+NS_IMETHODIMP
+CNavDTD::BuildModel(nsIContentSink* aSink) {
+ // NB: It is important to throw STOPPARSING if the sink is the wrong type in
+ // order to make sure nsParser cleans up properly after itself.
+ nsCOMPtr<nsIHTMLContentSink> sink = do_QueryInterface(aSink);
+ if (!sink) {
+ return NS_ERROR_HTMLPARSER_STOPPARSING;
+ }
+
+ nsresult rv = sink->OpenContainer(nsIHTMLContentSink::eHTML);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = sink->OpenContainer(nsIHTMLContentSink::eBody);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = sink->CloseContainer(nsIHTMLContentSink::eBody);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ rv = sink->CloseContainer(nsIHTMLContentSink::eHTML);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+ return NS_OK;
+}
+
+void CNavDTD::DidBuildModel() {}
+
+NS_IMETHODIMP_(void)
+CNavDTD::Terminate() {}
diff --git a/parser/htmlparser/CNavDTD.h b/parser/htmlparser/CNavDTD.h
new file mode 100644
index 0000000000..6b4c2511a9
--- /dev/null
+++ b/parser/htmlparser/CNavDTD.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef NS_NAVHTMLDTD__
+#define NS_NAVHTMLDTD__
+
+#include "nsIDTD.h"
+#include "nsISupports.h"
+#include "nsCOMPtr.h"
+
+#ifdef _MSC_VER
+# pragma warning(disable : 4275)
+#endif
+
+class CNavDTD : public nsIDTD {
+#ifdef _MSC_VER
+# pragma warning(default : 4275)
+#endif
+
+ virtual ~CNavDTD();
+
+ public:
+ CNavDTD();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDTD
+};
+
+#endif
diff --git a/parser/htmlparser/CParserContext.cpp b/parser/htmlparser/CParserContext.cpp
new file mode 100644
index 0000000000..d57c9855cc
--- /dev/null
+++ b/parser/htmlparser/CParserContext.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsAtom.h"
+#include "CParserContext.h"
+#include "prenv.h"
+#include "nsIHTMLContentSink.h"
+#include "nsMimeTypes.h"
+
+CParserContext::CParserContext(nsIURI* aURI, eParserCommands aCommand)
+ : mScanner(aURI),
+ mDTDMode(eDTDMode_autodetect),
+ mDocType(eUnknown),
+ mStreamListenerState(eNone),
+ mContextType(eCTURL),
+ mParserCommand(aCommand),
+ mMultipart(true),
+ mCopyUnused(false) {
+ MOZ_COUNT_CTOR(CParserContext);
+}
+
+CParserContext::CParserContext(const nsAString& aBuffer,
+ eParserCommands aCommand, bool aLastBuffer)
+ : mScanner(aBuffer, !aLastBuffer),
+ mMimeType("application/xml"_ns),
+ mDTDMode(eDTDMode_full_standards),
+ mDocType(eXML),
+ mStreamListenerState(aLastBuffer ? eOnStop : eOnDataAvail),
+ mContextType(eCTString),
+ mParserCommand(aCommand),
+ mMultipart(!aLastBuffer),
+ mCopyUnused(aLastBuffer) {
+ MOZ_COUNT_CTOR(CParserContext);
+}
+
+CParserContext::~CParserContext() {
+ // It's ok to simply ingore the PrevContext.
+ MOZ_COUNT_DTOR(CParserContext);
+}
+
+void CParserContext::SetMimeType(const nsACString& aMimeType) {
+ mMimeType.Assign(aMimeType);
+
+ mDocType = eUnknown;
+
+ if (mMimeType.EqualsLiteral(TEXT_HTML))
+ mDocType = eHTML_Strict;
+ else if (mMimeType.EqualsLiteral(TEXT_XML) ||
+ mMimeType.EqualsLiteral(APPLICATION_XML) ||
+ mMimeType.EqualsLiteral(APPLICATION_XHTML_XML) ||
+ mMimeType.EqualsLiteral(IMAGE_SVG_XML) ||
+ mMimeType.EqualsLiteral(APPLICATION_MATHML_XML) ||
+ mMimeType.EqualsLiteral(APPLICATION_RDF_XML) ||
+ mMimeType.EqualsLiteral(APPLICATION_WAPXHTML_XML) ||
+ mMimeType.EqualsLiteral(TEXT_RDF))
+ mDocType = eXML;
+}
diff --git a/parser/htmlparser/CParserContext.h b/parser/htmlparser/CParserContext.h
new file mode 100644
index 0000000000..b32436795b
--- /dev/null
+++ b/parser/htmlparser/CParserContext.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ */
+
+#ifndef __CParserContext
+#define __CParserContext
+
+#include "mozilla/UniquePtr.h"
+#include "nsIParser.h"
+#include "nsIDTD.h"
+#include "nsIRequest.h"
+#include "nsScanner.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+
+class nsITokenizer;
+
+/**
+ * Note that the parser is given FULL access to all
+ * data in a parsercontext. Hey, that what it's for!
+ */
+
+class CParserContext {
+ public:
+ enum eContextType { eCTURL, eCTString };
+
+ CParserContext(nsIURI* aURI, eParserCommands aCommand);
+ CParserContext(const nsAString& aBuffer, eParserCommands aCommand,
+ bool aLastBuffer);
+
+ ~CParserContext();
+
+ void SetMimeType(const nsACString& aMimeType);
+
+ nsCOMPtr<nsIRequest>
+ mRequest; // provided by necko to differnciate different input streams
+ // why is mRequest strongly referenced? see bug 102376.
+ nsScanner mScanner;
+
+ nsCString mMimeType;
+ nsDTDMode mDTDMode;
+
+ eParserDocType mDocType;
+ eStreamState mStreamListenerState;
+ eContextType mContextType;
+ eAutoDetectResult mAutoDetectStatus = eUnknownDetect;
+ eParserCommands mParserCommand;
+
+ bool mMultipart;
+ bool mCopyUnused;
+};
+
+#endif
diff --git a/parser/htmlparser/moz.build b/parser/htmlparser/moz.build
new file mode 100644
index 0000000000..ceac572399
--- /dev/null
+++ b/parser/htmlparser/moz.build
@@ -0,0 +1,52 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "XML")
+
+MOCHITEST_MANIFESTS += ["tests/mochitest/mochitest.ini"]
+BROWSER_CHROME_MANIFESTS += ["tests/mochitest/browser.ini"]
+
+XPIDL_SOURCES += [
+ "nsIExpatSink.idl",
+]
+
+XPIDL_MODULE = "htmlparser"
+
+EXPORTS += [
+ "nsElementTable.h",
+ "nsHTMLTagList.h",
+ "nsHTMLTags.h",
+ "nsIContentSink.h",
+ "nsIDTD.h",
+ "nsIFragmentContentSink.h",
+ "nsIHTMLContentSink.h",
+ "nsIParser.h",
+ "nsParserBase.h",
+ "nsParserConstants.h",
+ "nsRLBoxExpatDriver.h",
+ "nsScannerString.h",
+]
+
+UNIFIED_SOURCES += [
+ "CNavDTD.cpp",
+ "CParserContext.cpp",
+ "nsElementTable.cpp",
+ "nsExpatDriver.cpp",
+ "nsHTMLTags.cpp",
+ "nsParser.cpp",
+ "nsParserMsgUtils.cpp",
+ "nsScanner.cpp",
+ "nsScannerString.cpp",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul"
+
+LOCAL_INCLUDES += [
+ "!/security/rlbox",
+]
diff --git a/parser/htmlparser/nsElementTable.cpp b/parser/htmlparser/nsElementTable.cpp
new file mode 100644
index 0000000000..e6bf6b8dae
--- /dev/null
+++ b/parser/htmlparser/nsElementTable.cpp
@@ -0,0 +1,205 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsElementTable.h"
+
+struct HTMLElement {
+#ifdef DEBUG
+ nsHTMLTag mTagID;
+#endif
+ bool mIsBlock;
+ bool mIsContainer;
+};
+
+#ifdef DEBUG
+# define ELEM(tag, block, container) {eHTMLTag_##tag, block, container},
+#else
+# define ELEM(tag, block, container) {block, container},
+#endif
+
+#define ____ false // This makes the table easier to read.
+
+// Note that the mIsBlock field disagrees with
+// https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements for
+// the following elements: center, details, dialog, dir, dt, figcaption,
+// listing, menu, multicol, noscript, output, summary, tfoot, video.
+//
+// mrbkap thinks that the field values were pulled from the old HTML4 DTD and
+// then got modified in mostly random ways to make the old parser's behavior
+// compatible with the web. So it might make sense to change the mIsBlock
+// values for the abovementioned tags at some point.
+//
+static const HTMLElement gHTMLElements[] = {
+ // clang-format off
+ ELEM(unknown, ____, ____)
+ ELEM(a, ____, true)
+ ELEM(abbr, ____, true)
+ ELEM(acronym, ____, true)
+ ELEM(address, true, true)
+ ELEM(applet, ____, true)
+ ELEM(area, ____, ____)
+ ELEM(article, true, true)
+ ELEM(aside, true, true)
+ ELEM(audio, ____, true)
+ ELEM(b, ____, true)
+ ELEM(base, ____, ____)
+ ELEM(basefont, ____, ____)
+ ELEM(bdi, ____, true)
+ ELEM(bdo, ____, true)
+ ELEM(bgsound, ____, ____)
+ ELEM(big, ____, true)
+ ELEM(blockquote, true, true)
+ ELEM(body, ____, true)
+ ELEM(br, ____, ____)
+ ELEM(button, ____, true)
+ ELEM(canvas, ____, true)
+ ELEM(caption, ____, true)
+ ELEM(center, true, true)
+ ELEM(cite, ____, true)
+ ELEM(code, ____, true)
+ ELEM(col, ____, ____)
+ ELEM(colgroup, ____, true)
+ ELEM(data, ____, true)
+ ELEM(datalist, ____, true)
+ ELEM(dd, ____, true)
+ ELEM(del, ____, true)
+ ELEM(details, true, true)
+ ELEM(dfn, ____, true)
+ ELEM(dialog, true, true)
+ ELEM(dir, true, true)
+ ELEM(div, true, true)
+ ELEM(dl, true, true)
+ ELEM(dt, ____, true)
+ ELEM(em, ____, true)
+ ELEM(embed, ____, ____)
+ ELEM(fieldset, true, true)
+ ELEM(figcaption, ____, true)
+ ELEM(figure, true, true)
+ ELEM(font, ____, true)
+ ELEM(footer, true, true)
+ ELEM(form, true, true)
+ ELEM(frame, ____, ____)
+ ELEM(frameset, ____, true)
+ ELEM(h1, true, true)
+ ELEM(h2, true, true)
+ ELEM(h3, true, true)
+ ELEM(h4, true, true)
+ ELEM(h5, true, true)
+ ELEM(h6, true, true)
+ ELEM(head, ____, true)
+ ELEM(header, true, true)
+ ELEM(hgroup, true, true)
+ ELEM(hr, true, ____)
+ ELEM(html, ____, true)
+ ELEM(i, ____, true)
+ ELEM(iframe, ____, true)
+ ELEM(image, ____, ____)
+ ELEM(img, ____, ____)
+ ELEM(input, ____, ____)
+ ELEM(ins, ____, true)
+ ELEM(kbd, ____, true)
+ ELEM(keygen, ____, ____)
+ ELEM(label, ____, true)
+ ELEM(legend, ____, true)
+ ELEM(li, true, true)
+ ELEM(link, ____, ____)
+ ELEM(listing, true, true)
+ ELEM(main, true, true)
+ ELEM(map, ____, true)
+ ELEM(mark, ____, true)
+ ELEM(marquee, ____, true)
+ ELEM(menu, true, true)
+ ELEM(meta, ____, ____)
+ ELEM(meter, ____, true)
+ ELEM(multicol, true, true)
+ ELEM(nav, true, true)
+ ELEM(nobr, ____, true)
+ ELEM(noembed, ____, true)
+ ELEM(noframes, ____, true)
+ ELEM(noscript, ____, true)
+ ELEM(object, ____, true)
+ ELEM(ol, true, true)
+ ELEM(optgroup, ____, true)
+ ELEM(option, ____, true)
+ ELEM(output, ____, true)
+ ELEM(p, true, true)
+ ELEM(param, ____, ____)
+ ELEM(picture, ____, true)
+ ELEM(plaintext, ____, true)
+ ELEM(pre, true, true)
+ ELEM(progress, ____, true)
+ ELEM(q, ____, true)
+ ELEM(rb, ____, true)
+ ELEM(rp, ____, true)
+ ELEM(rt, ____, true)
+ ELEM(rtc, ____, true)
+ ELEM(ruby, ____, true)
+ ELEM(s, ____, true)
+ ELEM(samp, ____, true)
+ ELEM(script, ____, true)
+ ELEM(section, true, true)
+ ELEM(select, ____, true)
+ ELEM(small, ____, true)
+ ELEM(slot, ____, true)
+ ELEM(source, ____, ____)
+ ELEM(span, ____, true)
+ ELEM(strike, ____, true)
+ ELEM(strong, ____, true)
+ ELEM(style, ____, true)
+ ELEM(sub, ____, true)
+ ELEM(summary, true, true)
+ ELEM(sup, ____, true)
+ ELEM(table, true, true)
+ ELEM(tbody, ____, true)
+ ELEM(td, ____, true)
+ ELEM(textarea, ____, true)
+ ELEM(tfoot, ____, true)
+ ELEM(th, ____, true)
+ ELEM(thead, ____, true)
+ ELEM(template, ____, true)
+ ELEM(time, ____, true)
+ ELEM(title, ____, true)
+ ELEM(tr, ____, true)
+ ELEM(track, ____, ____)
+ ELEM(tt, ____, true)
+ ELEM(u, ____, true)
+ ELEM(ul, true, true)
+ ELEM(var, ____, true)
+ ELEM(video, ____, true)
+ ELEM(wbr, ____, ____)
+ ELEM(xmp, ____, true)
+ ELEM(text, ____, ____)
+ ELEM(whitespace, ____, ____)
+ ELEM(newline, ____, ____)
+ ELEM(comment, ____, true)
+ ELEM(entity, ____, true)
+ ELEM(doctypeDecl, ____, true)
+ ELEM(markupDecl, ____, true)
+ ELEM(instruction, ____, true)
+ ELEM(userdefined, ____, true)
+ // clang-format on
+};
+
+#undef ELEM
+#undef ____
+
+bool nsHTMLElement::IsContainer(nsHTMLTag aId) {
+ return gHTMLElements[aId].mIsContainer;
+}
+
+bool nsHTMLElement::IsBlock(nsHTMLTag aId) {
+ return gHTMLElements[aId].mIsBlock;
+}
+
+#ifdef DEBUG
+void CheckElementTable() {
+ for (nsHTMLTag t = eHTMLTag_unknown; t <= eHTMLTag_userdefined;
+ t = nsHTMLTag(t + 1)) {
+ MOZ_ASSERT(gHTMLElements[t].mTagID == t,
+ "gHTMLElements entries does match tag list.");
+ }
+}
+#endif
diff --git a/parser/htmlparser/nsElementTable.h b/parser/htmlparser/nsElementTable.h
new file mode 100644
index 0000000000..23edea76c7
--- /dev/null
+++ b/parser/htmlparser/nsElementTable.h
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsElementTable_h
+#define nsElementTable_h
+
+#include "nsHTMLTags.h"
+
+#ifdef DEBUG
+void CheckElementTable();
+#endif
+
+struct nsHTMLElement {
+ static bool IsContainer(nsHTMLTag aTag);
+ static bool IsBlock(nsHTMLTag aTag);
+};
+
+#endif // nsElementTable_h
diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp
new file mode 100644
index 0000000000..4da2444f84
--- /dev/null
+++ b/parser/htmlparser/nsExpatDriver.cpp
@@ -0,0 +1,1747 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsExpatDriver.h"
+#include "mozilla/fallible.h"
+#include "nsCOMPtr.h"
+#include "CParserContext.h"
+#include "nsIExpatSink.h"
+#include "nsIContentSink.h"
+#include "nsIDocShell.h"
+#include "nsParserMsgUtils.h"
+#include "nsIURL.h"
+#include "nsIUnicharInputStream.h"
+#include "nsIProtocolHandler.h"
+#include "nsNetUtil.h"
+#include "nsString.h"
+#include "nsTextFormatter.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCRT.h"
+#include "nsIConsoleService.h"
+#include "nsIScriptError.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIContentPolicy.h"
+#include "nsComponentManagerUtils.h"
+#include "nsContentPolicyUtils.h"
+#include "nsError.h"
+#include "nsXPCOMCIDInternal.h"
+#include "nsUnicharInputStream.h"
+#include "nsContentUtils.h"
+#include "mozilla/Array.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/IntegerTypeTraits.h"
+#include "mozilla/NullPrincipal.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/TelemetryComms.h"
+
+#include "nsThreadUtils.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/RLBoxUtils.h"
+#include "mozilla/UniquePtr.h"
+
+#include "mozilla/Logging.h"
+
+using mozilla::fallible;
+using mozilla::LogLevel;
+using mozilla::MakeStringSpan;
+using mozilla::Maybe;
+using mozilla::Unused;
+using mozilla::dom::Document;
+
+// We only pass chunks of length sMaxChunkLength to Expat in the RLBOX sandbox.
+// The RLBOX sandbox has a limited amount of memory, and we have to account for
+// other memory use by Expat (including the buffering it does).
+// Note that sMaxChunkLength is in number of characters.
+#ifdef DEBUG
+// On debug builds we set a much lower limit (1kB) to try to hit boundary
+// conditions more frequently.
+static const uint32_t sMaxChunkLength = 1024 / sizeof(char16_t);
+#else
+static const uint32_t sMaxChunkLength = (128 * 1024) / sizeof(char16_t);
+#endif
+
+#define kExpatSeparatorChar 0xFFFF
+
+static const char16_t kUTF16[] = {'U', 'T', 'F', '-', '1', '6', '\0'};
+
+static mozilla::LazyLogModule gExpatDriverLog("expatdriver");
+
+// Use the same maximum tree depth as Chromium (see
+// https://chromium.googlesource.com/chromium/src/+/f464165c1dedff1c955d3c051c5a9a1c6a0e8f6b/third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp#85).
+static const uint16_t sMaxXMLTreeDepth = 5000;
+
+/***************************** RLBOX HELPERS ********************************/
+// Helpers for calling sandboxed expat functions in handlers
+
+#define RLBOX_EXPAT_SAFE_CALL(foo, verifier, ...) \
+ aSandbox.invoke_sandbox_function(foo, self->mExpatParser, ##__VA_ARGS__) \
+ .copy_and_verify(verifier)
+
+#define RLBOX_EXPAT_SAFE_MCALL(foo, verifier, ...) \
+ Sandbox() \
+ ->invoke_sandbox_function(foo, mExpatParser, ##__VA_ARGS__) \
+ .copy_and_verify(verifier)
+
+#define RLBOX_EXPAT_CALL(foo, ...) \
+ aSandbox.invoke_sandbox_function(foo, self->mExpatParser, ##__VA_ARGS__)
+
+#define RLBOX_EXPAT_MCALL(foo, ...) \
+ Sandbox()->invoke_sandbox_function(foo, mExpatParser, ##__VA_ARGS__)
+
+#define RLBOX_SAFE_PRINT "Value used only for printing"
+#define MOZ_RELEASE_ASSERT_TAINTED(cond, ...) \
+ MOZ_RELEASE_ASSERT((cond).unverified_safe_because("Sanity check"), \
+ ##__VA_ARGS__)
+
+/* safe_unverified is used whenever it's safe to not use a validator */
+template <typename T>
+static T safe_unverified(T val) {
+ return val;
+}
+
+/* status_verifier is a type validator for XML_Status */
+inline enum XML_Status status_verifier(enum XML_Status s) {
+ MOZ_RELEASE_ASSERT(s >= XML_STATUS_ERROR && s <= XML_STATUS_SUSPENDED,
+ "unexpected status code");
+ return s;
+}
+
+/* error_verifier is a type validator for XML_Error */
+inline enum XML_Error error_verifier(enum XML_Error code) {
+ MOZ_RELEASE_ASSERT(
+ code >= XML_ERROR_NONE && code <= XML_ERROR_INVALID_ARGUMENT,
+ "unexpected XML error code");
+ return code;
+}
+
+/* We use unverified_xml_string to just expose sandbox expat strings to Firefox
+ * without any validation. On 64-bit we have guard pages at the sandbox
+ * boundary; on 32-bit we don't and a string could be used to read beyond the
+ * sandbox boundary. In our attacker model this is okay (the attacker can just
+ * Spectre).
+ *
+ * Nevertheless, we should try to add strings validators to the consumer code
+ * of expat whenever we have some semantics. At the very lest we should make
+ * sure that the strings are never written to. Bug 1693991 tracks this.
+ */
+static const XML_Char* unverified_xml_string(uintptr_t ptr) {
+ return reinterpret_cast<const XML_Char*>(ptr);
+}
+
+/* The TransferBuffer class is used to copy (or directly expose in the
+ * noop-sandbox case) buffers into the expat sandbox (and automatically
+ * when out of scope).
+ */
+template <typename T>
+using TransferBuffer =
+ mozilla::RLBoxTransferBufferToSandbox<T, rlbox_expat_sandbox_type>;
+
+/*************************** END RLBOX HELPERS ******************************/
+
+/***************************** EXPAT CALL BACKS ******************************/
+// The callback handlers that get called from the expat parser.
+
+static void Driver_HandleXMLDeclaration(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> /* aUserData */,
+ tainted_expat<const XML_Char*> aVersion,
+ tainted_expat<const XML_Char*> aEncoding, tainted_expat<int> aStandalone) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+
+ int standalone = aStandalone.copy_and_verify([&](auto a) {
+ // Standalone argument can be -1, 0, or 1 (see
+ // /parser/expat/lib/expat.h#185)
+ MOZ_RELEASE_ASSERT(a >= -1 && a <= 1, "Unexpected standalone parameter");
+ return a;
+ });
+
+ const auto* version = aVersion.copy_and_verify_address(unverified_xml_string);
+ const auto* encoding =
+ aEncoding.copy_and_verify_address(unverified_xml_string);
+ driver->HandleXMLDeclaration(version, encoding, standalone);
+}
+
+static void Driver_HandleCharacterData(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> /* aUserData */,
+ tainted_expat<const XML_Char*> aData,
+ tainted_expat<int> aLength) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ // aData is not null terminated; even with bad length we will not span beyond
+ // sandbox boundary
+ uint32_t length =
+ static_cast<uint32_t>(aLength.copy_and_verify(safe_unverified<int>));
+ const auto* data = aData.unverified_safe_pointer_because(
+ length, "Only care that the data is within sandbox boundary.");
+ driver->HandleCharacterData(data, length);
+}
+
+static void Driver_HandleComment(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> /* aUserData */,
+ tainted_expat<const XML_Char*> aName) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ const auto* name = aName.copy_and_verify_address(unverified_xml_string);
+ driver->HandleComment(name);
+}
+
+static void Driver_HandleProcessingInstruction(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> /* aUserData */,
+ tainted_expat<const XML_Char*> aTarget,
+ tainted_expat<const XML_Char*> aData) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ const auto* target = aTarget.copy_and_verify_address(unverified_xml_string);
+ const auto* data = aData.copy_and_verify_address(unverified_xml_string);
+ driver->HandleProcessingInstruction(target, data);
+}
+
+static void Driver_HandleDefault(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> /* aUserData */,
+ tainted_expat<const XML_Char*> aData,
+ tainted_expat<int> aLength) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ // aData is not null terminated; even with bad length we will not span
+ // beyond sandbox boundary
+ uint32_t length =
+ static_cast<uint32_t>(aLength.copy_and_verify(safe_unverified<int>));
+ const auto* data = aData.unverified_safe_pointer_because(
+ length, "Only care that the data is within sandbox boundary.");
+ driver->HandleDefault(data, length);
+}
+
+static void Driver_HandleStartCdataSection(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> /* aUserData */) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ driver->HandleStartCdataSection();
+}
+
+static void Driver_HandleEndCdataSection(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> /* aUserData */) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ driver->HandleEndCdataSection();
+}
+
+static void Driver_HandleStartDoctypeDecl(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> /* aUserData */,
+ tainted_expat<const XML_Char*> aDoctypeName,
+ tainted_expat<const XML_Char*> aSysid,
+ tainted_expat<const XML_Char*> aPubid,
+ tainted_expat<int> aHasInternalSubset) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ const auto* doctypeName =
+ aDoctypeName.copy_and_verify_address(unverified_xml_string);
+ const auto* sysid = aSysid.copy_and_verify_address(unverified_xml_string);
+ const auto* pubid = aPubid.copy_and_verify_address(unverified_xml_string);
+ bool hasInternalSubset =
+ !!(aHasInternalSubset.copy_and_verify(safe_unverified<int>));
+ driver->HandleStartDoctypeDecl(doctypeName, sysid, pubid, hasInternalSubset);
+}
+
+static void Driver_HandleEndDoctypeDecl(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> /* aUserData */) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+ driver->HandleEndDoctypeDecl();
+}
+
+static tainted_expat<int> Driver_HandleExternalEntityRef(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<XML_Parser> /* aParser */,
+ tainted_expat<const XML_Char*> aOpenEntityNames,
+ tainted_expat<const XML_Char*> aBase,
+ tainted_expat<const XML_Char*> aSystemId,
+ tainted_expat<const XML_Char*> aPublicId) {
+ nsExpatDriver* driver = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(driver);
+
+ const auto* openEntityNames =
+ aOpenEntityNames.copy_and_verify_address(unverified_xml_string);
+ const auto* base = aBase.copy_and_verify_address(unverified_xml_string);
+ const auto* systemId =
+ aSystemId.copy_and_verify_address(unverified_xml_string);
+ const auto* publicId =
+ aPublicId.copy_and_verify_address(unverified_xml_string);
+ return driver->HandleExternalEntityRef(openEntityNames, base, systemId,
+ publicId);
+}
+
+/***************************** END CALL BACKS ********************************/
+
+/***************************** CATALOG UTILS *********************************/
+
+// Initially added for bug 113400 to switch from the remote "XHTML 1.0 plus
+// MathML 2.0" DTD to the the lightweight customized version that Mozilla uses.
+// Since Mozilla is not validating, no need to fetch a *huge* file at each
+// click.
+// XXX The cleanest solution here would be to fix Bug 98413: Implement XML
+// Catalogs.
+struct nsCatalogData {
+ const char* mPublicID;
+ const char* mLocalDTD;
+ const char* mAgentSheet;
+};
+
+// The order of this table is guestimated to be in the optimum order
+static const nsCatalogData kCatalogTable[] = {
+ {"-//W3C//DTD XHTML 1.0 Transitional//EN", "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD XHTML 1.1//EN", "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD XHTML 1.0 Strict//EN", "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD XHTML 1.0 Frameset//EN", "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD XHTML Basic 1.0//EN", "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN", "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN",
+ "htmlmathml-f.ent", nullptr},
+ {"-//W3C//DTD MathML 2.0//EN", "htmlmathml-f.ent", nullptr},
+ {"-//WAPFORUM//DTD XHTML Mobile 1.0//EN", "htmlmathml-f.ent", nullptr},
+ {nullptr, nullptr, nullptr}};
+
+static const nsCatalogData* LookupCatalogData(const char16_t* aPublicID) {
+ nsDependentString publicID(aPublicID);
+
+ // linear search for now since the number of entries is going to
+ // be negligible, and the fix for bug 98413 would get rid of this
+ // code anyway
+ const nsCatalogData* data = kCatalogTable;
+ while (data->mPublicID) {
+ if (publicID.EqualsASCII(data->mPublicID)) {
+ return data;
+ }
+ ++data;
+ }
+
+ return nullptr;
+}
+
+// This function provides a resource URI to a local DTD
+// in resource://gre/res/dtd/ which may or may not exist.
+// If aCatalogData is provided, it is used to remap the
+// DTD instead of taking the filename from the URI. aDTD
+// may be null in some cases that are relying on
+// aCatalogData working for them.
+static void GetLocalDTDURI(const nsCatalogData* aCatalogData, nsIURI* aDTD,
+ nsIURI** aResult) {
+ nsAutoCString fileName;
+ if (aCatalogData) {
+ // remap the DTD to a known local DTD
+ fileName.Assign(aCatalogData->mLocalDTD);
+ }
+
+ if (fileName.IsEmpty()) {
+ // Try to see if the user has installed the DTD file -- we extract the
+ // filename.ext of the DTD here. Hence, for any DTD for which we have
+ // no predefined mapping, users just have to copy the DTD file to our
+ // special DTD directory and it will be picked.
+ nsCOMPtr<nsIURL> dtdURL = do_QueryInterface(aDTD);
+ if (!dtdURL) {
+ // Not a URL with a filename, or maybe it was null. Either way, nothing
+ // else we can do here.
+ return;
+ }
+
+ dtdURL->GetFileName(fileName);
+ if (fileName.IsEmpty()) {
+ return;
+ }
+ }
+
+ nsAutoCString respath("resource://gre/res/dtd/");
+ respath += fileName;
+ NS_NewURI(aResult, respath);
+}
+
+/***************************** END CATALOG UTILS *****************************/
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsExpatDriver)
+ NS_INTERFACE_MAP_ENTRY(nsIDTD)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsExpatDriver)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsExpatDriver)
+
+NS_IMPL_CYCLE_COLLECTION(nsExpatDriver, mSink)
+
+nsExpatDriver::nsExpatDriver()
+ : mExpatParser(nullptr),
+ mInCData(false),
+ mInInternalSubset(false),
+ mInExternalDTD(false),
+ mMadeFinalCallToExpat(false),
+ mInParser(false),
+ mInternalState(NS_OK),
+ mExpatBuffered(0),
+ mTagDepth(0),
+ mCatalogData(nullptr),
+ mInnerWindowID(0) {}
+
+nsExpatDriver::~nsExpatDriver() { Destroy(); }
+
+void nsExpatDriver::Destroy() {
+ if (mSandboxPoolData) {
+ SandboxData()->DetachDriver();
+ if (mExpatParser) {
+ RLBOX_EXPAT_MCALL(MOZ_XML_ParserFree);
+ }
+ }
+ mSandboxPoolData.reset();
+ mURIs.Clear();
+ mExpatParser = nullptr;
+}
+
+// The AllocAttrs class is used to speed up copying attributes from the
+// sandboxed expat by fast allocating attributes on the stack and only falling
+// back to malloc when we need to allocate lots of attributes.
+class MOZ_STACK_CLASS AllocAttrs {
+#define NUM_STACK_SLOTS 16
+ public:
+ const char16_t** Init(size_t size) {
+ if (size <= NUM_STACK_SLOTS) {
+ return mInlineArr;
+ }
+ mHeapPtr = mozilla::MakeUnique<const char16_t*[]>(size);
+ return mHeapPtr.get();
+ }
+
+ private:
+ const char16_t* mInlineArr[NUM_STACK_SLOTS];
+ mozilla::UniquePtr<const char16_t*[]> mHeapPtr;
+#undef NUM_STACK_SLOTS
+};
+
+/* static */
+void nsExpatDriver::HandleStartElement(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> /* aUserData */,
+ tainted_expat<const char16_t*> aName,
+ tainted_expat<const char16_t**> aAttrs) {
+ nsExpatDriver* self = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(self && self->mSink);
+
+ const auto* name = aName.copy_and_verify_address(unverified_xml_string);
+
+ // Calculate the total number of elements in aAttrs.
+ // XML_GetSpecifiedAttributeCount will only give us the number of specified
+ // attrs (twice that number, actually), so we have to check for default
+ // attrs ourselves.
+ tainted_expat<int> count =
+ RLBOX_EXPAT_CALL(MOZ_XML_GetSpecifiedAttributeCount);
+ MOZ_RELEASE_ASSERT_TAINTED(count >= 0, "Unexpected attribute count");
+
+ tainted_expat<uint64_t> attrArrayLengthTainted;
+ for (attrArrayLengthTainted = rlbox::sandbox_static_cast<uint64_t>(count);
+ (aAttrs[attrArrayLengthTainted] != nullptr)
+ .unverified_safe_because("Bad length is checked later");
+ attrArrayLengthTainted += 2) {
+ // Just looping till we find out what the length is
+ }
+
+ uint32_t attrArrayLength =
+ attrArrayLengthTainted.copy_and_verify([&](uint64_t value) {
+ // A malicious length could result in an overflow when we allocate
+ // aAttrs and then access elements of the array.
+ MOZ_RELEASE_ASSERT(value < UINT32_MAX, "Overflow attempt");
+ return value;
+ });
+
+ // Copy tainted aAttrs from sandbox
+ AllocAttrs allocAttrs;
+ const char16_t** attrs = allocAttrs.Init(attrArrayLength + 1);
+ if (NS_WARN_IF(!aAttrs || !attrs)) {
+ self->MaybeStopParser(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+
+ for (uint32_t i = 0; i < attrArrayLength; i++) {
+ attrs[i] = aAttrs[i].copy_and_verify_address(unverified_xml_string);
+ }
+ attrs[attrArrayLength] = nullptr;
+
+ if (self->mSink) {
+ // We store the tagdepth in a PRUint16, so make sure the limit fits in a
+ // PRUint16.
+ static_assert(
+ sMaxXMLTreeDepth <=
+ std::numeric_limits<decltype(nsExpatDriver::mTagDepth)>::max());
+
+ if (++self->mTagDepth > sMaxXMLTreeDepth) {
+ self->MaybeStopParser(NS_ERROR_HTMLPARSER_HIERARCHYTOODEEP);
+ return;
+ }
+
+ nsresult rv = self->mSink->HandleStartElement(
+ name, attrs, attrArrayLength,
+ RLBOX_EXPAT_SAFE_CALL(MOZ_XML_GetCurrentLineNumber,
+ safe_unverified<XML_Size>),
+ RLBOX_EXPAT_SAFE_CALL(MOZ_XML_GetCurrentColumnNumber,
+ safe_unverified<XML_Size>));
+ self->MaybeStopParser(rv);
+ }
+}
+
+/* static */
+void nsExpatDriver::HandleStartElementForSystemPrincipal(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName,
+ tainted_expat<const char16_t**> aAttrs) {
+ nsExpatDriver* self = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(self);
+ if (!RLBOX_EXPAT_SAFE_CALL(MOZ_XML_ProcessingEntityValue,
+ safe_unverified<XML_Bool>)) {
+ HandleStartElement(aSandbox, aUserData, aName, aAttrs);
+ } else {
+ nsCOMPtr<Document> doc =
+ do_QueryInterface(self->mOriginalSink->GetTarget());
+
+ // Adjust the column number so that it is one based rather than zero
+ // based.
+ tainted_expat<XML_Size> colNumber =
+ RLBOX_EXPAT_CALL(MOZ_XML_GetCurrentColumnNumber) + 1;
+ tainted_expat<XML_Size> lineNumber =
+ RLBOX_EXPAT_CALL(MOZ_XML_GetCurrentLineNumber);
+
+ int32_t nameSpaceID;
+ RefPtr<nsAtom> prefix, localName;
+ const auto* name = aName.copy_and_verify_address(unverified_xml_string);
+ nsContentUtils::SplitExpatName(name, getter_AddRefs(prefix),
+ getter_AddRefs(localName), &nameSpaceID);
+
+ nsAutoString error;
+ error.AppendLiteral("Ignoring element <");
+ if (prefix) {
+ error.Append(prefix->GetUTF16String());
+ error.Append(':');
+ }
+ error.Append(localName->GetUTF16String());
+ error.AppendLiteral("> created from entity value.");
+
+ nsContentUtils::ReportToConsoleNonLocalized(
+ error, nsIScriptError::warningFlag, "XML Document"_ns, doc, nullptr,
+ u""_ns, lineNumber.unverified_safe_because(RLBOX_SAFE_PRINT),
+ colNumber.unverified_safe_because(RLBOX_SAFE_PRINT));
+ }
+}
+
+/* static */
+void nsExpatDriver::HandleEndElement(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName) {
+ nsExpatDriver* self = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(self);
+ const auto* name = aName.copy_and_verify_address(unverified_xml_string);
+
+ NS_ASSERTION(self->mSink, "content sink not found!");
+ NS_ASSERTION(self->mInternalState != NS_ERROR_HTMLPARSER_BLOCK,
+ "Shouldn't block from HandleStartElement.");
+
+ if (self->mSink && self->mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
+ nsresult rv = self->mSink->HandleEndElement(name);
+ --self->mTagDepth;
+ self->MaybeStopParser(rv);
+ }
+}
+
+/* static */
+void nsExpatDriver::HandleEndElementForSystemPrincipal(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName) {
+ nsExpatDriver* self = static_cast<nsExpatDriver*>(aSandbox.sandbox_storage);
+ MOZ_ASSERT(self);
+ if (!RLBOX_EXPAT_SAFE_CALL(MOZ_XML_ProcessingEntityValue,
+ safe_unverified<XML_Bool>)) {
+ HandleEndElement(aSandbox, aUserData, aName);
+ }
+}
+
+nsresult nsExpatDriver::HandleCharacterData(const char16_t* aValue,
+ const uint32_t aLength) {
+ NS_ASSERTION(mSink, "content sink not found!");
+
+ if (mInCData) {
+ if (!mCDataText.Append(aValue, aLength, fallible)) {
+ MaybeStopParser(NS_ERROR_OUT_OF_MEMORY);
+ }
+ } else if (mSink) {
+ nsresult rv = mSink->HandleCharacterData(aValue, aLength);
+ MaybeStopParser(rv);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleComment(const char16_t* aValue) {
+ NS_ASSERTION(mSink, "content sink not found!");
+
+ if (mInExternalDTD) {
+ // Ignore comments from external DTDs
+ return NS_OK;
+ }
+
+ if (mInInternalSubset) {
+ mInternalSubset.AppendLiteral("<!--");
+ mInternalSubset.Append(aValue);
+ mInternalSubset.AppendLiteral("-->");
+ } else if (mSink) {
+ nsresult rv = mSink->HandleComment(aValue);
+ MaybeStopParser(rv);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleProcessingInstruction(const char16_t* aTarget,
+ const char16_t* aData) {
+ NS_ASSERTION(mSink, "content sink not found!");
+
+ if (mInExternalDTD) {
+ // Ignore PIs in external DTDs for now. Eventually we want to
+ // pass them to the sink in a way that doesn't put them in the DOM
+ return NS_OK;
+ }
+
+ if (mInInternalSubset) {
+ mInternalSubset.AppendLiteral("<?");
+ mInternalSubset.Append(aTarget);
+ mInternalSubset.Append(' ');
+ mInternalSubset.Append(aData);
+ mInternalSubset.AppendLiteral("?>");
+ } else if (mSink) {
+ nsresult rv = mSink->HandleProcessingInstruction(aTarget, aData);
+ MaybeStopParser(rv);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleXMLDeclaration(const char16_t* aVersion,
+ const char16_t* aEncoding,
+ int32_t aStandalone) {
+ if (mSink) {
+ nsresult rv = mSink->HandleXMLDeclaration(aVersion, aEncoding, aStandalone);
+ MaybeStopParser(rv);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleDefault(const char16_t* aValue,
+ const uint32_t aLength) {
+ NS_ASSERTION(mSink, "content sink not found!");
+
+ if (mInExternalDTD) {
+ // Ignore newlines in external DTDs
+ return NS_OK;
+ }
+
+ if (mInInternalSubset) {
+ mInternalSubset.Append(aValue, aLength);
+ } else if (mSink) {
+ uint32_t i;
+ nsresult rv = mInternalState;
+ for (i = 0; i < aLength && NS_SUCCEEDED(rv); ++i) {
+ if (aValue[i] == '\n' || aValue[i] == '\r') {
+ rv = mSink->HandleCharacterData(&aValue[i], 1);
+ }
+ }
+ MaybeStopParser(rv);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleStartCdataSection() {
+ mInCData = true;
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleEndCdataSection() {
+ NS_ASSERTION(mSink, "content sink not found!");
+
+ mInCData = false;
+ if (mSink) {
+ nsresult rv =
+ mSink->HandleCDataSection(mCDataText.get(), mCDataText.Length());
+ MaybeStopParser(rv);
+ }
+ mCDataText.Truncate();
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleStartDoctypeDecl(const char16_t* aDoctypeName,
+ const char16_t* aSysid,
+ const char16_t* aPubid,
+ bool aHasInternalSubset) {
+ mDoctypeName = aDoctypeName;
+ mSystemID = aSysid;
+ mPublicID = aPubid;
+
+ if (aHasInternalSubset) {
+ // Consuming a huge internal subset translates to numerous
+ // allocations. In an effort to avoid too many allocations
+ // setting mInternalSubset's capacity to be 1K ( just a guesstimate! ).
+ mInInternalSubset = true;
+ mInternalSubset.SetCapacity(1024);
+ } else {
+ // Distinguish missing internal subset from an empty one
+ mInternalSubset.SetIsVoid(true);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleEndDoctypeDecl() {
+ NS_ASSERTION(mSink, "content sink not found!");
+
+ mInInternalSubset = false;
+
+ if (mSink) {
+ // let the sink know any additional knowledge that we have about the
+ // document (currently, from bug 124570, we only expect to pass additional
+ // agent sheets needed to layout the XML vocabulary of the document)
+ nsCOMPtr<nsIURI> data;
+#if 0
+ if (mCatalogData && mCatalogData->mAgentSheet) {
+ NS_NewURI(getter_AddRefs(data), mCatalogData->mAgentSheet);
+ }
+#endif
+
+ // The unused support for "catalog style sheets" was removed. It doesn't
+ // look like we'll ever fix bug 98413 either.
+ MOZ_ASSERT(!mCatalogData || !mCatalogData->mAgentSheet,
+ "Need to add back support for catalog style sheets");
+
+ // Note: mInternalSubset already doesn't include the [] around it.
+ nsresult rv = mSink->HandleDoctypeDecl(mInternalSubset, mDoctypeName,
+ mSystemID, mPublicID, data);
+ MaybeStopParser(rv);
+ }
+
+ mInternalSubset.Truncate();
+
+ return NS_OK;
+}
+
+// Wrapper class for passing the sandbox data and parser as a closure to
+// ExternalDTDStreamReaderFunc.
+class RLBoxExpatClosure {
+ public:
+ RLBoxExpatClosure(RLBoxExpatSandboxData* aSbxData,
+ tainted_expat<XML_Parser> aExpatParser)
+ : mSbxData(aSbxData), mExpatParser(aExpatParser){};
+ inline rlbox_sandbox_expat* Sandbox() const { return mSbxData->Sandbox(); };
+ inline tainted_expat<XML_Parser> Parser() const { return mExpatParser; };
+
+ private:
+ RLBoxExpatSandboxData* mSbxData;
+ tainted_expat<XML_Parser> mExpatParser;
+};
+
+static nsresult ExternalDTDStreamReaderFunc(nsIUnicharInputStream* aIn,
+ void* aClosure,
+ const char16_t* aFromSegment,
+ uint32_t aToOffset, uint32_t aCount,
+ uint32_t* aWriteCount) {
+ MOZ_ASSERT(aClosure && aFromSegment && aWriteCount);
+
+ *aWriteCount = 0;
+
+ // Get sandbox and parser
+ auto* closure = reinterpret_cast<RLBoxExpatClosure*>(aClosure);
+ MOZ_ASSERT(closure);
+
+ // Transfer segment into the sandbox
+ auto fromSegment =
+ TransferBuffer<char16_t>(closure->Sandbox(), aFromSegment, aCount);
+ NS_ENSURE_TRUE(*fromSegment, NS_ERROR_OUT_OF_MEMORY);
+
+ // Pass the buffer to expat for parsing.
+ if (closure->Sandbox()
+ ->invoke_sandbox_function(
+ MOZ_XML_Parse, closure->Parser(),
+ rlbox::sandbox_reinterpret_cast<const char*>(*fromSegment),
+ aCount * sizeof(char16_t), 0)
+ .copy_and_verify(status_verifier) == XML_STATUS_OK) {
+ *aWriteCount = aCount;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+int nsExpatDriver::HandleExternalEntityRef(const char16_t* openEntityNames,
+ const char16_t* base,
+ const char16_t* systemId,
+ const char16_t* publicId) {
+ if (mInInternalSubset && !mInExternalDTD && openEntityNames) {
+ mInternalSubset.Append(char16_t('%'));
+ mInternalSubset.Append(nsDependentString(openEntityNames));
+ mInternalSubset.Append(char16_t(';'));
+ }
+
+ nsCOMPtr<nsIURI> baseURI = GetBaseURI(base);
+ NS_ENSURE_TRUE(baseURI, 1);
+
+ // Load the external entity into a buffer.
+ nsCOMPtr<nsIInputStream> in;
+ nsCOMPtr<nsIURI> absURI;
+ nsresult rv = OpenInputStreamFromExternalDTD(
+ publicId, systemId, baseURI, getter_AddRefs(in), getter_AddRefs(absURI));
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ nsCString message("Failed to open external DTD: publicId \"");
+ AppendUTF16toUTF8(MakeStringSpan(publicId), message);
+ message += "\" systemId \"";
+ AppendUTF16toUTF8(MakeStringSpan(systemId), message);
+ message += "\" base \"";
+ message.Append(baseURI->GetSpecOrDefault());
+ message += "\" URL \"";
+ if (absURI) {
+ message.Append(absURI->GetSpecOrDefault());
+ }
+ message += "\"";
+ NS_WARNING(message.get());
+#endif
+ return 1;
+ }
+
+ nsCOMPtr<nsIUnicharInputStream> uniIn;
+ rv = NS_NewUnicharInputStream(in, getter_AddRefs(uniIn));
+ NS_ENSURE_SUCCESS(rv, 1);
+
+ int result = 1;
+ if (uniIn) {
+ auto utf16 = TransferBuffer<char16_t>(
+ Sandbox(), kUTF16, nsCharTraits<char16_t>::length(kUTF16) + 1);
+ NS_ENSURE_TRUE(*utf16, 1);
+ tainted_expat<XML_Parser> entParser;
+ entParser =
+ RLBOX_EXPAT_MCALL(MOZ_XML_ExternalEntityParserCreate, nullptr, *utf16);
+ if (entParser) {
+ auto baseURI = GetExpatBaseURI(absURI);
+ auto url = TransferBuffer<XML_Char>(Sandbox(), &baseURI[0],
+ ArrayLength(baseURI));
+ NS_ENSURE_TRUE(*url, 1);
+ Sandbox()->invoke_sandbox_function(MOZ_XML_SetBase, entParser, *url);
+
+ mInExternalDTD = true;
+
+ bool inParser = mInParser; // Save in-parser status
+ mInParser = true;
+
+ RLBoxExpatClosure closure(SandboxData(), entParser);
+ uint32_t totalRead;
+ do {
+ rv = uniIn->ReadSegments(ExternalDTDStreamReaderFunc, &closure,
+ uint32_t(-1), &totalRead);
+ } while (NS_SUCCEEDED(rv) && totalRead > 0);
+
+ result =
+ Sandbox()
+ ->invoke_sandbox_function(MOZ_XML_Parse, entParser, nullptr, 0, 1)
+ .copy_and_verify(status_verifier);
+
+ mInParser = inParser; // Restore in-parser status
+ mInExternalDTD = false;
+
+ Sandbox()->invoke_sandbox_function(MOZ_XML_ParserFree, entParser);
+ }
+ }
+
+ return result;
+}
+
+nsresult nsExpatDriver::OpenInputStreamFromExternalDTD(const char16_t* aFPIStr,
+ const char16_t* aURLStr,
+ nsIURI* aBaseURI,
+ nsIInputStream** aStream,
+ nsIURI** aAbsURI) {
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(aURLStr),
+ nullptr, aBaseURI);
+ // Even if the URI is malformed (most likely because we have a
+ // non-hierarchical base URI and a relative DTD URI, with the latter
+ // being the normal XHTML DTD case), we can try to see whether we
+ // have catalog data for aFPIStr.
+ if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_MALFORMED_URI)) {
+ return rv;
+ }
+
+ // make sure the URI, if we have one, is allowed to be loaded in sync
+ bool isUIResource = false;
+ if (uri) {
+ rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_IS_UI_RESOURCE,
+ &isUIResource);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsCOMPtr<nsIURI> localURI;
+ if (!isUIResource) {
+ // Check to see if we can map the DTD to a known local DTD, or if a DTD
+ // file of the same name exists in the special DTD directory
+ if (aFPIStr) {
+ // see if the Formal Public Identifier (FPI) maps to a catalog entry
+ mCatalogData = LookupCatalogData(aFPIStr);
+ GetLocalDTDURI(mCatalogData, uri, getter_AddRefs(localURI));
+ }
+ if (!localURI) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ }
+
+ nsCOMPtr<nsIChannel> channel;
+ if (localURI) {
+ localURI.swap(uri);
+ rv = NS_NewChannel(getter_AddRefs(channel), uri,
+ nsContentUtils::GetSystemPrincipal(),
+ nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
+ nsIContentPolicy::TYPE_DTD);
+ NS_ENSURE_SUCCESS(rv, rv);
+ } else {
+ NS_ASSERTION(
+ mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)),
+ "In nsExpatDriver::OpenInputStreamFromExternalDTD: "
+ "mOriginalSink not the same object as mSink?");
+ nsContentPolicyType policyType = nsIContentPolicy::TYPE_INTERNAL_DTD;
+ if (mOriginalSink) {
+ nsCOMPtr<Document> doc;
+ doc = do_QueryInterface(mOriginalSink->GetTarget());
+ if (doc) {
+ if (doc->SkipDTDSecurityChecks()) {
+ policyType = nsIContentPolicy::TYPE_INTERNAL_FORCE_ALLOWED_DTD;
+ }
+ rv = NS_NewChannel(
+ getter_AddRefs(channel), uri, doc,
+ nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT |
+ nsILoadInfo::SEC_ALLOW_CHROME,
+ policyType);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+ if (!channel) {
+ nsCOMPtr<nsIPrincipal> nullPrincipal =
+ mozilla::NullPrincipal::CreateWithoutOriginAttributes();
+ rv = NS_NewChannel(
+ getter_AddRefs(channel), uri, nullPrincipal,
+ nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT |
+ nsILoadInfo::SEC_ALLOW_CHROME,
+ policyType);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ }
+
+ uri.forget(aAbsURI);
+
+ channel->SetContentType("application/xml"_ns);
+ return channel->Open(aStream);
+}
+
+static nsresult CreateErrorText(const char16_t* aDescription,
+ const char16_t* aSourceURL,
+ tainted_expat<XML_Size> aLineNumber,
+ tainted_expat<XML_Size> aColNumber,
+ nsString& aErrorString, bool spoofEnglish) {
+ aErrorString.Truncate();
+
+ nsAutoString msg;
+ nsresult rv = nsParserMsgUtils::GetLocalizedStringByName(
+ spoofEnglish ? XMLPARSER_PROPERTIES_en_US : XMLPARSER_PROPERTIES,
+ "XMLParsingError", msg);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$u, Column %4$u:
+ nsTextFormatter::ssprintf(
+ aErrorString, msg.get(), aDescription, aSourceURL,
+ aLineNumber.unverified_safe_because(RLBOX_SAFE_PRINT),
+ aColNumber.unverified_safe_because(RLBOX_SAFE_PRINT));
+ return NS_OK;
+}
+
+static nsresult AppendErrorPointer(tainted_expat<XML_Size> aColNumber,
+ const char16_t* aSourceLine,
+ size_t aSourceLineLength,
+ nsString& aSourceString) {
+ aSourceString.Append(char16_t('\n'));
+
+ MOZ_RELEASE_ASSERT_TAINTED(aColNumber != static_cast<XML_Size>(0),
+ "Unexpected value of column");
+
+ // Last character will be '^'.
+ XML_Size last =
+ (aColNumber - 1).copy_and_verify([&](XML_Size val) -> XML_Size {
+ if (val > aSourceLineLength) {
+ // Unexpected value of last column, just return a safe value
+ return 0;
+ }
+ return val;
+ });
+
+ XML_Size i;
+ uint32_t minuses = 0;
+ for (i = 0; i < last; ++i) {
+ if (aSourceLine[i] == '\t') {
+ // Since this uses |white-space: pre;| a tab stop equals 8 spaces.
+ uint32_t add = 8 - (minuses % 8);
+ aSourceString.AppendASCII("--------", add);
+ minuses += add;
+ } else {
+ aSourceString.Append(char16_t('-'));
+ ++minuses;
+ }
+ }
+ aSourceString.Append(char16_t('^'));
+
+ return NS_OK;
+}
+
+nsresult nsExpatDriver::HandleError() {
+ int32_t code =
+ RLBOX_EXPAT_MCALL(MOZ_XML_GetErrorCode).copy_and_verify(error_verifier);
+
+ // Map Expat error code to an error string
+ // XXX Deal with error returns.
+ nsAutoString description;
+ nsCOMPtr<Document> doc;
+ if (mOriginalSink) {
+ doc = do_QueryInterface(mOriginalSink->GetTarget());
+ }
+
+ bool spoofEnglish =
+ nsContentUtils::SpoofLocaleEnglish() && (!doc || !doc->AllowsL10n());
+ nsParserMsgUtils::GetLocalizedStringByID(
+ spoofEnglish ? XMLPARSER_PROPERTIES_en_US : XMLPARSER_PROPERTIES, code,
+ description);
+
+ if (code == XML_ERROR_TAG_MISMATCH) {
+ /**
+ * Expat can send the following:
+ * localName
+ * namespaceURI<separator>localName
+ * namespaceURI<separator>localName<separator>prefix
+ *
+ * and we use 0xFFFF for the <separator>.
+ *
+ */
+
+ const char16_t* mismatch =
+ RLBOX_EXPAT_MCALL(MOZ_XML_GetMismatchedTag)
+ .copy_and_verify_address(unverified_xml_string);
+ const char16_t* uriEnd = nullptr;
+ const char16_t* nameEnd = nullptr;
+ const char16_t* pos;
+ for (pos = mismatch; *pos; ++pos) {
+ if (*pos == kExpatSeparatorChar) {
+ if (uriEnd) {
+ nameEnd = pos;
+ } else {
+ uriEnd = pos;
+ }
+ }
+ }
+
+ nsAutoString tagName;
+ if (uriEnd && nameEnd) {
+ // We have a prefix.
+ tagName.Append(nameEnd + 1, pos - nameEnd - 1);
+ tagName.Append(char16_t(':'));
+ }
+ const char16_t* nameStart = uriEnd ? uriEnd + 1 : mismatch;
+ tagName.Append(nameStart, (nameEnd ? nameEnd : pos) - nameStart);
+
+ nsAutoString msg;
+ nsParserMsgUtils::GetLocalizedStringByName(
+ spoofEnglish ? XMLPARSER_PROPERTIES_en_US : XMLPARSER_PROPERTIES,
+ "Expected", msg);
+
+ // . Expected: </%S>.
+ nsAutoString message;
+ nsTextFormatter::ssprintf(message, msg.get(), tagName.get());
+ description.Append(message);
+ }
+
+ // Adjust the column number so that it is one based rather than zero based.
+ tainted_expat<XML_Size> colNumber =
+ RLBOX_EXPAT_MCALL(MOZ_XML_GetCurrentColumnNumber) + 1;
+ tainted_expat<XML_Size> lineNumber =
+ RLBOX_EXPAT_MCALL(MOZ_XML_GetCurrentLineNumber);
+
+ // Copy out the two character bufer that holds the expatBase
+ const std::unique_ptr<XML_Char[]> expatBase =
+ RLBOX_EXPAT_MCALL(MOZ_XML_GetBase)
+ .copy_and_verify_range(
+ [](std::unique_ptr<XML_Char[]> val) {
+ // No additional checks needed as this is sent to GetBaseURI
+ // which checks its inputs
+ return val;
+ },
+ ExpatBaseURI::Length);
+ nsAutoString uri;
+ nsCOMPtr<nsIURI> baseURI;
+ if (expatBase && (baseURI = GetBaseURI(expatBase.get()))) {
+ // Let's ignore if this fails, we're already reporting a parse error.
+ Unused << CopyUTF8toUTF16(baseURI->GetSpecOrDefault(), uri, fallible);
+ }
+ nsAutoString errorText;
+ CreateErrorText(description.get(), uri.get(), lineNumber, colNumber,
+ errorText, spoofEnglish);
+
+ nsAutoString sourceText(mLastLine);
+ AppendErrorPointer(colNumber, mLastLine.get(), mLastLine.Length(),
+ sourceText);
+
+ if (doc && nsContentUtils::IsChromeDoc(doc)) {
+ nsCString path = doc->GetDocumentURI()->GetSpecOrDefault();
+ nsCOMPtr<nsISupports> container = doc->GetContainer();
+ nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
+ nsCString docShellDestroyed("unknown"_ns);
+ if (docShell) {
+ bool destroyed = false;
+ docShell->IsBeingDestroyed(&destroyed);
+ docShellDestroyed.Assign(destroyed ? "true"_ns : "false"_ns);
+ }
+
+ mozilla::Maybe<nsTArray<mozilla::Telemetry::EventExtraEntry>> extra =
+ mozilla::Some<nsTArray<mozilla::Telemetry::EventExtraEntry>>({
+ mozilla::Telemetry::EventExtraEntry{"error_code"_ns,
+ nsPrintfCString("%u", code)},
+ mozilla::Telemetry::EventExtraEntry{
+ "location"_ns,
+ nsPrintfCString(
+ "%lu:%lu",
+ lineNumber.unverified_safe_because(RLBOX_SAFE_PRINT),
+ colNumber.unverified_safe_because(RLBOX_SAFE_PRINT))},
+ mozilla::Telemetry::EventExtraEntry{
+ "last_line"_ns, NS_ConvertUTF16toUTF8(mLastLine)},
+ mozilla::Telemetry::EventExtraEntry{
+ "last_line_len"_ns, nsPrintfCString("%zu", mLastLine.Length())},
+ mozilla::Telemetry::EventExtraEntry{
+ "hidden"_ns, doc->Hidden() ? "true"_ns : "false"_ns},
+ mozilla::Telemetry::EventExtraEntry{"destroyed"_ns,
+ docShellDestroyed},
+ });
+
+ mozilla::Telemetry::SetEventRecordingEnabled("ysod"_ns, true);
+ mozilla::Telemetry::RecordEvent(
+ mozilla::Telemetry::EventID::Ysod_Shown_Ysod, mozilla::Some(path),
+ extra);
+ }
+
+ // Try to create and initialize the script error.
+ nsCOMPtr<nsIScriptError> serr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+ nsresult rv = NS_ERROR_FAILURE;
+ if (serr) {
+ rv = serr->InitWithSourceURI(
+ errorText, mURIs.SafeElementAt(0), mLastLine,
+ lineNumber.unverified_safe_because(RLBOX_SAFE_PRINT),
+ colNumber.unverified_safe_because(RLBOX_SAFE_PRINT),
+ nsIScriptError::errorFlag, "malformed-xml", mInnerWindowID);
+ }
+
+ // If it didn't initialize, we can't do any logging.
+ bool shouldReportError = NS_SUCCEEDED(rv);
+
+ // mSink might be null here if our parser was terminated.
+ if (mSink && shouldReportError) {
+ rv = mSink->ReportError(errorText.get(), sourceText.get(), serr,
+ &shouldReportError);
+ if (NS_FAILED(rv)) {
+ shouldReportError = true;
+ }
+ }
+
+ // mOriginalSink might be null here if our parser was terminated.
+ if (mOriginalSink) {
+ nsCOMPtr<Document> doc = do_QueryInterface(mOriginalSink->GetTarget());
+ if (doc && doc->SuppressParserErrorConsoleMessages()) {
+ shouldReportError = false;
+ }
+ }
+
+ if (shouldReportError) {
+ nsCOMPtr<nsIConsoleService> cs(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+ if (cs) {
+ cs->LogMessage(serr);
+ }
+ }
+
+ return NS_ERROR_HTMLPARSER_STOPPARSING;
+}
+
+// Because we need to allocate a buffer in the RLBOX sandbox, and copy the data
+// to it for Expat to parse, we are limited in size by the memory available in
+// the RLBOX sandbox. nsExpatDriver::ChunkAndParseBuffer divides the buffer into
+// chunks of sMaxChunkLength characters or less, and passes them to
+// nsExpatDriver::ParseBuffer. That should ensure that we almost never run out
+// of memory in the sandbox.
+void nsExpatDriver::ChunkAndParseBuffer(const char16_t* aBuffer,
+ uint32_t aLength, bool aIsFinal,
+ uint32_t* aPassedToExpat,
+ uint32_t* aConsumed,
+ XML_Size* aLastLineLength) {
+ *aConsumed = 0;
+ *aLastLineLength = 0;
+
+ uint32_t remainder = aLength;
+ while (remainder > sMaxChunkLength) {
+ ParseChunk(aBuffer, sMaxChunkLength, ChunkOrBufferIsFinal::None, aConsumed,
+ aLastLineLength);
+ aBuffer += sMaxChunkLength;
+ remainder -= sMaxChunkLength;
+ if (NS_FAILED(mInternalState)) {
+ // Stop parsing if there's an error (including if we're blocked or
+ // interrupted).
+ *aPassedToExpat = aLength - remainder;
+ return;
+ }
+ }
+
+ ParseChunk(aBuffer, remainder,
+ aIsFinal ? ChunkOrBufferIsFinal::FinalChunkAndBuffer
+ : ChunkOrBufferIsFinal::FinalChunk,
+ aConsumed, aLastLineLength);
+ *aPassedToExpat = aLength;
+}
+
+void nsExpatDriver::ParseChunk(const char16_t* aBuffer, uint32_t aLength,
+ ChunkOrBufferIsFinal aIsFinal,
+ uint32_t* aConsumed, XML_Size* aLastLineLength) {
+ NS_ASSERTION((aBuffer && aLength != 0) || (!aBuffer && aLength == 0), "?");
+ NS_ASSERTION(mInternalState != NS_OK ||
+ (aIsFinal == ChunkOrBufferIsFinal::FinalChunkAndBuffer) ||
+ aBuffer,
+ "Useless call, we won't call Expat");
+ MOZ_ASSERT(!BlockedOrInterrupted() || !aBuffer,
+ "Non-null buffer when resuming");
+ MOZ_ASSERT(mExpatParser);
+
+ auto parserBytesBefore_verifier = [&](auto parserBytesBefore) {
+ MOZ_RELEASE_ASSERT(parserBytesBefore >= 0, "Unexpected value");
+ MOZ_RELEASE_ASSERT(parserBytesBefore % sizeof(char16_t) == 0,
+ "Consumed part of a char16_t?");
+ return parserBytesBefore;
+ };
+ int32_t parserBytesBefore = RLBOX_EXPAT_SAFE_MCALL(
+ XML_GetCurrentByteIndex, parserBytesBefore_verifier);
+
+ if (mInternalState != NS_OK && !BlockedOrInterrupted()) {
+ return;
+ }
+
+ XML_Status status;
+ bool inParser = mInParser; // Save in-parser status
+ mInParser = true;
+ Maybe<TransferBuffer<char16_t>> buffer;
+ if (BlockedOrInterrupted()) {
+ mInternalState = NS_OK; // Resume in case we're blocked.
+ status = RLBOX_EXPAT_SAFE_MCALL(MOZ_XML_ResumeParser, status_verifier);
+ } else {
+ buffer.emplace(Sandbox(), aBuffer, aLength);
+ MOZ_RELEASE_ASSERT(!aBuffer || !!*buffer.ref(),
+ "Chunking should avoid OOM in ParseBuffer");
+
+ status = RLBOX_EXPAT_SAFE_MCALL(
+ MOZ_XML_Parse, status_verifier,
+ rlbox::sandbox_reinterpret_cast<const char*>(*buffer.ref()),
+ aLength * sizeof(char16_t),
+ aIsFinal == ChunkOrBufferIsFinal::FinalChunkAndBuffer);
+ }
+ mInParser = inParser; // Restore in-parser status
+
+ auto parserBytesConsumed_verifier = [&](auto parserBytesConsumed) {
+ MOZ_RELEASE_ASSERT(parserBytesConsumed >= 0, "Unexpected value");
+ MOZ_RELEASE_ASSERT(parserBytesConsumed >= parserBytesBefore,
+ "How'd this happen?");
+ MOZ_RELEASE_ASSERT(parserBytesConsumed % sizeof(char16_t) == 0,
+ "Consumed part of a char16_t?");
+ return parserBytesConsumed;
+ };
+ int32_t parserBytesConsumed = RLBOX_EXPAT_SAFE_MCALL(
+ XML_GetCurrentByteIndex, parserBytesConsumed_verifier);
+
+ // Consumed something.
+ *aConsumed += (parserBytesConsumed - parserBytesBefore) / sizeof(char16_t);
+
+ NS_ASSERTION(status != XML_STATUS_SUSPENDED || BlockedOrInterrupted(),
+ "Inconsistent expat suspension state.");
+
+ if (status == XML_STATUS_ERROR) {
+ mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
+ }
+
+ if (*aConsumed > 0 &&
+ (aIsFinal != ChunkOrBufferIsFinal::None || NS_FAILED(mInternalState))) {
+ *aLastLineLength = RLBOX_EXPAT_SAFE_MCALL(MOZ_XML_GetCurrentColumnNumber,
+ safe_unverified<XML_Size>);
+ }
+}
+
+nsresult nsExpatDriver::ResumeParse(nsScanner& aScanner, bool aIsFinalChunk) {
+ // We keep the scanner pointing to the position where Expat will start
+ // parsing.
+ nsScannerIterator currentExpatPosition;
+ aScanner.CurrentPosition(currentExpatPosition);
+
+ // This is the start of the first buffer that we need to pass to Expat.
+ nsScannerIterator start = currentExpatPosition;
+ start.advance(mExpatBuffered);
+
+ // This is the end of the last buffer (at this point, more data could come in
+ // later).
+ nsScannerIterator end;
+ aScanner.EndReading(end);
+
+ MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+ ("Remaining in expat's buffer: %i, remaining in scanner: %zu.",
+ mExpatBuffered, Distance(start, end)));
+
+ // We want to call Expat if we have more buffers, or if we know there won't
+ // be more buffers (and so we want to flush the remaining data), or if we're
+ // currently blocked and there's data in Expat's buffer.
+ while (start != end || (aIsFinalChunk && !mMadeFinalCallToExpat) ||
+ (BlockedOrInterrupted() && mExpatBuffered > 0)) {
+ bool noMoreBuffers = start == end && aIsFinalChunk;
+ bool blocked = BlockedOrInterrupted();
+
+ const char16_t* buffer;
+ uint32_t length;
+ if (blocked || noMoreBuffers) {
+ // If we're blocked we just resume Expat so we don't need a buffer, if
+ // there aren't any more buffers we pass a null buffer to Expat.
+ buffer = nullptr;
+ length = 0;
+
+ if (blocked) {
+ MOZ_LOG(
+ gExpatDriverLog, LogLevel::Debug,
+ ("Resuming Expat, will parse data remaining in Expat's "
+ "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
+ NS_ConvertUTF16toUTF8(currentExpatPosition.get(), mExpatBuffered)
+ .get()));
+ } else {
+ NS_ASSERTION(mExpatBuffered == Distance(currentExpatPosition, end),
+ "Didn't pass all the data to Expat?");
+ MOZ_LOG(
+ gExpatDriverLog, LogLevel::Debug,
+ ("Last call to Expat, will parse data remaining in Expat's "
+ "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
+ NS_ConvertUTF16toUTF8(currentExpatPosition.get(), mExpatBuffered)
+ .get()));
+ }
+ } else {
+ buffer = start.get();
+ length = uint32_t(start.size_forward());
+
+ MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+ ("Calling Expat, will parse data remaining in Expat's buffer and "
+ "new data.\nContent of Expat's buffer:\n-----\n%s\n-----\nNew "
+ "data:\n-----\n%s\n-----\n",
+ NS_ConvertUTF16toUTF8(currentExpatPosition.get(), mExpatBuffered)
+ .get(),
+ NS_ConvertUTF16toUTF8(start.get(), length).get()));
+ }
+
+ uint32_t passedToExpat;
+ uint32_t consumed;
+ XML_Size lastLineLength;
+ ChunkAndParseBuffer(buffer, length, noMoreBuffers, &passedToExpat,
+ &consumed, &lastLineLength);
+ MOZ_ASSERT_IF(passedToExpat != length, NS_FAILED(mInternalState));
+ MOZ_ASSERT(consumed <= passedToExpat + mExpatBuffered);
+ if (consumed > 0) {
+ nsScannerIterator oldExpatPosition = currentExpatPosition;
+ currentExpatPosition.advance(consumed);
+
+ // We consumed some data, we want to store the last line of data that
+ // was consumed in case we run into an error (to show the line in which
+ // the error occurred).
+
+ if (lastLineLength <= consumed) {
+ // The length of the last line was less than what expat consumed, so
+ // there was at least one line break in the consumed data. Store the
+ // last line until the point where we stopped parsing.
+ nsScannerIterator startLastLine = currentExpatPosition;
+ startLastLine.advance(-((ptrdiff_t)lastLineLength));
+ if (!CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine)) {
+ return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
+ }
+ } else {
+ // There was no line break in the consumed data, append the consumed
+ // data.
+ if (!AppendUnicodeTo(oldExpatPosition, currentExpatPosition,
+ mLastLine)) {
+ return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
+ }
+ }
+ }
+
+ mExpatBuffered += passedToExpat - consumed;
+
+ if (BlockedOrInterrupted()) {
+ MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+ ("Blocked or interrupted parser (probably for loading linked "
+ "stylesheets or scripts)."));
+
+ aScanner.SetPosition(currentExpatPosition, true);
+ aScanner.Mark();
+
+ return mInternalState;
+ }
+
+ if (noMoreBuffers && mExpatBuffered == 0) {
+ mMadeFinalCallToExpat = true;
+ }
+
+ if (NS_FAILED(mInternalState)) {
+ if (RLBOX_EXPAT_SAFE_MCALL(MOZ_XML_GetErrorCode, error_verifier) !=
+ XML_ERROR_NONE) {
+ NS_ASSERTION(mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING,
+ "Unexpected error");
+
+ // Look for the next newline after the last one we consumed
+ nsScannerIterator lastLine = currentExpatPosition;
+ while (lastLine != end) {
+ length = uint32_t(lastLine.size_forward());
+ uint32_t endOffset = 0;
+ const char16_t* buffer = lastLine.get();
+ while (endOffset < length && buffer[endOffset] != '\n' &&
+ buffer[endOffset] != '\r') {
+ ++endOffset;
+ }
+ mLastLine.Append(Substring(buffer, buffer + endOffset));
+ if (endOffset < length) {
+ // We found a newline.
+ break;
+ }
+
+ lastLine.advance(length);
+ }
+
+ HandleError();
+ }
+
+ return mInternalState;
+ }
+
+ // Either we have more buffers, or we were blocked (and we'll flush in the
+ // next iteration), or we should have emptied Expat's buffer.
+ NS_ASSERTION(!noMoreBuffers || blocked ||
+ (mExpatBuffered == 0 && currentExpatPosition == end),
+ "Unreachable data left in Expat's buffer");
+
+ start.advance(length);
+
+ // It's possible for start to have passed end if we received more data
+ // (e.g. if we spun the event loop in an inline script). Reload end now
+ // to compensate.
+ aScanner.EndReading(end);
+ }
+
+ aScanner.SetPosition(currentExpatPosition, true);
+ aScanner.Mark();
+
+ MOZ_LOG(gExpatDriverLog, LogLevel::Debug,
+ ("Remaining in expat's buffer: %i, remaining in scanner: %zu.",
+ mExpatBuffered, Distance(currentExpatPosition, end)));
+
+ return NS_SUCCEEDED(mInternalState) ? NS_ERROR_HTMLPARSER_EOF : NS_OK;
+}
+
+mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase>
+RLBoxExpatSandboxPool::CreateSandboxData(uint64_t aSize) {
+ // Create expat sandbox
+ auto sandbox = mozilla::MakeUnique<rlbox_sandbox_expat>();
+
+#ifdef MOZ_WASM_SANDBOXING_EXPAT
+ const w2c_mem_capacity capacity =
+ get_valid_wasm2c_memory_capacity(aSize, true /* 32-bit wasm memory*/);
+ bool create_ok = sandbox->create_sandbox(/* infallible = */ false, &capacity);
+#else
+ bool create_ok = sandbox->create_sandbox();
+#endif
+
+ NS_ENSURE_TRUE(create_ok, nullptr);
+
+ mozilla::UniquePtr<RLBoxExpatSandboxData> sbxData =
+ mozilla::MakeUnique<RLBoxExpatSandboxData>(aSize);
+
+ // Register callbacks common to both system and non-system principals
+ sbxData->mHandleXMLDeclaration =
+ sandbox->register_callback(Driver_HandleXMLDeclaration);
+ sbxData->mHandleCharacterData =
+ sandbox->register_callback(Driver_HandleCharacterData);
+ sbxData->mHandleProcessingInstruction =
+ sandbox->register_callback(Driver_HandleProcessingInstruction);
+ sbxData->mHandleDefault = sandbox->register_callback(Driver_HandleDefault);
+ sbxData->mHandleExternalEntityRef =
+ sandbox->register_callback(Driver_HandleExternalEntityRef);
+ sbxData->mHandleComment = sandbox->register_callback(Driver_HandleComment);
+ sbxData->mHandleStartCdataSection =
+ sandbox->register_callback(Driver_HandleStartCdataSection);
+ sbxData->mHandleEndCdataSection =
+ sandbox->register_callback(Driver_HandleEndCdataSection);
+ sbxData->mHandleStartDoctypeDecl =
+ sandbox->register_callback(Driver_HandleStartDoctypeDecl);
+ sbxData->mHandleEndDoctypeDecl =
+ sandbox->register_callback(Driver_HandleEndDoctypeDecl);
+
+ sbxData->mSandbox = std::move(sandbox);
+
+ return sbxData;
+}
+
+mozilla::StaticRefPtr<RLBoxExpatSandboxPool> RLBoxExpatSandboxPool::sSingleton;
+
+void RLBoxExpatSandboxPool::Initialize(size_t aDelaySeconds) {
+ mozilla::AssertIsOnMainThread();
+ RLBoxExpatSandboxPool::sSingleton = new RLBoxExpatSandboxPool(aDelaySeconds);
+ ClearOnShutdown(&RLBoxExpatSandboxPool::sSingleton);
+}
+
+void RLBoxExpatSandboxData::AttachDriver(bool aIsSystemPrincipal,
+ void* aDriver) {
+ MOZ_ASSERT(!mSandbox->sandbox_storage);
+ MOZ_ASSERT(mHandleStartElement.is_unregistered());
+ MOZ_ASSERT(mHandleEndElement.is_unregistered());
+
+ if (aIsSystemPrincipal) {
+ mHandleStartElement = mSandbox->register_callback(
+ nsExpatDriver::HandleStartElementForSystemPrincipal);
+ mHandleEndElement = mSandbox->register_callback(
+ nsExpatDriver::HandleEndElementForSystemPrincipal);
+ } else {
+ mHandleStartElement =
+ mSandbox->register_callback(nsExpatDriver::HandleStartElement);
+ mHandleEndElement =
+ mSandbox->register_callback(nsExpatDriver::HandleEndElement);
+ }
+
+ mSandbox->sandbox_storage = aDriver;
+}
+
+void RLBoxExpatSandboxData::DetachDriver() {
+ mSandbox->sandbox_storage = nullptr;
+ mHandleStartElement.unregister();
+ mHandleEndElement.unregister();
+}
+
+RLBoxExpatSandboxData::~RLBoxExpatSandboxData() {
+ MOZ_ASSERT(mSandbox);
+
+ // DetachDriver should always be called before a sandbox goes back into the
+ // pool, and thus before it's freed.
+ MOZ_ASSERT(!mSandbox->sandbox_storage);
+ MOZ_ASSERT(mHandleStartElement.is_unregistered());
+ MOZ_ASSERT(mHandleEndElement.is_unregistered());
+
+ // Unregister callbacks
+ mHandleXMLDeclaration.unregister();
+ mHandleCharacterData.unregister();
+ mHandleProcessingInstruction.unregister();
+ mHandleDefault.unregister();
+ mHandleExternalEntityRef.unregister();
+ mHandleComment.unregister();
+ mHandleStartCdataSection.unregister();
+ mHandleEndCdataSection.unregister();
+ mHandleStartDoctypeDecl.unregister();
+ mHandleEndDoctypeDecl.unregister();
+ // Destroy sandbox
+ mSandbox->destroy_sandbox();
+ MOZ_COUNT_DTOR(RLBoxExpatSandboxData);
+}
+
+nsresult nsExpatDriver::Initialize(nsIURI* aURI, nsIContentSink* aSink) {
+ mSink = do_QueryInterface(aSink);
+ if (!mSink) {
+ NS_ERROR("nsExpatDriver didn't get an nsIExpatSink");
+ // Make sure future calls to us bail out as needed
+ mInternalState = NS_ERROR_UNEXPECTED;
+ return mInternalState;
+ }
+
+ mOriginalSink = aSink;
+
+ static const char16_t kExpatSeparator[] = {kExpatSeparatorChar, '\0'};
+
+ // Get the doc if any
+ nsCOMPtr<Document> doc = do_QueryInterface(mOriginalSink->GetTarget());
+ if (doc) {
+ nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
+ nsCOMPtr<nsPIDOMWindowInner> inner;
+ if (win) {
+ inner = win->GetCurrentInnerWindow();
+ } else {
+ bool aHasHadScriptHandlingObject;
+ nsIScriptGlobalObject* global =
+ doc->GetScriptHandlingObject(aHasHadScriptHandlingObject);
+ if (global) {
+ inner = do_QueryInterface(global);
+ }
+ }
+ if (inner) {
+ mInnerWindowID = inner->WindowID();
+ }
+ }
+
+ // Create sandbox
+ //
+ // We have to make sure the sandbox is large enough. We unscientifically
+ // request two MB. Note that the parsing itself is chunked so as not to
+ // require a large sandbox.
+ static const uint64_t minSandboxSize = 2 * 1024 * 1024;
+ MOZ_ASSERT(!mSandboxPoolData);
+ mSandboxPoolData =
+ RLBoxExpatSandboxPool::sSingleton->PopOrCreate(minSandboxSize);
+ NS_ENSURE_TRUE(mSandboxPoolData, NS_ERROR_OUT_OF_MEMORY);
+
+ MOZ_ASSERT(SandboxData());
+
+ SandboxData()->AttachDriver(doc && doc->NodePrincipal()->IsSystemPrincipal(),
+ static_cast<void*>(this));
+
+ // Create expat parser.
+ // We need to copy the encoding and namespace separator into the sandbox.
+ // For the noop sandbox we pass in the memsuite; for the Wasm sandbox, we
+ // pass in nullptr to let expat use the standard library memory suite.
+ auto expatSeparator = TransferBuffer<char16_t>(
+ Sandbox(), kExpatSeparator,
+ nsCharTraits<char16_t>::length(kExpatSeparator) + 1);
+ MOZ_RELEASE_ASSERT(*expatSeparator);
+ auto utf16 = TransferBuffer<char16_t>(
+ Sandbox(), kUTF16, nsCharTraits<char16_t>::length(kUTF16) + 1);
+ MOZ_RELEASE_ASSERT(*utf16);
+ mExpatParser = Sandbox()->invoke_sandbox_function(
+ MOZ_XML_ParserCreate_MM, *utf16, nullptr, *expatSeparator);
+ NS_ENSURE_TRUE(mExpatParser, NS_ERROR_FAILURE);
+
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetReturnNSTriplet, XML_TRUE);
+
+#ifdef XML_DTD
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetParamEntityParsing,
+ XML_PARAM_ENTITY_PARSING_ALWAYS);
+#endif
+
+ auto baseURI = GetExpatBaseURI(aURI);
+ auto uri =
+ TransferBuffer<XML_Char>(Sandbox(), &baseURI[0], ArrayLength(baseURI));
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetBase, *uri);
+
+ // Set up the callbacks
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetXmlDeclHandler,
+ SandboxData()->mHandleXMLDeclaration);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetElementHandler,
+ SandboxData()->mHandleStartElement,
+ SandboxData()->mHandleEndElement);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetCharacterDataHandler,
+ SandboxData()->mHandleCharacterData);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetProcessingInstructionHandler,
+ SandboxData()->mHandleProcessingInstruction);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetDefaultHandlerExpand,
+ SandboxData()->mHandleDefault);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetExternalEntityRefHandler,
+ SandboxData()->mHandleExternalEntityRef);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetCommentHandler, SandboxData()->mHandleComment);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetCdataSectionHandler,
+ SandboxData()->mHandleStartCdataSection,
+ SandboxData()->mHandleEndCdataSection);
+
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetParamEntityParsing,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
+ RLBOX_EXPAT_MCALL(MOZ_XML_SetDoctypeDeclHandler,
+ SandboxData()->mHandleStartDoctypeDecl,
+ SandboxData()->mHandleEndDoctypeDecl);
+
+ return mInternalState;
+}
+
+NS_IMETHODIMP
+nsExpatDriver::BuildModel(nsIContentSink* aSink) { return mInternalState; }
+
+void nsExpatDriver::DidBuildModel() {
+ if (!mInParser) {
+ // Because nsExpatDriver is cycle-collected, it gets destroyed
+ // asynchronously. We want to eagerly release the sandbox back into the
+ // pool so that it can be reused immediately, unless this is a reentrant
+ // call (which we track with mInParser).
+ Destroy();
+ }
+ mOriginalSink = nullptr;
+ mSink = nullptr;
+}
+
+NS_IMETHODIMP_(void)
+nsExpatDriver::Terminate() {
+ // XXX - not sure what happens to the unparsed data.
+ if (mExpatParser) {
+ RLBOX_EXPAT_MCALL(MOZ_XML_StopParser, XML_FALSE);
+ }
+ mInternalState = NS_ERROR_HTMLPARSER_STOPPARSING;
+}
+
+/*************************** Unused methods **********************************/
+
+void nsExpatDriver::MaybeStopParser(nsresult aState) {
+ if (NS_FAILED(aState)) {
+ // If we had a failure we want to override NS_ERROR_HTMLPARSER_INTERRUPTED
+ // and we want to override NS_ERROR_HTMLPARSER_BLOCK but not with
+ // NS_ERROR_HTMLPARSER_INTERRUPTED.
+ if (NS_SUCCEEDED(mInternalState) ||
+ mInternalState == NS_ERROR_HTMLPARSER_INTERRUPTED ||
+ (mInternalState == NS_ERROR_HTMLPARSER_BLOCK &&
+ aState != NS_ERROR_HTMLPARSER_INTERRUPTED)) {
+ mInternalState = (aState == NS_ERROR_HTMLPARSER_INTERRUPTED ||
+ aState == NS_ERROR_HTMLPARSER_BLOCK)
+ ? aState
+ : NS_ERROR_HTMLPARSER_STOPPARSING;
+ }
+
+ // If we get an error then we need to stop Expat (by calling XML_StopParser
+ // with false as the last argument). If the parser should be blocked or
+ // interrupted we need to pause Expat (by calling XML_StopParser with
+ // true as the last argument).
+
+ // Note that due to Bug 1742913, we need to explicitly cast the parameter to
+ // an int so that the value is correctly zero extended.
+ int resumable = BlockedOrInterrupted();
+ RLBOX_EXPAT_MCALL(MOZ_XML_StopParser, resumable);
+ } else if (NS_SUCCEEDED(mInternalState)) {
+ // Only clobber mInternalState with the success code if we didn't block or
+ // interrupt before.
+ mInternalState = aState;
+ }
+}
+
+nsExpatDriver::ExpatBaseURI nsExpatDriver::GetExpatBaseURI(nsIURI* aURI) {
+ mURIs.AppendElement(aURI);
+
+ MOZ_RELEASE_ASSERT(mURIs.Length() <= std::numeric_limits<XML_Char>::max());
+
+ return ExpatBaseURI(static_cast<XML_Char>(mURIs.Length()), XML_T('\0'));
+}
+
+nsIURI* nsExpatDriver::GetBaseURI(const XML_Char* aBase) const {
+ MOZ_ASSERT(aBase[0] != '\0' && aBase[1] == '\0');
+
+ if (aBase[0] == '\0' || aBase[1] != '\0') {
+ return nullptr;
+ }
+
+ uint32_t index = aBase[0] - 1;
+ MOZ_ASSERT(index < mURIs.Length());
+
+ return mURIs.SafeElementAt(index);
+}
+
+inline RLBoxExpatSandboxData* nsExpatDriver::SandboxData() const {
+ return reinterpret_cast<RLBoxExpatSandboxData*>(
+ mSandboxPoolData->SandboxData());
+}
+
+inline rlbox_sandbox_expat* nsExpatDriver::Sandbox() const {
+ return SandboxData()->Sandbox();
+}
diff --git a/parser/htmlparser/nsExpatDriver.h b/parser/htmlparser/nsExpatDriver.h
new file mode 100644
index 0000000000..b07ba72b6b
--- /dev/null
+++ b/parser/htmlparser/nsExpatDriver.h
@@ -0,0 +1,256 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef NS_EXPAT_DRIVER__
+#define NS_EXPAT_DRIVER__
+
+#include "expat_config.h"
+#include "expat.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsIDTD.h"
+#include "nsIInputStream.h"
+#include "nsIParser.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsScanner.h"
+
+#include "rlbox_expat.h"
+#include "nsRLBoxExpatDriver.h"
+#include "mozilla/UniquePtr.h"
+
+class nsIExpatSink;
+struct nsCatalogData;
+class RLBoxExpatSandboxData;
+namespace mozilla {
+template <typename, size_t>
+class Array;
+}
+
+class nsExpatDriver : public nsIDTD {
+ virtual ~nsExpatDriver();
+
+ public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
+ NS_DECL_NSIDTD
+ NS_DECL_CYCLE_COLLECTION_CLASS(nsExpatDriver)
+
+ nsExpatDriver();
+
+ nsresult Initialize(nsIURI* aURI, nsIContentSink* aSink);
+
+ nsresult ResumeParse(nsScanner& aScanner, bool aIsFinalChunk);
+
+ int HandleExternalEntityRef(const char16_t* aOpenEntityNames,
+ const char16_t* aBase, const char16_t* aSystemId,
+ const char16_t* aPublicId);
+ static void HandleStartElement(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName,
+ tainted_expat<const char16_t**> aAtts);
+ static void HandleStartElementForSystemPrincipal(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName,
+ tainted_expat<const char16_t**> aAtts);
+ static void HandleEndElement(rlbox_sandbox_expat& aSandbox,
+ tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName);
+ static void HandleEndElementForSystemPrincipal(
+ rlbox_sandbox_expat& aSandbox, tainted_expat<void*> aUserData,
+ tainted_expat<const char16_t*> aName);
+ nsresult HandleCharacterData(const char16_t* aCData, const uint32_t aLength);
+ nsresult HandleComment(const char16_t* aName);
+ nsresult HandleProcessingInstruction(const char16_t* aTarget,
+ const char16_t* aData);
+ nsresult HandleXMLDeclaration(const char16_t* aVersion,
+ const char16_t* aEncoding, int32_t aStandalone);
+ nsresult HandleDefault(const char16_t* aData, const uint32_t aLength);
+ nsresult HandleStartCdataSection();
+ nsresult HandleEndCdataSection();
+ nsresult HandleStartDoctypeDecl(const char16_t* aDoctypeName,
+ const char16_t* aSysid,
+ const char16_t* aPubid,
+ bool aHasInternalSubset);
+ nsresult HandleEndDoctypeDecl();
+
+ private:
+ // Load up an external stream to get external entity information
+ nsresult OpenInputStreamFromExternalDTD(const char16_t* aFPIStr,
+ const char16_t* aURLStr,
+ nsIURI* aBaseURI,
+ nsIInputStream** aStream,
+ nsIURI** aAbsURI);
+
+ enum class ChunkOrBufferIsFinal {
+ None,
+ FinalChunk,
+ FinalChunkAndBuffer,
+ };
+
+ /**
+ * Pass a buffer to Expat. If Expat is blocked aBuffer should be null and
+ * aLength should be 0. The result of the call will be stored in
+ * mInternalState. Expat will parse as much of the buffer as it can and store
+ * the rest in its internal buffer.
+ *
+ * @param aBuffer the buffer to pass to Expat. May be null.
+ * @param aLength the length of the buffer to pass to Expat (in number of
+ * char16_t's). Must be 0 if aBuffer is null and > 0 if
+ * aBuffer is not null.
+ * @param aIsFinal whether this is the last chunk in a row passed to
+ * ParseChunk, and if so whether it's the last chunk and
+ * buffer passed to ParseChunk (meaning there will be no more
+ * calls to ParseChunk for the document being parsed).
+ * @param aConsumed [out] the number of PRUnichars that Expat consumed. This
+ * doesn't include the PRUnichars that Expat stored in
+ * its buffer but didn't parse yet.
+ * @param aLastLineLength [out] the length of the last line that Expat has
+ * consumed. This will only be computed if
+ * aIsFinal is not None or mInternalState is set
+ * to a failure.
+ */
+ void ParseChunk(const char16_t* aBuffer, uint32_t aLength,
+ ChunkOrBufferIsFinal aIsFinal, uint32_t* aConsumed,
+ XML_Size* aLastLineLength);
+ /**
+ * Wrapper for ParseBuffer. If the buffer is too large to be copied into the
+ * sandbox all at once, splits it into chunks and invokes ParseBuffer in a
+ * loop.
+ *
+ * @param aBuffer the buffer to pass to Expat. May be null.
+ * @param aLength the length of the buffer to pass to Expat (in number of
+ * char16_t's). Must be 0 if aBuffer is null and > 0 if
+ * aBuffer is not null.
+ * @param aIsFinal whether there will definitely not be any more new buffers
+ * passed in to ParseBuffer
+ * @param aConsumed [out] the number of PRUnichars that Expat consumed. This
+ * doesn't include the PRUnichars that Expat stored in
+ * its buffer but didn't parse yet.
+ * @param aLastLineLength [out] the length of the last line that Expat has
+ * consumed.
+ */
+ void ChunkAndParseBuffer(const char16_t* aBuffer, uint32_t aLength,
+ bool aIsFinal, uint32_t* aPassedToExpat,
+ uint32_t* aConsumed, XML_Size* aLastLineLength);
+
+ nsresult HandleError();
+
+ void MaybeStopParser(nsresult aState);
+
+ bool BlockedOrInterrupted() {
+ return mInternalState == NS_ERROR_HTMLPARSER_BLOCK ||
+ mInternalState == NS_ERROR_HTMLPARSER_INTERRUPTED;
+ }
+
+ // Expat allows us to set the base URI for entities. It doesn't use the base
+ // URI itself, but just passes it along to all the entity handlers (just the
+ // external entity reference handler for us). It does expect the base URI as a
+ // null-terminated string, with the same character type as the parsed buffers
+ // (char16_t in our case). Because nsIURI stores a UTF-8 string we have to do
+ // a conversion to UTF-16 for Expat. We also RLBox the Expat parser, so we
+ // also do 2 copies (into RLBox sandbox, and Expat does a copy into its pool).
+ // Most of the time this base URI is unused (the external entity handler is
+ // rarely called), but when it is we also convert it back to a nsIURI, so we
+ // convert the string back to UTF-8.
+ //
+ // We'd rather not do any of these conversions and copies, so we use a (hacky)
+ // workaround. We store all base URIs in an array of nsIURIs. Instead of
+ // passing the real URI to Expat as a string, we pass it a null-terminated
+ // 2-character buffer. The first character of that buffer stores the index of
+ // the corresponding nsIURI in the array (incremented with 1 because 0 is used
+ // to terminate a string). The entity handler can then use the index from the
+ // base URI that Expat passes it to look up the right nsIURI from the array.
+ //
+ // GetExpatBaseURI pushes the nsIURI to the array, and creates the
+ // two-character buffer for it.
+ //
+ // GetBaseURI looks up the right nsIURI in the array, based on the index from
+ // the two-character buffer.
+ using ExpatBaseURI = mozilla::Array<XML_Char, 2>;
+ ExpatBaseURI GetExpatBaseURI(nsIURI* aURI);
+ nsIURI* GetBaseURI(const XML_Char* aBase) const;
+
+ RLBoxExpatSandboxData* SandboxData() const;
+ rlbox_sandbox_expat* Sandbox() const;
+
+ // Destroy expat parser and return sandbox to pool
+ void Destroy();
+
+ mozilla::UniquePtr<mozilla::RLBoxSandboxPoolData> mSandboxPoolData;
+ tainted_expat<XML_Parser> mExpatParser;
+
+ nsString mLastLine;
+ nsString mCDataText;
+ // Various parts of a doctype
+ nsString mDoctypeName;
+ nsString mSystemID;
+ nsString mPublicID;
+ nsString mInternalSubset;
+ bool mInCData;
+ bool mInInternalSubset;
+ bool mInExternalDTD;
+ bool mMadeFinalCallToExpat;
+
+ // Used to track if we're in the parser.
+ bool mInParser;
+
+ nsresult mInternalState;
+
+ // The length of the data in Expat's buffer (in number of PRUnichars).
+ uint32_t mExpatBuffered;
+
+ uint16_t mTagDepth;
+
+ // These sinks all refer the same conceptual object. mOriginalSink is
+ // identical with the nsIContentSink* passed to WillBuildModel, and exists
+ // only to avoid QI-ing back to nsIContentSink*.
+ nsCOMPtr<nsIContentSink> mOriginalSink;
+ nsCOMPtr<nsIExpatSink> mSink;
+
+ const nsCatalogData* mCatalogData; // weak
+ nsTArray<nsCOMPtr<nsIURI>> mURIs;
+
+ // Used for error reporting.
+ uint64_t mInnerWindowID;
+};
+
+class RLBoxExpatSandboxData : public mozilla::RLBoxSandboxDataBase {
+ friend class RLBoxExpatSandboxPool;
+ friend class nsExpatDriver;
+
+ public:
+ explicit RLBoxExpatSandboxData(uint64_t aSize)
+ : mozilla::RLBoxSandboxDataBase(aSize) {
+ MOZ_COUNT_CTOR(RLBoxExpatSandboxData);
+ }
+ ~RLBoxExpatSandboxData();
+ rlbox_sandbox_expat* Sandbox() const { return mSandbox.get(); }
+ // After getting a sandbox from the pool we need to register the
+ // Handle{Start,End}Element callbacks and associate the driver with the
+ // sandbox.
+ void AttachDriver(bool IsSystemPrincipal, void* aDriver);
+ void DetachDriver();
+
+ private:
+ mozilla::UniquePtr<rlbox_sandbox_expat> mSandbox;
+ // Common expat callbacks that persist across calls to {Attach,Detach}Driver,
+ // and consequently across sandbox reuses.
+ sandbox_callback_expat<XML_XmlDeclHandler> mHandleXMLDeclaration;
+ sandbox_callback_expat<XML_CharacterDataHandler> mHandleCharacterData;
+ sandbox_callback_expat<XML_ProcessingInstructionHandler>
+ mHandleProcessingInstruction;
+ sandbox_callback_expat<XML_DefaultHandler> mHandleDefault;
+ sandbox_callback_expat<XML_ExternalEntityRefHandler> mHandleExternalEntityRef;
+ sandbox_callback_expat<XML_CommentHandler> mHandleComment;
+ sandbox_callback_expat<XML_StartCdataSectionHandler> mHandleStartCdataSection;
+ sandbox_callback_expat<XML_EndCdataSectionHandler> mHandleEndCdataSection;
+ sandbox_callback_expat<XML_StartDoctypeDeclHandler> mHandleStartDoctypeDecl;
+ sandbox_callback_expat<XML_EndDoctypeDeclHandler> mHandleEndDoctypeDecl;
+ // Expat callbacks specific to each driver, and thus (re)set across sandbox
+ // reuses.
+ sandbox_callback_expat<XML_StartElementHandler> mHandleStartElement;
+ sandbox_callback_expat<XML_EndElementHandler> mHandleEndElement;
+};
+
+#endif
diff --git a/parser/htmlparser/nsHTMLTagList.h b/parser/htmlparser/nsHTMLTagList.h
new file mode 100644
index 0000000000..b64dea4854
--- /dev/null
+++ b/parser/htmlparser/nsHTMLTagList.h
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// IWYU pragma: private, include "nsHTMLTags.h"
+
+/******
+
+ This file contains the list of all HTML tags.
+ See nsHTMLTags.h for access to the enum values for tags.
+
+ It is designed to be used as input to various places that will define the
+ HTML_TAG macro in useful ways through the magic of C preprocessing.
+ Additionally, it is consumed by the self-regeneration code in
+ ElementName.java from which nsHtml5ElementName.cpp/h is translated.
+ See parser/html/java/README.txt.
+
+ If you edit this list, you need to re-run ElementName.java
+ self-regeneration and the HTML parser Java to C++ translation.
+
+ All entries must be enclosed in the macro HTML_TAG which will have cruel
+ and unusual things done to it.
+
+ It is recommended (but not strictly necessary) to keep all entries
+ in alphabetical order.
+
+ The first argument to HTML_TAG is the tag name. The second argument is the
+ "creator" method of the form NS_New$TAGNAMEElement, that will be used by
+ nsHTMLContentSink.cpp to create a content object for a tag of that
+ type. Use NOTUSED, if the particular tag has a non-standard creator.
+ The third argument is the interface name specified for this element
+ in the HTML specification. It can be empty if the relevant interface name
+ is "HTMLElement".
+
+ The HTML_OTHER macro is for values in the nsHTMLTag enum that are
+ not strictly tags.
+
+ Entries *must* use only lowercase characters.
+
+ Don't forget to update /editor/libeditor/HTMLEditUtils.cpp as well.
+
+ ** Break these invariants and bad things will happen. **
+
+ ******/
+
+#define HTML_HTMLELEMENT_TAG(_tag) HTML_TAG(_tag, , )
+
+HTML_TAG(a, Anchor, Anchor)
+HTML_HTMLELEMENT_TAG(abbr)
+HTML_HTMLELEMENT_TAG(acronym)
+HTML_HTMLELEMENT_TAG(address)
+HTML_TAG(applet, Unknown, Unknown)
+HTML_TAG(area, Area, Area)
+HTML_HTMLELEMENT_TAG(article)
+HTML_HTMLELEMENT_TAG(aside)
+HTML_TAG(audio, Audio, Audio)
+HTML_HTMLELEMENT_TAG(b)
+HTML_TAG(base, Shared, Base)
+HTML_HTMLELEMENT_TAG(basefont)
+HTML_HTMLELEMENT_TAG(bdi)
+HTML_HTMLELEMENT_TAG(bdo)
+HTML_TAG(bgsound, Unknown, Unknown)
+HTML_HTMLELEMENT_TAG(big)
+HTML_TAG(blockquote, Shared, Quote)
+HTML_TAG(body, Body, Body)
+HTML_TAG(br, BR, BR)
+HTML_TAG(button, Button, Button)
+HTML_TAG(canvas, Canvas, Canvas)
+HTML_TAG(caption, TableCaption, TableCaption)
+HTML_HTMLELEMENT_TAG(center)
+HTML_HTMLELEMENT_TAG(cite)
+HTML_HTMLELEMENT_TAG(code)
+HTML_TAG(col, TableCol, TableCol)
+HTML_TAG(colgroup, TableCol, TableCol)
+HTML_TAG(data, Data, Data)
+HTML_TAG(datalist, DataList, DataList)
+HTML_HTMLELEMENT_TAG(dd)
+HTML_TAG(del, Mod, Mod)
+HTML_TAG(details, Details, Details)
+HTML_HTMLELEMENT_TAG(dfn)
+HTML_TAG(dialog, Dialog, Dialog)
+HTML_TAG(dir, Shared, Directory)
+HTML_TAG(div, Div, Div)
+HTML_TAG(dl, SharedList, DList)
+HTML_HTMLELEMENT_TAG(dt)
+HTML_HTMLELEMENT_TAG(em)
+HTML_TAG(embed, Embed, Embed)
+HTML_TAG(fieldset, FieldSet, FieldSet)
+HTML_HTMLELEMENT_TAG(figcaption)
+HTML_HTMLELEMENT_TAG(figure)
+HTML_TAG(font, Font, Font)
+HTML_HTMLELEMENT_TAG(footer)
+HTML_TAG(form, Form, Form)
+HTML_TAG(frame, Frame, Frame)
+HTML_TAG(frameset, FrameSet, FrameSet)
+HTML_TAG(h1, Heading, Heading)
+HTML_TAG(h2, Heading, Heading)
+HTML_TAG(h3, Heading, Heading)
+HTML_TAG(h4, Heading, Heading)
+HTML_TAG(h5, Heading, Heading)
+HTML_TAG(h6, Heading, Heading)
+HTML_TAG(head, Shared, Head)
+HTML_HTMLELEMENT_TAG(header)
+HTML_HTMLELEMENT_TAG(hgroup)
+HTML_TAG(hr, HR, HR)
+HTML_TAG(html, Shared, Html)
+HTML_HTMLELEMENT_TAG(i)
+HTML_TAG(iframe, IFrame, IFrame)
+HTML_HTMLELEMENT_TAG(image)
+HTML_TAG(img, Image, Image)
+HTML_TAG(input, Input, Input)
+HTML_TAG(ins, Mod, Mod)
+HTML_HTMLELEMENT_TAG(kbd)
+HTML_TAG(keygen, Unknown, Unknown)
+HTML_TAG(label, Label, Label)
+HTML_TAG(legend, Legend, Legend)
+HTML_TAG(li, LI, LI)
+HTML_TAG(link, Link, Link)
+HTML_TAG(listing, Pre, Pre)
+HTML_HTMLELEMENT_TAG(main)
+HTML_TAG(map, Map, Map)
+HTML_HTMLELEMENT_TAG(mark)
+HTML_TAG(marquee, Marquee, Marquee)
+HTML_TAG(menu, Menu, Menu)
+HTML_TAG(meta, Meta, Meta)
+HTML_TAG(meter, Meter, Meter)
+HTML_TAG(multicol, Unknown, Unknown)
+HTML_HTMLELEMENT_TAG(nav)
+HTML_HTMLELEMENT_TAG(nobr)
+HTML_HTMLELEMENT_TAG(noembed)
+HTML_HTMLELEMENT_TAG(noframes)
+HTML_HTMLELEMENT_TAG(noscript)
+HTML_TAG(object, Object, Object)
+HTML_TAG(ol, SharedList, OList)
+HTML_TAG(optgroup, OptGroup, OptGroup)
+HTML_TAG(option, Option, Option)
+HTML_TAG(output, Output, Output)
+HTML_TAG(p, Paragraph, Paragraph)
+HTML_TAG(param, Shared, Param)
+HTML_TAG(picture, Picture, Picture)
+HTML_HTMLELEMENT_TAG(plaintext)
+HTML_TAG(pre, Pre, Pre)
+HTML_TAG(progress, Progress, Progress)
+HTML_TAG(q, Shared, Quote)
+HTML_HTMLELEMENT_TAG(rb)
+HTML_HTMLELEMENT_TAG(rp)
+HTML_HTMLELEMENT_TAG(rt)
+HTML_HTMLELEMENT_TAG(rtc)
+HTML_HTMLELEMENT_TAG(ruby)
+HTML_HTMLELEMENT_TAG(s)
+HTML_HTMLELEMENT_TAG(samp)
+HTML_TAG(script, Script, Script)
+HTML_HTMLELEMENT_TAG(section)
+HTML_TAG(select, Select, Select)
+HTML_HTMLELEMENT_TAG(small)
+HTML_TAG(slot, Slot, Slot)
+HTML_TAG(source, Source, Source)
+HTML_TAG(span, Span, Span)
+HTML_HTMLELEMENT_TAG(strike)
+HTML_HTMLELEMENT_TAG(strong)
+HTML_TAG(style, Style, Style)
+HTML_HTMLELEMENT_TAG(sub)
+HTML_TAG(summary, Summary, )
+HTML_HTMLELEMENT_TAG(sup)
+HTML_TAG(table, Table, Table)
+HTML_TAG(tbody, TableSection, TableSection)
+HTML_TAG(td, TableCell, TableCell)
+HTML_TAG(textarea, TextArea, TextArea)
+HTML_TAG(tfoot, TableSection, TableSection)
+HTML_TAG(th, TableCell, TableCell)
+HTML_TAG(thead, TableSection, TableSection)
+HTML_TAG(template, Template, Template)
+HTML_TAG(time, Time, Time)
+HTML_TAG(title, Title, Title)
+HTML_TAG(tr, TableRow, TableRow)
+HTML_TAG(track, Track, Track)
+HTML_HTMLELEMENT_TAG(tt)
+HTML_HTMLELEMENT_TAG(u)
+HTML_TAG(ul, SharedList, UList)
+HTML_HTMLELEMENT_TAG(var)
+HTML_TAG(video, Video, Video)
+HTML_HTMLELEMENT_TAG(wbr)
+HTML_TAG(xmp, Pre, Pre)
+
+/* These are not for tags. But they will be included in the nsHTMLTag
+ enum anyway */
+
+HTML_OTHER(text)
+HTML_OTHER(whitespace)
+HTML_OTHER(newline)
+HTML_OTHER(comment)
+HTML_OTHER(entity)
+HTML_OTHER(doctypeDecl)
+HTML_OTHER(markupDecl)
+HTML_OTHER(instruction)
+
+#undef HTML_HTMLELEMENT_TAG
diff --git a/parser/htmlparser/nsHTMLTags.cpp b/parser/htmlparser/nsHTMLTags.cpp
new file mode 100644
index 0000000000..ec3c4f322d
--- /dev/null
+++ b/parser/htmlparser/nsHTMLTags.cpp
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHTMLTags.h"
+#include "nsCRT.h"
+#include "nsElementTable.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+#include "nsUnicharUtils.h"
+#include "mozilla/HashFunctions.h"
+#include <algorithm>
+
+using namespace mozilla;
+
+// static array of unicode tag names
+#define HTML_TAG(_tag, _classname, _interfacename) (u"" #_tag),
+#define HTML_OTHER(_tag)
+const char16_t* const nsHTMLTags::sTagNames[] = {
+#include "nsHTMLTagList.h"
+};
+#undef HTML_TAG
+#undef HTML_OTHER
+
+int32_t nsHTMLTags::gTableRefCount;
+nsHTMLTags::TagStringHash* nsHTMLTags::gTagTable;
+nsHTMLTags::TagAtomHash* nsHTMLTags::gTagAtomTable;
+
+#define NS_HTMLTAG_NAME_MAX_LENGTH 10
+
+// static
+nsresult nsHTMLTags::AddRefTable(void) {
+ if (gTableRefCount++ == 0) {
+ NS_ASSERTION(!gTagTable && !gTagAtomTable, "pre existing hash!");
+
+ gTagTable = new TagStringHash(64);
+ gTagAtomTable = new TagAtomHash(64);
+
+ // Fill in gTagTable with the above static char16_t strings as
+ // keys and the value of the corresponding enum as the value in
+ // the table.
+
+ for (int32_t i = 0; i < NS_HTML_TAG_MAX; ++i) {
+ const char16_t* tagName = sTagNames[i];
+ const nsHTMLTag tagValue = static_cast<nsHTMLTag>(i + 1);
+
+ // We use AssignLiteral here to avoid a string copy. This is okay
+ // because this is truly static data.
+ nsString tmp;
+ tmp.AssignLiteral(tagName, nsString::char_traits::length(tagName));
+ gTagTable->InsertOrUpdate(tmp, tagValue);
+
+ // All the HTML tag names are static atoms within nsGkAtoms, and they are
+ // registered before this code is reached.
+ nsStaticAtom* atom = NS_GetStaticAtom(tmp);
+ MOZ_ASSERT(atom);
+ gTagAtomTable->InsertOrUpdate(atom, tagValue);
+ }
+
+#ifdef DEBUG
+ // Check all tagNames are lowercase, and that NS_HTMLTAG_NAME_MAX_LENGTH is
+ // correct.
+ uint32_t maxTagNameLength = 0;
+ for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
+ const char16_t* tagName = sTagNames[i];
+
+ nsAutoString lowerTagName(tagName);
+ ToLowerCase(lowerTagName);
+ MOZ_ASSERT(lowerTagName.Equals(tagName));
+
+ maxTagNameLength = std::max(NS_strlen(tagName), maxTagNameLength);
+ }
+
+ MOZ_ASSERT(maxTagNameLength == NS_HTMLTAG_NAME_MAX_LENGTH);
+
+ CheckElementTable();
+ TestTagTable();
+#endif
+ }
+
+ return NS_OK;
+}
+
+// static
+void nsHTMLTags::ReleaseTable(void) {
+ if (0 == --gTableRefCount) {
+ delete gTagTable;
+ delete gTagAtomTable;
+ gTagTable = nullptr;
+ gTagAtomTable = nullptr;
+ }
+}
+
+// static
+nsHTMLTag nsHTMLTags::StringTagToId(const nsAString& aTagName) {
+ uint32_t length = aTagName.Length();
+
+ if (length > NS_HTMLTAG_NAME_MAX_LENGTH) {
+ return eHTMLTag_userdefined;
+ }
+
+ // Setup a stack allocated string buffer with the appropriate length.
+ nsAutoString lowerCase;
+ lowerCase.SetLength(length);
+
+ // Operate on the raw buffers to avoid bounds checks.
+ auto src = aTagName.BeginReading();
+ auto dst = lowerCase.BeginWriting();
+
+ // Fast lowercasing-while-copying of ASCII characters into a
+ // nsString buffer.
+
+ for (uint32_t i = 0; i < length; i++) {
+ char16_t c = src[i];
+
+ if (c <= 'Z' && c >= 'A') {
+ c |= 0x20; // Lowercase the ASCII character.
+ }
+
+ dst[i] = c; // Copy ASCII character.
+ }
+
+ return CaseSensitiveStringTagToId(lowerCase);
+}
+
+#ifdef DEBUG
+void nsHTMLTags::TestTagTable() {
+ const char16_t* tag;
+ nsHTMLTag id;
+ RefPtr<nsAtom> atom;
+
+ nsHTMLTags::AddRefTable();
+ // Make sure we can find everything we are supposed to
+ for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
+ tag = sTagNames[i];
+ const nsAString& tagString = nsDependentString(tag);
+ id = StringTagToId(tagString);
+ NS_ASSERTION(id != eHTMLTag_userdefined, "can't find tag id");
+
+ nsAutoString uname(tagString);
+ ToUpperCase(uname);
+ NS_ASSERTION(id == StringTagToId(uname), "wrong id");
+
+ NS_ASSERTION(id == CaseSensitiveStringTagToId(tagString), "wrong id");
+
+ atom = NS_Atomize(tag);
+ NS_ASSERTION(id == CaseSensitiveAtomTagToId(atom), "wrong id");
+ }
+
+ // Make sure we don't find things that aren't there
+ id = StringTagToId(u"@"_ns);
+ NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
+ id = StringTagToId(u"zzzzz"_ns);
+ NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
+
+ atom = NS_Atomize("@");
+ id = CaseSensitiveAtomTagToId(atom);
+ NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
+ atom = NS_Atomize("zzzzz");
+ id = CaseSensitiveAtomTagToId(atom);
+ NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
+
+ ReleaseTable();
+}
+
+#endif // DEBUG
diff --git a/parser/htmlparser/nsHTMLTags.h b/parser/htmlparser/nsHTMLTags.h
new file mode 100644
index 0000000000..eb7e3aaa25
--- /dev/null
+++ b/parser/htmlparser/nsHTMLTags.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHTMLTags_h___
+#define nsHTMLTags_h___
+
+#include "nsAtom.h"
+#include "nsString.h"
+#include "nsTHashMap.h"
+#include "nsHashKeys.h"
+
+/*
+ Declare the enum list using the magic of preprocessing
+ enum values are "eHTMLTag_foo" (where foo is the tag)
+
+ To change the list of tags, see nsHTMLTagList.h
+
+ These enum values are used as the index of array in various places.
+ If we change the structure of the enum by adding entries to it or removing
+ entries from it _directly_, not via nsHTMLTagList.h, don't forget to update
+ dom/bindings/BindingUtils.cpp and dom/html/nsHTMLContentSink.cpp as well.
+ */
+#define HTML_TAG(_tag, _classname, _interfacename) eHTMLTag_##_tag,
+#define HTML_OTHER(_tag) eHTMLTag_##_tag,
+enum nsHTMLTag {
+ /* this enum must be first and must be zero */
+ eHTMLTag_unknown = 0,
+#include "nsHTMLTagList.h"
+
+ /* can't be moved into nsHTMLTagList since gcc3.4 doesn't like a
+ comma at the end of enum list*/
+ eHTMLTag_userdefined
+};
+#undef HTML_TAG
+#undef HTML_OTHER
+
+// All tags before eHTMLTag_text are HTML tags
+#define NS_HTML_TAG_MAX int32_t(eHTMLTag_text - 1)
+
+class nsHTMLTags {
+ public:
+ using TagStringHash = nsTHashMap<nsStringHashKey, nsHTMLTag>;
+ using TagAtomHash = nsTHashMap<nsPtrHashKey<nsAtom>, nsHTMLTag>;
+
+ static nsresult AddRefTable(void);
+ static void ReleaseTable(void);
+
+ // Functions for converting string or atom to id
+ static nsHTMLTag StringTagToId(const nsAString& aTagName);
+ static nsHTMLTag AtomTagToId(nsAtom* aTagName) {
+ return StringTagToId(nsDependentAtomString(aTagName));
+ }
+
+ static nsHTMLTag CaseSensitiveStringTagToId(const nsAString& aTagName) {
+ NS_ASSERTION(gTagTable, "no lookup table, needs addref");
+
+ return gTagTable->MaybeGet(aTagName).valueOr(eHTMLTag_userdefined);
+ }
+ static nsHTMLTag CaseSensitiveAtomTagToId(nsAtom* aTagName) {
+ NS_ASSERTION(gTagAtomTable, "no lookup table, needs addref");
+ NS_ASSERTION(aTagName, "null tagname!");
+
+ return gTagAtomTable->MaybeGet(aTagName).valueOr(eHTMLTag_userdefined);
+ }
+
+#ifdef DEBUG
+ static void TestTagTable();
+#endif
+
+ private:
+ static const char16_t* const sTagNames[];
+
+ static int32_t gTableRefCount;
+ static TagStringHash* gTagTable;
+ static TagAtomHash* gTagAtomTable;
+};
+
+#endif /* nsHTMLTags_h___ */
diff --git a/parser/htmlparser/nsIContentSink.h b/parser/htmlparser/nsIContentSink.h
new file mode 100644
index 0000000000..aa77c192c7
--- /dev/null
+++ b/parser/htmlparser/nsIContentSink.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsIContentSink_h___
+#define nsIContentSink_h___
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ * This pure virtual interface is used as the "glue" that connects the parsing
+ * process to the content model construction process.
+ *
+ * The icontentsink interface is a very lightweight wrapper that represents the
+ * content-sink model building process. There is another one that you may care
+ * about more, which is the IHTMLContentSink interface. (See that file for
+ * details).
+ */
+#include "nsISupports.h"
+#include "nsString.h"
+#include "mozilla/FlushType.h"
+#include "mozilla/NotNull.h"
+#include "nsIDTD.h"
+
+class nsParserBase;
+namespace mozilla {
+class Encoding;
+}
+
+#define NS_ICONTENT_SINK_IID \
+ { \
+ 0xcf9a7cbb, 0xfcbc, 0x4e13, { \
+ 0x8e, 0xf5, 0x18, 0xef, 0x2d, 0x3d, 0x58, 0x29 \
+ } \
+ }
+
+class nsIContentSink : public nsISupports {
+ protected:
+ using Encoding = mozilla::Encoding;
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENT_SINK_IID)
+
+ /**
+ * This method is called by the parser when it is entered from
+ * the event loop. The content sink wants to know how long the
+ * parser has been active since we last processed events on the
+ * main event loop and this call calibrates that measurement.
+ */
+ NS_IMETHOD WillParse(void) = 0;
+
+ /**
+ * This method gets called when the parser begins the process
+ * of building the content model via the content sink.
+ *
+ * Default implementation provided since the sink should have the option of
+ * doing nothing in response to this call.
+ *
+ * @update 5/7/98 gess
+ */
+ NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) { return NS_OK; }
+
+ /**
+ * This method gets called when the parser concludes the process
+ * of building the content model via the content sink.
+ *
+ * Default implementation provided since the sink should have the option of
+ * doing nothing in response to this call.
+ *
+ * @update 5/7/98 gess
+ */
+ NS_IMETHOD DidBuildModel(bool aTerminated) { return NS_OK; }
+
+ /**
+ * This method gets called when the parser gets i/o blocked,
+ * and wants to notify the sink that it may be a while before
+ * more data is available.
+ *
+ * @update 5/7/98 gess
+ */
+ NS_IMETHOD WillInterrupt(void) = 0;
+
+ /**
+ * This method gets called when the parser i/o gets unblocked,
+ * and we're about to start dumping content again to the sink.
+ */
+ virtual void WillResume() = 0;
+
+ /**
+ * This method returns nullptr unless `this` can
+ * be cast as nsHtml5TreeOpExecutor.
+ */
+ virtual nsIContentSink* AsExecutor() { return nullptr; }
+
+ /**
+ * This method gets called by the parser so that the content
+ * sink can retain a reference to the parser. The expectation
+ * is that the content sink will drop the reference when it
+ * gets the DidBuildModel notification i.e. when parsing is done.
+ */
+ NS_IMETHOD SetParser(nsParserBase* aParser) = 0;
+
+ /**
+ * Flush content so that the content model is in sync with the state
+ * of the sink.
+ *
+ * @param aType the type of flush to perform
+ */
+ virtual void FlushPendingNotifications(mozilla::FlushType aType) = 0;
+
+ /**
+ * Set the document character set. This should be passed on to the
+ * document itself.
+ */
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) = 0;
+
+ /**
+ * Returns the target object (often a document object) into which
+ * the content built by this content sink is being added, if any
+ * (IOW, may return null).
+ */
+ virtual nsISupports* GetTarget() = 0;
+
+ /**
+ * Returns true if there's currently script executing that we need to hold
+ * parsing for.
+ */
+ virtual bool IsScriptExecuting() { return false; }
+
+ /**
+ * Posts a runnable that continues parsing.
+ */
+ virtual void ContinueInterruptedParsingAsync() {}
+
+ virtual void InitialTranslationCompleted() {}
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentSink, NS_ICONTENT_SINK_IID)
+
+#endif /* nsIContentSink_h___ */
diff --git a/parser/htmlparser/nsIDTD.h b/parser/htmlparser/nsIDTD.h
new file mode 100644
index 0000000000..67f7af4ec2
--- /dev/null
+++ b/parser/htmlparser/nsIDTD.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsIDTD_h___
+#define nsIDTD_h___
+
+/**
+ * MODULE NOTES:
+ * @update gess 7/20/98
+ *
+ * This interface defines standard interface for DTD's. Note that this
+ * isn't HTML specific. DTD's have several functions within the parser
+ * system:
+ * 1) To coordinate the consumption of an input stream via the
+ * parser
+ * 2) To serve as proxy to represent the containment rules of the
+ * underlying document
+ * 3) To offer autodetection services to the parser (mainly for doc
+ * conversion)
+ * */
+
+#include "nsISupports.h"
+#include "nsString.h"
+
+#define NS_IDTD_IID \
+ { \
+ 0x3de05873, 0xefa7, 0x410d, { \
+ 0xa4, 0x61, 0x80, 0x33, 0xaf, 0xd9, 0xe3, 0x26 \
+ } \
+ }
+
+enum eAutoDetectResult {
+ eUnknownDetect,
+ ePrimaryDetect,
+};
+
+enum nsDTDMode {
+ eDTDMode_quirks, // pre 4.0 versions
+ eDTDMode_full_standards,
+ eDTDMode_autodetect
+};
+
+class nsIContentSink;
+class CParserContext;
+
+class nsIDTD : public nsISupports {
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDTD_IID)
+
+ /**
+ * Called by the parser after the parsing process has concluded
+ */
+ virtual void DidBuildModel() = 0;
+
+ /**
+ * Called (possibly repeatedly) by the parser to parse tokens and construct
+ * the document model via the sink provided to WillBuildModel.
+ *
+ * @param aCountLines - informs the DTD whether to count newlines
+ * (not wanted, e.g., when handling document.write)
+ * @param aCharsetPtr - address of an nsCString containing the charset
+ * that the DTD should use (pointer in case the DTD
+ * opts to ignore this parameter)
+ */
+ NS_IMETHOD BuildModel(nsIContentSink* aSink) = 0;
+
+ /**
+ * Use this id you want to stop the building content model
+ * --------------[ Sets DTD to STOP mode ]----------------
+ * It's recommended to use this method in accordance with
+ * the parser's terminate() method.
+ *
+ * @update harishd 07/22/99
+ * @param
+ * @return
+ */
+ NS_IMETHOD_(void) Terminate() = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIDTD, NS_IDTD_IID)
+
+#define NS_DECL_NSIDTD \
+ void DidBuildModel() override; \
+ NS_IMETHOD BuildModel(nsIContentSink* aSink) override; \
+ NS_IMETHOD_(void) Terminate() override;
+#endif /* nsIDTD_h___ */
diff --git a/parser/htmlparser/nsIExpatSink.idl b/parser/htmlparser/nsIExpatSink.idl
new file mode 100644
index 0000000000..f505eda8c9
--- /dev/null
+++ b/parser/htmlparser/nsIExpatSink.idl
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+interface nsIScriptError;
+
+/**
+ * This interface should be implemented by any content sink that wants
+ * to get output from expat and do something with it; in other words,
+ * by any sink that handles some sort of XML dialect.
+ */
+
+[scriptable, uuid(01f681af-0f22-4725-a914-0d396114daf0)]
+interface nsIExpatSink : nsISupports
+{
+ /**
+ * Called to handle the opening tag of an element.
+ * @param aName the fully qualified tagname of the element
+ * @param aAtts the array of attribute names and values. There are
+ * aAttsCount/2 names and aAttsCount/2 values, so the total number of
+ * elements in the array is aAttsCount. The names and values
+ * alternate. Thus, if we number attributes starting with 0,
+ * aAtts[2*k] is the name of the k-th attribute and aAtts[2*k+1] is
+ * the value of that attribute Both explicitly specified attributes
+ * and attributes that are defined to have default values in a DTD are
+ * present in aAtts.
+ * @param aAttsCount the number of elements in aAtts.
+ * @param aLineNumber the line number of the start tag in the data stream.
+ * @param aColumnNumber the column number of the start tag in the data stream.
+ */
+ void HandleStartElement(in wstring aName,
+ [array, size_is(aAttsCount)] in wstring aAtts,
+ in unsigned long aAttsCount,
+ in unsigned long aLineNumber,
+ in unsigned long aColumnNumber);
+
+ /**
+ * Called to handle the closing tag of an element.
+ * @param aName the fully qualified tagname of the element
+ */
+ void HandleEndElement(in wstring aName);
+
+ /**
+ * Called to handle a comment
+ * @param aCommentText the text of the comment (not including the
+ * "<!--" and "-->")
+ */
+ void HandleComment(in wstring aCommentText);
+
+ /**
+ * Called to handle a CDATA section
+ * @param aData the text in the CDATA section. This is null-terminated.
+ * @param aLength the length of the aData string
+ */
+ void HandleCDataSection([size_is(aLength)] in wstring aData,
+ in unsigned long aLength);
+
+ /**
+ * Called to handle the doctype declaration
+ */
+ void HandleDoctypeDecl(in AString aSubset,
+ in AString aName,
+ in AString aSystemId,
+ in AString aPublicId,
+ in nsISupports aCatalogData);
+
+ /**
+ * Called to handle character data. Note that this does NOT get
+ * called for the contents of CDATA sections.
+ * @param aData the data to handle. aData is NOT NULL-TERMINATED.
+ * @param aLength the length of the aData string
+ */
+ void HandleCharacterData([size_is(aLength)] in wstring aData,
+ in unsigned long aLength);
+
+ /**
+ * Called to handle a processing instruction
+ * @param aTarget the PI target (e.g. xml-stylesheet)
+ * @param aData all the rest of the data in the PI
+ */
+ void HandleProcessingInstruction(in wstring aTarget,
+ in wstring aData);
+
+ /**
+ * Handle the XML Declaration.
+ *
+ * @param aVersion The version string, can be null if not specified.
+ * @param aEncoding The encoding string, can be null if not specified.
+ * @param aStandalone -1, 0, or 1 indicating respectively that there was no
+ * standalone parameter in the declaration, that it was
+ * given as no, or that it was given as yes.
+ */
+ void HandleXMLDeclaration(in wstring aVersion,
+ in wstring aEncoding,
+ in long aStandalone);
+
+ /**
+ * Ask the content sink if the expat driver should log an error to the console.
+ *
+ * @param aErrorText Error message to pass to content sink.
+ * @param aSourceText Source text of the document we're parsing.
+ * @param aError Script error object with line number & column number
+ *
+ * @retval True if the expat driver should report the error.
+ */
+ boolean ReportError(in wstring aErrorText,
+ in wstring aSourceText,
+ in nsIScriptError aError);
+};
diff --git a/parser/htmlparser/nsIFragmentContentSink.h b/parser/htmlparser/nsIFragmentContentSink.h
new file mode 100644
index 0000000000..351963cfa3
--- /dev/null
+++ b/parser/htmlparser/nsIFragmentContentSink.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsIFragmentContentSink_h___
+#define nsIFragmentContentSink_h___
+
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+class Document;
+class DocumentFragment;
+} // namespace dom
+} // namespace mozilla
+
+#define NS_I_FRAGMENT_CONTENT_SINK_IID \
+ { \
+ 0x1a8ce30b, 0x63fc, 0x441a, { \
+ 0xa3, 0xaa, 0xf7, 0x16, 0xc0, 0xfe, 0x96, 0x69 \
+ } \
+ }
+
+/**
+ * The fragment sink allows a client to parse a fragment of sink, possibly
+ * surrounded in context. Also see nsParser::ParseFragment().
+ * Note: once you've parsed a fragment, the fragment sink must be re-set on
+ * the parser in order to parse another fragment.
+ */
+class nsIFragmentContentSink : public nsISupports {
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_I_FRAGMENT_CONTENT_SINK_IID)
+ /**
+ * This method is used to obtain the fragment created by
+ * a fragment content sink and to release resources held by the parser.
+ *
+ * The sink drops its reference to the fragment.
+ */
+ NS_IMETHOD FinishFragmentParsing(mozilla::dom::DocumentFragment** aFragment) =
+ 0;
+
+ /**
+ * This method is used to set the target document for this fragment
+ * sink. This document's nodeinfo manager will be used to create
+ * the content objects. This MUST be called before the sink is used.
+ *
+ * @param aDocument the document the new nodes will belong to
+ * (should not be null)
+ */
+ NS_IMETHOD SetTargetDocument(mozilla::dom::Document*) = 0;
+
+ /**
+ * This method is used to indicate to the sink that we're done building
+ * the context and should start paying attention to the incoming content
+ */
+ NS_IMETHOD WillBuildContent() = 0;
+
+ /**
+ * This method is used to indicate to the sink that we're done building
+ * The real content. This is useful if you want to parse additional context
+ * (such as an end context).
+ */
+ NS_IMETHOD DidBuildContent() = 0;
+
+ /**
+ * This method is a total hack to help with parsing fragments. It is called to
+ * tell the fragment sink that a container from the context will be delivered
+ * after the call to WillBuildContent(). This is only relevent for HTML
+ * fragments that use nsHTMLTokenizer/CNavDTD.
+ */
+ NS_IMETHOD IgnoreFirstContainer() = 0;
+
+ /**
+ * Sets whether scripts elements are marked as unexecutable.
+ */
+ NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIFragmentContentSink,
+ NS_I_FRAGMENT_CONTENT_SINK_IID)
+
+nsresult NS_NewXMLFragmentContentSink(
+ nsIFragmentContentSink** aInstancePtrResult);
+
+#endif
diff --git a/parser/htmlparser/nsIHTMLContentSink.h b/parser/htmlparser/nsIHTMLContentSink.h
new file mode 100644
index 0000000000..3e81d5d770
--- /dev/null
+++ b/parser/htmlparser/nsIHTMLContentSink.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsIHTMLContentSink_h___
+#define nsIHTMLContentSink_h___
+
+/**
+ * This interface is OBSOLETE and in the process of being REMOVED.
+ * Do NOT implement!
+ *
+ * This file declares the concrete HTMLContentSink class.
+ * This class is used during the parsing process as the
+ * primary interface between the parser and the content
+ * model.
+ *
+ * After the tokenizer completes, the parser iterates over
+ * the known token list. As the parser identifies valid
+ * elements, it calls the contentsink interface to notify
+ * the content model that a new node or child node is being
+ * created and added to the content model.
+ *
+ * The HTMLContentSink interface assumes 4 underlying
+ * containers: HTML, HEAD, BODY and FRAMESET. Before
+ * accessing any these, the parser will call the appropriate
+ * OpennsIHTMLContentSink method: OpenHTML,OpenHead,OpenBody,OpenFrameSet;
+ * likewise, the ClosensIHTMLContentSink version will be called when the
+ * parser is done with a given section.
+ *
+ * IMPORTANT: The parser may Open each container more than
+ * once! This is due to the irregular nature of HTML files.
+ * For example, it is possible to encounter plain text at
+ * the start of an HTML document (that precedes the HTML tag).
+ * Such text is treated as if it were part of the body.
+ * In such cases, the parser will Open the body, pass the text-
+ * node in and then Close the body. The body will likely be
+ * re-Opened later when the actual <BODY> tag has been seen.
+ *
+ * Containers within the body are Opened and Closed
+ * using the OpenContainer(...) and CloseContainer(...) calls.
+ * It is assumed that the document or contentSink is
+ * maintaining its state to manage where new content should
+ * be added to the underlying document.
+ *
+ * NOTE: OpenHTML() and OpenBody() may get called multiple times
+ * in the same document. That's fine, and it doesn't mean
+ * that we have multiple bodies or HTML's.
+ *
+ * NOTE: I haven't figured out how sub-documents (non-frames)
+ * are going to be handled. Stay tuned.
+ */
+#include "nsIContentSink.h"
+#include "nsHTMLTags.h"
+
+#define NS_IHTML_CONTENT_SINK_IID \
+ { \
+ 0xefc5af86, 0x5cfd, 0x4918, { \
+ 0x9d, 0xd3, 0x5f, 0x7a, 0xb2, 0x88, 0xb2, 0x68 \
+ } \
+ }
+
+/**
+ * This interface is OBSOLETE and in the process of being REMOVED.
+ * Do NOT implement!
+ */
+class nsIHTMLContentSink : public nsIContentSink {
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTML_CONTENT_SINK_IID)
+
+ enum ElementType { eHTML, eBody };
+
+ /**
+ * This method is used to open a generic container in the sink.
+ *
+ * @update 4/1/98 gess
+ */
+ NS_IMETHOD OpenContainer(ElementType aNodeType) = 0;
+
+ /**
+ * This method gets called by the parser when a close
+ * container tag has been consumed and needs to be closed.
+ *
+ * @param aTag - The tag to be closed.
+ */
+ NS_IMETHOD CloseContainer(ElementType aTag) = 0;
+
+ /**
+ * This method returns true if there are more than one
+ * pending style sheets, false otherwise.
+ */
+ virtual bool WaitForPendingSheets() = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLContentSink, NS_IHTML_CONTENT_SINK_IID)
+
+#endif /* nsIHTMLContentSink_h___ */
diff --git a/parser/htmlparser/nsIParser.h b/parser/htmlparser/nsIParser.h
new file mode 100644
index 0000000000..8cf3940ffb
--- /dev/null
+++ b/parser/htmlparser/nsIParser.h
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef NS_IPARSER___
+#define NS_IPARSER___
+
+/**
+ * This GECKO-INTERNAL interface is on track to being REMOVED (or refactored
+ * to the point of being near-unrecognizable).
+ *
+ * Please DO NOT #include this file in comm-central code, in your XULRunner
+ * app or binary extensions.
+ *
+ * Please DO NOT #include this into new files even inside Gecko. It is more
+ * likely than not that #including this header is the wrong thing to do.
+ */
+
+#include "nsISupports.h"
+#include "nsIStreamListener.h"
+#include "nsIDTD.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsAtom.h"
+#include "nsParserBase.h"
+#include "mozilla/NotNull.h"
+
+#define NS_IPARSER_IID \
+ { \
+ 0x2c4ad90a, 0x740e, 0x4212, { \
+ 0xba, 0x3f, 0xfe, 0xac, 0xda, 0x4b, 0x92, 0x9e \
+ } \
+ }
+
+class nsIContentSink;
+class nsIRequestObserver;
+class nsIURI;
+class nsIChannel;
+namespace mozilla {
+class Encoding;
+}
+
+enum eParserCommands { eViewNormal, eViewSource, eViewFragment, eViewErrors };
+
+enum eParserDocType { eUnknown = 0, eXML, eHTML_Quirks, eHTML_Strict };
+
+enum eStreamState { eNone, eOnStart, eOnDataAvail, eOnStop };
+
+/**
+ * This GECKO-INTERNAL interface is on track to being REMOVED (or refactored
+ * to the point of being near-unrecognizable).
+ *
+ * Please DO NOT #include this file in comm-central code, in your XULRunner
+ * app or binary extensions.
+ *
+ * Please DO NOT #include this into new files even inside Gecko. It is more
+ * likely than not that #including this header is the wrong thing to do.
+ */
+class nsIParser : public nsParserBase {
+ protected:
+ using Encoding = mozilla::Encoding;
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPARSER_IID)
+
+ /**
+ * Select given content sink into parser for parser output
+ * @update gess5/11/98
+ * @param aSink is the new sink to be used by parser
+ * @return
+ */
+ NS_IMETHOD_(void) SetContentSink(nsIContentSink* aSink) = 0;
+
+ /**
+ * retrieve the sink set into the parser
+ * @update gess5/11/98
+ * @return current sink
+ */
+ NS_IMETHOD_(nsIContentSink*) GetContentSink(void) = 0;
+
+ /**
+ * Call this method once you've created a parser, and want to instruct it
+ * about the command which caused the parser to be constructed. For example,
+ * this allows us to select a DTD which can do, say, view-source.
+ *
+ * @update gess 3/25/98
+ * @param aCommand -- ptrs to string that contains command
+ * @return nada
+ */
+ NS_IMETHOD_(void) GetCommand(nsCString& aCommand) = 0;
+ NS_IMETHOD_(void) SetCommand(const char* aCommand) = 0;
+ NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand) = 0;
+
+ /**
+ * Call this method once you've created a parser, and want to instruct it
+ * about what charset to load
+ *
+ * @update ftang 4/23/99
+ * @param aCharset- the charest of a document
+ * @param aCharsetSource- the soure of the chares
+ * @param aForceAutoDetection- whether Repair Text Encoding menu item was
+ * invoked
+ * @return nada
+ */
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aCharset,
+ int32_t aSource,
+ bool aForceAutoDetection = false) = 0;
+
+ /**
+ * Get the nsIStreamListener for this parser
+ */
+ virtual nsIStreamListener* GetStreamListener() = 0;
+
+ /**************************************************************************
+ * Parse methods always begin with an input source, and perform
+ * conversions until you wind up being emitted to the given contentsink
+ * (which may or may not be a proxy for the NGLayout content model).
+ ************************************************************************/
+
+ // Call this method to resume the parser from an unblocked state.
+ // This can happen, for example, if parsing was interrupted and then the
+ // consumer needed to restart the parser without waiting for more data.
+ // This also happens after loading scripts, which unblock the parser in
+ // order to process the output of document.write() and then need to
+ // continue on with the page load on an enabled parser.
+ NS_IMETHOD ContinueInterruptedParsing() = 0;
+
+ // Stops parsing temporarily.
+ NS_IMETHOD_(void) BlockParser() = 0;
+
+ // Open up the parser for tokenization, building up content
+ // model..etc. However, this method does not resume parsing
+ // automatically. It's the callers' responsibility to restart
+ // the parsing engine.
+ NS_IMETHOD_(void) UnblockParser() = 0;
+
+ /**
+ * Asynchronously continues parsing.
+ */
+ NS_IMETHOD_(void) ContinueInterruptedParsingAsync() = 0;
+
+ NS_IMETHOD_(bool) IsParserEnabled() override = 0;
+ NS_IMETHOD_(bool) IsComplete() = 0;
+
+ NS_IMETHOD Parse(nsIURI* aURL) = 0;
+
+ NS_IMETHOD Terminate(void) = 0;
+
+ /**
+ * True if the insertion point (per HTML5) is defined.
+ */
+ virtual bool IsInsertionPointDefined() = 0;
+
+ /**
+ * Call immediately before starting to evaluate a parser-inserted script or
+ * in general when the spec says to increment the script nesting level.
+ */
+ virtual void IncrementScriptNestingLevel() = 0;
+
+ /**
+ * Call immediately after having evaluated a parser-inserted script or
+ * generally want to restore to the state before the last
+ * IncrementScriptNestingLevel call.
+ */
+ virtual void DecrementScriptNestingLevel() = 0;
+
+ /**
+ * True if this is an HTML5 parser whose script nesting level (in
+ * the sense of
+ * <https://html.spec.whatwg.org/multipage/parsing.html#script-nesting-level>)
+ * is nonzero.
+ */
+ virtual bool HasNonzeroScriptNestingLevel() const = 0;
+
+ /**
+ * True if this is a script-created HTML5 parser.
+ */
+ virtual bool IsScriptCreated() = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIParser, NS_IPARSER_IID)
+
+#endif
diff --git a/parser/htmlparser/nsParser.cpp b/parser/htmlparser/nsParser.cpp
new file mode 100644
index 0000000000..04d02e2084
--- /dev/null
+++ b/parser/htmlparser/nsParser.cpp
@@ -0,0 +1,1075 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsAtom.h"
+#include "nsParser.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsScanner.h"
+#include "plstr.h"
+#include "nsIChannel.h"
+#include "nsIInputStream.h"
+#include "CNavDTD.h"
+#include "prenv.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "nsReadableUtils.h"
+#include "nsCOMPtr.h"
+#include "nsExpatDriver.h"
+#include "nsIFragmentContentSink.h"
+#include "nsStreamUtils.h"
+#include "nsXPCOMCIDInternal.h"
+#include "nsMimeTypes.h"
+#include "nsCharsetSource.h"
+#include "nsThreadUtils.h"
+#include "nsIHTMLContentSink.h"
+
+#include "mozilla/BinarySearch.h"
+#include "mozilla/CondVar.h"
+#include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/Encoding.h"
+#include "mozilla/Mutex.h"
+
+using namespace mozilla;
+
+#define NS_PARSER_FLAG_PENDING_CONTINUE_EVENT 0x00000001
+#define NS_PARSER_FLAG_CAN_TOKENIZE 0x00000002
+
+//-------------- Begin ParseContinue Event Definition ------------------------
+/*
+The parser can be explicitly interrupted by passing a return value of
+NS_ERROR_HTMLPARSER_INTERRUPTED from BuildModel on the DTD. This will cause
+the parser to stop processing and allow the application to return to the event
+loop. The data which was left at the time of interruption will be processed
+the next time OnDataAvailable is called. If the parser has received its final
+chunk of data then OnDataAvailable will no longer be called by the networking
+module, so the parser will schedule a nsParserContinueEvent which will call
+the parser to process the remaining data after returning to the event loop.
+If the parser is interrupted while processing the remaining data it will
+schedule another ParseContinueEvent. The processing of data followed by
+scheduling of the continue events will proceed until either:
+
+ 1) All of the remaining data can be processed without interrupting
+ 2) The parser has been cancelled.
+
+
+This capability is currently used in CNavDTD and nsHTMLContentSink. The
+nsHTMLContentSink is notified by CNavDTD when a chunk of tokens is going to be
+processed and when each token is processed. The nsHTML content sink records
+the time when the chunk has started processing and will return
+NS_ERROR_HTMLPARSER_INTERRUPTED if the token processing time has exceeded a
+threshold called max tokenizing processing time. This allows the content sink
+to limit how much data is processed in a single chunk which in turn gates how
+much time is spent away from the event loop. Processing smaller chunks of data
+also reduces the time spent in subsequent reflows.
+
+This capability is most apparent when loading large documents. If the maximum
+token processing time is set small enough the application will remain
+responsive during document load.
+
+A side-effect of this capability is that document load is not complete when
+the last chunk of data is passed to OnDataAvailable since the parser may have
+been interrupted when the last chunk of data arrived. The document is complete
+when all of the document has been tokenized and there aren't any pending
+nsParserContinueEvents. This can cause problems if the application assumes
+that it can monitor the load requests to determine when the document load has
+been completed. This is what happens in Mozilla. The document is considered
+completely loaded when all of the load requests have been satisfied. To delay
+the document load until all of the parsing has been completed the
+nsHTMLContentSink adds a dummy parser load request which is not removed until
+the nsHTMLContentSink's DidBuildModel is called. The CNavDTD will not call
+DidBuildModel until the final chunk of data has been passed to the parser
+through the OnDataAvailable and there aren't any pending
+nsParserContineEvents.
+
+Currently the parser is ignores requests to be interrupted during the
+processing of script. This is because a document.write followed by JavaScript
+calls to manipulate the DOM may fail if the parser was interrupted during the
+document.write.
+
+For more details @see bugzilla bug 76722
+*/
+
+class nsParserContinueEvent : public Runnable {
+ public:
+ RefPtr<nsParser> mParser;
+
+ explicit nsParserContinueEvent(nsParser* aParser)
+ : mozilla::Runnable("nsParserContinueEvent"), mParser(aParser) {}
+
+ NS_IMETHOD Run() override {
+ mParser->HandleParserContinueEvent(this);
+ return NS_OK;
+ }
+};
+
+//-------------- End ParseContinue Event Definition ------------------------
+
+/**
+ * default constructor
+ */
+nsParser::nsParser() : mCharset(WINDOWS_1252_ENCODING) { Initialize(); }
+
+nsParser::~nsParser() { Cleanup(); }
+
+void nsParser::Initialize() {
+ mContinueEvent = nullptr;
+ mCharsetSource = kCharsetUninitialized;
+ mCharset = WINDOWS_1252_ENCODING;
+ mInternalState = NS_OK;
+ mStreamStatus = NS_OK;
+ mCommand = eViewNormal;
+ mBlocked = 0;
+ mFlags = NS_PARSER_FLAG_CAN_TOKENIZE;
+
+ mProcessingNetworkData = false;
+ mIsAboutBlank = false;
+}
+
+void nsParser::Cleanup() {
+ // It should not be possible for this flag to be set when we are getting
+ // destroyed since this flag implies a pending nsParserContinueEvent, which
+ // has an owning reference to |this|.
+ NS_ASSERTION(!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT), "bad");
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsParser)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsParser)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mDTD)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mSink)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsParser)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDTD)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSink)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsParser)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsParser)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsParser)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+ NS_INTERFACE_MAP_ENTRY(nsIParser)
+ NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+ NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIParser)
+NS_INTERFACE_MAP_END
+
+// The parser continue event is posted only if
+// all of the data to parse has been passed to ::OnDataAvailable
+// and the parser has been interrupted by the content sink
+// because the processing of tokens took too long.
+
+nsresult nsParser::PostContinueEvent() {
+ if (!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT)) {
+ // If this flag isn't set, then there shouldn't be a live continue event!
+ NS_ASSERTION(!mContinueEvent, "bad");
+
+ // This creates a reference cycle between this and the event that is
+ // broken when the event fires.
+ nsCOMPtr<nsIRunnable> event = new nsParserContinueEvent(this);
+ if (NS_FAILED(NS_DispatchToCurrentThread(event))) {
+ NS_WARNING("failed to dispatch parser continuation event");
+ } else {
+ mFlags |= NS_PARSER_FLAG_PENDING_CONTINUE_EVENT;
+ mContinueEvent = event;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(void)
+nsParser::GetCommand(nsCString& aCommand) { aCommand = mCommandStr; }
+
+/**
+ * Call this method once you've created a parser, and want to instruct it
+ * about the command which caused the parser to be constructed. For example,
+ * this allows us to select a DTD which can do, say, view-source.
+ *
+ * @param aCommand the command string to set
+ */
+NS_IMETHODIMP_(void)
+nsParser::SetCommand(const char* aCommand) {
+ mCommandStr.Assign(aCommand);
+ if (mCommandStr.EqualsLiteral("view-source")) {
+ mCommand = eViewSource;
+ } else if (mCommandStr.EqualsLiteral("view-fragment")) {
+ mCommand = eViewFragment;
+ } else {
+ mCommand = eViewNormal;
+ }
+}
+
+/**
+ * Call this method once you've created a parser, and want to instruct it
+ * about the command which caused the parser to be constructed. For example,
+ * this allows us to select a DTD which can do, say, view-source.
+ *
+ * @param aParserCommand the command to set
+ */
+NS_IMETHODIMP_(void)
+nsParser::SetCommand(eParserCommands aParserCommand) {
+ mCommand = aParserCommand;
+}
+
+/**
+ * Call this method once you've created a parser, and want to instruct it
+ * about what charset to load
+ *
+ * @param aCharset- the charset of a document
+ * @param aCharsetSource- the source of the charset
+ */
+void nsParser::SetDocumentCharset(NotNull<const Encoding*> aCharset,
+ int32_t aCharsetSource,
+ bool aForceAutoDetection) {
+ mCharset = aCharset;
+ mCharsetSource = aCharsetSource;
+ if (mParserContext) {
+ mParserContext->mScanner.SetDocumentCharset(aCharset, aCharsetSource);
+ }
+}
+
+void nsParser::SetSinkCharset(NotNull<const Encoding*> aCharset) {
+ if (mSink) {
+ mSink->SetDocumentCharset(aCharset);
+ }
+}
+
+/**
+ * This method gets called in order to set the content
+ * sink for this parser to dump nodes to.
+ *
+ * @param nsIContentSink interface for node receiver
+ */
+NS_IMETHODIMP_(void)
+nsParser::SetContentSink(nsIContentSink* aSink) {
+ MOZ_ASSERT(aSink, "sink cannot be null!");
+ mSink = aSink;
+
+ if (mSink) {
+ mSink->SetParser(this);
+ nsCOMPtr<nsIHTMLContentSink> htmlSink = do_QueryInterface(mSink);
+ if (htmlSink) {
+ mIsAboutBlank = true;
+ }
+ }
+}
+
+/**
+ * retrieve the sink set into the parser
+ * @return current sink
+ */
+NS_IMETHODIMP_(nsIContentSink*)
+nsParser::GetContentSink() { return mSink; }
+
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * This gets called just prior to the model actually
+ * being constructed. It's important to make this the
+ * last thing that happens right before parsing, so we
+ * can delay until the last moment the resolution of
+ * which DTD to use (unless of course we're assigned one).
+ */
+nsresult nsParser::WillBuildModel() {
+ if (!mParserContext) return NS_ERROR_HTMLPARSER_INVALIDPARSERCONTEXT;
+
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ if (eUnknownDetect != mParserContext->mAutoDetectStatus) return NS_OK;
+
+ if (eDTDMode_autodetect == mParserContext->mDTDMode) {
+ if (mIsAboutBlank) {
+ mParserContext->mDTDMode = eDTDMode_quirks;
+ mParserContext->mDocType = eHTML_Quirks;
+ } else {
+ mParserContext->mDTDMode = eDTDMode_full_standards;
+ mParserContext->mDocType = eXML;
+ }
+ } // else XML fragment with nested parser context
+
+ // We always find a DTD.
+ mParserContext->mAutoDetectStatus = ePrimaryDetect;
+
+ // Quick check for view source.
+ MOZ_ASSERT(mParserContext->mParserCommand != eViewSource,
+ "The old parser is not supposed to be used for View Source "
+ "anymore.");
+
+ // Now see if we're parsing XML or HTML (which, as far as we're concerned,
+ // simply means "not XML").
+ if (mParserContext->mDocType == eXML) {
+ RefPtr<nsExpatDriver> expat = new nsExpatDriver();
+ nsresult rv = expat->Initialize(mParserContext->mScanner.GetURI(), mSink);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mDTD = expat.forget();
+ } else {
+ mDTD = new CNavDTD();
+ }
+
+ return mSink->WillBuildModel(mParserContext->mDTDMode);
+}
+
+/**
+ * This gets called when the parser is done with its input.
+ */
+void nsParser::DidBuildModel() {
+ if (IsComplete() && mParserContext) {
+ // Let sink know if we're about to end load because we've been terminated.
+ // In that case we don't want it to run deferred scripts.
+ bool terminated = mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING;
+ if (mDTD && mSink) {
+ mDTD->DidBuildModel();
+ mSink->DidBuildModel(terminated);
+ }
+
+ // Ref. to bug 61462.
+ mParserContext->mRequest = nullptr;
+ }
+}
+
+/**
+ * Call this when you want to *force* the parser to terminate the
+ * parsing process altogether. This is binary -- so once you terminate
+ * you can't resume without restarting altogether.
+ */
+NS_IMETHODIMP
+nsParser::Terminate(void) {
+ // We should only call DidBuildModel once, so don't do anything if this is
+ // the second time that Terminate has been called.
+ if (mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING) {
+ return NS_OK;
+ }
+
+ nsresult result = NS_OK;
+ // XXX - [ until we figure out a way to break parser-sink circularity ]
+ // Hack - Hold a reference until we are completely done...
+ nsCOMPtr<nsIParser> kungFuDeathGrip(this);
+ mInternalState = result = NS_ERROR_HTMLPARSER_STOPPARSING;
+
+ // @see bug 108049
+ // If NS_PARSER_FLAG_PENDING_CONTINUE_EVENT is set then reset it so
+ // DidBuildModel will call DidBuildModel on the DTD. Note: The IsComplete()
+ // call inside of DidBuildModel looks at the pendingContinueEvents flag.
+ if (mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT) {
+ NS_ASSERTION(mContinueEvent, "mContinueEvent is null");
+ // Revoke the pending continue parsing event
+ mContinueEvent = nullptr;
+ mFlags &= ~NS_PARSER_FLAG_PENDING_CONTINUE_EVENT;
+ }
+
+ if (mDTD) {
+ mDTD->Terminate();
+ DidBuildModel();
+ } else if (mSink) {
+ // We have no parser context or no DTD yet (so we got terminated before we
+ // got any data). Manually break the reference cycle with the sink.
+ result = mSink->DidBuildModel(true);
+ NS_ENSURE_SUCCESS(result, result);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsParser::ContinueInterruptedParsing() {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ // If there are scripts executing, then the content sink is jumping the gun
+ // (probably due to a synchronous XMLHttpRequest) and will re-enable us
+ // later, see bug 460706.
+ if (!IsOkToProcessNetworkData()) {
+ return NS_OK;
+ }
+
+ // If the stream has already finished, there's a good chance
+ // that we might start closing things down when the parser
+ // is reenabled. To make sure that we're not deleted across
+ // the reenabling process, hold a reference to ourselves.
+ nsresult result = NS_OK;
+ nsCOMPtr<nsIParser> kungFuDeathGrip(this);
+ nsCOMPtr<nsIContentSink> sinkDeathGrip(mSink);
+
+#ifdef DEBUG
+ if (mBlocked) {
+ NS_WARNING("Don't call ContinueInterruptedParsing on a blocked parser.");
+ }
+#endif
+
+ bool isFinalChunk =
+ mParserContext && mParserContext->mStreamListenerState == eOnStop;
+
+ mProcessingNetworkData = true;
+ if (sinkDeathGrip) {
+ sinkDeathGrip->WillParse();
+ }
+ result = ResumeParse(true, isFinalChunk); // Ref. bug 57999
+ mProcessingNetworkData = false;
+
+ if (result != NS_OK) {
+ result = mInternalState;
+ }
+
+ return result;
+}
+
+/**
+ * Stops parsing temporarily. That is, it will prevent the
+ * parser from building up content model while scripts
+ * are being loaded (either an external script from a web
+ * page, or any number of extension content scripts).
+ */
+NS_IMETHODIMP_(void)
+nsParser::BlockParser() { mBlocked++; }
+
+/**
+ * Open up the parser for tokenization, building up content
+ * model..etc. However, this method does not resume parsing
+ * automatically. It's the callers' responsibility to restart
+ * the parsing engine.
+ */
+NS_IMETHODIMP_(void)
+nsParser::UnblockParser() {
+ MOZ_DIAGNOSTIC_ASSERT(mBlocked > 0);
+ if (MOZ_LIKELY(mBlocked > 0)) {
+ mBlocked--;
+ }
+}
+
+NS_IMETHODIMP_(void)
+nsParser::ContinueInterruptedParsingAsync() {
+ MOZ_ASSERT(mSink);
+ if (MOZ_LIKELY(mSink)) {
+ mSink->ContinueInterruptedParsingAsync();
+ }
+}
+
+/**
+ * Call this to query whether the parser is enabled or not.
+ */
+NS_IMETHODIMP_(bool)
+nsParser::IsParserEnabled() { return !mBlocked; }
+
+/**
+ * Call this to query whether the parser thinks it's done with parsing.
+ */
+NS_IMETHODIMP_(bool)
+nsParser::IsComplete() {
+ return !(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT);
+}
+
+void nsParser::HandleParserContinueEvent(nsParserContinueEvent* ev) {
+ // Ignore any revoked continue events...
+ if (mContinueEvent != ev) return;
+
+ mFlags &= ~NS_PARSER_FLAG_PENDING_CONTINUE_EVENT;
+ mContinueEvent = nullptr;
+
+ NS_ASSERTION(IsOkToProcessNetworkData(),
+ "Interrupted in the middle of a script?");
+ ContinueInterruptedParsing();
+}
+
+bool nsParser::IsInsertionPointDefined() { return false; }
+
+void nsParser::IncrementScriptNestingLevel() {}
+
+void nsParser::DecrementScriptNestingLevel() {}
+
+bool nsParser::HasNonzeroScriptNestingLevel() const { return false; }
+
+bool nsParser::IsScriptCreated() { return false; }
+
+/**
+ * This is the main controlling routine in the parsing process.
+ * Note that it may get called multiple times for the same scanner,
+ * since this is a pushed based system, and all the tokens may
+ * not have been consumed by the scanner during a given invocation
+ * of this method.
+ */
+NS_IMETHODIMP
+nsParser::Parse(nsIURI* aURL) {
+ MOZ_ASSERT(aURL, "Error: Null URL given");
+
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ if (!aURL) {
+ return NS_ERROR_HTMLPARSER_BADURL;
+ }
+
+ MOZ_ASSERT(!mParserContext, "We expect mParserContext to be null.");
+
+ mParserContext = MakeUnique<CParserContext>(aURL, mCommand);
+
+ return NS_OK;
+}
+
+/**
+ * Used by XML fragment parsing below.
+ *
+ * @param aSourceBuffer contains a string-full of real content
+ */
+nsresult nsParser::Parse(const nsAString& aSourceBuffer, bool aLastCall) {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ // Don't bother if we're never going to parse this.
+ if (mInternalState == NS_ERROR_HTMLPARSER_STOPPARSING) {
+ return NS_OK;
+ }
+
+ if (!aLastCall && aSourceBuffer.IsEmpty()) {
+ // Nothing is being passed to the parser so return
+ // immediately. mUnusedInput will get processed when
+ // some data is actually passed in.
+ // But if this is the last call, make sure to finish up
+ // stuff correctly.
+ return NS_OK;
+ }
+
+ // Maintain a reference to ourselves so we don't go away
+ // till we're completely done.
+ nsCOMPtr<nsIParser> kungFuDeathGrip(this);
+
+ if (!mParserContext) {
+ // Only make a new context if we don't have one.
+ mParserContext =
+ MakeUnique<CParserContext>(mUnusedInput, mCommand, aLastCall);
+
+ mUnusedInput.Truncate();
+ } else if (aLastCall) {
+ // Set stream listener state to eOnStop, on the final context - Fix
+ // 68160, to guarantee DidBuildModel() call - Fix 36148
+ mParserContext->mStreamListenerState = eOnStop;
+ mParserContext->mScanner.SetIncremental(false);
+ }
+
+ mParserContext->mScanner.Append(aSourceBuffer);
+ return ResumeParse(false, false, false);
+}
+
+nsresult nsParser::ParseFragment(const nsAString& aSourceBuffer,
+ nsTArray<nsString>& aTagStack) {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ nsresult result = NS_OK;
+ nsAutoString theContext;
+ uint32_t theCount = aTagStack.Length();
+ uint32_t theIndex = 0;
+
+ for (theIndex = 0; theIndex < theCount; theIndex++) {
+ theContext.Append('<');
+ theContext.Append(aTagStack[theCount - theIndex - 1]);
+ theContext.Append('>');
+ }
+
+ if (theCount == 0) {
+ // Ensure that the buffer is not empty. Because none of the DTDs care
+ // about leading whitespace, this doesn't change the result.
+ theContext.Assign(' ');
+ }
+
+ // First, parse the context to build up the DTD's tag stack. Note that we
+ // pass false for the aLastCall parameter.
+ result = Parse(theContext, false);
+ if (NS_FAILED(result)) {
+ return result;
+ }
+
+ if (!mSink) {
+ // Parse must have failed in the XML case and so the sink was killed.
+ return NS_ERROR_HTMLPARSER_STOPPARSING;
+ }
+
+ nsCOMPtr<nsIFragmentContentSink> fragSink = do_QueryInterface(mSink);
+ NS_ASSERTION(fragSink, "ParseFragment requires a fragment content sink");
+
+ fragSink->WillBuildContent();
+ // Now, parse the actual content. Note that this is the last call
+ // for HTML content, but for XML, we will want to build and parse
+ // the end tags. However, if tagStack is empty, it's the last call
+ // for XML as well.
+ if (theCount == 0) {
+ result = Parse(aSourceBuffer, true);
+ fragSink->DidBuildContent();
+ } else {
+ // Add an end tag chunk, so expat will read the whole source buffer,
+ // and not worry about ']]' etc.
+ result = Parse(aSourceBuffer + u"</"_ns, false);
+ fragSink->DidBuildContent();
+
+ if (NS_SUCCEEDED(result)) {
+ nsAutoString endContext;
+ for (theIndex = 0; theIndex < theCount; theIndex++) {
+ // we already added an end tag chunk above
+ if (theIndex > 0) {
+ endContext.AppendLiteral("</");
+ }
+
+ nsString& thisTag = aTagStack[theIndex];
+ // was there an xmlns=?
+ int32_t endOfTag = thisTag.FindChar(char16_t(' '));
+ if (endOfTag == -1) {
+ endContext.Append(thisTag);
+ } else {
+ endContext.Append(Substring(thisTag, 0, endOfTag));
+ }
+
+ endContext.Append('>');
+ }
+
+ result = Parse(endContext, true);
+ }
+ }
+
+ mParserContext.reset();
+
+ return result;
+}
+
+/**
+ * This routine is called to cause the parser to continue parsing its
+ * underlying stream. This call allows the parse process to happen in
+ * chunks, such as when the content is push based, and we need to parse in
+ * pieces.
+ *
+ * An interesting change in how the parser gets used has led us to add extra
+ * processing to this method. The case occurs when the parser is blocked in
+ * one context, and gets a parse(string) call in another context. In this
+ * case, the parserContexts are linked. No problem.
+ *
+ * The problem is that Parse(string) assumes that it can proceed unabated,
+ * but if the parser is already blocked that assumption is false. So we
+ * needed to add a mechanism here to allow the parser to continue to process
+ * (the pop and free) contexts until 1) it get's blocked again; 2) it runs
+ * out of contexts.
+ *
+ *
+ * @param allowItertion : set to true if non-script resumption is requested
+ * @param aIsFinalChunk : tells us when the last chunk of data is provided.
+ * @return error code -- 0 if ok, non-zero if error.
+ */
+nsresult nsParser::ResumeParse(bool allowIteration, bool aIsFinalChunk,
+ bool aCanInterrupt) {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ nsresult result = NS_OK;
+
+ if (!mBlocked && mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
+ result = WillBuildModel();
+ if (NS_FAILED(result)) {
+ mFlags &= ~NS_PARSER_FLAG_CAN_TOKENIZE;
+ return result;
+ }
+
+ if (mDTD) {
+ mSink->WillResume();
+ bool theIterationIsOk = true;
+
+ while (result == NS_OK && theIterationIsOk) {
+ if (!mUnusedInput.IsEmpty()) {
+ // -- Ref: Bug# 22485 --
+ // Insert the unused input into the source buffer
+ // as if it was read from the input stream.
+ // Adding UngetReadable() per vidur!!
+ mParserContext->mScanner.UngetReadable(mUnusedInput);
+ mUnusedInput.Truncate(0);
+ }
+
+ // Only allow parsing to be interrupted in the subsequent call to
+ // build model.
+ nsresult theTokenizerResult;
+ if (mFlags & NS_PARSER_FLAG_CAN_TOKENIZE) {
+ mParserContext->mScanner.Mark();
+ if (mParserContext->mDocType == eXML &&
+ mParserContext->mParserCommand != eViewSource) {
+ nsExpatDriver* expat = static_cast<nsExpatDriver*>(mDTD.get());
+ theTokenizerResult =
+ expat->ResumeParse(mParserContext->mScanner, aIsFinalChunk);
+ if (NS_FAILED(theTokenizerResult)) {
+ mParserContext->mScanner.RewindToMark();
+ if (NS_ERROR_HTMLPARSER_STOPPARSING == theTokenizerResult) {
+ theTokenizerResult = Terminate();
+ mSink = nullptr;
+ }
+ }
+ } else {
+ // Nothing to do for non-XML. Note that this should only be
+ // about:blank at this point, we're also checking for view-source
+ // above, but that shouldn't end up here anymore.
+ theTokenizerResult = NS_ERROR_HTMLPARSER_EOF;
+ }
+ } else {
+ theTokenizerResult = NS_OK;
+ }
+
+ result = mDTD->BuildModel(mSink);
+ if (result == NS_ERROR_HTMLPARSER_INTERRUPTED && aIsFinalChunk) {
+ PostContinueEvent();
+ }
+
+ theIterationIsOk = theTokenizerResult != NS_ERROR_HTMLPARSER_EOF &&
+ result != NS_ERROR_HTMLPARSER_INTERRUPTED;
+
+ // Make sure not to stop parsing too early. Therefore, before shutting
+ // down the parser, it's important to check whether the input buffer
+ // has been scanned to completion (theTokenizerResult should be kEOF).
+ // kEOF -> End of buffer.
+
+ // If we're told the parser has been blocked, we disable all further
+ // parsing (and cache any data coming in) until the parser is
+ // re-enabled.
+ if (NS_ERROR_HTMLPARSER_BLOCK == result) {
+ mSink->WillInterrupt();
+ return NS_OK;
+ }
+ if (NS_ERROR_HTMLPARSER_STOPPARSING == result) {
+ // Note: Parser Terminate() calls DidBuildModel.
+ if (mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
+ DidBuildModel();
+ mInternalState = result;
+ }
+
+ return NS_OK;
+ }
+ if (((NS_OK == result &&
+ theTokenizerResult == NS_ERROR_HTMLPARSER_EOF) ||
+ result == NS_ERROR_HTMLPARSER_INTERRUPTED) &&
+ mParserContext->mStreamListenerState == eOnStop) {
+ DidBuildModel();
+ return NS_OK;
+ }
+
+ if (theTokenizerResult == NS_ERROR_HTMLPARSER_EOF ||
+ result == NS_ERROR_HTMLPARSER_INTERRUPTED) {
+ result = (result == NS_ERROR_HTMLPARSER_INTERRUPTED) ? NS_OK : result;
+ mSink->WillInterrupt();
+ }
+ }
+ } else {
+ mInternalState = result = NS_ERROR_HTMLPARSER_UNRESOLVEDDTD;
+ }
+ }
+
+ return (result == NS_ERROR_HTMLPARSER_INTERRUPTED) ? NS_OK : result;
+}
+
+/*******************************************************************
+ These methods are used to talk to the netlib system...
+ *******************************************************************/
+
+nsresult nsParser::OnStartRequest(nsIRequest* request) {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ MOZ_ASSERT(eNone == mParserContext->mStreamListenerState,
+ "Parser's nsIStreamListener API was not setup "
+ "correctly in constructor.");
+
+ mParserContext->mStreamListenerState = eOnStart;
+ mParserContext->mAutoDetectStatus = eUnknownDetect;
+ mParserContext->mRequest = request;
+
+ mDTD = nullptr;
+
+ nsresult rv;
+ nsAutoCString contentType;
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+ if (channel) {
+ rv = channel->GetContentType(contentType);
+ if (NS_SUCCEEDED(rv)) {
+ mParserContext->SetMimeType(contentType);
+ }
+ }
+
+ rv = NS_OK;
+
+ return rv;
+}
+
+static bool ExtractCharsetFromXmlDeclaration(const unsigned char* aBytes,
+ int32_t aLen,
+ nsCString& oCharset) {
+ // This code is rather pointless to have. Might as well reuse expat as
+ // seen in nsHtml5StreamParser. -- hsivonen
+ oCharset.Truncate();
+ if ((aLen >= 5) && ('<' == aBytes[0]) && ('?' == aBytes[1]) &&
+ ('x' == aBytes[2]) && ('m' == aBytes[3]) && ('l' == aBytes[4])) {
+ int32_t i;
+ bool versionFound = false, encodingFound = false;
+ for (i = 6; i < aLen && !encodingFound; ++i) {
+ // end of XML declaration?
+ if ((((char*)aBytes)[i] == '?') && ((i + 1) < aLen) &&
+ (((char*)aBytes)[i + 1] == '>')) {
+ break;
+ }
+ // Version is required.
+ if (!versionFound) {
+ // Want to avoid string comparisons, hence looking for 'n'
+ // and only if found check the string leading to it. Not
+ // foolproof, but fast.
+ // The shortest string allowed before this is (strlen==13):
+ // <?xml version
+ if ((((char*)aBytes)[i] == 'n') && (i >= 12) &&
+ (0 == strncmp("versio", (char*)(aBytes + i - 6), 6))) {
+ // Fast forward through version
+ char q = 0;
+ for (++i; i < aLen; ++i) {
+ char qi = ((char*)aBytes)[i];
+ if (qi == '\'' || qi == '"') {
+ if (q && q == qi) {
+ // ending quote
+ versionFound = true;
+ break;
+ } else {
+ // Starting quote
+ q = qi;
+ }
+ }
+ }
+ }
+ } else {
+ // encoding must follow version
+ // Want to avoid string comparisons, hence looking for 'g'
+ // and only if found check the string leading to it. Not
+ // foolproof, but fast.
+ // The shortest allowed string before this (strlen==26):
+ // <?xml version="1" encoding
+ if ((((char*)aBytes)[i] == 'g') && (i >= 25) &&
+ (0 == strncmp("encodin", (char*)(aBytes + i - 7), 7))) {
+ int32_t encStart = 0;
+ char q = 0;
+ for (++i; i < aLen; ++i) {
+ char qi = ((char*)aBytes)[i];
+ if (qi == '\'' || qi == '"') {
+ if (q && q == qi) {
+ int32_t count = i - encStart;
+ // encoding value is invalid if it is UTF-16
+ if (count > 0 &&
+ PL_strncasecmp("UTF-16", (char*)(aBytes + encStart),
+ count)) {
+ oCharset.Assign((char*)(aBytes + encStart), count);
+ }
+ encodingFound = true;
+ break;
+ } else {
+ encStart = i + 1;
+ q = qi;
+ }
+ }
+ }
+ }
+ } // if (!versionFound)
+ } // for
+ }
+ return !oCharset.IsEmpty();
+}
+
+inline char GetNextChar(nsACString::const_iterator& aStart,
+ nsACString::const_iterator& aEnd) {
+ NS_ASSERTION(aStart != aEnd, "end of buffer");
+ return (++aStart != aEnd) ? *aStart : '\0';
+}
+
+static nsresult NoOpParserWriteFunc(nsIInputStream* in, void* closure,
+ const char* fromRawSegment,
+ uint32_t toOffset, uint32_t count,
+ uint32_t* writeCount) {
+ *writeCount = count;
+ return NS_OK;
+}
+
+typedef struct {
+ bool mNeedCharsetCheck;
+ nsParser* mParser;
+ nsScanner* mScanner;
+ nsIRequest* mRequest;
+} ParserWriteStruct;
+
+/*
+ * This function is invoked as a result of a call to a stream's
+ * ReadSegments() method. It is called for each contiguous buffer
+ * of data in the underlying stream or pipe. Using ReadSegments
+ * allows us to avoid copying data to read out of the stream.
+ */
+static nsresult ParserWriteFunc(nsIInputStream* in, void* closure,
+ const char* fromRawSegment, uint32_t toOffset,
+ uint32_t count, uint32_t* writeCount) {
+ nsresult result;
+ ParserWriteStruct* pws = static_cast<ParserWriteStruct*>(closure);
+ const unsigned char* buf =
+ reinterpret_cast<const unsigned char*>(fromRawSegment);
+ uint32_t theNumRead = count;
+
+ if (!pws) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (pws->mNeedCharsetCheck) {
+ pws->mNeedCharsetCheck = false;
+ int32_t source;
+ auto preferred = pws->mParser->GetDocumentCharset(source);
+
+ // This code was bogus when I found it. It expects the BOM or the XML
+ // declaration to be entirely in the first network buffer. -- hsivonen
+ const Encoding* encoding;
+ std::tie(encoding, std::ignore) = Encoding::ForBOM(Span(buf, count));
+ if (encoding) {
+ // The decoder will swallow the BOM. The UTF-16 will re-sniff for
+ // endianness. The value of preferred is now "UTF-8", "UTF-16LE"
+ // or "UTF-16BE".
+ preferred = WrapNotNull(encoding);
+ source = kCharsetFromByteOrderMark;
+ } else if (source < kCharsetFromChannel) {
+ nsAutoCString declCharset;
+
+ if (ExtractCharsetFromXmlDeclaration(buf, count, declCharset)) {
+ encoding = Encoding::ForLabel(declCharset);
+ if (encoding) {
+ preferred = WrapNotNull(encoding);
+ source = kCharsetFromMetaTag;
+ }
+ }
+ }
+
+ pws->mParser->SetDocumentCharset(preferred, source, false);
+ pws->mParser->SetSinkCharset(preferred);
+ }
+
+ result = pws->mScanner->Append(fromRawSegment, theNumRead);
+ if (NS_SUCCEEDED(result)) {
+ *writeCount = count;
+ }
+
+ return result;
+}
+
+nsresult nsParser::OnDataAvailable(nsIRequest* request,
+ nsIInputStream* pIStream,
+ uint64_t sourceOffset, uint32_t aLength) {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ MOZ_ASSERT((eOnStart == mParserContext->mStreamListenerState ||
+ eOnDataAvail == mParserContext->mStreamListenerState),
+ "Error: OnStartRequest() must be called before OnDataAvailable()");
+ MOZ_ASSERT(NS_InputStreamIsBuffered(pIStream),
+ "Must have a buffered input stream");
+
+ nsresult rv = NS_OK;
+
+ if (mIsAboutBlank) {
+ MOZ_ASSERT(false, "Must not get OnDataAvailable for about:blank");
+ // ... but if an extension tries to feed us data for about:blank in a
+ // release build, silently ignore the data.
+ uint32_t totalRead;
+ rv = pIStream->ReadSegments(NoOpParserWriteFunc, nullptr, aLength,
+ &totalRead);
+ return rv;
+ }
+
+ if (mParserContext->mRequest == request) {
+ mParserContext->mStreamListenerState = eOnDataAvail;
+
+ uint32_t totalRead;
+ ParserWriteStruct pws;
+ pws.mNeedCharsetCheck = true;
+ pws.mParser = this;
+ pws.mScanner = &mParserContext->mScanner;
+ pws.mRequest = request;
+
+ rv = pIStream->ReadSegments(ParserWriteFunc, &pws, aLength, &totalRead);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (IsOkToProcessNetworkData()) {
+ nsCOMPtr<nsIParser> kungFuDeathGrip(this);
+ nsCOMPtr<nsIContentSink> sinkDeathGrip(mSink);
+ mProcessingNetworkData = true;
+ if (sinkDeathGrip) {
+ sinkDeathGrip->WillParse();
+ }
+ rv = ResumeParse();
+ mProcessingNetworkData = false;
+ }
+ } else {
+ rv = NS_ERROR_UNEXPECTED;
+ }
+
+ return rv;
+}
+
+/**
+ * This is called by the networking library once the last block of data
+ * has been collected from the net.
+ */
+nsresult nsParser::OnStopRequest(nsIRequest* request, nsresult status) {
+ if (mInternalState == NS_ERROR_OUT_OF_MEMORY) {
+ // Checking NS_ERROR_OUT_OF_MEMORY instead of NS_FAILED
+ // to avoid introducing unintentional changes to behavior.
+ return mInternalState;
+ }
+
+ nsresult rv = NS_OK;
+
+ if (mParserContext->mRequest == request) {
+ mParserContext->mStreamListenerState = eOnStop;
+ mParserContext->mScanner.SetIncremental(false);
+ }
+
+ mStreamStatus = status;
+
+ if (IsOkToProcessNetworkData() && NS_SUCCEEDED(rv)) {
+ mProcessingNetworkData = true;
+ if (mSink) {
+ mSink->WillParse();
+ }
+ rv = ResumeParse(true, true);
+ mProcessingNetworkData = false;
+ }
+
+ // If the parser isn't enabled, we don't finish parsing till
+ // it is reenabled.
+
+ return rv;
+}
+
+/**
+ * Get this as nsIStreamListener
+ */
+nsIStreamListener* nsParser::GetStreamListener() { return this; }
diff --git a/parser/htmlparser/nsParser.h b/parser/htmlparser/nsParser.h
new file mode 100644
index 0000000000..95782e954b
--- /dev/null
+++ b/parser/htmlparser/nsParser.h
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * MODULE NOTES:
+ *
+ * This class does two primary jobs:
+ * 1) It iterates the tokens provided during the
+ * tokenization process, identifing where elements
+ * begin and end (doing validation and normalization).
+ * 2) It controls and coordinates with an instance of
+ * the IContentSink interface, to coordinate the
+ * the production of the content model.
+ *
+ * The basic operation of this class assumes that an HTML
+ * document is non-normalized. Therefore, we don't process
+ * the document in a normalized way. Don't bother to look
+ * for methods like: doHead() or doBody().
+ *
+ * Instead, in order to be backward compatible, we must
+ * scan the set of tokens and perform this basic set of
+ * operations:
+ * 1) Determine the token type (easy, since the tokens know)
+ * 2) Determine the appropriate section of the HTML document
+ * each token belongs in (HTML,HEAD,BODY,FRAMESET).
+ * 3) Insert content into our document (via the sink) into
+ * the correct section.
+ * 4) In the case of tags that belong in the BODY, we must
+ * ensure that our underlying document state reflects
+ * the appropriate context for our tag.
+ *
+ * For example,if we see a <TR>, we must ensure our
+ * document contains a table into which the row can
+ * be placed. This may result in "implicit containers"
+ * created to ensure a well-formed document.
+ *
+ */
+
+#ifndef NS_PARSER__
+#define NS_PARSER__
+
+#include "nsIParser.h"
+#include "nsDeque.h"
+#include "CParserContext.h"
+#include "nsHTMLTags.h"
+#include "nsIContentSink.h"
+#include "nsCOMArray.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWeakReference.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/UniquePtr.h"
+
+class nsIDTD;
+class nsIRunnable;
+
+#ifdef _MSC_VER
+# pragma warning(disable : 4275)
+#endif
+
+class nsParser final : public nsIParser,
+ public nsIStreamListener,
+ public nsSupportsWeakReference {
+ /**
+ * Destructor
+ * @update gess5/11/98
+ */
+ virtual ~nsParser();
+
+ public:
+ /**
+ * Called on module init
+ */
+ static nsresult Init();
+
+ /**
+ * Called on module shutdown
+ */
+ static void Shutdown();
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsParser, nsIParser)
+
+ /**
+ * default constructor
+ * @update gess5/11/98
+ */
+ nsParser();
+
+ /**
+ * Select given content sink into parser for parser output
+ * @update gess5/11/98
+ * @param aSink is the new sink to be used by parser
+ * @return old sink, or nullptr
+ */
+ NS_IMETHOD_(void) SetContentSink(nsIContentSink* aSink) override;
+
+ /**
+ * retrive the sink set into the parser
+ * @update gess5/11/98
+ * @param aSink is the new sink to be used by parser
+ * @return old sink, or nullptr
+ */
+ NS_IMETHOD_(nsIContentSink*) GetContentSink(void) override;
+
+ /**
+ * Call this method once you've created a parser, and want to instruct it
+ * about the command which caused the parser to be constructed. For example,
+ * this allows us to select a DTD which can do, say, view-source.
+ *
+ * @update gess 3/25/98
+ * @param aCommand -- ptrs to string that contains command
+ * @return nada
+ */
+ NS_IMETHOD_(void) GetCommand(nsCString& aCommand) override;
+ NS_IMETHOD_(void) SetCommand(const char* aCommand) override;
+ NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand) override;
+
+ /**
+ * Call this method once you've created a parser, and want to instruct it
+ * about what charset to load
+ *
+ * @update ftang 4/23/99
+ * @param aCharset- the charset of a document
+ * @param aCharsetSource- the source of the charset
+ * @param aChannelHadCharset- ignored
+ * @return nada
+ */
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aCharset,
+ int32_t aSource,
+ bool aForceAutoDetection) override;
+
+ NotNull<const Encoding*> GetDocumentCharset(int32_t& aSource) {
+ aSource = mCharsetSource;
+ return mCharset;
+ }
+
+ /**
+ * Cause parser to parse input from given URL
+ */
+ NS_IMETHOD Parse(nsIURI* aURL) override;
+
+ /**
+ * This method gets called when you want to parse a fragment of XML surrounded
+ * by the context |aTagStack|. It requires that the parser have been given a
+ * fragment content sink.
+ *
+ * @param aSourceBuffer The XML that hasn't been parsed yet.
+ * @param aTagStack The context of the source buffer.
+ */
+ nsresult ParseFragment(const nsAString& aSourceBuffer,
+ nsTArray<nsString>& aTagStack);
+
+ NS_IMETHOD ContinueInterruptedParsing() override;
+ NS_IMETHOD_(void) BlockParser() override;
+ NS_IMETHOD_(void) UnblockParser() override;
+ NS_IMETHOD_(void) ContinueInterruptedParsingAsync() override;
+ NS_IMETHOD Terminate(void) override;
+
+ /**
+ * Call this to query whether the parser is enabled or not.
+ *
+ * @update vidur 4/12/99
+ * @return current state
+ */
+ NS_IMETHOD_(bool) IsParserEnabled() override;
+
+ /**
+ * Call this to query whether the parser thinks it's done with parsing.
+ *
+ * @update rickg 5/12/01
+ * @return complete state
+ */
+ NS_IMETHOD_(bool) IsComplete() override;
+
+ /**
+ * This method gets called (automatically) during incremental parsing
+ * @update gess5/11/98
+ * @return TRUE if all went well, otherwise FALSE
+ */
+ virtual nsresult ResumeParse(bool allowIteration = true,
+ bool aIsFinalChunk = false,
+ bool aCanInterrupt = true);
+
+ //*********************************************
+ // These methods are callback methods used by
+ // net lib to let us know about our inputstream.
+ //*********************************************
+ // nsIRequestObserver methods:
+ NS_DECL_NSIREQUESTOBSERVER
+
+ // nsIStreamListener methods:
+ NS_DECL_NSISTREAMLISTENER
+
+ /**
+ * Get the nsIStreamListener for this parser
+ */
+ virtual nsIStreamListener* GetStreamListener() override;
+
+ void SetSinkCharset(NotNull<const Encoding*> aCharset);
+
+ /**
+ * Return true.
+ */
+ virtual bool IsInsertionPointDefined() override;
+
+ /**
+ * No-op.
+ */
+ void IncrementScriptNestingLevel() final;
+
+ /**
+ * No-op.
+ */
+ void DecrementScriptNestingLevel() final;
+
+ bool HasNonzeroScriptNestingLevel() const final;
+
+ /**
+ * Always false.
+ */
+ virtual bool IsScriptCreated() override;
+
+ /**
+ * This is called when the final chunk has been
+ * passed to the parser and the content sink has
+ * interrupted token processing. It schedules
+ * a ParserContinue PL_Event which will ask the parser
+ * to HandleParserContinueEvent when it is handled.
+ * @update kmcclusk6/1/2001
+ */
+ nsresult PostContinueEvent();
+
+ /**
+ * Fired when the continue parse event is triggered.
+ * @update kmcclusk 5/18/98
+ */
+ void HandleParserContinueEvent(class nsParserContinueEvent*);
+
+ void Reset() {
+ Cleanup();
+ mUnusedInput.Truncate();
+ Initialize();
+ }
+
+ bool IsScriptExecuting() { return mSink && mSink->IsScriptExecuting(); }
+
+ bool IsOkToProcessNetworkData() {
+ return !IsScriptExecuting() && !mProcessingNetworkData;
+ }
+
+ // Returns Nothing() if we haven't determined yet what the parser is being
+ // used for. Else returns whether this parser is used for parsing XML.
+ mozilla::Maybe<bool> IsForParsingXML() {
+ if (!mParserContext || mParserContext->mDTDMode == eDTDMode_autodetect) {
+ return mozilla::Nothing();
+ }
+
+ return mozilla::Some(mParserContext->mDocType == eXML);
+ }
+
+ protected:
+ void Initialize();
+ void Cleanup();
+
+ /**
+ *
+ * @update gess5/18/98
+ * @param
+ * @return
+ */
+ nsresult WillBuildModel();
+
+ /**
+ * Called when parsing is done.
+ */
+ void DidBuildModel();
+
+ private:
+ /**
+ * Pushes XML fragment parsing data to expat without an input stream.
+ */
+ nsresult Parse(const nsAString& aSourceBuffer, bool aLastCall);
+
+ protected:
+ //*********************************************
+ // And now, some data members...
+ //*********************************************
+
+ mozilla::UniquePtr<CParserContext> mParserContext;
+ nsCOMPtr<nsIDTD> mDTD;
+ nsCOMPtr<nsIContentSink> mSink;
+ nsIRunnable* mContinueEvent; // weak ref
+
+ eParserCommands mCommand;
+ nsresult mInternalState;
+ nsresult mStreamStatus;
+ int32_t mCharsetSource;
+
+ uint16_t mFlags;
+ uint32_t mBlocked;
+
+ nsString mUnusedInput;
+ NotNull<const Encoding*> mCharset;
+ nsCString mCommandStr;
+
+ bool mProcessingNetworkData;
+ bool mIsAboutBlank;
+};
+
+#endif
diff --git a/parser/htmlparser/nsParserBase.h b/parser/htmlparser/nsParserBase.h
new file mode 100644
index 0000000000..13c8883d4c
--- /dev/null
+++ b/parser/htmlparser/nsParserBase.h
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsParserBase_h_
+#define nsParserBase_h_
+
+#include "nsIChannel.h"
+
+class nsParserBase : public nsISupports {
+ public:
+ NS_IMETHOD_(bool) IsParserEnabled() { return true; }
+};
+
+#endif // nsParserBase_h_
diff --git a/parser/htmlparser/nsParserConstants.h b/parser/htmlparser/nsParserConstants.h
new file mode 100644
index 0000000000..bd6e4d477d
--- /dev/null
+++ b/parser/htmlparser/nsParserConstants.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsParserConstants_h_
+#define nsParserConstants_h_
+
+const char16_t kSpace = ' ';
+const char16_t kQuote = '"';
+const char16_t kApostrophe = '\'';
+const char16_t kLessThan = '<';
+const char16_t kGreaterThan = '>';
+const char16_t kAmpersand = '&';
+const char16_t kBackSlash = '\\';
+const char16_t kEqual = '=';
+const char16_t kSemicolon = ';';
+const char16_t kComma = ',';
+const char16_t kNullCh = '\0';
+
+#endif // nsParserConstants_h_
diff --git a/parser/htmlparser/nsParserMsgUtils.cpp b/parser/htmlparser/nsParserMsgUtils.cpp
new file mode 100644
index 0000000000..a629bcc5e3
--- /dev/null
+++ b/parser/htmlparser/nsParserMsgUtils.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIStringBundle.h"
+#include "nsString.h"
+#include "nsParserMsgUtils.h"
+#include "nsNetCID.h"
+#include "mozilla/Components.h"
+
+static nsresult GetBundle(const char* aPropFileName,
+ nsIStringBundle** aBundle) {
+ NS_ENSURE_ARG_POINTER(aPropFileName);
+ NS_ENSURE_ARG_POINTER(aBundle);
+
+ // Create a bundle for the localization
+
+ nsCOMPtr<nsIStringBundleService> stringService =
+ mozilla::components::StringBundle::Service();
+ if (!stringService) return NS_ERROR_FAILURE;
+
+ return stringService->CreateBundle(aPropFileName, aBundle);
+}
+
+nsresult nsParserMsgUtils::GetLocalizedStringByName(const char* aPropFileName,
+ const char* aKey,
+ nsString& oVal) {
+ oVal.Truncate();
+
+ NS_ENSURE_ARG_POINTER(aKey);
+
+ nsCOMPtr<nsIStringBundle> bundle;
+ nsresult rv = GetBundle(aPropFileName, getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv) && bundle) {
+ nsAutoString valUni;
+ rv = bundle->GetStringFromName(aKey, valUni);
+ if (NS_SUCCEEDED(rv)) {
+ oVal.Assign(valUni);
+ }
+ }
+
+ return rv;
+}
+
+nsresult nsParserMsgUtils::GetLocalizedStringByID(const char* aPropFileName,
+ uint32_t aID,
+ nsString& oVal) {
+ oVal.Truncate();
+
+ nsCOMPtr<nsIStringBundle> bundle;
+ nsresult rv = GetBundle(aPropFileName, getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv) && bundle) {
+ nsAutoString valUni;
+ rv = bundle->GetStringFromID(aID, valUni);
+ if (NS_SUCCEEDED(rv)) {
+ oVal.Assign(valUni);
+ }
+ }
+
+ return rv;
+}
diff --git a/parser/htmlparser/nsParserMsgUtils.h b/parser/htmlparser/nsParserMsgUtils.h
new file mode 100644
index 0000000000..3645610385
--- /dev/null
+++ b/parser/htmlparser/nsParserMsgUtils.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsParserMsgUtils_h
+#define nsParserMsgUtils_h
+
+#include "nsString.h"
+
+#define XMLPARSER_PROPERTIES \
+ "chrome://global/locale/layout/xmlparser.properties"
+
+#define XMLPARSER_PROPERTIES_en_US \
+ "resource://gre/res/locale/layout/xmlparser.properties"
+
+class nsParserMsgUtils {
+ nsParserMsgUtils(); // Currently this is not meant to be created, use the
+ // static methods
+ ~nsParserMsgUtils(); // If perf required, change this to cache values etc.
+ public:
+ static nsresult GetLocalizedStringByName(const char* aPropFileName,
+ const char* aKey, nsString& aVal);
+ static nsresult GetLocalizedStringByID(const char* aPropFileName,
+ uint32_t aID, nsString& aVal);
+};
+
+#endif
diff --git a/parser/htmlparser/nsRLBoxExpatDriver.h b/parser/htmlparser/nsRLBoxExpatDriver.h
new file mode 100644
index 0000000000..84236f3365
--- /dev/null
+++ b/parser/htmlparser/nsRLBoxExpatDriver.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef NS_RLBOX_EXPAT_DRIVER__
+#define NS_RLBOX_EXPAT_DRIVER__
+
+#include "mozilla/RLBoxSandboxPool.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/UniquePtr.h"
+
+class RLBoxExpatSandboxPool : public mozilla::RLBoxSandboxPool {
+ public:
+ explicit RLBoxExpatSandboxPool(size_t aDelaySeconds)
+ : RLBoxSandboxPool(aDelaySeconds) {}
+
+ static mozilla::StaticRefPtr<RLBoxExpatSandboxPool> sSingleton;
+ static void Initialize(size_t aDelaySeconds = 10);
+
+ protected:
+ mozilla::UniquePtr<mozilla::RLBoxSandboxDataBase> CreateSandboxData(
+ uint64_t aSize) override;
+ ~RLBoxExpatSandboxPool() = default;
+};
+
+#endif
diff --git a/parser/htmlparser/nsScanner.cpp b/parser/htmlparser/nsScanner.cpp
new file mode 100644
index 0000000000..36a14e1083
--- /dev/null
+++ b/parser/htmlparser/nsScanner.cpp
@@ -0,0 +1,331 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// #define __INCREMENTAL 1
+
+#include "nsScanner.h"
+
+#include "mozilla/Attributes.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Encoding.h"
+#include "mozilla/UniquePtr.h"
+#include "nsDebug.h"
+#include "nsReadableUtils.h"
+#include "nsUTF8Utils.h" // for LossyConvertEncoding
+#include "nsCRT.h"
+#include "nsParser.h"
+#include "nsCharsetSource.h"
+
+nsReadEndCondition::nsReadEndCondition(const char16_t* aTerminateChars)
+ : mChars(aTerminateChars),
+ mFilter(char16_t(~0)) // All bits set
+{
+ // Build filter that will be used to filter out characters with
+ // bits that none of the terminal chars have. This works very well
+ // because terminal chars often have only the last 4-6 bits set and
+ // normal ascii letters have bit 7 set. Other letters have even higher
+ // bits set.
+
+ // Calculate filter
+ const char16_t* current = aTerminateChars;
+ char16_t terminalChar = *current;
+ while (terminalChar) {
+ mFilter &= ~terminalChar;
+ ++current;
+ terminalChar = *current;
+ }
+}
+
+/**
+ * Use this constructor if you want i/o to be based on
+ * a single string you hand in during construction.
+ * This short cut was added for Javascript.
+ *
+ * @update gess 5/12/98
+ * @param aMode represents the parser mode (nav, other)
+ * @return
+ */
+nsScanner::nsScanner(const nsAString& anHTMLString, bool aIncremental)
+ : mIncremental(aIncremental) {
+ MOZ_COUNT_CTOR(nsScanner);
+
+ AppendToBuffer(anHTMLString);
+ MOZ_ASSERT(mMarkPosition == mCurrentPosition);
+}
+
+/**
+ * Use this constructor if you want i/o to be based on strings
+ * the scanner receives. If you pass a null filename, you
+ * can still provide data to the scanner via append.
+ */
+nsScanner::nsScanner(nsIURI* aURI) : mURI(aURI), mIncremental(true) {
+ MOZ_COUNT_CTOR(nsScanner);
+
+ // XXX This is a big hack. We need to initialize the iterators to something.
+ // What matters is that mCurrentPosition == mEndPosition, so that our methods
+ // believe that we are at EOF (see bug 182067). We null out mCurrentPosition
+ // so that we have some hope of catching null pointer dereferences associated
+ // with this hack. --darin
+ memset(&mCurrentPosition, 0, sizeof(mCurrentPosition));
+ mMarkPosition = mCurrentPosition;
+ mEndPosition = mCurrentPosition;
+
+ // XML defaults to UTF-8 and about:blank is UTF-8, too.
+ SetDocumentCharset(UTF_8_ENCODING, kCharsetFromDocTypeDefault);
+}
+
+nsresult nsScanner::SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ int32_t aSource) {
+ if (aSource < mCharsetSource) // priority is lower than the current one
+ return NS_OK;
+
+ mCharsetSource = aSource;
+ nsCString charsetName;
+ aEncoding->Name(charsetName);
+ if (!mCharset.IsEmpty() && charsetName.Equals(mCharset)) {
+ return NS_OK; // no difference, don't change it
+ }
+
+ // different, need to change it
+
+ mCharset.Assign(charsetName);
+
+ mUnicodeDecoder = aEncoding->NewDecoderWithBOMRemoval();
+
+ return NS_OK;
+}
+
+/**
+ * default destructor
+ *
+ * @update gess 3/25/98
+ * @param
+ * @return
+ */
+nsScanner::~nsScanner() { MOZ_COUNT_DTOR(nsScanner); }
+
+/**
+ * Resets current offset position of input stream to marked position.
+ * This allows us to back up to this point if the need should arise,
+ * such as when tokenization gets interrupted.
+ * NOTE: IT IS REALLY BAD FORM TO CALL RELEASE WITHOUT CALLING MARK FIRST!
+ *
+ * @update gess 5/12/98
+ * @param
+ * @return
+ */
+void nsScanner::RewindToMark(void) {
+ if (mSlidingBuffer) {
+ mCurrentPosition = mMarkPosition;
+ }
+}
+
+/**
+ * Records current offset position in input stream. This allows us
+ * to back up to this point if the need should arise, such as when
+ * tokenization gets interrupted.
+ *
+ * @update gess 7/29/98
+ * @param
+ * @return
+ */
+int32_t nsScanner::Mark() {
+ int32_t distance = 0;
+ if (mSlidingBuffer) {
+ nsScannerIterator oldStart;
+ mSlidingBuffer->BeginReading(oldStart);
+
+ distance = Distance(oldStart, mCurrentPosition);
+
+ mSlidingBuffer->DiscardPrefix(mCurrentPosition);
+ mSlidingBuffer->BeginReading(mCurrentPosition);
+ mMarkPosition = mCurrentPosition;
+ }
+
+ return distance;
+}
+
+/**
+ * Insert data to our underlying input buffer as
+ * if it were read from an input stream.
+ *
+ * @update harishd 01/12/99
+ * @return error code
+ */
+bool nsScanner::UngetReadable(const nsAString& aBuffer) {
+ if (!mSlidingBuffer) {
+ return false;
+ }
+
+ mSlidingBuffer->UngetReadable(aBuffer, mCurrentPosition);
+ mSlidingBuffer->BeginReading(
+ mCurrentPosition); // Insertion invalidated our iterators
+ mSlidingBuffer->EndReading(mEndPosition);
+
+ return true;
+}
+
+/**
+ * Append data to our underlying input buffer as
+ * if it were read from an input stream.
+ *
+ * @update gess4/3/98
+ * @return error code
+ */
+nsresult nsScanner::Append(const nsAString& aBuffer) {
+ if (!AppendToBuffer(aBuffer)) return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/**
+ *
+ *
+ * @update gess 5/21/98
+ * @param
+ * @return
+ */
+nsresult nsScanner::Append(const char* aBuffer, uint32_t aLen) {
+ nsresult res = NS_OK;
+ if (mUnicodeDecoder) {
+ mozilla::CheckedInt<size_t> needed =
+ mUnicodeDecoder->MaxUTF16BufferLength(aLen);
+ if (!needed.isValid()) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mozilla::CheckedInt<uint32_t> allocLen(
+ 1); // null terminator due to legacy sadness
+ allocLen += needed.value();
+ if (!allocLen.isValid()) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ nsScannerString::Buffer* buffer =
+ nsScannerString::AllocBuffer(allocLen.value());
+ NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
+ char16_t* unichars = buffer->DataStart();
+
+ uint32_t result;
+ size_t read;
+ size_t written;
+ // Do not use structured binding lest deal with [-Werror=unused-variable]
+ std::tie(result, read, written) =
+ mUnicodeDecoder->DecodeToUTF16WithoutReplacement(
+ AsBytes(mozilla::Span(aBuffer, aLen)),
+ mozilla::Span(unichars, needed.value()),
+ false); // Retain bug about failure to handle EOF
+ MOZ_ASSERT(result != mozilla::kOutputFull);
+ MOZ_ASSERT(read <= aLen);
+ MOZ_ASSERT(written <= needed.value());
+ if (result != mozilla::kInputEmpty) {
+ // Since about:blank is empty, this line runs only for XML. Use a
+ // character that's illegal in XML instead of U+FFFD in order to make
+ // expat flag the error. There is no need to loop and convert more, since
+ // expat will stop here anyway.
+ unichars[written++] = 0xFFFF;
+ }
+ buffer->SetDataLength(written);
+ // Don't propagate return code of unicode decoder
+ // since it doesn't reflect on our success or failure
+ // - Ref. bug 87110
+ res = NS_OK;
+ AppendToBuffer(buffer);
+ } else {
+ NS_WARNING("No decoder found.");
+ res = NS_ERROR_FAILURE;
+ }
+
+ return res;
+}
+
+/**
+ * retrieve next char from scanners internal input stream
+ *
+ * @update gess 3/25/98
+ * @param
+ * @return error code reflecting read status
+ */
+nsresult nsScanner::GetChar(char16_t& aChar) {
+ if (!mSlidingBuffer || mCurrentPosition == mEndPosition) {
+ aChar = 0;
+ return NS_ERROR_HTMLPARSER_EOF;
+ }
+
+ aChar = *mCurrentPosition++;
+
+ return NS_OK;
+}
+
+void nsScanner::BindSubstring(nsScannerSubstring& aSubstring,
+ const nsScannerIterator& aStart,
+ const nsScannerIterator& aEnd) {
+ aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd);
+}
+
+void nsScanner::CurrentPosition(nsScannerIterator& aPosition) {
+ aPosition = mCurrentPosition;
+}
+
+void nsScanner::EndReading(nsScannerIterator& aPosition) {
+ aPosition = mEndPosition;
+}
+
+void nsScanner::SetPosition(nsScannerIterator& aPosition, bool aTerminate) {
+ if (mSlidingBuffer) {
+ mCurrentPosition = aPosition;
+ if (aTerminate && (mCurrentPosition == mEndPosition)) {
+ mMarkPosition = mCurrentPosition;
+ mSlidingBuffer->DiscardPrefix(mCurrentPosition);
+ }
+ }
+}
+
+void nsScanner::AppendToBuffer(nsScannerString::Buffer* aBuf) {
+ if (!mSlidingBuffer) {
+ mSlidingBuffer = mozilla::MakeUnique<nsScannerString>(aBuf);
+ mSlidingBuffer->BeginReading(mCurrentPosition);
+ mMarkPosition = mCurrentPosition;
+ } else {
+ mSlidingBuffer->AppendBuffer(aBuf);
+ if (mCurrentPosition == mEndPosition) {
+ mSlidingBuffer->BeginReading(mCurrentPosition);
+ }
+ }
+ mSlidingBuffer->EndReading(mEndPosition);
+}
+
+/**
+ * call this to copy bytes out of the scanner that have not yet been consumed
+ * by the tokenization process.
+ *
+ * @update gess 5/12/98
+ * @param aCopyBuffer is where the scanner buffer will be copied to
+ * @return true if OK or false on OOM
+ */
+bool nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
+ if (!mSlidingBuffer) {
+ aCopyBuffer.Truncate();
+ return true;
+ }
+
+ nsScannerIterator start, end;
+ start = mCurrentPosition;
+ end = mEndPosition;
+
+ return CopyUnicodeTo(start, end, aCopyBuffer);
+}
+
+/**
+ * Conduct self test. Actually, selftesting for this class
+ * occurs in the parser selftest.
+ *
+ * @update gess 3/25/98
+ * @param
+ * @return
+ */
+
+void nsScanner::SelfTest(void) {
+#ifdef _DEBUG
+#endif
+}
diff --git a/parser/htmlparser/nsScanner.h b/parser/htmlparser/nsScanner.h
new file mode 100644
index 0000000000..ca0e51bc5e
--- /dev/null
+++ b/parser/htmlparser/nsScanner.h
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * MODULE NOTES:
+ * @update gess 4/1/98
+ *
+ * The scanner is a low-level service class that knows
+ * how to consume characters out of an (internal) stream.
+ * This class also offers a series of utility methods
+ * that most tokenizers want, such as readUntil()
+ * and SkipWhitespace().
+ */
+
+#ifndef SCANNER
+#define SCANNER
+
+#include "nsCharsetSource.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsIParser.h"
+#include "mozilla/Encoding.h"
+#include "nsScannerString.h"
+#include "mozilla/CheckedInt.h"
+
+class nsReadEndCondition {
+ public:
+ const char16_t* mChars;
+ char16_t mFilter;
+ explicit nsReadEndCondition(const char16_t* aTerminateChars);
+
+ private:
+ nsReadEndCondition(const nsReadEndCondition& aOther); // No copying
+ void operator=(const nsReadEndCondition& aOther); // No assigning
+};
+
+class nsScanner final {
+ using Encoding = mozilla::Encoding;
+ template <typename T>
+ using NotNull = mozilla::NotNull<T>;
+
+ public:
+ /**
+ * Use this constructor for the XML fragment parsing case
+ */
+ nsScanner(const nsAString& anHTMLString, bool aIncremental);
+
+ /**
+ * Use this constructor if you want i/o to be based on
+ * a file (therefore a stream) or just data you provide via Append().
+ */
+ explicit nsScanner(nsIURI* aURI);
+
+ ~nsScanner();
+
+ /**
+ * retrieve next char from internal input stream
+ *
+ * @update gess 3/25/98
+ * @param ch is the char to accept new value
+ * @return error code reflecting read status
+ */
+ nsresult GetChar(char16_t& ch);
+
+ /**
+ * Records current offset position in input stream. This allows us
+ * to back up to this point if the need should arise, such as when
+ * tokenization gets interrupted.
+ *
+ * @update gess 5/12/98
+ * @param
+ * @return
+ */
+ int32_t Mark(void);
+
+ /**
+ * Resets current offset position of input stream to marked position.
+ * This allows us to back up to this point if the need should arise,
+ * such as when tokenization gets interrupted.
+ * NOTE: IT IS REALLY BAD FORM TO CALL RELEASE WITHOUT CALLING MARK FIRST!
+ *
+ * @update gess 5/12/98
+ * @param
+ * @return
+ */
+ void RewindToMark(void);
+
+ /**
+ *
+ *
+ * @update harishd 01/12/99
+ * @param
+ * @return
+ */
+ bool UngetReadable(const nsAString& aBuffer);
+
+ /**
+ *
+ *
+ * @update gess 5/13/98
+ * @param
+ * @return
+ */
+ nsresult Append(const nsAString& aBuffer);
+
+ /**
+ *
+ *
+ * @update gess 5/21/98
+ * @param
+ * @return
+ */
+ nsresult Append(const char* aBuffer, uint32_t aLen);
+
+ /**
+ * Call this to copy bytes out of the scanner that have not yet been consumed
+ * by the tokenization process.
+ *
+ * @update gess 5/12/98
+ * @param aCopyBuffer is where the scanner buffer will be copied to
+ * @return true if OK or false on OOM
+ */
+ bool CopyUnusedData(nsString& aCopyBuffer);
+
+ /**
+ * Retrieve the URI of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
+ */
+ nsIURI* GetURI(void) const { return mURI; }
+
+ static void SelfTest();
+
+ /**
+ * Use this setter to change the scanner's unicode decoder
+ *
+ * @update ftang 3/02/99
+ * @param aCharset a normalized (alias resolved) charset name
+ * @param aCharsetSource- where the charset info came from
+ * @return
+ */
+ nsresult SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ int32_t aSource);
+
+ void BindSubstring(nsScannerSubstring& aSubstring,
+ const nsScannerIterator& aStart,
+ const nsScannerIterator& aEnd);
+ void CurrentPosition(nsScannerIterator& aPosition);
+ void EndReading(nsScannerIterator& aPosition);
+ void SetPosition(nsScannerIterator& aPosition, bool aTruncate = false);
+
+ /**
+ * Internal method used to cause the internal buffer to
+ * be filled with data.
+ *
+ * @update gess4/3/98
+ */
+ bool IsIncremental(void) { return mIncremental; }
+ void SetIncremental(bool anIncrValue) { mIncremental = anIncrValue; }
+
+ protected:
+ void AppendToBuffer(nsScannerString::Buffer* aBuffer);
+ bool AppendToBuffer(const nsAString& aStr) {
+ nsScannerString::Buffer* buf = nsScannerString::AllocBufferFromString(aStr);
+ if (!buf) return false;
+ AppendToBuffer(buf);
+ return true;
+ }
+
+ mozilla::UniquePtr<nsScannerString> mSlidingBuffer;
+ nsScannerIterator mCurrentPosition; // The position we will next read from in
+ // the scanner buffer
+ nsScannerIterator
+ mMarkPosition; // The position last marked (we may rewind to here)
+ nsScannerIterator mEndPosition; // The current end of the scanner buffer
+ nsCOMPtr<nsIURI> mURI;
+ bool mIncremental;
+ int32_t mCharsetSource = kCharsetUninitialized;
+ nsCString mCharset;
+ mozilla::UniquePtr<mozilla::Decoder> mUnicodeDecoder;
+
+ private:
+ nsScanner& operator=(const nsScanner&); // Not implemented.
+};
+
+#endif
diff --git a/parser/htmlparser/nsScannerString.cpp b/parser/htmlparser/nsScannerString.cpp
new file mode 100644
index 0000000000..2c7f09cfdd
--- /dev/null
+++ b/parser/htmlparser/nsScannerString.cpp
@@ -0,0 +1,379 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdlib.h>
+#include "nsScannerString.h"
+#include "mozilla/CheckedInt.h"
+
+/**
+ * nsScannerBufferList
+ */
+
+#define MAX_CAPACITY \
+ ((UINT32_MAX / sizeof(char16_t)) - (sizeof(Buffer) + sizeof(char16_t)))
+
+nsScannerBufferList::Buffer* nsScannerBufferList::AllocBufferFromString(
+ const nsAString& aString) {
+ uint32_t len = aString.Length();
+ Buffer* buf = AllocBuffer(len);
+
+ if (buf) {
+ nsAString::const_iterator source;
+ aString.BeginReading(source);
+ nsCharTraits<char16_t>::copy(buf->DataStart(), source.get(), len);
+ }
+ return buf;
+}
+
+nsScannerBufferList::Buffer* nsScannerBufferList::AllocBuffer(
+ uint32_t capacity) {
+ if (capacity > MAX_CAPACITY) return nullptr;
+
+ void* ptr = malloc(sizeof(Buffer) + (capacity + 1) * sizeof(char16_t));
+ if (!ptr) return nullptr;
+
+ Buffer* buf = new (ptr) Buffer();
+
+ buf->mUsageCount = 0;
+ buf->mDataEnd = buf->DataStart() + capacity;
+
+ // XXX null terminate. this shouldn't be required, but we do it because
+ // nsScanner erroneously thinks it can dereference DataEnd :-(
+ *buf->mDataEnd = char16_t(0);
+ return buf;
+}
+
+void nsScannerBufferList::ReleaseAll() {
+ while (!mBuffers.isEmpty()) {
+ Buffer* node = mBuffers.popFirst();
+ // printf(">>> freeing buffer @%p\n", node);
+ free(node);
+ }
+}
+
+void nsScannerBufferList::SplitBuffer(const Position& pos) {
+ // splitting to the right keeps the work string and any extant token
+ // pointing to and holding a reference count on the same buffer.
+
+ Buffer* bufferToSplit = pos.mBuffer;
+ NS_ASSERTION(bufferToSplit, "null pointer");
+
+ uint32_t splitOffset = pos.mPosition - bufferToSplit->DataStart();
+ NS_ASSERTION(pos.mPosition >= bufferToSplit->DataStart() &&
+ splitOffset <= bufferToSplit->DataLength(),
+ "split offset is outside buffer");
+
+ uint32_t len = bufferToSplit->DataLength() - splitOffset;
+ Buffer* new_buffer = AllocBuffer(len);
+ if (new_buffer) {
+ nsCharTraits<char16_t>::copy(new_buffer->DataStart(),
+ bufferToSplit->DataStart() + splitOffset, len);
+ InsertAfter(new_buffer, bufferToSplit);
+ bufferToSplit->SetDataLength(splitOffset);
+ }
+}
+
+void nsScannerBufferList::DiscardUnreferencedPrefix(Buffer* aBuf) {
+ if (aBuf == Head()) {
+ while (!mBuffers.isEmpty() && !Head()->IsInUse()) {
+ Buffer* buffer = Head();
+ buffer->remove();
+ free(buffer);
+ }
+ }
+}
+
+size_t nsScannerBufferList::Position::Distance(const Position& aStart,
+ const Position& aEnd) {
+ size_t result = 0;
+ if (aStart.mBuffer == aEnd.mBuffer) {
+ result = aEnd.mPosition - aStart.mPosition;
+ } else {
+ result = aStart.mBuffer->DataEnd() - aStart.mPosition;
+ for (Buffer* b = aStart.mBuffer->Next(); b != aEnd.mBuffer; b = b->Next())
+ result += b->DataLength();
+ result += aEnd.mPosition - aEnd.mBuffer->DataStart();
+ }
+ return result;
+}
+
+/**
+ * nsScannerSubstring
+ */
+
+nsScannerSubstring::nsScannerSubstring()
+ : mStart(nullptr, nullptr),
+ mEnd(nullptr, nullptr),
+ mBufferList(nullptr),
+ mLength(0) {}
+
+nsScannerSubstring::nsScannerSubstring(const nsAString& s)
+ : mBufferList(nullptr) {
+ Rebind(s);
+}
+
+nsScannerSubstring::~nsScannerSubstring() {
+ release_ownership_of_buffer_list();
+}
+
+void nsScannerSubstring::Rebind(const nsScannerSubstring& aString,
+ const nsScannerIterator& aStart,
+ const nsScannerIterator& aEnd) {
+ // allow for the case where &aString == this
+
+ aString.acquire_ownership_of_buffer_list();
+ release_ownership_of_buffer_list();
+
+ mStart = aStart;
+ mEnd = aEnd;
+ mBufferList = aString.mBufferList;
+ mLength = Distance(aStart, aEnd);
+}
+
+void nsScannerSubstring::Rebind(const nsAString& aString) {
+ release_ownership_of_buffer_list();
+
+ mBufferList = new nsScannerBufferList(AllocBufferFromString(aString));
+
+ init_range_from_buffer_list();
+ acquire_ownership_of_buffer_list();
+}
+
+nsScannerIterator& nsScannerSubstring::BeginReading(
+ nsScannerIterator& iter) const {
+ iter.mOwner = this;
+
+ iter.mFragment.mBuffer = mStart.mBuffer;
+ iter.mFragment.mFragmentStart = mStart.mPosition;
+ if (mStart.mBuffer == mEnd.mBuffer)
+ iter.mFragment.mFragmentEnd = mEnd.mPosition;
+ else
+ iter.mFragment.mFragmentEnd = mStart.mBuffer->DataEnd();
+
+ iter.mPosition = mStart.mPosition;
+ iter.normalize_forward();
+ return iter;
+}
+
+nsScannerIterator& nsScannerSubstring::EndReading(
+ nsScannerIterator& iter) const {
+ iter.mOwner = this;
+
+ iter.mFragment.mBuffer = mEnd.mBuffer;
+ iter.mFragment.mFragmentEnd = mEnd.mPosition;
+ if (mStart.mBuffer == mEnd.mBuffer)
+ iter.mFragment.mFragmentStart = mStart.mPosition;
+ else
+ iter.mFragment.mFragmentStart = mEnd.mBuffer->DataStart();
+
+ iter.mPosition = mEnd.mPosition;
+ // must not |normalize_backward| as that would likely invalidate tests like
+ // |while ( first != last )|
+ return iter;
+}
+
+bool nsScannerSubstring::GetNextFragment(nsScannerFragment& frag) const {
+ // check to see if we are at the end of the buffer list
+ if (frag.mBuffer == mEnd.mBuffer) return false;
+
+ frag.mBuffer = frag.mBuffer->getNext();
+
+ if (frag.mBuffer == mStart.mBuffer)
+ frag.mFragmentStart = mStart.mPosition;
+ else
+ frag.mFragmentStart = frag.mBuffer->DataStart();
+
+ if (frag.mBuffer == mEnd.mBuffer)
+ frag.mFragmentEnd = mEnd.mPosition;
+ else
+ frag.mFragmentEnd = frag.mBuffer->DataEnd();
+
+ return true;
+}
+
+bool nsScannerSubstring::GetPrevFragment(nsScannerFragment& frag) const {
+ // check to see if we are at the beginning of the buffer list
+ if (frag.mBuffer == mStart.mBuffer) return false;
+
+ frag.mBuffer = frag.mBuffer->getPrevious();
+
+ if (frag.mBuffer == mStart.mBuffer)
+ frag.mFragmentStart = mStart.mPosition;
+ else
+ frag.mFragmentStart = frag.mBuffer->DataStart();
+
+ if (frag.mBuffer == mEnd.mBuffer)
+ frag.mFragmentEnd = mEnd.mPosition;
+ else
+ frag.mFragmentEnd = frag.mBuffer->DataEnd();
+
+ return true;
+}
+
+/**
+ * nsScannerString
+ */
+
+nsScannerString::nsScannerString(Buffer* aBuf) {
+ mBufferList = new nsScannerBufferList(aBuf);
+
+ init_range_from_buffer_list();
+ acquire_ownership_of_buffer_list();
+}
+
+void nsScannerString::AppendBuffer(Buffer* aBuf) {
+ mBufferList->Append(aBuf);
+ mLength += aBuf->DataLength();
+
+ mEnd.mBuffer = aBuf;
+ mEnd.mPosition = aBuf->DataEnd();
+}
+
+void nsScannerString::DiscardPrefix(const nsScannerIterator& aIter) {
+ Position old_start(mStart);
+ mStart = aIter;
+ mLength -= Position::Distance(old_start, mStart);
+
+ mStart.mBuffer->IncrementUsageCount();
+ old_start.mBuffer->DecrementUsageCount();
+
+ mBufferList->DiscardUnreferencedPrefix(old_start.mBuffer);
+}
+
+void nsScannerString::UngetReadable(const nsAString& aReadable,
+ const nsScannerIterator& aInsertPoint)
+/*
+ * Warning: this routine manipulates the shared buffer list in an
+ * unexpected way. The original design did not really allow for
+ * insertions, but this call promises that if called for a point after the
+ * end of all extant token strings, that no token string or the work string
+ * will be invalidated.
+ *
+ * This routine is protected because it is the responsibility of the
+ * derived class to keep those promises.
+ */
+{
+ Position insertPos(aInsertPoint);
+
+ mBufferList->SplitBuffer(insertPos);
+ // splitting to the right keeps the work string and any extant token
+ // pointing to and holding a reference count on the same buffer
+
+ Buffer* new_buffer = AllocBufferFromString(aReadable);
+ // make a new buffer with all the data to insert...
+ // ALERT: we may have empty space to re-use in the split buffer,
+ // measure the cost of this and decide if we should do the work to fill
+ // it
+
+ Buffer* buffer_to_split = insertPos.mBuffer;
+ mBufferList->InsertAfter(new_buffer, buffer_to_split);
+ mLength += aReadable.Length();
+
+ mEnd.mBuffer = mBufferList->Tail();
+ mEnd.mPosition = mEnd.mBuffer->DataEnd();
+}
+
+/**
+ * nsScannerSharedSubstring
+ */
+
+void nsScannerSharedSubstring::Rebind(const nsScannerIterator& aStart,
+ const nsScannerIterator& aEnd) {
+ // If the start and end positions are inside the same buffer, we must
+ // acquire ownership of the buffer. If not, we can optimize by not holding
+ // onto it.
+
+ Buffer* buffer = const_cast<Buffer*>(aStart.buffer());
+ bool sameBuffer = buffer == aEnd.buffer();
+
+ nsScannerBufferList* bufferList;
+
+ if (sameBuffer) {
+ bufferList = aStart.mOwner->mBufferList;
+ bufferList->AddRef();
+ buffer->IncrementUsageCount();
+ }
+
+ if (mBufferList) ReleaseBuffer();
+
+ if (sameBuffer) {
+ mBuffer = buffer;
+ mBufferList = bufferList;
+ mString.Rebind(aStart.mPosition, aEnd.mPosition);
+ } else {
+ mBuffer = nullptr;
+ mBufferList = nullptr;
+ CopyUnicodeTo(aStart, aEnd, mString);
+ }
+}
+
+void nsScannerSharedSubstring::ReleaseBuffer() {
+ NS_ASSERTION(mBufferList, "Should only be called with non-null mBufferList");
+ mBuffer->DecrementUsageCount();
+ mBufferList->DiscardUnreferencedPrefix(mBuffer);
+ mBufferList->Release();
+}
+
+/**
+ * utils -- based on code from nsReadableUtils.cpp
+ */
+
+// private helper function
+static inline nsAString::iterator& copy_multifragment_string(
+ nsScannerIterator& first, const nsScannerIterator& last,
+ nsAString::iterator& result) {
+ typedef nsCharSourceTraits<nsScannerIterator> source_traits;
+ typedef nsCharSinkTraits<nsAString::iterator> sink_traits;
+
+ while (first != last) {
+ uint32_t distance = source_traits::readable_distance(first, last);
+ sink_traits::write(result, source_traits::read(first), distance);
+ NS_ASSERTION(distance > 0,
+ "|copy_multifragment_string| will never terminate");
+ source_traits::advance(first, distance);
+ }
+
+ return result;
+}
+
+bool CopyUnicodeTo(const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd, nsAString& aDest) {
+ mozilla::CheckedInt<nsAString::size_type> distance(
+ Distance(aSrcStart, aSrcEnd));
+ if (!distance.isValid()) {
+ return false; // overflow detected
+ }
+
+ if (!aDest.SetLength(distance.value(), mozilla::fallible)) {
+ aDest.Truncate();
+ return false; // out of memory
+ }
+ auto writer = aDest.BeginWriting();
+ nsScannerIterator fromBegin(aSrcStart);
+
+ copy_multifragment_string(fromBegin, aSrcEnd, writer);
+ return true;
+}
+
+bool AppendUnicodeTo(const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd, nsAString& aDest) {
+ const nsAString::size_type oldLength = aDest.Length();
+ mozilla::CheckedInt<nsAString::size_type> newLen(
+ Distance(aSrcStart, aSrcEnd));
+ newLen += oldLength;
+ if (!newLen.isValid()) {
+ return false; // overflow detected
+ }
+
+ if (!aDest.SetLength(newLen.value(), mozilla::fallible))
+ return false; // out of memory
+ auto writer = aDest.BeginWriting();
+ std::advance(writer, oldLength);
+ nsScannerIterator fromBegin(aSrcStart);
+
+ copy_multifragment_string(fromBegin, aSrcEnd, writer);
+ return true;
+}
diff --git a/parser/htmlparser/nsScannerString.h b/parser/htmlparser/nsScannerString.h
new file mode 100644
index 0000000000..195e63e4bb
--- /dev/null
+++ b/parser/htmlparser/nsScannerString.h
@@ -0,0 +1,459 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsScannerString_h___
+#define nsScannerString_h___
+
+#include "nsString.h"
+#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator
+#include "mozilla/LinkedList.h"
+#include <algorithm>
+
+/**
+ * NOTE: nsScannerString (and the other classes defined in this file) are
+ * not related to nsAString or any of the other xpcom/string classes.
+ *
+ * nsScannerString is based on the nsSlidingString implementation that used
+ * to live in xpcom/string. Now that nsAString is limited to representing
+ * only single fragment strings, nsSlidingString can no longer be used.
+ *
+ * An advantage to this design is that it does not employ any virtual
+ * functions.
+ *
+ * This file uses SCC-style indenting in deference to the nsSlidingString
+ * code from which this code is derived ;-)
+ */
+
+class nsScannerIterator;
+class nsScannerSubstring;
+class nsScannerString;
+
+/**
+ * nsScannerBufferList
+ *
+ * This class maintains a list of heap-allocated Buffer objects. The buffers
+ * are maintained in a circular linked list. Each buffer has a usage count
+ * that is decremented by the owning nsScannerSubstring.
+ *
+ * The buffer list itself is reference counted. This allows the buffer list
+ * to be shared by multiple nsScannerSubstring objects. The reference
+ * counting is not threadsafe, which is not at all a requirement.
+ *
+ * When a nsScannerSubstring releases its reference to a buffer list, it
+ * decrements the usage count of the first buffer in the buffer list that it
+ * was referencing. It informs the buffer list that it can discard buffers
+ * starting at that prefix. The buffer list will do so if the usage count of
+ * that buffer is 0 and if it is the first buffer in the list. It will
+ * continue to prune buffers starting from the front of the buffer list until
+ * it finds a buffer that has a usage count that is non-zero.
+ */
+class nsScannerBufferList {
+ public:
+ /**
+ * Buffer objects are directly followed by a data segment. The start
+ * of the data segment is determined by increment the |this| pointer
+ * by 1 unit.
+ */
+ class Buffer : public mozilla::LinkedListElement<Buffer> {
+ public:
+ void IncrementUsageCount() { ++mUsageCount; }
+ void DecrementUsageCount() { --mUsageCount; }
+
+ bool IsInUse() const { return mUsageCount != 0; }
+
+ const char16_t* DataStart() const { return (const char16_t*)(this + 1); }
+ char16_t* DataStart() { return (char16_t*)(this + 1); }
+
+ const char16_t* DataEnd() const { return mDataEnd; }
+ char16_t* DataEnd() { return mDataEnd; }
+
+ const Buffer* Next() const { return getNext(); }
+ Buffer* Next() { return getNext(); }
+
+ const Buffer* Prev() const { return getPrevious(); }
+ Buffer* Prev() { return getPrevious(); }
+
+ uint32_t DataLength() const { return mDataEnd - DataStart(); }
+ void SetDataLength(uint32_t len) { mDataEnd = DataStart() + len; }
+
+ private:
+ friend class nsScannerBufferList;
+
+ int32_t mUsageCount;
+ char16_t* mDataEnd;
+ };
+
+ /**
+ * Position objects serve as lightweight pointers into a buffer list.
+ * The mPosition member must be contained with mBuffer->DataStart()
+ * and mBuffer->DataEnd().
+ */
+ class Position {
+ public:
+ Position() : mBuffer(nullptr), mPosition(nullptr) {}
+
+ Position(Buffer* buffer, char16_t* position)
+ : mBuffer(buffer), mPosition(position) {}
+
+ inline explicit Position(const nsScannerIterator& aIter);
+
+ inline Position& operator=(const nsScannerIterator& aIter);
+
+ static size_t Distance(const Position& p1, const Position& p2);
+
+ Buffer* mBuffer;
+ char16_t* mPosition;
+ };
+
+ static Buffer* AllocBufferFromString(const nsAString&);
+ static Buffer* AllocBuffer(uint32_t capacity); // capacity = number of chars
+
+ explicit nsScannerBufferList(Buffer* buf) : mRefCnt(0) {
+ mBuffers.insertBack(buf);
+ }
+
+ void AddRef() { ++mRefCnt; }
+ void Release() {
+ if (--mRefCnt == 0) delete this;
+ }
+
+ void Append(Buffer* buf) { mBuffers.insertBack(buf); }
+ void InsertAfter(Buffer* buf, Buffer* prev) { prev->setNext(buf); }
+ void SplitBuffer(const Position&);
+ void DiscardUnreferencedPrefix(Buffer*);
+
+ Buffer* Head() { return mBuffers.getFirst(); }
+ const Buffer* Head() const { return mBuffers.getFirst(); }
+
+ Buffer* Tail() { return mBuffers.getLast(); }
+ const Buffer* Tail() const { return mBuffers.getLast(); }
+
+ private:
+ friend class nsScannerSubstring;
+
+ ~nsScannerBufferList() { ReleaseAll(); }
+ void ReleaseAll();
+
+ int32_t mRefCnt;
+ mozilla::LinkedList<Buffer> mBuffers;
+};
+
+/**
+ * nsScannerFragment represents a "slice" of a Buffer object.
+ */
+struct nsScannerFragment {
+ typedef nsScannerBufferList::Buffer Buffer;
+
+ const Buffer* mBuffer;
+ const char16_t* mFragmentStart;
+ const char16_t* mFragmentEnd;
+};
+
+/**
+ * nsScannerSubstring is the base class for nsScannerString. It provides
+ * access to iterators and methods to bind the substring to another
+ * substring or nsAString instance.
+ *
+ * This class owns the buffer list.
+ */
+class nsScannerSubstring {
+ public:
+ typedef nsScannerBufferList::Buffer Buffer;
+ typedef nsScannerBufferList::Position Position;
+ typedef uint32_t size_type;
+
+ nsScannerSubstring();
+ explicit nsScannerSubstring(const nsAString& s);
+
+ ~nsScannerSubstring();
+
+ nsScannerIterator& BeginReading(nsScannerIterator& iter) const;
+ nsScannerIterator& EndReading(nsScannerIterator& iter) const;
+
+ size_type Length() const { return mLength; }
+
+ void Rebind(const nsScannerSubstring&, const nsScannerIterator&,
+ const nsScannerIterator&);
+ void Rebind(const nsAString&);
+
+ bool GetNextFragment(nsScannerFragment&) const;
+ bool GetPrevFragment(nsScannerFragment&) const;
+
+ static inline Buffer* AllocBufferFromString(const nsAString& aStr) {
+ return nsScannerBufferList::AllocBufferFromString(aStr);
+ }
+ static inline Buffer* AllocBuffer(size_type aCapacity) {
+ return nsScannerBufferList::AllocBuffer(aCapacity);
+ }
+
+ protected:
+ void acquire_ownership_of_buffer_list() const {
+ mBufferList->AddRef();
+ mStart.mBuffer->IncrementUsageCount();
+ }
+
+ void release_ownership_of_buffer_list() {
+ if (mBufferList) {
+ mStart.mBuffer->DecrementUsageCount();
+ mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer);
+ mBufferList->Release();
+ }
+ }
+
+ void init_range_from_buffer_list() {
+ mStart.mBuffer = mBufferList->Head();
+ mStart.mPosition = mStart.mBuffer->DataStart();
+
+ mEnd.mBuffer = mBufferList->Tail();
+ mEnd.mPosition = mEnd.mBuffer->DataEnd();
+
+ mLength = Position::Distance(mStart, mEnd);
+ }
+
+ Position mStart;
+ Position mEnd;
+ nsScannerBufferList* mBufferList;
+ size_type mLength;
+
+ friend class nsScannerSharedSubstring;
+};
+
+/**
+ * nsScannerString provides methods to grow and modify a buffer list.
+ */
+class nsScannerString : public nsScannerSubstring {
+ public:
+ explicit nsScannerString(Buffer*);
+
+ // you are giving ownership to the string, it takes and keeps your
+ // buffer, deleting it when done.
+ // Use AllocBuffer or AllocBufferFromString to create a Buffer object
+ // for use with this function.
+ void AppendBuffer(Buffer*);
+
+ void DiscardPrefix(const nsScannerIterator&);
+ // any other way you want to do this?
+
+ void UngetReadable(const nsAString& aReadable,
+ const nsScannerIterator& aCurrentPosition);
+};
+
+/**
+ * nsScannerSharedSubstring implements copy-on-write semantics for
+ * nsScannerSubstring. This class also manages releasing
+ * the reference to the scanner buffer when it is no longer needed.
+ */
+
+class nsScannerSharedSubstring {
+ public:
+ nsScannerSharedSubstring() : mBuffer(nullptr), mBufferList(nullptr) {}
+
+ ~nsScannerSharedSubstring() {
+ if (mBufferList) ReleaseBuffer();
+ }
+
+ // Acquire a copy-on-write reference to the given substring.
+ void Rebind(const nsScannerIterator& aStart, const nsScannerIterator& aEnd);
+
+ // Get a const reference to this string
+ const nsAString& str() const { return mString; }
+
+ private:
+ typedef nsScannerBufferList::Buffer Buffer;
+
+ void ReleaseBuffer();
+
+ nsDependentSubstring mString;
+ Buffer* mBuffer;
+ nsScannerBufferList* mBufferList;
+};
+
+/**
+ * nsScannerIterator works just like nsReadingIterator<CharT> except that
+ * it knows how to iterate over a list of scanner buffers.
+ */
+class nsScannerIterator {
+ public:
+ typedef nsScannerIterator self_type;
+ typedef ptrdiff_t difference_type;
+ typedef char16_t value_type;
+ typedef const char16_t* pointer;
+ typedef const char16_t& reference;
+ typedef nsScannerSubstring::Buffer Buffer;
+
+ protected:
+ nsScannerFragment mFragment;
+ const char16_t* mPosition;
+ const nsScannerSubstring* mOwner;
+
+ friend class nsScannerSubstring;
+ friend class nsScannerSharedSubstring;
+
+ public:
+ // nsScannerIterator(); // auto-generate
+ // default constructor is OK nsScannerIterator( const nsScannerIterator& ); //
+ // auto-generated copy-constructor OK nsScannerIterator& operator=( const
+ // nsScannerIterator& ); // auto-generated copy-assignment operator OK
+
+ inline void normalize_forward();
+ inline void normalize_backward();
+
+ pointer get() const { return mPosition; }
+
+ char16_t operator*() const { return *get(); }
+
+ const nsScannerFragment& fragment() const { return mFragment; }
+
+ const Buffer* buffer() const { return mFragment.mBuffer; }
+
+ self_type& operator++() {
+ ++mPosition;
+ normalize_forward();
+ return *this;
+ }
+
+ self_type operator++(int) {
+ self_type result(*this);
+ ++mPosition;
+ normalize_forward();
+ return result;
+ }
+
+ self_type& operator--() {
+ normalize_backward();
+ --mPosition;
+ return *this;
+ }
+
+ self_type operator--(int) {
+ self_type result(*this);
+ normalize_backward();
+ --mPosition;
+ return result;
+ }
+
+ difference_type size_forward() const {
+ return mFragment.mFragmentEnd - mPosition;
+ }
+
+ difference_type size_backward() const {
+ return mPosition - mFragment.mFragmentStart;
+ }
+
+ self_type& advance(difference_type n) {
+ while (n > 0) {
+ difference_type one_hop = std::min(n, size_forward());
+
+ NS_ASSERTION(one_hop > 0,
+ "Infinite loop: can't advance a reading iterator beyond the "
+ "end of a string");
+ // perhaps I should |break| if |!one_hop|?
+
+ mPosition += one_hop;
+ normalize_forward();
+ n -= one_hop;
+ }
+
+ while (n < 0) {
+ normalize_backward();
+ difference_type one_hop = std::max(n, -size_backward());
+
+ NS_ASSERTION(one_hop < 0,
+ "Infinite loop: can't advance (backward) a reading iterator "
+ "beyond the end of a string");
+ // perhaps I should |break| if |!one_hop|?
+
+ mPosition += one_hop;
+ n -= one_hop;
+ }
+
+ return *this;
+ }
+};
+
+inline bool SameFragment(const nsScannerIterator& a,
+ const nsScannerIterator& b) {
+ return a.fragment().mFragmentStart == b.fragment().mFragmentStart;
+}
+
+/**
+ * this class is needed in order to make use of the methods in nsAlgorithm.h
+ */
+template <>
+struct nsCharSourceTraits<nsScannerIterator> {
+ typedef nsScannerIterator::difference_type difference_type;
+
+ static uint32_t readable_distance(const nsScannerIterator& first,
+ const nsScannerIterator& last) {
+ return uint32_t(SameFragment(first, last) ? last.get() - first.get()
+ : first.size_forward());
+ }
+
+ static const nsScannerIterator::value_type* read(
+ const nsScannerIterator& iter) {
+ return iter.get();
+ }
+
+ static void advance(nsScannerIterator& s, difference_type n) { s.advance(n); }
+};
+
+/**
+ * inline methods follow
+ */
+
+inline void nsScannerIterator::normalize_forward() {
+ while (mPosition == mFragment.mFragmentEnd &&
+ mOwner->GetNextFragment(mFragment))
+ mPosition = mFragment.mFragmentStart;
+}
+
+inline void nsScannerIterator::normalize_backward() {
+ while (mPosition == mFragment.mFragmentStart &&
+ mOwner->GetPrevFragment(mFragment))
+ mPosition = mFragment.mFragmentEnd;
+}
+
+inline bool operator==(const nsScannerIterator& lhs,
+ const nsScannerIterator& rhs) {
+ return lhs.get() == rhs.get();
+}
+
+inline bool operator!=(const nsScannerIterator& lhs,
+ const nsScannerIterator& rhs) {
+ return lhs.get() != rhs.get();
+}
+
+inline nsScannerBufferList::Position::Position(const nsScannerIterator& aIter)
+ : mBuffer(const_cast<Buffer*>(aIter.buffer())),
+ mPosition(const_cast<char16_t*>(aIter.get())) {}
+
+inline nsScannerBufferList::Position& nsScannerBufferList::Position::operator=(
+ const nsScannerIterator& aIter) {
+ mBuffer = const_cast<Buffer*>(aIter.buffer());
+ mPosition = const_cast<char16_t*>(aIter.get());
+ return *this;
+}
+
+/**
+ * scanner string utils
+ *
+ * These methods mimic the API provided by nsReadableUtils in xpcom/string.
+ * Here we provide only the methods that the htmlparser module needs.
+ */
+
+inline size_t Distance(const nsScannerIterator& aStart,
+ const nsScannerIterator& aEnd) {
+ typedef nsScannerBufferList::Position Position;
+ return Position::Distance(Position(aStart), Position(aEnd));
+}
+
+bool CopyUnicodeTo(const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd, nsAString& aDest);
+
+bool AppendUnicodeTo(const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd, nsAString& aDest);
+
+#endif // !defined(nsScannerString_h___)
diff --git a/parser/htmlparser/tests/crashtests/121591-1.html b/parser/htmlparser/tests/crashtests/121591-1.html
new file mode 100644
index 0000000000..b411a18518
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/121591-1.html
@@ -0,0 +1,22 @@
+<HTML>
+<body>
+<span>
+<head><link></head>
+ <table border=1>
+ <tr><td>
+ <table border=1 align="left">
+ <tr><td></td></tr>
+ <tr><td>
+ <form>
+ <button></button>
+ </form>
+ </td></tr>
+ </table>
+ </td></tr>
+ </table>
+</span>
+</body>
+</html>
+
+
+
diff --git a/parser/htmlparser/tests/crashtests/1373045-1.html b/parser/htmlparser/tests/crashtests/1373045-1.html
new file mode 100644
index 0000000000..d0bea2fa44
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1373045-1.html
@@ -0,0 +1 @@
+<object data="data:image/svg+xml;charset=ISO-2022-KR,%30"></object>
diff --git a/parser/htmlparser/tests/crashtests/147179-1.html b/parser/htmlparser/tests/crashtests/147179-1.html
new file mode 100644
index 0000000000..2aaac19844
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/147179-1.html
@@ -0,0 +1,7 @@
+<html><head><title>Testcase for bug 141561</title></head>
+<body>
+
+<script>document.write("<form><input type='password'></form>");</script>
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/151956-1.html b/parser/htmlparser/tests/crashtests/151956-1.html
new file mode 100644
index 0000000000..0ae77f6a6c
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/151956-1.html
@@ -0,0 +1,18 @@
+<html>
+<body>
+<!-- script isn't actually required for the crash of bug 151956 -->
+<table border>
+ <tbody>
+ <form>
+ <script>
+ var foo = 42;
+ </script>
+ </form>
+ <tr>
+ <td> X </td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/crashtests/152444-1.html b/parser/htmlparser/tests/crashtests/152444-1.html
new file mode 100644
index 0000000000..6576444544
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/152444-1.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<title>Untitled</title>
+</head>
+<body>
+<table>
+<tbody>
+<form>
+<tr><td colspan=2></td></tr>
+<tr><td></td><td></td></tr>
+</form>
+</tbody>
+</table>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/1534346-1.html b/parser/htmlparser/tests/crashtests/1534346-1.html
new file mode 100644
index 0000000000..34ab7930db
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1534346-1.html
@@ -0,0 +1 @@
+<svg><script></svg>
diff --git a/parser/htmlparser/tests/crashtests/1547895-1.html b/parser/htmlparser/tests/crashtests/1547895-1.html
new file mode 100644
index 0000000000..72d19c6caa
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1547895-1.html
@@ -0,0 +1,10 @@
+<script>
+var func0 = async function(a) {
+ a.currentTarget.close()
+}
+document.addEventListener('DOMContentLoaded', () => {
+ document.write()
+ document.addEventListener('readystatechange', func0, true)
+ setTimeout(window.close, 0)
+})
+</script>
diff --git a/parser/htmlparser/tests/crashtests/1604307-1.html b/parser/htmlparser/tests/crashtests/1604307-1.html
new file mode 100644
index 0000000000..28a2e7caf0
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1604307-1.html
@@ -0,0 +1,10 @@
+<script>
+function go() {
+ b.crossOrigin = ""
+ document.execCommand("insertHTML", false, c.innerHTML)
+}
+</script>
+<image id="b" src="data:;base64,R0lGODlhIAAgAPIBAGbMzP///wAAADOZZpn/zAAAAAAAAAAAACH5BAAAAAAALAAAAAAgACAAAA" onload="go()"></image>
+<data id="c">
+<s contenteditable="true"
+<!-- A -->
diff --git a/parser/htmlparser/tests/crashtests/1606499-1.html b/parser/htmlparser/tests/crashtests/1606499-1.html
new file mode 100644
index 0000000000..5771d73d8d
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1606499-1.html
@@ -0,0 +1,15 @@
+<html class="reftest-wait">
+<script>
+let alreadyRun = sessionStorage.getItem("ran1606499");
+if (alreadyRun) {
+ document.documentElement.removeAttribute("class");
+} else {
+ sessionStorage.setItem("ran1606499", "ran1606499");
+ document.addEventListener('DOMContentLoaded', () => {
+ setTimeout(() => { document.close() }, 146)
+ setTimeout(() => { location.reload() }, 145)
+ self.stop()
+ document.write('<body></body>')
+ })
+}
+</script>
diff --git a/parser/htmlparser/tests/crashtests/1747514.html b/parser/htmlparser/tests/crashtests/1747514.html
new file mode 100644
index 0000000000..e8a93b9280
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1747514.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script>
+ // Generate an SVG data URI whose URI string will consume 20 MB in expat
+ // (which uses two-byte chars).
+ let img = document.createElement('img');
+ let rect = "<rect />";
+ let src = "data:image/svg+xml;utf8,<svg>" + rect.repeat(20 * 1000 * 1000 / rect.length / 2) + "</svg>";
+ img.src = src;
+ document.body.appendChild(img);
+ </script>
+
diff --git a/parser/htmlparser/tests/crashtests/1810896-1.html b/parser/htmlparser/tests/crashtests/1810896-1.html
new file mode 100644
index 0000000000..2c16456302
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/1810896-1.html
@@ -0,0 +1,1081 @@
+<!DOCTYPE html>
+<head>
+<title>$B$"(B</title>
+</head>
+<body>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ã‚
+</body>
+
diff --git a/parser/htmlparser/tests/crashtests/185073-1.html b/parser/htmlparser/tests/crashtests/185073-1.html
new file mode 100644
index 0000000000..39504ede22
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/185073-1.html
@@ -0,0 +1,15 @@
+<html>
+ <head>
+ <title>bug 185073</title>
+ </head>
+ <body>
+ <font>
+ <div id="updateText">
+ <script language=javascript type=text/javascript>
+ document.write('</div>');
+ document.getElementById("updateText").innerHTML = "foo";
+ </script>
+ </div>
+ </font>
+ </body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/188474-1.html b/parser/htmlparser/tests/crashtests/188474-1.html
new file mode 100644
index 0000000000..2e8b03d197
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/188474-1.html
@@ -0,0 +1,13 @@
+<HTML><HEAD>
+<SCRIPT language="javascript" type="text/javascript">
+
+var header ="<body><div id=\"foo\"></div><div id=\"foo2\"><!-- comment -->";
+
+var footer = "</div><!-- comment -->";
+
+</SCRIPT>
+<SCRIPT language="javascript" type="text/javascript">document.write(header);</SCRIPT>
+</HEAD>
+<BODY>
+<SCRIPT language="javascript" type="text/javascript">document.write(footer);</SCRIPT>
+</BODY></HTML>
diff --git a/parser/htmlparser/tests/crashtests/194329-1.html b/parser/htmlparser/tests/crashtests/194329-1.html
new file mode 100644
index 0000000000..c7ab69007e
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/194329-1.html
@@ -0,0 +1,15 @@
+<html>
+ <head>
+ <title>bug 188474</title>
+ </head>
+ <body>
+ <head>
+ <div>
+ <script>
+ document.write("<\/div>");
+ </script>
+ <noscript>
+ </div>
+ </noscript><!-- End PayPal Logo -->
+ </body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/197052-1.html b/parser/htmlparser/tests/crashtests/197052-1.html
new file mode 100644
index 0000000000..d0b30c761b
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/197052-1.html
@@ -0,0 +1 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"> <html> <head> <title>testcase - crasher</title> </head> <body> <div id="uniqid"> <script language="JavaScript" type="text/JavaScript"> document.write("&gt;"+document.getElementById('uniqid').innerHTML+"&lt;"); </script> </div> </body> </html> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/220542-1.html b/parser/htmlparser/tests/crashtests/220542-1.html
new file mode 100644
index 0000000000..f664734664
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/220542-1.html
@@ -0,0 +1,2 @@
+<script>document.write('<link href="l:\\" rel=stylesheet>')</script>
+
diff --git a/parser/htmlparser/tests/crashtests/253979-1.html b/parser/htmlparser/tests/crashtests/253979-1.html
new file mode 100644
index 0000000000..5e47ee84c9
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/253979-1.html
@@ -0,0 +1,4 @@
+<html><head></head><body>
+<a><a><p><font><p><font><b><a></font></a>
+</body></html>
+
diff --git a/parser/htmlparser/tests/crashtests/269095-1.html b/parser/htmlparser/tests/crashtests/269095-1.html
new file mode 100644
index 0000000000..83cc52828e
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/269095-1.html
@@ -0,0 +1 @@
+<TABLE > <FRAMESET> <PARAM> <FORM> <MAP> <FORM> <TABLE> <RTABLE> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/286733-1.html b/parser/htmlparser/tests/crashtests/286733-1.html
new file mode 100644
index 0000000000..04be4f11d3
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/286733-1.html
@@ -0,0 +1,4 @@
+<TABLE>
+<FRAMESET><FRAME></FRAMESET>
+<TR><TD><TABLE>
+ <TR><BR><TD><MAP><TABLE><BR></MAP>
diff --git a/parser/htmlparser/tests/crashtests/286733-2.html b/parser/htmlparser/tests/crashtests/286733-2.html
new file mode 100644
index 0000000000..5fcf7a7ff9
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/286733-2.html
@@ -0,0 +1,4 @@
+<TABLE>
+<FRAMESET><FRAME></FRAMESET>
+<TR><TD><TABLE>
+ <TR><BR><TD><MAP><TABLE><TR><BR></MAP>
diff --git a/parser/htmlparser/tests/crashtests/299036-1.html b/parser/htmlparser/tests/crashtests/299036-1.html
new file mode 100644
index 0000000000..e21ce2b9b7
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/299036-1.html
@@ -0,0 +1,2 @@
+<table><textarea></textarea></table>
+
diff --git a/parser/htmlparser/tests/crashtests/30885-1.html b/parser/htmlparser/tests/crashtests/30885-1.html
new file mode 100644
index 0000000000..2dc0fe035d
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/30885-1.html
@@ -0,0 +1,17 @@
+<HTML>
+ <BODY>
+
+ <TABLE BORDER="1">
+ <TR>
+ <TD>
+ <A HREF="foo.htm">
+ <FONT></A>
+ <A HREF="bar.htm">
+ <FONT>
+ MacDesktops</A>
+ </FONT>
+ </TD>
+ </TR>
+</TABLE>
+</BODY>
+</HTML>
diff --git a/parser/htmlparser/tests/crashtests/30956-1.html b/parser/htmlparser/tests/crashtests/30956-1.html
new file mode 100644
index 0000000000..508149a97d
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/30956-1.html
@@ -0,0 +1,10 @@
+<HTML>
+
+<body>
+<table>
+ <td>
+ <li><font size="-1">
+ <li><a href="foo.html"></font></a>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/31392-1.html b/parser/htmlparser/tests/crashtests/31392-1.html
new file mode 100644
index 0000000000..0a4a138b34
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/31392-1.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<title>Crash Test page</title>
+</head>
+<body>
+
+<table>
+<tr>
+<td>
+<LINK REL="stylesheet" HREF="garbagestyle.css" TYPE="text/css">
+</td>
+</tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/31694-1.html b/parser/htmlparser/tests/crashtests/31694-1.html
new file mode 100644
index 0000000000..8be2d47f02
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/31694-1.html
@@ -0,0 +1,8 @@
+<HTML><HEAD>
+<script src="foo.js"></script>
+<csactions>
+<csaction name="bar" class="foobar" type="ONEVENT">
+</csactions>
+</HEAD>
+<BODY>
+<DD></DD></BODY></HTML>
diff --git a/parser/htmlparser/tests/crashtests/31940-1.html b/parser/htmlparser/tests/crashtests/31940-1.html
new file mode 100644
index 0000000000..ec2f370e83
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/31940-1.html
@@ -0,0 +1,15 @@
+<HEAD>
+ <LINK rel="stylesheet">
+ <rdf:RDF>
+ <rdf:Description/>
+ </rdf:RDF>
+</HEAD>
+
+<BODY>
+
+<rdf:RDF>
+<rdfs:Class/>
+</rdf:RDF>
+
+</BODY>
+</HTML>
diff --git a/parser/htmlparser/tests/crashtests/32613-1.html b/parser/htmlparser/tests/crashtests/32613-1.html
new file mode 100644
index 0000000000..f50c342e9f
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/32613-1.html
@@ -0,0 +1,18 @@
+<P><font color="003366" FACE="Serif">
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+<P><FONT size="2"></P>
+</FONT><BR>
diff --git a/parser/htmlparser/tests/crashtests/328751-1.html b/parser/htmlparser/tests/crashtests/328751-1.html
new file mode 100644
index 0000000000..37b46af345
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/328751-1.html
@@ -0,0 +1,9 @@
+<HEAD >
+<OBJECT >
+<APPLET CODE=" >
+<BODY TEXT=https://n%ItGEv5%&N8%6USN5i9"
+<TABLE >
+<ISINDEX >
+<TITLE >
+<TBODY >
+</HEAD > \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/34168-1.html b/parser/htmlparser/tests/crashtests/34168-1.html
new file mode 100644
index 0000000000..a191a03681
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/34168-1.html
@@ -0,0 +1 @@
+<!ENTITY editAwayMessageSpecial3.label " %d = Current date"> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/34168-1.xml b/parser/htmlparser/tests/crashtests/34168-1.xml
new file mode 100644
index 0000000000..71a058c316
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/34168-1.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<!DOCTYPE foo [
+<!ENTITY editAwayMessageSpecial3.label " %%d = Current date">
+<!ELEMENT foo EMPTY>
+]>
+<foo/>
diff --git a/parser/htmlparser/tests/crashtests/408939-1.html b/parser/htmlparser/tests/crashtests/408939-1.html
new file mode 100644
index 0000000000..844c70e72e
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/408939-1.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+
+<div>
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+</div>
+
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/41427-1.html b/parser/htmlparser/tests/crashtests/41427-1.html
new file mode 100644
index 0000000000..5612153da5
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/41427-1.html
@@ -0,0 +1 @@
+<A HREF=""><font><B>t</A><head><script>
diff --git a/parser/htmlparser/tests/crashtests/423373-1.html b/parser/htmlparser/tests/crashtests/423373-1.html
new file mode 100644
index 0000000000..4876095480
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/423373-1.html
@@ -0,0 +1 @@
+<body><asdf><legend>
diff --git a/parser/htmlparser/tests/crashtests/44178-1.html b/parser/htmlparser/tests/crashtests/44178-1.html
new file mode 100644
index 0000000000..0ecb40ef77
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/44178-1.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<div>
+<server>
+</server>
+</div>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/445171-1-inner.svg b/parser/htmlparser/tests/crashtests/445171-1-inner.svg
new file mode 100644
index 0000000000..24ed6f8a70
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/445171-1-inner.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" onload="location = 'file_445171-1.html'">
+
+<rect x="5" y="5" width="50" height="50" />
+
+</svg>
diff --git a/parser/htmlparser/tests/crashtests/445171-1.html b/parser/htmlparser/tests/crashtests/445171-1.html
new file mode 100644
index 0000000000..0abaacdfba
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/445171-1.html
@@ -0,0 +1,9 @@
+<html class="reftest-wait">
+<head>
+<script>
+function done() { document.documentElement.removeAttribute("class"); }
+</script>
+<body>
+<iframe src="445171-1-inner.svg"></iframe>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/46495-1.html b/parser/htmlparser/tests/crashtests/46495-1.html
new file mode 100644
index 0000000000..a0947ff2ca
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/46495-1.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ <p ">
+ </body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/468538-1.xhtml b/parser/htmlparser/tests/crashtests/468538-1.xhtml
new file mode 100644
index 0000000000..576b333c19
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/468538-1.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<head>
+<script type="text/javascript">
+
+function boom()
+{
+ var v = document.getElementById("v");
+ document.body.removeChild(document.body.firstChild);
+ v.innerHTML = "f";
+}
+
+</script>
+</head>
+<body onload="boom();"><xul:box><div id="v"/></xul:box></body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/50134-1.html b/parser/htmlparser/tests/crashtests/50134-1.html
new file mode 100644
index 0000000000..efe680a1f4
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/50134-1.html
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Mozilla Bug 50134</title>
+ </head>
+ <body>
+ <!--->
+ </body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/502103.html b/parser/htmlparser/tests/crashtests/502103.html
new file mode 100644
index 0000000000..171a2890e5
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/502103.html
@@ -0,0 +1 @@
+<isindex action=""> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/502869-iframe.html b/parser/htmlparser/tests/crashtests/502869-iframe.html
new file mode 100644
index 0000000000..ff76e020bf
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/502869-iframe.html
@@ -0,0 +1,9 @@
+<html><head><title>[HTML5] Crash [@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster] with document.write and removing stuff</title></head><body><a>
+<script>
+var x=document.getElementsByTagName("*");
+x[1].remove();
+x[2].remove();
+</script>
+<div>
+<script>document.write('<'+'script>document.removeChild(document.documentElement);<'+'/script>');</script>
+</a></body></html>
diff --git a/parser/htmlparser/tests/crashtests/502869.html b/parser/htmlparser/tests/crashtests/502869.html
new file mode 100644
index 0000000000..5da23b5076
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/502869.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+ <meta charset="utf-8">
+ <title>Testcase for bug 502869</title>
+<script>
+function done()
+{
+ document.documentElement.removeAttribute("class");
+}
+</script>
+</head>
+<body onload="setTimeout(done,1000)">
+
+<iframe src="502869-iframe.html"></iframe>
+
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/50994-1.html b/parser/htmlparser/tests/crashtests/50994-1.html
new file mode 100644
index 0000000000..11bd9aaf07
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/50994-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<HTML>
+ <HEAD>
+ <TITLE>Mozilla Bug 50994</TITLE>
+ </HEAD>
+ <BODY>
+ <P>
+ <FORM action="">
+ <P>
+ </FORM>
+ </BODY>
+</HTML>
diff --git a/parser/htmlparser/tests/crashtests/515278-1.html b/parser/htmlparser/tests/crashtests/515278-1.html
new file mode 100644
index 0000000000..33e01f2224
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/515278-1.html
@@ -0,0 +1,3 @@
+
+<fooz>
+
diff --git a/parser/htmlparser/tests/crashtests/515533-1-inner.html b/parser/htmlparser/tests/crashtests/515533-1-inner.html
new file mode 100644
index 0000000000..6bd0684e21
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/515533-1-inner.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+</head>
+<body>
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<script language="javascript">
+window.location.replace("data:text/plain,");
+</script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/515533-1.html b/parser/htmlparser/tests/crashtests/515533-1.html
new file mode 100644
index 0000000000..b0d5b570b8
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/515533-1.html
@@ -0,0 +1 @@
+<iframe src="515533-1-inner.html"></iframe>
diff --git a/parser/htmlparser/tests/crashtests/515816-1.html b/parser/htmlparser/tests/crashtests/515816-1.html
new file mode 100644
index 0000000000..c518d2a3cf
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/515816-1.html
@@ -0,0 +1,11 @@
+<html>
+<body>
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<!-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -->
+<form>
+<input>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
diff --git a/parser/htmlparser/tests/crashtests/522326-1.html b/parser/htmlparser/tests/crashtests/522326-1.html
new file mode 100644
index 0000000000..d06ab6cf7d
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/522326-1.html
@@ -0,0 +1 @@
+<html><head><META http-equiv="Content-Type" content="text/html; charset=utf-16"><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></head><body>abcd</body></html>
diff --git a/parser/htmlparser/tests/crashtests/525229-1.html b/parser/htmlparser/tests/crashtests/525229-1.html
new file mode 100644
index 0000000000..8bffa7d601
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/525229-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<title>Test for bug 525229</title>
+<body>
+<script>
+document.write("<script src='data:text/javascript,'><\/script><div>");
+</script>
+text
diff --git a/parser/htmlparser/tests/crashtests/536097-1.html b/parser/htmlparser/tests/crashtests/536097-1.html
new file mode 100644
index 0000000000..76befb3cc8
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/536097-1.html
@@ -0,0 +1 @@
+<script>document.write("<iframe></iframe\n");</script><img>
diff --git a/parser/htmlparser/tests/crashtests/555462-iframe.html b/parser/htmlparser/tests/crashtests/555462-iframe.html
new file mode 100644
index 0000000000..3ddd6282db
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/555462-iframe.html
@@ -0,0 +1,3 @@
+<!--mmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmm mmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmm mmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmm -->
+<textarea><mmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmmmmmmm mmmmmmmmmmmmmmm
+</textarea> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/555462.html b/parser/htmlparser/tests/crashtests/555462.html
new file mode 100644
index 0000000000..f8d4afad71
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/555462.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait"><head>
+ <meta charset="utf-8">
+ <title>Testcase for bug 555462</title>
+<script>
+function f1() {
+ window.frames[0].frameElement.removeAttribute("onload");
+ window.frames[0].location.reload();
+ setTimeout(f2,200);
+}
+function f2() { window.frames[0].location.reload(); setTimeout(done,400); }
+function done() { document.documentElement.removeAttribute("class"); }
+</script>
+</head>
+<body>
+
+<iframe src="555462-iframe.html" onload="setTimeout(f1,100)"></iframe>
+
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/563514-1.html b/parser/htmlparser/tests/crashtests/563514-1.html
new file mode 100644
index 0000000000..b96ce14661
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/563514-1.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<script>
+function boom()
+{
+ document.createElement("span").innerHTML = "<body a='b'>";
+}
+</script>
+</head>
+<body onload="boom();"></body> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/574884-1.html b/parser/htmlparser/tests/crashtests/574884-1.html
new file mode 100644
index 0000000000..19de3c74a4
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/574884-1.html
@@ -0,0 +1 @@
+<svg></html>
diff --git a/parser/htmlparser/tests/crashtests/574884-2.html b/parser/htmlparser/tests/crashtests/574884-2.html
new file mode 100644
index 0000000000..09bec52e6d
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/574884-2.html
@@ -0,0 +1 @@
+<math></html>
diff --git a/parser/htmlparser/tests/crashtests/58455-1.html b/parser/htmlparser/tests/crashtests/58455-1.html
new file mode 100644
index 0000000000..7c235f9806
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/58455-1.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+ <title>Computer Market Online</title>
+ <BASE HREF="http://www.computermarket.com.au/">
+</head>
+
+<body bgcolor="#ffffff">
+
+<table>
+<tr><td><a href='prodDetail.asp?id=6007&catid=241'>This shows</a></td></tr>
+<tr><td><a href='prodDetail.asp?id=6007&catid=241'">This does not show</a></td></tr>
+</table>
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/591330-1.html b/parser/htmlparser/tests/crashtests/591330-1.html
new file mode 100644
index 0000000000..31719fac6a
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/591330-1.html
@@ -0,0 +1,284 @@
+<script>
+var sleep = 500; // 0.5 seconds
+var start = Number(new Date());
+while(Number(new Date()) - start < sleep) {
+}
+document.write("<div>"); // make speculation fail
+</script>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+<span>
+
diff --git a/parser/htmlparser/tests/crashtests/60110-1.html b/parser/htmlparser/tests/crashtests/60110-1.html
new file mode 100644
index 0000000000..34f8c406b8
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/60110-1.html
@@ -0,0 +1,22 @@
+<HTML><HEAD>
+<TITLE>Edit parameters</TITLE>
+
+
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000"
+LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000" >
+
+<p>
+Any item you check Reset on will get reset to its default value.
+<form method=post action=doeditparams.cgi><table>
+
+<tr><td valign=top><input type=checkbox name=reset-newchangedmail>Reset</td><td>
+<textarea wrap=hard name=newchangedmail rows=10 cols=80>From: bugzilla-daemon&#010;To: %to%&#013;&#010;Cc: %cc%&#013;&#010;Subject: [Bug %bugid%] %neworchanged% - %summary%&#013;&#010;&#013;&#010;%urlbase%show_bug.cgi?id=%bugid%&#013;&#010;&#013;&#010;%diffs%</textarea>
+</td></tr>
+<tr><td valign=top><input type=checkbox name=reset-whinemail>Reset</td><td>
+<textarea wrap=hard name=whinemail rows=10 cols=80>From: bugzilla-daemon&#010;To: %email%&#013;&#010;Subject: Your Bugzilla buglist needs attention.&#013;&#010;&#013;&#010;[This e-mail has been automatically generated.]&#013;&#010;&#013;&#010;You have one or more bugs assigned to you in the Bugzilla &#013;&#010;bugsystem (%urlbase%) that require&#013;&#010;attention.&#013;&#010;&#013;&#010;All of these bugs are in the NEW state, and have not been touched&#013;&#010;in %whinedays% days or more. You need to take a look at them, and &#013;&#010;decide on an initial action.&#013;&#010;&#013;&#010;&#013;&#010;&#013;&#010;</textarea>
+</td></tr>
+<tr><td></td><td>2.11</td></tr></table>
+<input type=reset value="Reset form"><br>
+<input type=submit value="Submit changes">
+</form> \ No newline at end of file
diff --git a/parser/htmlparser/tests/crashtests/616027-1.html b/parser/htmlparser/tests/crashtests/616027-1.html
new file mode 100644
index 0000000000..d4707c9359
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/616027-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+
+
+for (var fuzzRepeat = 0; fuzzRepeat < 500; ++fuzzRepeat) {
+ document.write("<span>");
+}
+document.write("<isindex>");
+
+
+</script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/650501-1.xhtml b/parser/htmlparser/tests/crashtests/650501-1.xhtml
new file mode 100644
index 0000000000..c701a0c76c
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/650501-1.xhtml
@@ -0,0 +1,22 @@
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script>
+<![CDATA[
+
+function boom()
+{
+ var a = document.createElement("div");
+ a.innerHTML = "<script>1;<\/script>";
+
+ var b = document.createElement("div")
+ try { b.innerHTML = "<"; } catch (invalidXML) { }
+
+ document.documentElement.appendChild(a);
+}
+
+]]>
+</script>
+</head>
+<body onload="boom();"></body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/662185-1.html b/parser/htmlparser/tests/crashtests/662185-1.html
new file mode 100644
index 0000000000..41d67e5355
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/662185-1.html
@@ -0,0 +1 @@
+<meta charset=t>
diff --git a/parser/htmlparser/tests/crashtests/696651-1.html b/parser/htmlparser/tests/crashtests/696651-1.html
new file mode 100644
index 0000000000..8c5ee9ed3a
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/696651-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+function runTest() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ var doc = iframe.contentDocument;
+ doc.write("\u003cscript>document.close();\u003c/script>foo");
+}
+</script>
+<body onload="runTest();">
+<iframe></iframe>
+
diff --git a/parser/htmlparser/tests/crashtests/699347-1.xml b/parser/htmlparser/tests/crashtests/699347-1.xml
new file mode 100644
index 0000000000..c6dd4bfa1b
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/699347-1.xml
@@ -0,0 +1 @@
+<?xml version="1.0"?><root/>
diff --git a/parser/htmlparser/tests/crashtests/721313-1.html b/parser/htmlparser/tests/crashtests/721313-1.html
new file mode 100644
index 0000000000..06497cd65b
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/721313-1.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<script>(new DOMParser()).parseFromString("", "text/html");</script>
diff --git a/parser/htmlparser/tests/crashtests/73331-1.html b/parser/htmlparser/tests/crashtests/73331-1.html
new file mode 100644
index 0000000000..6761a6686a
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/73331-1.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+<script>
+function crashme() {
+ var obj = document.getElementById('popupid');
+ obj.style.visibility='hidden';
+}
+</script>
+</head>
+<body onload="crashme();">
+<a href="http://www.mozilla.org/">http://www.mozilla.org/</a>
+
+<div id="popupid">
+<font>
+<script>
+ document.write('<form>');
+ document.write('<span>');
+ document.write('<input>');
+ document.write('</span>');
+ document.write('<br>');
+ document.write('</form>');
+</script>
+</font>
+</div>
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/crashtests/742414-1.html b/parser/htmlparser/tests/crashtests/742414-1.html
new file mode 100644
index 0000000000..e35b125603
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/742414-1.html
@@ -0,0 +1,4 @@
+<script></script
+><script></script
+><script></script
+>
diff --git a/parser/htmlparser/tests/crashtests/762726-1.html b/parser/htmlparser/tests/crashtests/762726-1.html
new file mode 100644
index 0000000000..4692b73e1e
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/762726-1.html
@@ -0,0 +1 @@
+<meta charset>
diff --git a/parser/htmlparser/tests/crashtests/92647-1.html b/parser/htmlparser/tests/crashtests/92647-1.html
new file mode 100644
index 0000000000..16be8d98e1
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/92647-1.html
@@ -0,0 +1,33 @@
+<HTML>
+<BODY>
+ <form>
+<TABLE border="1">
+ <TR>
+ <TD>
+ <TABLE border="2">
+ <TR>
+ <TD WIDTH="30%">
+ Member Number:
+ </TD>
+ <TD WIDTH="70%">
+ <INPUT NAME="EchoUser" TYPE="TEXT">
+ </TD>
+ </TR>
+ <TR>
+ <TD>
+ PIN:
+ </TD>
+ <TD>
+ <INPUT TYPE="password">
+ </TD>
+ <TD>
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+</TABLE>
+</Form>
+</BODY>
+</HTML>
+
diff --git a/parser/htmlparser/tests/crashtests/92788-1.html b/parser/htmlparser/tests/crashtests/92788-1.html
new file mode 100644
index 0000000000..955301e3f2
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/92788-1.html
@@ -0,0 +1,20 @@
+<HTML><HEAD><TITLE>Bug #92788</TITLE></HEAD>
+<BODY>
+<TABLE>
+ <TR>
+ <TD>
+ <CENTER>
+ <TR>
+ <TD>
+ <IFRAME
+ marginWidth=0 marginHeight=0 src="foo" frameBorder=0 width=125 scrolling=no
+ height=125><SCRIPT LANGUAGE="JavaScript">document.write('<SCR'+'IPT LANGUAGE="JavaScript" SRC="http://ads1.ad-flow.com/?DC=tweak3d+-+rst&JS=Y&TARGET=_blank"></SCR'+'IPT>');</SCRIPT><NOSCRIPT><A HREF="http://ads1.ad-flow.com/?SHT=tweak3d+-+rst" TARGET="_blank"><IMG SRC="http://ads1.ad-flow.com/?SIT=tweak3d+-+rst" HEIGHT="125" WIDTH="125"></A></NOSCRIPT></IFRAME>--&gt;
+ <FORM name=EmailSub onsubmit="if ( (document.EmailSub.email.length == 0) || (document.EmailSub.email.value.indexOf('@') == -1) || (document.EmailSub.email.value.indexOf('.') == -1) ) {('Invalid Email address');return false;} window.open('http://www.pluginnewsletter.com/nl-popsub.cfm?wsnum=369&amp;' + 'Email=' + document.EmailSub.email.value,'WinOpen','toolbar=no,scrollbars=yes,resizable=yes,width=666,height=666'); return false;">
+ <SCRIPT language=JavaScript src="foo.js"></SCRIPT>
+ <NOSCRIPT><A target=_blank href="http://ads1.ad-flow.com/?SHT=tweak3d-lst" WIDTH="468" HEIGHT="60"><IMG src="Tweak3D_net - Your Freakin' Tweakin' Source!_fichiers/ads1.ad-flow.gif"></A>
+ </NOSCRIPT></CENTER>
+
+ <TR bgColor=#ffffff>
+ <CENTER><IFRAME marginWidth=0 marginHeight=0 src="foo" frameBorder=0 width=468 scrolling=no height=60><SCRIPT LANGUAGE="JavaScript">document.write('<SCR'+'IPT LANGUAGE="JavaScript" SRC="http://ads1.ad-flow.com/?DC=tweak3d-top&JS=Y&TARGET=_blank"></SCR'+'IPT>');</SCRIPT><NOSCRIPT><A HREF="http://ads1.ad-flow.com/?SHT=tweak3d-top" TARGET="_blank"><IMG SRC="http://ads1.ad-flow.com/?SIT=tweak3d-top&SC=Y" HEIGHT="60" WIDTH="468"></A></NOSCRIPT></IFRAME>
+</CENTER></TR>
+</BODY></HTML>
diff --git a/parser/htmlparser/tests/crashtests/981279-1.html b/parser/htmlparser/tests/crashtests/981279-1.html
new file mode 100644
index 0000000000..5f14c8af37
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/981279-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+</head>
+<body>
+<div></div>
+<script>
+var div = document.getElementsByTagName("div")[0];
+div.innerHTML = "<div À à Â Ã Ä Å ";
+div.innerHTML = "<div a>";
+</script>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/crashtests/982285-1.html b/parser/htmlparser/tests/crashtests/982285-1.html
new file mode 100644
index 0000000000..d3e124d957
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/982285-1.html
@@ -0,0 +1,19 @@
+<q>
+<u>
+<pre>
+<pre>
+<center>
+<em>
+<center>
+<center>
+</rp>
+<address>
+<address>
+<address>
+</rt>
+<q>
+<q>
+<rt>
+</u>
+<pre>
+</em>
diff --git a/parser/htmlparser/tests/crashtests/crashtests.list b/parser/htmlparser/tests/crashtests/crashtests.list
new file mode 100644
index 0000000000..bc630b2a6d
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/crashtests.list
@@ -0,0 +1,67 @@
+load 30885-1.html
+load 30956-1.html
+load 31392-1.html
+load 31694-1.html
+load 31940-1.html
+load 32613-1.html
+load 34168-1.html
+load 34168-1.xml
+load 41427-1.html
+load 44178-1.html
+load 46495-1.html
+load 50134-1.html
+load 50994-1.html
+load 58455-1.html
+load 60110-1.html
+load 73331-1.html
+load 92647-1.html
+load 92788-1.html
+load 121591-1.html
+load 147179-1.html
+load 151956-1.html
+load 152444-1.html
+load 185073-1.html
+load 188474-1.html
+load 194329-1.html
+load 197052-1.html
+load 220542-1.html
+load 253979-1.html
+load 269095-1.html
+load 286733-1.html
+load 286733-2.html
+load 299036-1.html
+skip-if(cocoaWidget&&browserIsRemote) load 328751-1.html # Bug 849747
+load 408939-1.html
+load 423373-1.html
+load 445171-1.html
+load 468538-1.xhtml
+load 502103.html
+load 502869.html
+load 515278-1.html
+load 515533-1.html
+load 515816-1.html
+load 522326-1.html
+load 525229-1.html
+load 536097-1.html
+load 555462.html
+load 563514-1.html
+load 574884-1.html
+load 574884-2.html
+load 591330-1.html
+load 616027-1.html
+load 650501-1.xhtml
+load 662185-1.html
+load 696651-1.html
+load view-source:699347-1.xml
+load 721313-1.html
+load view-source:742414-1.html
+load 762726-1.html
+load 981279-1.html
+load 982285-1.html
+load 1373045-1.html
+load 1534346-1.html
+load 1604307-1.html
+load 1606499-1.html
+load 1547895-1.html
+skip-if(Android) skip-if(isDebugBuild) load 1747514.html # Bug 1780219
+HTTP load 1810896-1.html
diff --git a/parser/htmlparser/tests/crashtests/file_445171-1.html b/parser/htmlparser/tests/crashtests/file_445171-1.html
new file mode 100644
index 0000000000..de8a5eb065
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/file_445171-1.html
@@ -0,0 +1 @@
+<script>parent.done()</script>
diff --git a/parser/htmlparser/tests/mochitest/blue.png b/parser/htmlparser/tests/mochitest/blue.png
new file mode 100644
index 0000000000..8df58f3a5f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/blue.png
Binary files differ
diff --git a/parser/htmlparser/tests/mochitest/broken_xml.xhtml b/parser/htmlparser/tests/mochitest/broken_xml.xhtml
new file mode 100644
index 0000000000..f81bf3998b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/broken_xml.xhtml
@@ -0,0 +1,7 @@
+<html>
+ <head>
+ <title>&nonExistingEntity;</title>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/browser.ini b/parser/htmlparser/tests/mochitest/browser.ini
new file mode 100644
index 0000000000..6b7a43b105
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/browser.ini
@@ -0,0 +1,17 @@
+[DEFAULT]
+prefs =
+ # we need to reload the XML file to make the test pass
+ nglayout.debug.disable_xul_cache=true
+
+[browser_viewsource.js]
+support-files =
+ file_viewsource.html
+
+[browser_ysod_telemetry.js]
+support-files =
+ broken_xml.xhtml
+
+[browser_elementindtd.js]
+support-files =
+ browser_elementindtd.xml
+ browser_elementindtd.dtd
diff --git a/parser/htmlparser/tests/mochitest/browser_elementindtd.dtd b/parser/htmlparser/tests/mochitest/browser_elementindtd.dtd
new file mode 100644
index 0000000000..1c2acdcda8
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/browser_elementindtd.dtd
@@ -0,0 +1,2 @@
+<!ENTITY entitywithelement
+'<p id="fromdtd">From dtd</p>'>
diff --git a/parser/htmlparser/tests/mochitest/browser_elementindtd.js b/parser/htmlparser/tests/mochitest/browser_elementindtd.js
new file mode 100644
index 0000000000..bc146ba73e
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/browser_elementindtd.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/*
+ * Test for bug 1539759
+ * Loads a chrome XML document that has an exteernal DTD file with an entity
+ * that contains an element, and verifies that that element was not inserted
+ * into the document (but its content was).
+ */
+
+add_task(async function test() {
+ await BrowserTestUtils.withNewTab(
+ getRootDirectory(gTestPath) + "browser_elementindtd.xml",
+ async function (newBrowser) {
+ // NB: We load the chrome:// page in the parent process.
+ testNoElementFromEntity(newBrowser);
+ }
+ );
+});
+
+function testNoElementFromEntity(newBrowser) {
+ let doc = newBrowser.contentDocument;
+ is(doc.body.textContent, "From dtd", "Should load DTD.");
+ is(
+ doc.body.firstElementChild,
+ null,
+ "Shouldn't have an element inserted from the DTD"
+ );
+}
diff --git a/parser/htmlparser/tests/mochitest/browser_elementindtd.xml b/parser/htmlparser/tests/mochitest/browser_elementindtd.xml
new file mode 100644
index 0000000000..937c896f43
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/browser_elementindtd.xml
@@ -0,0 +1,8 @@
+<!DOCTYPE html
+[
+ <!ENTITY % externaldtd SYSTEM "chrome://mochitests/content/browser/parser/htmlparser/tests/mochitest/browser_elementindtd.dtd" >
+ %externaldtd;
+]>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<body>&entitywithelement;</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/browser_viewsource.js b/parser/htmlparser/tests/mochitest/browser_viewsource.js
new file mode 100644
index 0000000000..e4d44e05be
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/browser_viewsource.js
@@ -0,0 +1,28 @@
+"use strict";
+
+add_task(async function () {
+ const PAGE_URL = getRootDirectory(gTestPath) + "file_viewsource.html";
+ let viewSourceTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "view-source:" + PAGE_URL
+ );
+
+ let xhrPromise = new Promise(resolve => {
+ let xhr = new XMLHttpRequest();
+ xhr.open("GET", PAGE_URL, true);
+ xhr.onload = event => resolve(event.target.responseText);
+ xhr.send();
+ });
+
+ let viewSourceContentPromise = SpecialPowers.spawn(
+ viewSourceTab.linkedBrowser,
+ [],
+ async function () {
+ return content.document.body.textContent;
+ }
+ );
+
+ let results = await Promise.all([viewSourceContentPromise, xhrPromise]);
+ is(results[0], results[1], "Sources should match");
+ BrowserTestUtils.removeTab(viewSourceTab);
+});
diff --git a/parser/htmlparser/tests/mochitest/browser_ysod_telemetry.js b/parser/htmlparser/tests/mochitest/browser_ysod_telemetry.js
new file mode 100644
index 0000000000..d7a654cad0
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/browser_ysod_telemetry.js
@@ -0,0 +1,49 @@
+"use strict";
+
+const { TelemetryTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TelemetryTestUtils.sys.mjs"
+);
+
+add_task(async function test_popup_opened() {
+ Services.telemetry.clearEvents();
+ Services.telemetry.setEventRecordingEnabled("ysod", true);
+
+ const PAGE_URL = getRootDirectory(gTestPath) + "broken_xml.xhtml";
+ let viewSourceTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ PAGE_URL
+ );
+
+ let content = await SpecialPowers.spawn(
+ viewSourceTab.linkedBrowser,
+ [],
+ async function () {
+ return content.document.documentElement.innerHTML;
+ }
+ );
+
+ ok(content.includes("XML"), "Document shows XML error");
+
+ TelemetryTestUtils.assertEvents(
+ [
+ {
+ method: "shown",
+ object: "ysod",
+ value: PAGE_URL.substr(0, 80),
+ extra: {
+ error_code: "11",
+ location: "3:12",
+ last_line: " <title>&nonExistingEntity;</title>",
+ last_line_len: "38",
+ hidden: "false",
+ destroyed: "false",
+ },
+ },
+ ],
+ {
+ category: "ysod",
+ },
+ { process: "parent" }
+ );
+ BrowserTestUtils.removeTab(viewSourceTab);
+});
diff --git a/parser/htmlparser/tests/mochitest/bug_502091_iframe.html b/parser/htmlparser/tests/mochitest/bug_502091_iframe.html
new file mode 100644
index 0000000000..076d3ed662
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/bug_502091_iframe.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+<title>Crash [@ nsContentSink::ProcessHeaderData] with meta in innerHTML</title>
+</head>
+<body>
+<div id="testdiv">
+ testdiv
+ </div>
+<script>
+var x = document.createElement("div");
+x.innerHTML = '<meta http-equiv="Content-Type" content="text/html;"></meta>';
+document.getElementById("testdiv").appendChild(x);
+</script>
+some text here
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/dir_bug534293/file_bug534293.sjs b/parser/htmlparser/tests/mochitest/dir_bug534293/file_bug534293.sjs
new file mode 100644
index 0000000000..faf44df66c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/dir_bug534293/file_bug534293.sjs
@@ -0,0 +1,13 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/javascript", false);
+ if (request.queryString.includes("report")) {
+ if (getState("loaded") == "loaded") {
+ response.write("ok(true, 'This script was supposed to get fetched.');");
+ } else {
+ response.write("ok(false, 'This script was supposed to get fetched.');");
+ }
+ } else {
+ setState("loaded", "loaded");
+ response.write("ok(true, 'This script is supposed to run.');");
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_async_bug1104732.sjs b/parser/htmlparser/tests/mochitest/file_async_bug1104732.sjs
new file mode 100644
index 0000000000..5e83e50510
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_async_bug1104732.sjs
@@ -0,0 +1,17 @@
+var timer = null;
+
+function handleRequest(request, response) {
+ response.processAsync();
+ response.setHeader("Content-Type", "application/javascript", false);
+ response.write("asyncState = 'mid-async';\n");
+
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ function () {
+ response.write("asyncState = 'loaded';\n");
+ response.finish();
+ },
+ 5 * 1000 /* milliseconds */,
+ timer.TYPE_ONE_SHOT
+ );
+}
diff --git a/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs b/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs
new file mode 100644
index 0000000000..aae7bde6a1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs
@@ -0,0 +1,18 @@
+function handleRequest(request, response) {
+ var hosts = getState("hosts");
+ hosts = hosts ? JSON.parse(hosts) : [];
+
+ if (request.queryString == "result") {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/json", false);
+ response.write(JSON.stringify(hosts));
+
+ setState("hosts", "[]");
+ } else {
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", "blue.png", false);
+
+ hosts.push(request.host);
+ setState("hosts", JSON.stringify(hosts));
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug102699.sjs b/parser/htmlparser/tests/mochitest/file_bug102699.sjs
new file mode 100644
index 0000000000..6e7c57cae4
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug102699.sjs
@@ -0,0 +1,19 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/javascript", false);
+ if (request.queryString.includes("report")) {
+ if (getState("loaded") == "loaded") {
+ response.write(
+ "ok(false, 'This script was not supposed to get fetched.'); continueAfterReport();"
+ );
+ } else {
+ response.write(
+ "ok(true, 'This script was not supposed to get fetched.'); continueAfterReport();"
+ );
+ }
+ } else {
+ setState("loaded", "loaded");
+ response.write(
+ 'document.documentElement.setAttribute("data-fail", "FAIL");'
+ );
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug534293-slow.sjs b/parser/htmlparser/tests/mochitest/file_bug534293-slow.sjs
new file mode 100644
index 0000000000..d2236de612
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug534293-slow.sjs
@@ -0,0 +1,16 @@
+var timer;
+
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/javascript", false);
+ response.write("ok(true, 'Slow script ran.');");
+ response.processAsync();
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ function () {
+ response.finish();
+ },
+ 500,
+ Ci.nsITimer.TYPE_ONE_SHOT
+ );
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug534293.sjs b/parser/htmlparser/tests/mochitest/file_bug534293.sjs
new file mode 100644
index 0000000000..279897c567
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug534293.sjs
@@ -0,0 +1,17 @@
+function handleRequest(request, response) {
+ response.setHeader("Content-Type", "text/javascript", false);
+ if (request.queryString.includes("report")) {
+ if (getState("loaded") == "loaded") {
+ response.write(
+ "ok(false, 'This script was not supposed to get fetched.');"
+ );
+ } else {
+ response.write(
+ "ok(true, 'This script was not supposed to get fetched.');"
+ );
+ }
+ } else {
+ setState("loaded", "loaded");
+ response.write("ok(false, 'This script is not supposed to run.');");
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug543062.sjs b/parser/htmlparser/tests/mochitest/file_bug543062.sjs
new file mode 100644
index 0000000000..508cde5644
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug543062.sjs
@@ -0,0 +1,38 @@
+var timer;
+
+function armTimer(response) {
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ function () {
+ if (
+ getState("docwritepreloadssecond") == "second" &&
+ getState("docwritepreloadsthird") == "third"
+ ) {
+ response.write(
+ "ok(true, 'Second and third scripts should have started loading while the first one is loading');"
+ );
+ response.finish();
+ } else {
+ armTimer(response);
+ }
+ },
+ 20,
+ Ci.nsITimer.TYPE_ONE_SHOT
+ );
+}
+
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/javascript", false);
+ if (request.queryString.includes("first")) {
+ response.write("// first\n");
+ response.processAsync();
+ armTimer(response);
+ } else if (request.queryString.includes("second")) {
+ response.write("// second\n");
+ setState("docwritepreloadssecond", "second");
+ } else {
+ response.write("// third\n");
+ setState("docwritepreloadsthird", "third");
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug568470-script.sjs b/parser/htmlparser/tests/mochitest/file_bug568470-script.sjs
new file mode 100644
index 0000000000..7cd25ddc08
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug568470-script.sjs
@@ -0,0 +1,17 @@
+var timer = null; // Declare outside to prevent premature GC
+
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/javascript", false);
+ response.write("var i = 0;");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ function () {
+ response.finish();
+ },
+ 500,
+ Ci.nsITimer.TYPE_ONE_SHOT
+ );
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug568470.sjs b/parser/htmlparser/tests/mochitest/file_bug568470.sjs
new file mode 100644
index 0000000000..57559e2f6e
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug568470.sjs
@@ -0,0 +1,22 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html", false);
+ response.write("<script src='file_bug568470-script.sjs'></script>");
+ response.write("<div id='flushable'>");
+ for (var i = 0; i < 2000; i++) {
+ response.write("Lorem ipsum dolor sit amet. ");
+ }
+ response.write("</div>");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ function () {
+ response.finish();
+ },
+ 1200,
+ Ci.nsITimer.TYPE_ONE_SHOT
+ );
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-1.html b/parser/htmlparser/tests/mochitest/file_bug594730-1.html
new file mode 100644
index 0000000000..8877311e21
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-1.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset="Windows-1250">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-2.html b/parser/htmlparser/tests/mochitest/file_bug594730-2.html
new file mode 100644
index 0000000000..f609df3976
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-2.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta http-equiv="content-TYPE" content="text/html; charset=Windows-1250">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-3.html b/parser/htmlparser/tests/mochitest/file_bug594730-3.html
new file mode 100644
index 0000000000..d6470d80fc
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-3.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta content="text/html; charset=Windows-1250" http-equiv="content-TYPE">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-4.html b/parser/htmlparser/tests/mochitest/file_bug594730-4.html
new file mode 100644
index 0000000000..bdce353a59
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-4.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta content="text/html; charset=Windows-1250">
+<script>parent.isnot("ø", "\u0159", "Decoded bytes should not have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-5.html b/parser/htmlparser/tests/mochitest/file_bug594730-5.html
new file mode 100644
index 0000000000..9fdbdded5c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-5.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset="Windows-1250" content="text/html; charset=Windows-1252">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-6.html b/parser/htmlparser/tests/mochitest/file_bug594730-6.html
new file mode 100644
index 0000000000..570fa460bc
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-6.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset="Windows-1250" http-equiv="Content-Type" content="text/html; charset=Windows-1252">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-7.html b/parser/htmlparser/tests/mochitest/file_bug594730-7.html
new file mode 100644
index 0000000000..92c19c8ffa
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-7.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta content="text/html; charset=Windows-1250" http-equiv="Content-Type" content="text/html; charset=Windows-1252">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-8.html b/parser/htmlparser/tests/mochitest/file_bug594730-8.html
new file mode 100644
index 0000000000..a9e7525c2c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-8.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset="Windows-1250" charset="Windows-1252">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug594730-9.html b/parser/htmlparser/tests/mochitest/file_bug594730-9.html
new file mode 100644
index 0000000000..60fab3a399
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug594730-9.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="
+ Windows-1250
+ ">
+<script>parent.is("ø", "\u0159", "Decoded bytes should have matched the Unicode escape.");</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug642908.sjs b/parser/htmlparser/tests/mochitest/file_bug642908.sjs
new file mode 100644
index 0000000000..6d83609216
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug642908.sjs
@@ -0,0 +1,19 @@
+function handleRequest(request, response) {
+ if (request.queryString.includes("report")) {
+ response.setHeader("Content-Type", "text/javascript", false);
+ if (getState("loaded") == "loaded") {
+ response.write(
+ "ok(false, 'There was an attempt to preload the image.');"
+ );
+ } else {
+ response.write("ok(true, 'There was no attempt to preload the image.');");
+ }
+ response.write("SimpleTest.finish();");
+ } else {
+ setState("loaded", "loaded");
+ response.setHeader("Content-Type", "image/svg", false);
+ response.write(
+ "<svg xmlns='http://www.w3.org/2000/svg'>Not supposed to load this</svg>"
+ );
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug655682.sjs b/parser/htmlparser/tests/mochitest/file_bug655682.sjs
new file mode 100644
index 0000000000..2f1e0211c3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug655682.sjs
@@ -0,0 +1,31 @@
+var timer;
+var callback;
+
+function handleRequest(request, response) {
+ if (request.queryString.includes("trigger")) {
+ setState("triggered", "triggered");
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/javascript; charset=utf-8", false);
+ response.write(";");
+ } else {
+ // Reset the state when running more than once in same browser session.
+ setState("triggered", "");
+
+ response.processAsync();
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html; charset=utf-8", false);
+ response.write("<table><tr><td>A</td> ");
+ response.bodyOutputStream.flush();
+ timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+
+ callback = function () {
+ if (getState("triggered") == "triggered") {
+ response.write("<td>B</td></tr></table>");
+ response.finish();
+ } else {
+ timer.initWithCallback(callback, 10, Ci.nsITimer.TYPE_ONE_SHOT);
+ }
+ };
+ timer.initWithCallback(callback, 10, Ci.nsITimer.TYPE_ONE_SHOT);
+ }
+}
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_enc_error.html b/parser/htmlparser/tests/mochitest/file_bug672453_enc_error.html
new file mode 100644
index 0000000000..07d037497d
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_enc_error.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Encoding error</title>
+</head>
+<body>
+<p>ä</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_enc_error_inherited.html b/parser/htmlparser/tests/mochitest/file_bug672453_enc_error_inherited.html
new file mode 100644
index 0000000000..06d44ba9b1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_enc_error_inherited.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Encoding error</title>
+</head>
+<body>
+<p>ä</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html b/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html
new file mode 100644
index 0000000000..0e76edd65b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html
@@ -0,0 +1 @@
+<!DOCTYPE html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html^headers^ b/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html^headers^
new file mode 100644
index 0000000000..0cb0a6b1bf
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html^headers^
@@ -0,0 +1,2 @@
+HTTP 200 OK
+Content-Type: text/html; charset=iso-2022-kr
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html b/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html
new file mode 100644
index 0000000000..0e76edd65b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html
@@ -0,0 +1 @@
+<!DOCTYPE html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html^headers^ b/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html^headers^
new file mode 100644
index 0000000000..35885d0cc1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html^headers^
@@ -0,0 +1,2 @@
+HTTP 200 OK
+Content-Type: text/html; charset=bogus
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html b/parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html
new file mode 100644
index 0000000000..1e0b5870f7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html
@@ -0,0 +1,1028 @@
+<!DOCTYPE html>
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+<meta charset="UTF-8">
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_after_head.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_after_head.html
new file mode 100644
index 0000000000..3def05a535
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_after_head.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Meta after head</title>
+</head>
+<body>
+<meta charset="windows-1251">
+<p>Meta after head</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html
new file mode 100644
index 0000000000..dab8635286
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html
@@ -0,0 +1 @@
+<meta charset="x-imap4-modified-utf7">
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_replacement.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_replacement.html
new file mode 100644
index 0000000000..9bbbe52313
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_replacement.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="iso-2022-kr">
+ <title>Replacement encoding</title>
+</head>
+<body>
+<p>Replacement encoding</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html
new file mode 100644
index 0000000000..84bd1d3641
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html
@@ -0,0 +1,1028 @@
+<!DOCTYPE html>
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+<meta charset="ISO-8859-2">
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_speculation_fail.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_speculation_fail.html
new file mode 100644
index 0000000000..b63255e981
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_speculation_fail.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Speculation fäilure</title>
+ <meta charset="windows-1252">
+</head>
+<body>
+<p>Speculation fails</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html
new file mode 100644
index 0000000000..91111d7e74
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html
@@ -0,0 +1 @@
+<meta charset="bogus">
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_userdefined.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_userdefined.html
new file mode 100644
index 0000000000..250f6fa67c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_userdefined.html
@@ -0,0 +1 @@
+<meta charset="x-user-defined">
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html b/parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html
new file mode 100644
index 0000000000..2e6fb9c8b7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html
@@ -0,0 +1 @@
+<meta charset="UTF-16">
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html b/parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html
new file mode 100644
index 0000000000..0e76edd65b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html
@@ -0,0 +1 @@
+<!DOCTYPE html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_xml_decl.html b/parser/htmlparser/tests/mochitest/file_bug672453_xml_decl.html
new file mode 100644
index 0000000000..ed350a1157
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_xml_decl.html
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Has only XML decl</title>
+</head>
+<body>
+<p>Only XML decl</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug672453_xml_speculation_fail.html b/parser/htmlparser/tests/mochitest/file_bug672453_xml_speculation_fail.html
new file mode 100644
index 0000000000..08ba678590
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug672453_xml_speculation_fail.html
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Speculation fäilure</title>
+</head>
+<body>
+<p>Speculation fails</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug688580.js b/parser/htmlparser/tests/mochitest/file_bug688580.js
new file mode 100644
index 0000000000..bee04dde23
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug688580.js
@@ -0,0 +1,8 @@
+/* globals state:true */
+is(
+ document.readyState,
+ "interactive",
+ "readyState should be interactive during defer."
+);
+is(state, "readyState interactive", "Bad state upon defer");
+state = "defer";
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-16.html b/parser/htmlparser/tests/mochitest/file_bug716579-16.html
new file mode 100644
index 0000000000..1cd07ca9a5
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-16.html
Binary files differ
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-16.html^headers^ b/parser/htmlparser/tests/mochitest/file_bug716579-16.html^headers^
new file mode 100644
index 0000000000..3fadd3bad3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-16.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=windows-874
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml b/parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml
new file mode 100644
index 0000000000..cc828a7ce7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml
Binary files differ
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml^headers^ b/parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml^headers^
new file mode 100644
index 0000000000..208b923e8f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-16.xhtml^headers^
@@ -0,0 +1 @@
+Content-Type: application/xhtml+xml; charset=windows-874
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-8.html b/parser/htmlparser/tests/mochitest/file_bug716579-8.html
new file mode 100644
index 0000000000..bbeb036db1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-8.html
@@ -0,0 +1,3 @@
+<script>
+parent.html8 = "€";
+</script>
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-8.html^headers^ b/parser/htmlparser/tests/mochitest/file_bug716579-8.html^headers^
new file mode 100644
index 0000000000..3fadd3bad3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-8.html^headers^
@@ -0,0 +1 @@
+Content-Type: text/html; charset=windows-874
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml b/parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml
new file mode 100644
index 0000000000..a1221cafc7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<body>
+<script>
+parent.xml8 = "€";
+</script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml^headers^ b/parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml^headers^
new file mode 100644
index 0000000000..208b923e8f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug716579-8.xhtml^headers^
@@ -0,0 +1 @@
+Content-Type: application/xhtml+xml; charset=windows-874
diff --git a/parser/htmlparser/tests/mochitest/file_bug717180.html b/parser/htmlparser/tests/mochitest/file_bug717180.html
new file mode 100644
index 0000000000..ff43ca4091
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_bug717180.html
@@ -0,0 +1 @@
+SUCCESS
diff --git a/parser/htmlparser/tests/mochitest/file_defer_bug1104732.js b/parser/htmlparser/tests/mochitest/file_defer_bug1104732.js
new file mode 100644
index 0000000000..5ba15f287b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_defer_bug1104732.js
@@ -0,0 +1,7 @@
+/* globals state:true */
+is(
+ document.readyState,
+ "interactive",
+ "readyState should be interactive during defer."
+);
+state = "defer";
diff --git a/parser/htmlparser/tests/mochitest/file_img_picture_preload.html b/parser/htmlparser/tests/mochitest/file_img_picture_preload.html
new file mode 100644
index 0000000000..a5a55a56a3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_img_picture_preload.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<html>
+<!--
+ Helper for test_img_picture_preload.htm. Can be merged in to the test file
+ when dom.image.{picture,srcset} are removed and we don't need to do pref
+ flipping before the load.
+
+ https://bugzilla.mozilla.org/show_bug.cgi?id=1067345
+-->
+<head>
+ <title>Test for Bug 1067345</title>
+</head>
+<body onload="afterLoad();">
+ <script type="text/javascript">
+ var is = window.parent.is;
+ var ok = window.parent.ok;
+ var SimpleTest = window.parent.SimpleTest;
+ // Called with number of requests made
+ var notifyTestFinished = window.parent.childTestFinished;
+ var currentDPI = window.parent.currentDPI;
+
+ // This script is intentionally blocking the images below from
+ // loading. It issues sync XHRs to the sjs to wait for the files
+ // to be requested before unblocking DOM creation, then asserts
+ // that the same sources were selected by the preloader and the
+ // real DOM.
+
+ // Number of images to wait for before unblocking load
+ const EXPECTED_PRELOADS = 11;
+
+ function busyWait(waitms) {
+ var start = Date.now();
+ while (Date.now() < start + waitms);
+ }
+
+ // Send sync XHRs asking the sjs what images it's seen until we
+ // see EXPECTED_PRELOADS images. (If this test is timing out, you broke
+ // the preloader)
+ var preloadedImages = [];
+ while (preloadedImages.length < EXPECTED_PRELOADS) {
+ var request = new XMLHttpRequest();
+ request.open("GET", "./file_img_picture_preload.sjs?status", false);
+ request.send(null);
+ is(request.status, 200, "Getting status from sjs helper should succeed");
+ if (request.status === 200) {
+ preloadedImages = JSON.parse(request.responseText);
+ }
+ }
+
+ // Ensure the DOM is still blocked on us before proceeding
+ is(document.querySelector("img"), null, "No <img> elements should exist yet");
+ </script>
+
+ <!-- All images below will be checked, use sources of the format
+ ./file_img_picture_preload.sjs?imgName:sourceName
+ Update numImages when adding or removing images below -->
+
+ <!-- Basic src -->
+ <img id="img1"
+ src="./file_img_picture_preload.sjs?img1:source1">
+ <!-- Basic srcset, no src -->
+ <img id="img2"
+ srcset="./file_img_picture_preload.sjs?img2:source1, ./file_img_picture_preload.sjs?img2:source2 2x, ./file_img_picture_preload.sjs?img2:source3 0.5x">
+ <!-- srcset + src, srcset should shadow entirley -->
+ <img id="img3"
+ srcset="./file_img_picture_preload.sjs?img3:source1, ./file_img_picture_preload.sjs?img3:source2 2x, ./file_img_picture_preload.sjs?img3:source3 0.5x">
+ <!-- Ditto with sizes selector -->
+ <img id="img4"
+ sizes="50vw"
+ srcset="./file_img_picture_preload.sjs?img4:source1 500w, ./file_img_picture_preload.sjs?img4:source2 200w, ./file_img_picture_preload.sjs?img4:source3 5w">
+ <!-- Default source shouldn't be selected -->
+ <img id="img5"
+ srcset="./file_img_picture_preload.sjs?img5:source1, ./file_img_picture_preload.sjs?img5:source2 2x"
+ src="./file_img_picture_preload.sjs?img5:source3">
+ <!-- Default source should be the 1x source, but srcset for others -->
+ <img id="img6"
+ srcset="./file_img_picture_preload.sjs?img6:source1 0.5x, ./file_img_picture_preload.sjs?img6:source2 2x"
+ src="./file_img_picture_preload.sjs?img6:source3">
+
+ <!-- Ensure we skip various invalid sources -->
+ <picture>
+ <source type="image/png">
+ <source type="image/png" srcset="">
+ <source media="(min-width: 1px)">
+ <source media="(min-width: 1px)" srcset=" ">
+ <source type="invalid/x-bogus-type" srcset="./file_img_picture_preload.sjs?img7:source1">
+ <source media="(unknown-query-value-thing: 1000something)" srcset="./file_img_picture_preload.sjs?img7:source2">
+ <source media="(unknown-query-value-thing: 1000something)" srcset="bogus ./file_img_picture_preload.sjs?img7:source3 ./file_img_picture_preload.sjs?img7:source4">
+ <img id="img7" src="./file_img_picture_preload.sjs?img7:source5">
+ </picture>
+
+ <!-- Should select matching sources with known type, and shouldn't select later sources that have closer densities-->
+ <picture>
+ <source type="invalid/x-unsupported-image-type" srcset="./file_img_picture_preload.sjs?img8:source1">
+ <source type="image/png" srcset="./file_img_picture_preload.sjs?img8:source2 2x">
+ <source type="image/png" srcset="./file_img_picture_preload.sjs?img8:source3 1x">
+ <img id="img8" src="./file_img_picture_preload.sjs?img8:source4" srcset="./file_img_picture_preload.sjs?img8:source5 2x">
+ </picture>
+
+ <!-- Should select matching sources by media, and shouldn't select later sources that have closer densities -->
+ <picture>
+ <source media="(bogusxx)" srcset="./file_img_picture_preload.sjs?img9:source1">
+ <source media="(minimum-width: 1px)" srcset="./file_img_picture_preload.sjs?img9:source2 2x">
+ <source media="(max-resolution: 0.5dppx)" srcset="./file_img_picture_preload.sjs?img9:source3 1x">
+ <source media="(min-resolution: 2dppx)" srcset="./file_img_picture_preload.sjs?img9:source4 1x">
+ <source media="(min-resolution: 1dppx)" srcset="./file_img_picture_preload.sjs?img9:source5 1x">
+ <source media="(min-resolution: 1dppx)" srcset="./file_img_picture_preload.sjs?img9:source6 2x">
+ <img id="img9" src="./file_img_picture_preload.sjs?img9:source7" srcset="./file_img_picture_preload.sjs?img9:source8 2x">
+ </picture>
+
+ <!-- Make sure we consider sizes properly in sources -->
+ <picture>
+ <source type="image/png"
+ sizes="10px"
+ srcset="./file_img_picture_preload.sjs?img10:source1 10w, ./file_img_picture_preload.sjs?img10:source2 20w">
+ <img id="img10" src="./file_img_picture_preload.sjs?img10:source3">
+ </picture>
+
+ <!-- Make sure we consider sizes properly -->
+ <img id="img11" sizes="10px"
+ srcset="./file_img_picture_preload.sjs?img11:source1 10w, ./file_img_picture_preload.sjs?img11:source2 20w"
+ src="./file_img_picture_preload.sjs?img11:source3">
+
+ <script type="text/javascript">
+ function afterLoad() {
+ // All images should have picked a source of the format
+ // imgName:sourceName, ensure we have one source per image and
+ // that it was preloaded.
+
+ is(preloadedImages.length, EXPECTED_PRELOADS,
+ "Should have exactly " + EXPECTED_PRELOADS + " preloaded URLs");
+
+ // Split "imgName:source" sources we saw preload by img name
+ var preloadByName = {};
+ for (var preload of preloadedImages) {
+ var split = preload.split(":");
+ // Ensure we didn't preload two sources for the same image
+ ok(preloadByName[split[0]] === undefined,
+ "Should not have queried multiple sources for " + split[0] +
+ " (got " + split[1] + ", already had " + preloadByName[split[0]] + ")");
+ preloadByName[split[0]] = split[1];
+ }
+
+ // Check all images, ensure each one had a preload
+ var images = document.querySelectorAll("img");
+ for (var img of images) {
+ var imgName = img.id;
+ if (img.currentSrc) {
+ split = img.currentSrc.split("?")[1].split(":");
+ is(split[0], imgName,
+ "image " + imgName + " source matches element id");
+ is(split[1], preloadByName[imgName],
+ "image " + imgName + " source should match preloaded source");
+ // Remove from array
+ delete preloadByName[imgName];
+ } else {
+ // img loaded nothing
+ is(preloadByName[imgName], null,
+ "Should not have preloaded anything for image " + imgName);
+ }
+ }
+
+ notifyTestFinished(preloadedImages.length);
+ }
+ </script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_img_picture_preload.sjs b/parser/htmlparser/tests/mochitest/file_img_picture_preload.sjs
new file mode 100644
index 0000000000..e91da04352
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_img_picture_preload.sjs
@@ -0,0 +1,27 @@
+// Return a PNG, saving an array of query strings we see as state. When query
+// string is 'status', return array as JSON
+
+function handleRequest(request, response) {
+ var seenImages = getState("seenImages");
+ seenImages = seenImages ? JSON.parse(seenImages) : [];
+
+ response.setHeader("Cache-Control", "must-revalidate", false);
+
+ if (request.queryString == "status") {
+ response.setHeader("Content-Type", "text/javascript", false);
+ response.write(JSON.stringify(seenImages));
+ } else if (request.queryString == "reset") {
+ // Respond with how many requests we had seen, drop them
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write(String(seenImages.length));
+ seenImages = [];
+ } else {
+ // Return an image
+ response.setStatusLine("1.1", 302, "Found");
+ response.setHeader("Location", "blue.png", false);
+ dump(request.queryString + "\n");
+ seenImages.push(request.queryString);
+ }
+
+ setState("seenImages", JSON.stringify(seenImages));
+}
diff --git a/parser/htmlparser/tests/mochitest/file_viewsource.html b/parser/htmlparser/tests/mochitest/file_viewsource.html
new file mode 100644
index 0000000000..3ed00150a7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_viewsource.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for view source</title>
+ </head>
+
+ <body>
+
+<!--
+ this is a multi-line comment
+-->
+
+ <script class="testbody" type="text/javascript">
+ // This is a script comment / text.
+ </script>
+
+ </body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/file_xml_parse_error.js b/parser/htmlparser/tests/mochitest/file_xml_parse_error.js
new file mode 100644
index 0000000000..8ab5425bce
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_xml_parse_error.js
@@ -0,0 +1 @@
+parent.ok(true, "Loaded script.");
diff --git a/parser/htmlparser/tests/mochitest/file_xml_parse_error.xml b/parser/htmlparser/tests/mochitest/file_xml_parse_error.xml
new file mode 100644
index 0000000000..d75a4525e4
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/file_xml_parse_error.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" standalone="yes" ?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<p> <script src="file_xml_parse_error.js" /> Not a <<b>well-formed</b> xml string</p></html>
diff --git a/parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js b/parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js
new file mode 100644
index 0000000000..fed7e353e2
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5_tree_construction_exceptions.js
@@ -0,0 +1,11 @@
+/*
+ * These are the tests we don't pass. The test data comes from the .dat
+ * files under html5lib_tree_construction/. Please see
+ * html5lib_tree_construction/html5lib_license.txt for the license for these
+ * tests.
+ */
+var html5Exceptions = {
+ "<select><keygen>": true, // Bug 101019
+ "<p><table></p>": true, // parser_web_testrunner.js uses srcdoc which forces quirks mode
+ "<p><table></table>": true, // parser_web_testrunner.js uses srcdoc which forces quirks mode
+};
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/README.md b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/README.md
new file mode 100644
index 0000000000..be41fa44f8
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/README.md
@@ -0,0 +1,104 @@
+Tree Construction Tests
+=======================
+
+Each file containing tree construction tests consists of any number of
+tests separated by two newlines (LF) and a single newline before the end
+of the file. For instance:
+
+ [TEST]LF
+ LF
+ [TEST]LF
+ LF
+ [TEST]LF
+
+Where [TEST] is the following format:
+
+Each test must begin with a string "\#data" followed by a newline (LF).
+All subsequent lines until a line that says "\#errors" are the test data
+and must be passed to the system being tested unchanged, except with the
+final newline (on the last line) removed.
+
+Then there must be a line that says "\#errors". It must be followed by
+one line per parse error that a conformant checker would return. It
+doesn't matter what those lines are, although they can't be
+"\#document-fragment", "\#document", "\#script-off", "\#script-on", or
+empty, the only thing that matters is that there be the right number
+of parse errors.
+
+Then there \*may\* be a line that says "\#document-fragment", which must
+be followed by a newline (LF), followed by a string of characters that
+indicates the context element, followed by a newline (LF). If the string
+of characters starts with "svg ", the context element is in the SVG
+namespace and the substring after "svg " is the local name. If the
+string of characters starts with "math ", the context element is in the
+MathML namespace and the substring after "math " is the local name.
+Otherwise, the context element is in the HTML namespace and the string
+is the local name. If this line is present the "\#data" must be parsed
+using the HTML fragment parsing algorithm with the context element as
+context.
+
+Then there \*may\* be a line that says "\#script-off" or
+"\#script-in". If a line that says "\#script-off" is present, the
+parser must set the scripting flag to disabled. If a line that says
+"\#script-on" is present, it must set it to enabled. Otherwise, the
+test should be run in both modes.
+
+Then there must be a line that says "\#document", which must be followed
+by a dump of the tree of the parsed DOM. Each node must be represented
+by a single line. Each line must start with "| ", followed by two spaces
+per parent node that the node has before the root document node.
+
+- Element nodes must be represented by a "`<`" then the *tag name
+ string* "`>`", and all the attributes must be given, sorted
+ lexicographically by UTF-16 code unit according to their *attribute
+ name string*, on subsequent lines, as if they were children of the
+ element node.
+- Attribute nodes must have the *attribute name string*, then an "="
+ sign, then the attribute value in double quotes (").
+- Text nodes must be the string, in double quotes. Newlines aren't
+ escaped.
+- Comments must be "`<`" then "`!-- `" then the data then "` -->`".
+- DOCTYPEs must be "`<!DOCTYPE `" then the name then if either of the
+ system id or public id is non-empty a space, public id in
+ double-quotes, another space an the system id in double-quotes, and
+ then in any case "`>`".
+- Processing instructions must be "`<?`", then the target, then a
+ space, then the data and then "`>`". (The HTML parser cannot emit
+ processing instructions, but scripts can, and the WebVTT to DOM
+ rules can emit them.)
+- Template contents are represented by the string "content" with the
+ children below it.
+
+The *tag name string* is the local name prefixed by a namespace
+designator. For the HTML namespace, the namespace designator is the
+empty string, i.e. there's no prefix. For the SVG namespace, the
+namespace designator is "svg ". For the MathML namespace, the namespace
+designator is "math ".
+
+The *attribute name string* is the local name prefixed by a namespace
+designator. For no namespace, the namespace designator is the empty
+string, i.e. there's no prefix. For the XLink namespace, the namespace
+designator is "xlink ". For the XML namespace, the namespace designator
+is "xml ". For the XMLNS namespace, the namespace designator is "xmlns
+". Note the difference between "xlink:href" which is an attribute in no
+namespace with the local name "xlink:href" and "xlink href" which is an
+attribute in the xlink namespace with the local name "href".
+
+If there is also a "\#document-fragment" the bit following "\#document"
+must be a representation of the HTML fragment serialization for the
+context element given by "\#document-fragment".
+
+For example:
+
+ #data
+ <p>One<p>Two
+ #errors
+ 3: Missing document type declaration
+ #document
+ | <html>
+ | <head>
+ | <body>
+ | <p>
+ | "One"
+ | <p>
+ | "Two"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption01.dat
new file mode 100644
index 0000000000..2e1127e517
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption01.dat
@@ -0,0 +1,337 @@
+#data
+<a><p></a></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+
+#data
+<a>1<p>2</a>3</p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,12): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <p>
+| <a>
+| "2"
+| "3"
+
+#data
+<a>1<button>2</a>3</button>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,17): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <button>
+| <a>
+| "2"
+| "3"
+
+#data
+<a>1<b>2</a>3</b>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,12): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <b>
+| "2"
+| <b>
+| "3"
+
+#data
+<a>1<div>2<div>3</a>4</div>5</div>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,20): adoption-agency-1.3
+(1,20): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <div>
+| <a>
+| "2"
+| <div>
+| <a>
+| "3"
+| "4"
+| "5"
+
+#data
+<table><a>1<p>2</a>3</p>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,11): unexpected-character-implies-table-voodoo
+(1,14): unexpected-start-tag-implies-table-voodoo
+(1,15): unexpected-character-implies-table-voodoo
+(1,19): unexpected-end-tag-implies-table-voodoo
+(1,19): adoption-agency-1.3
+(1,20): unexpected-character-implies-table-voodoo
+(1,24): unexpected-end-tag-implies-table-voodoo
+(1,24): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <p>
+| <a>
+| "2"
+| "3"
+| <table>
+
+#data
+<b><b><a><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| <a>
+| <p>
+| <a>
+
+#data
+<b><a><b><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <a>
+| <b>
+| <b>
+| <p>
+| <a>
+
+#data
+<a><b><b><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <b>
+| <b>
+| <p>
+| <a>
+
+#data
+<p>1<s id="A">2<b id="B">3</p>4</s>5</b>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,30): unexpected-end-tag
+(1,35): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "1"
+| <s>
+| id="A"
+| "2"
+| <b>
+| id="B"
+| "3"
+| <s>
+| id="A"
+| <b>
+| id="B"
+| "4"
+| <b>
+| id="B"
+| "5"
+
+#data
+<table><a>1<td>2</td>3</table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,11): unexpected-character-implies-table-voodoo
+(1,15): unexpected-cell-in-table-body
+(1,30): unexpected-implied-end-tag-in-table-view
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <a>
+| "3"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "2"
+
+#data
+<table>A<td>B</td>C</table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,8): unexpected-character-implies-table-voodoo
+(1,12): unexpected-cell-in-table-body
+(1,22): unexpected-character-implies-table-voodoo
+#document
+| <html>
+| <head>
+| <body>
+| "AC"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "B"
+
+#data
+<a><svg><tr><input></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+(1,23): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <svg svg>
+| <svg tr>
+| <svg input>
+
+#data
+<div><a><b><div><div><div><div><div><div><div><div><div><div></a>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| <b>
+| <b>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <div>
+
+#data
+<div><a><b><u><i><code><div></a>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,32): adoption-agency-1.3
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| <b>
+| <u>
+| <i>
+| <code>
+| <u>
+| <i>
+| <code>
+| <div>
+| <a>
+
+#data
+<b><b><b><b>x</b></b></b></b>y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| <b>
+| <b>
+| "x"
+| "y"
+
+#data
+<p><b><b><b><b><p>x
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag
+(1,19): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <b>
+| <b>
+| <b>
+| <p>
+| <b>
+| <b>
+| <b>
+| "x"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat
new file mode 100644
index 0000000000..0502cf3021
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/adoption02.dat
@@ -0,0 +1,99 @@
+#data
+<b>1<i>2<p>3</b>4
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "1"
+| <i>
+| "2"
+| <i>
+| <p>
+| <b>
+| "3"
+| "4"
+
+#data
+<a><div><style></style><address><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,35): unexpected-start-tag-implies-end-tag
+(1,35): adoption-agency-1.3
+(1,35): adoption-agency-1.3
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <div>
+| <a>
+| <style>
+| <address>
+| <a>
+| <a>
+
+#data
+<b><i><a><s><tt><div></b>first</b></div></tt></s></a>second</i>
+#errors
+3: Start tag seen without seeing a doctype first. Expected "<!DOCTYPE html>".
+25: End tag "b" violates nesting rules.
+34: Stray end tag "b".
+63: Stray end tag "i".
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <i>
+| <a>
+| <s>
+| <tt>
+| <a>
+| <s>
+| <tt>
+| <div>
+| <b>
+| "first"
+| "second"
+
+#data
+<code foo="bar"><code><code><code><code></code></code></code></code>text</code>
+#errors
+16: Start tag seen without seeing a doctype first. Expected "<!DOCTYPE html>".
+#document
+| <html>
+| <head>
+| <body>
+| <code>
+| foo="bar"
+| <code>
+| <code>
+| <code>
+| <code>
+| "text"
+
+#data
+<code foo="bar"><code><code><code><div><code></div></code></code></code></code>text</code>
+#errors
+16: Start tag seen without seeing a doctype first. Expected "<!DOCTYPE html>".
+51: End tag "div" seen, but there were open elements.
+45: Unclosed element "code".
+58: No "code" element in scope but a "code" end tag seen.
+#document
+| <html>
+| <head>
+| <body>
+| <code>
+| foo="bar"
+| <code>
+| <code>
+| <code>
+| <div>
+| <code>
+| "text"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/comments01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/comments01.dat
new file mode 100644
index 0000000000..32021e15ca
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/comments01.dat
@@ -0,0 +1,206 @@
+#data
+FOO<!-- BAR -->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -->
+| "BAZ"
+
+#data
+FOO<!-- BAR --!>BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-bang-after-double-dash-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -->
+| "BAZ"
+
+#data
+FOO<!-- BAR --! >BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+#new-errors
+(1:20) eof-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR --! >BAZ -->
+
+#data
+FOO<!-- BAR --!
+>BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+#new-errors
+(1:20) eof-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR --!
+>BAZ -->
+
+#data
+FOO<!-- BAR -- >BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,21): eof-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- >BAZ -->
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX -->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,24): unexpected-char-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX --!>BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,24): unexpected-char-in-comment
+(1,31): unexpected-bang-after-double-dash-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX -- >BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,24): unexpected-char-in-comment
+(1,31): unexpected-char-in-comment
+(1,35): eof-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -- >BAZ -->
+
+#data
+FOO<!---->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+FOO<!--->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,9): incorrect-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+FOO<!-->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,8): incorrect-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+<?xml version="1.0">Hi
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,22): expected-doctype-but-got-chars
+#document
+| <!-- ?xml version="1.0" -->
+| <html>
+| <head>
+| <body>
+| "Hi"
+
+#data
+<?xml version="1.0">
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,20): expected-doctype-but-got-eof
+#document
+| <!-- ?xml version="1.0" -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?xml version
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,13): expected-doctype-but-got-eof
+#document
+| <!-- ?xml version -->
+| <html>
+| <head>
+| <body>
+
+#data
+FOO<!----->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,10): unexpected-dash-after-double-dash-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- - -->
+| "BAZ"
+
+#data
+<html><!-- comment --><title>Comment before head</title>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <!-- comment -->
+| <head>
+| <title>
+| "Comment before head"
+| <body>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/doctype01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/doctype01.dat
new file mode 100644
index 0000000000..cec6638971
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/doctype01.dat
@@ -0,0 +1,424 @@
+#data
+<!DOCTYPE html>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!dOctYpE HtMl>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPEhtml>Hello
+#errors
+(1,9): need-space-after-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE>Hello
+#errors
+(1,9): need-space-after-doctype
+(1,10): expected-doctype-name-but-got-right-bracket
+(1,10): unknown-doctype
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE >Hello
+#errors
+(1,11): expected-doctype-name-but-got-right-bracket
+(1,11): unknown-doctype
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato>Hello
+#errors
+(1,17): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato >Hello
+#errors
+(1,18): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato taco>Hello
+#errors
+(1,17): expected-space-or-right-bracket-in-doctype
+(1,22): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato taco "ddd>Hello
+#errors
+(1,17): expected-space-or-right-bracket-in-doctype
+(1,27): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM>Hello
+#errors
+(1,24): unexpected-char-in-doctype
+(1,24): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM >Hello
+#errors
+(1,28): unexpected-char-in-doctype
+(1,28): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM ggg>Hello
+#errors
+(1,34): unexpected-char-in-doctype
+(1,37): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM taco >Hello
+#errors
+(1,25): unexpected-char-in-doctype
+(1,31): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM 'taco"'>Hello
+#errors
+(1,32): unknown-doctype
+#document
+| <!DOCTYPE potato "" "taco"">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM "taco">Hello
+#errors
+(1,31): unknown-doctype
+#document
+| <!DOCTYPE potato "" "taco">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM "tai'co">Hello
+#errors
+(1,33): unknown-doctype
+#document
+| <!DOCTYPE potato "" "tai'co">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEMtaco "ddd">Hello
+#errors
+(1,24): unexpected-char-in-doctype
+(1,34): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato grass SYSTEM taco>Hello
+#errors
+(1,17): expected-space-or-right-bracket-in-doctype
+(1,35): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIc>Hello
+#errors
+(1,24): unexpected-end-of-doctype
+(1,24): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIc >Hello
+#errors
+(1,25): unexpected-end-of-doctype
+(1,25): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIcgoof>Hello
+#errors
+(1,24): unexpected-char-in-doctype
+(1,28): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC goof>Hello
+#errors
+(1,25): unexpected-char-in-doctype
+(1,29): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC "go'of">Hello
+#errors
+(1,32): unknown-doctype
+#document
+| <!DOCTYPE potato "go'of" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC 'go'of'>Hello
+#errors
+(1,29): unexpected-char-in-doctype
+(1,32): unknown-doctype
+#document
+| <!DOCTYPE potato "go" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC 'go:hh of' >Hello
+#errors
+(1,38): unknown-doctype
+#document
+| <!DOCTYPE potato "go:hh of" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC "W3C-//dfdf" SYSTEM ggg>Hello
+#errors
+(1,38): unexpected-char-in-doctype
+(1,48): unknown-doctype
+#document
+| <!DOCTYPE potato "W3C-//dfdf" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">Hello
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE ...>Hello
+#errors
+(1,14): unknown-doctype
+#document
+| <!DOCTYPE ...>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+#errors
+(2,58): unknown-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+#errors
+(2,54): unknown-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [
+<!-- internal declarations -->
+]>
+#errors
+(1,23): expected-space-or-right-bracket-in-doctype
+(2,30): unknown-doctype
+#document
+| <!DOCTYPE root-element>
+| <html>
+| <head>
+| <body>
+| "]>"
+
+#data
+<!DOCTYPE html PUBLIC
+ "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+ "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+#errors
+(3,53): unknown-doctype
+#document
+| <!DOCTYPE html "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML SYSTEM "http://www.w3.org/DTD/HTML4-strict.dtd"><body><b>Mine!</b></body>
+#errors
+(1,63): unknown-doctype
+#document
+| <!DOCTYPE html "" "http://www.w3.org/DTD/HTML4-strict.dtd">
+| <html>
+| <head>
+| <body>
+| <b>
+| "Mine!"
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
+#errors
+(1,50): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+(1,50): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+(1,21): unexpected-char-in-doctype
+(1,49): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC'-//W3C//DTD HTML 4.01//EN''http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+(1,21): unexpected-char-in-doctype
+(1,49): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/domjs-unsafe.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/domjs-unsafe.dat
new file mode 100644
index 0000000000..34b4e62716
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/domjs-unsafe.dat
Binary files differ
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities01.dat
new file mode 100644
index 0000000000..b271f8220f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities01.dat
@@ -0,0 +1,792 @@
+#data
+FOO&gt;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>BAR"
+
+#data
+FOO&gtBAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>BAR"
+
+#data
+FOO&gt BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO> BAR"
+
+#data
+FOO&gt;;;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>;;BAR"
+
+#data
+I'm &notit; I tell you
+#errors
+(1,4): expected-doctype-but-got-chars
+(1,9): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "I'm ¬it; I tell you"
+
+#data
+I'm &notin; I tell you
+#errors
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "I'm ∉ I tell you"
+
+#data
+FOO& BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO& BAR"
+
+#data
+FOO&<BAR>
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&"
+| <bar>
+
+#data
+FOO&&&&gt;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&&&>BAR"
+
+#data
+FOO&#41;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO)BAR"
+
+#data
+FOO&#x41;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOABAR"
+
+#data
+FOO&#X41;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOABAR"
+
+#data
+FOO&#BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,5): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#BAR"
+
+#data
+FOO&#ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,5): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#ZOO"
+
+#data
+FOO&#xBAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,7): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOºR"
+
+#data
+FOO&#xZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#xZOO"
+
+#data
+FOO&#XZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#XZOO"
+
+#data
+FOO&#41BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,7): numeric-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO)BAR"
+
+#data
+FOO&#x41BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,10): numeric-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO䆺R"
+
+#data
+FOO&#x41ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,8): numeric-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOOAZOO"
+
+#data
+FOO&#x0000;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#x0078;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOxZOO"
+
+#data
+FOO&#x0079;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOyZOO"
+
+#data
+FOO&#x0080;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO€ZOO"
+
+#data
+FOO&#x0081;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÂZOO"
+
+#data
+FOO&#x0082;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‚ZOO"
+
+#data
+FOO&#x0083;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÆ’ZOO"
+
+#data
+FOO&#x0084;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO„ZOO"
+
+#data
+FOO&#x0085;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO…ZOO"
+
+#data
+FOO&#x0086;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO†ZOO"
+
+#data
+FOO&#x0087;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‡ZOO"
+
+#data
+FOO&#x0088;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOˆZOO"
+
+#data
+FOO&#x0089;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‰ZOO"
+
+#data
+FOO&#x008A;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÅ ZOO"
+
+#data
+FOO&#x008B;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‹ZOO"
+
+#data
+FOO&#x008C;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÅ’ZOO"
+
+#data
+FOO&#x008D;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÂZOO"
+
+#data
+FOO&#x008E;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŽZOO"
+
+#data
+FOO&#x008F;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÂZOO"
+
+#data
+FOO&#x0090;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÂZOO"
+
+#data
+FOO&#x0091;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‘ZOO"
+
+#data
+FOO&#x0092;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO’ZOO"
+
+#data
+FOO&#x0093;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO“ZOO"
+
+#data
+FOO&#x0094;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOâ€ZOO"
+
+#data
+FOO&#x0095;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO•ZOO"
+
+#data
+FOO&#x0096;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO–ZOO"
+
+#data
+FOO&#x0097;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO—ZOO"
+
+#data
+FOO&#x0098;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOËœZOO"
+
+#data
+FOO&#x0099;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOâ„¢ZOO"
+
+#data
+FOO&#x009A;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÅ¡ZOO"
+
+#data
+FOO&#x009B;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO›ZOO"
+
+#data
+FOO&#x009C;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÅ“ZOO"
+
+#data
+FOO&#x009D;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOÂZOO"
+
+#data
+FOO&#x009E;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOžZOO"
+
+#data
+FOO&#x009F;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŸZOO"
+
+#data
+FOO&#x00A0;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO ZOO"
+
+#data
+FOO&#xD7FF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO퟿ZOO"
+
+#data
+FOO&#xD800;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xD801;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xDFFE;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xDFFF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xE000;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x10FFFE;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOô¿¾ZOO"
+
+#data
+FOO&#x1087D4;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􈟔ZOO"
+
+#data
+FOO&#x10FFFF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOô¿¿ZOO"
+
+#data
+FOO&#x110000;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xFFFFFF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#11111111111
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+(1,13): eof-in-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�"
+
+#data
+FOO&#1111111111
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+(1,13): eof-in-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�"
+
+#data
+FOO&#111111111111
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+(1,13): eof-in-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�"
+
+#data
+FOO&#11111111111ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#1111111111ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#111111111111ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities02.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities02.dat
new file mode 100644
index 0000000000..f117f068a0
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/entities02.dat
@@ -0,0 +1,283 @@
+#data
+<div bar="ZZ&gt;YY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>YY"
+
+#data
+<div bar="ZZ&"></div>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar='ZZ&'></div>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar=ZZ&></div>
+#errors
+(1,13): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar="ZZ&gt=YY"></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt=YY"
+
+#data
+<div bar="ZZ&gt0YY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt0YY"
+
+#data
+<div bar="ZZ&gt9YY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt9YY"
+
+#data
+<div bar="ZZ&gtaYY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gtaYY"
+
+#data
+<div bar="ZZ&gtZYY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gtZYY"
+
+#data
+<div bar="ZZ&gt YY"></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ> YY"
+
+#data
+<div bar="ZZ&gt"></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,17): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar='ZZ&gt'></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,17): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar=ZZ&gt></div>
+#errors
+(1,14): named-entity-without-semicolon
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar="ZZ&pound_id=23"></div>
+#errors
+(1,18): named-entity-without-semicolon
+(1,26): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ£_id=23"
+
+#data
+<div bar="ZZ&prod_id=23"></div>
+#errors
+(1,25): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&prod_id=23"
+
+#data
+<div bar="ZZ&pound;_id=23"></div>
+#errors
+(1,27): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ£_id=23"
+
+#data
+<div bar="ZZ&prod;_id=23"></div>
+#errors
+(1,26): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZâˆ_id=23"
+
+#data
+<div bar="ZZ&pound=23"></div>
+#errors
+(1,18): named-entity-without-semicolon
+(1,23): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&pound=23"
+
+#data
+<div bar="ZZ&prod=23"></div>
+#errors
+(1,22): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&prod=23"
+
+#data
+<div>ZZ&pound_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£_id=23"
+
+#data
+<div>ZZ&prod_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ&prod_id=23"
+
+#data
+<div>ZZ&pound;_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£_id=23"
+
+#data
+<div>ZZ&prod;_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZâˆ_id=23"
+
+#data
+<div>ZZ&pound=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£=23"
+
+#data
+<div>ZZ&prod=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ&prod=23"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/foreign-fragment.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/foreign-fragment.dat
new file mode 100644
index 0000000000..2e3cb6c6f6
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/foreign-fragment.dat
@@ -0,0 +1,550 @@
+#data
+<nobr>X
+#errors
+6: HTML start tag “nobr†in a foreign namespace context.
+7: End of file seen and there were open elements.
+6: Unclosed element “nobrâ€.
+#document-fragment
+svg path
+#document
+| <svg nobr>
+| "X"
+
+#data
+<font color></font>X
+#errors
+12: HTML start tag “font†in a foreign namespace context.
+#document-fragment
+svg path
+#document
+| <svg font>
+| color=""
+| "X"
+
+#data
+<font></font>X
+#errors
+#document-fragment
+svg path
+#document
+| <svg font>
+| "X"
+
+#data
+<g></path>X
+#errors
+10: End tag “path†did not match the name of the current open element (“gâ€).
+11: End of file seen and there were open elements.
+3: Unclosed element “gâ€.
+#document-fragment
+svg path
+#document
+| <svg g>
+| "X"
+
+#data
+</path>X
+#errors
+5: Stray end tag “pathâ€.
+#document-fragment
+svg path
+#document
+| "X"
+
+#data
+</foreignObject>X
+#errors
+5: Stray end tag “foreignobjectâ€.
+#document-fragment
+svg foreignObject
+#document
+| "X"
+
+#data
+</desc>X
+#errors
+5: Stray end tag “descâ€.
+#document-fragment
+svg desc
+#document
+| "X"
+
+#data
+</title>X
+#errors
+5: Stray end tag “titleâ€.
+#document-fragment
+svg title
+#document
+| "X"
+
+#data
+</svg>X
+#errors
+5: Stray end tag “svgâ€.
+#document-fragment
+svg svg
+#document
+| "X"
+
+#data
+</mfenced>X
+#errors
+5: Stray end tag “mfencedâ€.
+#document-fragment
+math mfenced
+#document
+| "X"
+
+#data
+</malignmark>X
+#errors
+5: Stray end tag “malignmarkâ€.
+#document-fragment
+math malignmark
+#document
+| "X"
+
+#data
+</math>X
+#errors
+5: Stray end tag “mathâ€.
+#document-fragment
+math math
+#document
+| "X"
+
+#data
+</annotation-xml>X
+#errors
+5: Stray end tag “annotation-xmlâ€.
+#document-fragment
+math annotation-xml
+#document
+| "X"
+
+#data
+</mtext>X
+#errors
+5: Stray end tag “mtextâ€.
+#document-fragment
+math mtext
+#document
+| "X"
+
+#data
+</mi>X
+#errors
+5: Stray end tag “miâ€.
+#document-fragment
+math mi
+#document
+| "X"
+
+#data
+</mo>X
+#errors
+5: Stray end tag “moâ€.
+#document-fragment
+math mo
+#document
+| "X"
+
+#data
+</mn>X
+#errors
+5: Stray end tag “mnâ€.
+#document-fragment
+math mn
+#document
+| "X"
+
+#data
+</ms>X
+#errors
+5: Stray end tag “msâ€.
+#document-fragment
+math ms
+#document
+| "X"
+
+#data
+<b></b><mglyph/><i></i><malignmark/><u></u><ms/>X
+#errors
+51: Self-closing syntax (“/>â€) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
+52: End of file seen and there were open elements.
+51: Unclosed element “msâ€.
+#document-fragment
+math ms
+#document
+| <b>
+| <math mglyph>
+| <i>
+| <math malignmark>
+| <u>
+| <ms>
+| "X"
+
+#data
+<malignmark></malignmark>
+#errors
+#document-fragment
+math ms
+#document
+| <math malignmark>
+
+#data
+<div></div>
+#errors
+#document-fragment
+math ms
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math ms
+#document
+| <figure>
+
+#data
+<b></b><mglyph/><i></i><malignmark/><u></u><mn/>X
+#errors
+51: Self-closing syntax (“/>â€) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
+52: End of file seen and there were open elements.
+51: Unclosed element “mnâ€.
+#document-fragment
+math mn
+#document
+| <b>
+| <math mglyph>
+| <i>
+| <math malignmark>
+| <u>
+| <mn>
+| "X"
+
+#data
+<malignmark></malignmark>
+#errors
+#document-fragment
+math mn
+#document
+| <math malignmark>
+
+#data
+<div></div>
+#errors
+#document-fragment
+math mn
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math mn
+#document
+| <figure>
+
+#data
+<b></b><mglyph/><i></i><malignmark/><u></u><mo/>X
+#errors
+51: Self-closing syntax (“/>â€) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
+52: End of file seen and there were open elements.
+51: Unclosed element “moâ€.
+#document-fragment
+math mo
+#document
+| <b>
+| <math mglyph>
+| <i>
+| <math malignmark>
+| <u>
+| <mo>
+| "X"
+
+#data
+<malignmark></malignmark>
+#errors
+#document-fragment
+math mo
+#document
+| <math malignmark>
+
+#data
+<div></div>
+#errors
+#document-fragment
+math mo
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math mo
+#document
+| <figure>
+
+#data
+<b></b><mglyph/><i></i><malignmark/><u></u><mi/>X
+#errors
+51: Self-closing syntax (“/>â€) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
+52: End of file seen and there were open elements.
+51: Unclosed element “miâ€.
+#document-fragment
+math mi
+#document
+| <b>
+| <math mglyph>
+| <i>
+| <math malignmark>
+| <u>
+| <mi>
+| "X"
+
+#data
+<malignmark></malignmark>
+#errors
+#document-fragment
+math mi
+#document
+| <math malignmark>
+
+#data
+<div></div>
+#errors
+#document-fragment
+math mi
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math mi
+#document
+| <figure>
+
+#data
+<b></b><mglyph/><i></i><malignmark/><u></u><mtext/>X
+#errors
+51: Self-closing syntax (“/>â€) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
+52: End of file seen and there were open elements.
+51: Unclosed element “mtextâ€.
+#document-fragment
+math mtext
+#document
+| <b>
+| <math mglyph>
+| <i>
+| <math malignmark>
+| <u>
+| <mtext>
+| "X"
+
+#data
+<malignmark></malignmark>
+#errors
+#document-fragment
+math mtext
+#document
+| <math malignmark>
+
+#data
+<div></div>
+#errors
+#document-fragment
+math mtext
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math mtext
+#document
+| <figure>
+
+#data
+<div></div>
+#errors
+5: HTML start tag “div†in a foreign namespace context.
+#document-fragment
+math annotation-xml
+#document
+| <math div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math annotation-xml
+#document
+| <math figure>
+
+#data
+<div></div>
+#errors
+5: HTML start tag “div†in a foreign namespace context.
+#document-fragment
+math math
+#document
+| <math div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+math math
+#document
+| <math figure>
+
+#data
+<div></div>
+#errors
+#document-fragment
+svg foreignObject
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+svg foreignObject
+#document
+| <figure>
+
+#data
+<div></div>
+#errors
+#document-fragment
+svg title
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+svg title
+#document
+| <figure>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+svg desc
+#document
+| <figure>
+
+#data
+<div><h1>X</h1></div>
+#errors
+5: HTML start tag “div†in a foreign namespace context.
+9: HTML start tag “h1†in a foreign namespace context.
+#document-fragment
+svg svg
+#document
+| <svg div>
+| <svg h1>
+| "X"
+
+#data
+<div></div>
+#errors
+5: HTML start tag “div†in a foreign namespace context.
+#document-fragment
+svg svg
+#document
+| <svg div>
+
+#data
+<div></div>
+#errors
+#document-fragment
+svg desc
+#document
+| <div>
+
+#data
+<figure></figure>
+#errors
+#document-fragment
+svg desc
+#document
+| <figure>
+
+#data
+<plaintext><foo>
+#errors
+16: End of file seen and there were open elements.
+11: Unclosed element “plaintextâ€.
+#document-fragment
+svg desc
+#document
+| <plaintext>
+| "<foo>"
+
+#data
+<frameset>X
+#errors
+6: Stray start tag “framesetâ€.
+#document-fragment
+svg desc
+#document
+| "X"
+
+#data
+<head>X
+#errors
+6: Stray start tag “headâ€.
+#document-fragment
+svg desc
+#document
+| "X"
+
+#data
+<body>X
+#errors
+6: Stray start tag “bodyâ€.
+#document-fragment
+svg desc
+#document
+| "X"
+
+#data
+<html>X
+#errors
+6: Stray start tag “htmlâ€.
+#document-fragment
+svg desc
+#document
+| "X"
+
+#data
+<html class="foo">X
+#errors
+6: Stray start tag “htmlâ€.
+#document-fragment
+svg desc
+#document
+| "X"
+
+#data
+<body class="foo">X
+#errors
+6: Stray start tag “bodyâ€.
+#document-fragment
+svg desc
+#document
+| "X"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_license.txt b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_license.txt
new file mode 100644
index 0000000000..63faa963ea
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_license.txt
@@ -0,0 +1,21 @@
+Copyright (c) 2006-2010 The Authors
+
+Contributors:
+James Graham - jg307@cam.ac.uk
+Anne van Kesteren - annevankesteren@gmail.com
+Lachlan Hunt - lachlan.hunt@lachy.id.au
+Matt McDonald - kanashii@kanashii.ca
+Sam Ruby - rubys@intertwingly.net
+Ian Hickson (Google) - ian@hixie.ch
+Thomas Broyer - t.broyer@ltgt.net
+Jacques Distler - distler@golem.ph.utexas.edu
+Henri Sivonen - hsivonen@iki.fi
+Adam Barth - abarth@webkit.org
+Eric Seidel - eric@webkit.org
+The Mozilla Foundation (contributions from Henri Sivonen since 2008)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_upstream.txt b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_upstream.txt
new file mode 100644
index 0000000000..5b466c614c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5lib_upstream.txt
@@ -0,0 +1,11 @@
+The test data in this directory comes from the html5lib project
+(http://code.google.com/p/html5lib/). Please avoid making
+mozilla-central-specific changes to these files. If Gecko doesn't pass a test,
+please add the test's input data to ../html5_tree_construction_exceptions.js
+instead of removing it.
+
+If you add or edit tests, please push the test to upstream and then
+resynchronize this directory with the upstream.
+
+See html5lib_license.txt for the license that covers the files in this
+directory.
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5test-com.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5test-com.dat
new file mode 100644
index 0000000000..8c6ec40cd7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/html5test-com.dat
@@ -0,0 +1,291 @@
+#data
+<div<div>
+#errors
+(1,9): expected-doctype-but-got-start-tag
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div<div>
+
+#data
+<div foo<bar=''>
+#errors
+(1,9): invalid-character-in-attribute-name
+(1,16): expected-doctype-but-got-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo<bar=""
+
+#data
+<div foo=`bar`>
+#errors
+(1,10): equals-in-unquoted-attribute-value
+(1,14): unexpected-character-in-unquoted-attribute-value
+(1,15): expected-doctype-but-got-start-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo="`bar`"
+
+#data
+<div \"foo=''>
+#errors
+(1,7): invalid-character-in-attribute-name
+(1,14): expected-doctype-but-got-start-tag
+(1,14): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| \"foo=""
+
+#data
+<a href='\nbar'></a>
+#errors
+(1,16): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="\nbar"
+
+#data
+<!DOCTYPE html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+&lang;&rang;
+#errors
+(1,6): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "⟨⟩"
+
+#data
+&apos;
+#errors
+(1,6): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "'"
+
+#data
+&ImaginaryI;
+#errors
+(1,12): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "â…ˆ"
+
+#data
+&Kopf;
+#errors
+(1,6): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "ð•‚"
+
+#data
+&notinva;
+#errors
+(1,9): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "∉"
+
+#data
+<?import namespace="foo" implementation="#bar">
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,47): expected-doctype-but-got-eof
+#document
+| <!-- ?import namespace="foo" implementation="#bar" -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!--foo--bar-->
+#errors
+(1,10): unexpected-char-in-comment
+(1,15): expected-doctype-but-got-eof
+#document
+| <!-- foo--bar -->
+| <html>
+| <head>
+| <body>
+
+#data
+<![CDATA[x]]>
+#errors
+(1,2): expected-dashes-or-doctype
+(1,13): expected-doctype-but-got-eof
+#document
+| <!-- [CDATA[x]] -->
+| <html>
+| <head>
+| <body>
+
+#data
+<textarea><!--</textarea>--></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,39): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--"
+| "-->"
+
+#data
+<textarea><!--</textarea>-->
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--"
+| "-->"
+
+#data
+<style><!--</style>--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<style><!--</style>-->
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<ul><li>A </li> <li>B</li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| "A "
+| " "
+| <li>
+| "B"
+
+#data
+<table><form><input type=hidden><input></form><div></div></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,13): unexpected-form-in-table
+(1,32): unexpected-hidden-input-in-table
+(1,39): unexpected-start-tag-implies-table-voodoo
+(1,46): unexpected-end-tag-implies-table-voodoo
+(1,46): unexpected-end-tag
+(1,51): unexpected-start-tag-implies-table-voodoo
+(1,57): unexpected-end-tag-implies-table-voodoo
+#document
+| <html>
+| <head>
+| <body>
+| <input>
+| <div>
+| <table>
+| <form>
+| <input>
+| type="hidden"
+
+#data
+<i>A<b>B<p></i>C</b>D
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+(1,20): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <i>
+| "A"
+| <b>
+| "B"
+| <b>
+| <p>
+| <b>
+| <i>
+| "C"
+| "D"
+
+#data
+<div></div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<svg></svg>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<math></math>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/inbody01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/inbody01.dat
new file mode 100644
index 0000000000..10f6520f6f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/inbody01.dat
@@ -0,0 +1,54 @@
+#data
+<button>1</foo>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,15): unexpected-end-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| "1"
+
+#data
+<foo>1<p>2</foo>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,16): unexpected-end-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| "1"
+| <p>
+| "2"
+
+#data
+<dd>1</foo>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <dd>
+| "1"
+
+#data
+<foo>1<dd>2</foo>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): unexpected-end-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| "1"
+| <dd>
+| "2"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/isindex.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/isindex.dat
new file mode 100644
index 0000000000..733f82ea8e
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/isindex.dat
@@ -0,0 +1,49 @@
+#data
+<isindex>
+#errors
+(1,9): expected-doctype-but-got-start-tag
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <isindex>
+
+#data
+<isindex name="A" action="B" prompt="C" foo="D">
+#errors
+(1,48): expected-doctype-but-got-start-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <isindex>
+| action="B"
+| foo="D"
+| name="A"
+| prompt="C"
+
+#data
+<form><isindex>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <isindex>
+
+#data
+<!doctype html><isindex>x</isindex>x
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <isindex>
+| "x"
+| "x"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/main-element.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/main-element.dat
new file mode 100644
index 0000000000..0d2102ed3f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/main-element.dat
@@ -0,0 +1,44 @@
+#data
+<!doctype html><p>foo<main>bar<p>baz
+#errors
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+| <main>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!doctype html><main><p>foo</main>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <main>
+| <p>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html>xxx<svg><x><g><a><main><b>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "xxx"
+| <svg svg>
+| <svg x>
+| <svg g>
+| <svg a>
+| <svg main>
+| <b>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes-plain-text-unsafe.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes-plain-text-unsafe.dat
new file mode 100644
index 0000000000..3ee8cec904
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes-plain-text-unsafe.dat
Binary files differ
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes.dat
new file mode 100644
index 0000000000..1647d7f23a
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/pending-spec-changes.dat
@@ -0,0 +1,46 @@
+#data
+<input type="hidden"><frameset>
+#errors
+(1,21): expected-doctype-but-got-start-tag
+(1,31): unexpected-start-tag
+(1,31): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><table><caption><svg>foo</table>bar
+#errors
+(1,47): unexpected-end-tag
+(1,47): end-table-tag-in-caption
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| "foo"
+| "bar"
+
+#data
+<table><tr><td><svg><desc><td></desc><circle>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): unexpected-cell-end-tag
+(1,37): unexpected-end-tag
+(1,45): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
+| <circle>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/plain-text-unsafe.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/plain-text-unsafe.dat
new file mode 100644
index 0000000000..f40dd57607
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/plain-text-unsafe.dat
Binary files differ
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/ruby.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/ruby.dat
new file mode 100644
index 0000000000..1ca8016cf1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/ruby.dat
@@ -0,0 +1,298 @@
+#data
+<html><ruby>a<rb>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rb>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rb>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rb>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rb>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <span>
+
+#data
+<html><ruby>a<rt>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rt>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rt>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rt>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rt>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <span>
+
+#data
+<html><ruby>a<rtc>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rtc>b<rt>c<rt>d</ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rt>
+| "c"
+| <rt>
+| "d"
+
+#data
+<html><ruby>a<rtc>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rtc>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rtc>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <span>
+
+#data
+<html><ruby>a<rp>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rp>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rp>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rp>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rp>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <span>
+
+#data
+<html><ruby><rtc><ruby>a<rb>b<rt></ruby></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <rtc>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rt>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scriptdata01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scriptdata01.dat
new file mode 100644
index 0000000000..710f5414b6
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scriptdata01.dat
@@ -0,0 +1,352 @@
+#data
+FOO<script>'Hello'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'Hello'"
+| "BAR"
+
+#data
+FOO<script></script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script >BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script/>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,21): self-closing-flag-on-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script/ >BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,20): unexpected-character-after-solidus-in-tag
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script type="text/plain"></scriptx>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,42): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "</scriptx>BAR"
+
+#data
+FOO<script></script foo=">" dd>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,31): attributes-in-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script>'<'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<'"
+| "BAR"
+
+#data
+FOO<script>'<!'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!'"
+| "BAR"
+
+#data
+FOO<script>'<!-'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-'"
+| "BAR"
+
+#data
+FOO<script>'<!--'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!--'"
+| "BAR"
+
+#data
+FOO<script>'<!---'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!---'"
+| "BAR"
+
+#data
+FOO<script>'<!-->'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-->'"
+| "BAR"
+
+#data
+FOO<script>'<!-->'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-->'"
+| "BAR"
+
+#data
+FOO<script>'<!-- potato'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- potato'"
+| "BAR"
+
+#data
+FOO<script>'<!-- <sCrIpt'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- <sCrIpt'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt>'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,56): expected-script-data-but-got-eof
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt>'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> -'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,58): expected-script-data-but-got-eof
+(1,58): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> -'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> --'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,59): expected-script-data-but-got-eof
+(1,59): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> --'</script>BAR"
+
+#data
+FOO<script>'<!-- <sCrIpt> -->'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- <sCrIpt> -->'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> --!>'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,61): expected-script-data-but-got-eof
+(1,61): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> --!>'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> -- >'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,61): expected-script-data-but-got-eof
+(1,61): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> -- >'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt '</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,56): expected-script-data-but-got-eof
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt '</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,56): expected-script-data-but-got-eof
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt/'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt\'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt\'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR</script>QUX
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt/'</script>BAR"
+| "QUX"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/adoption01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/adoption01.dat
new file mode 100644
index 0000000000..4e08d0e84a
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/adoption01.dat
@@ -0,0 +1,15 @@
+#data
+<p><b id="A"><script>document.getElementById("A").id = "B"</script></p>TEXT</b>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| id="B"
+| <script>
+| "document.getElementById("A").id = "B""
+| <b>
+| id="A"
+| "TEXT"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/ark.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/ark.dat
new file mode 100644
index 0000000000..acbac41df1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/ark.dat
@@ -0,0 +1,26 @@
+#data
+<p><font size=4><font size=4><font size=4><script>document.getElementsByTagName("font")[2].setAttribute("size", "5");</script><font size=4><p>X
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <script>
+| "document.getElementsByTagName("font")[2].setAttribute("size", "5");"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/webkit01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/webkit01.dat
new file mode 100644
index 0000000000..ef4a41ca00
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/scripted/webkit01.dat
@@ -0,0 +1,28 @@
+#data
+1<script>document.write("2")</script>3
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "1"
+| <script>
+| "document.write("2")"
+| "23"
+
+#data
+1<script>document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")</script>4
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "1"
+| <script>
+| "document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")"
+| <script>
+| "document.write('2')"
+| "2"
+| <script>
+| "document.write('3')"
+| "34"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tables01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tables01.dat
new file mode 100644
index 0000000000..f0caaa3c5f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tables01.dat
@@ -0,0 +1,286 @@
+#data
+<table><th>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,11): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <th>
+
+#data
+<table><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,11): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><col foo='bar'>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| foo="bar"
+
+#data
+<table><colgroup></html>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,24): unexpected-end-tag
+(1,27): foster-parenting-character-in-table
+(1,27): foster-parenting-character-in-table
+(1,27): foster-parenting-character-in-table
+(1,27): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "foo"
+| <table>
+| <colgroup>
+
+#data
+<table></table><p>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <p>
+| "foo"
+
+#data
+<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,30): unexpected-end-tag
+(1,41): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,56): unexpected-end-tag
+(1,61): unexpected-end-tag
+(1,69): unexpected-end-tag
+(1,74): unexpected-end-tag
+(1,82): unexpected-end-tag
+(1,87): unexpected-end-tag
+(1,91): unexpected-cell-in-table-body
+(1,91): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><select><option>3</select></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "3"
+| <table>
+
+#data
+<table><select><table></table></select></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+(1,22): unexpected-table-element-start-tag-in-select-in-table
+(1,22): unexpected-start-tag-implies-end-tag
+(1,39): unexpected-end-tag
+(1,47): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <table>
+
+#data
+<table><select></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+(1,23): unexpected-table-element-end-tag-in-select-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+
+#data
+<table><select><option>A<tr><td>B</td></tr></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+(1,28): unexpected-table-element-start-tag-in-select-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "A"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "B"
+
+#data
+<table><td></body></caption></col></colgroup></html>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,18): unexpected-end-tag
+(1,28): unexpected-end-tag
+(1,34): unexpected-end-tag
+(1,45): unexpected-end-tag
+(1,52): unexpected-end-tag
+(1,55): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "foo"
+
+#data
+<table><td>A</table>B
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+| "B"
+
+#data
+<table><tr><caption>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <caption>
+
+#data
+<table><tr></body></caption></col></colgroup></html></td></th><td>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag-in-table-row
+(1,28): unexpected-end-tag-in-table-row
+(1,34): unexpected-end-tag-in-table-row
+(1,45): unexpected-end-tag-in-table-row
+(1,52): unexpected-end-tag-in-table-row
+(1,57): unexpected-end-tag-in-table-row
+(1,62): unexpected-end-tag-in-table-row
+(1,69): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "foo"
+
+#data
+<table><td><tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,15): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <tr>
+
+#data
+<table><td><button><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,23): unexpected-cell-end-tag
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <button>
+| <td>
+
+#data
+<table><tr><td><svg><desc><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): unexpected-cell-end-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/template.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/template.dat
new file mode 100644
index 0000000000..daf587e2d7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/template.dat
@@ -0,0 +1,1406 @@
+#data
+<body><template>Hello</template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| "Hello"
+
+#data
+<template>Hello</template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| "Hello"
+| <body>
+
+#data
+<template></template><div></div>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <body>
+| <div>
+
+#data
+<html><template>Hello</template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| "Hello"
+| <body>
+
+#data
+<head><template><div></div></template></head>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <div>
+| <body>
+
+#data
+<div><template><div><span></template><b>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| <div>
+| <span>
+| <b>
+
+#data
+<div><template></div>Hello
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| "Hello"
+
+#data
+<div></template></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<table><template></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+
+#data
+<table><template></template></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+
+#data
+<table><div><template></template></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| <table>
+
+#data
+<table><template></template><div></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <template>
+| content
+
+#data
+<table> <template></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <template>
+| content
+
+#data
+<table><tbody><template></template></tbody>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <template>
+| content
+
+#data
+<table><tbody><template></tbody></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <template>
+| content
+
+#data
+<table><tbody><template></template></tbody></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <template>
+| content
+
+#data
+<table><thead><template></template></thead>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <template>
+| content
+
+#data
+<table><tfoot><template></template></tfoot>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tfoot>
+| <template>
+| content
+
+#data
+<select><template></template></select>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+
+#data
+<select><template><option></option></template></select>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+| <option>
+
+#data
+<template><option></option></select><option></option></template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <option>
+| <option>
+| <body>
+
+#data
+<select><template></template><option></select>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+| <option>
+
+#data
+<select><option><template></template></select>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <template>
+| content
+
+#data
+<select><template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+
+#data
+<select><option></option><template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <template>
+| content
+
+#data
+<select><option></option><template><option>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <template>
+| content
+| <option>
+
+#data
+<table><thead><template><td></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><thead></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <thead>
+
+#data
+<body><table><template><td></tr><div></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <td>
+| <div>
+
+#data
+<table><template><thead></template></thead></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <thead>
+
+#data
+<table><thead><template><tr></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <template>
+| content
+| <tr>
+
+#data
+<table><template><tr></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <tr>
+
+#data
+<table><tr><template><td>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><tr><template><td></template></tr></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <tr>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><tr><template><td></td></template></tr></template></table>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <tr>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <td>
+
+#data
+<body><template><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <template>
+| content
+| <tr>
+| <td>
+
+#data
+<table><colgroup><template><col>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <template>
+| content
+| <col>
+
+#data
+<frameset><template><frame></frame></template></frameset>
+#errors
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<template><frame></frame></frameset><frame></frame></template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <body>
+
+#data
+<template><div><frameset><span></span></div><span></span></template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <div>
+| <span>
+| <span>
+| <body>
+
+#data
+<body><template><div><frameset><span></span></div><span></span></template></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <div>
+| <span>
+| <span>
+
+#data
+<body><template><script>var i = 1;</script><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <script>
+| "var i = 1;"
+| <td>
+
+#data
+<body><template><tr><div></div></tr></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <div>
+
+#data
+<body><template><tr>Foo</tr></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| "Foo"
+
+#data
+<body><template><tr></tr><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+| <td>
+
+#data
+<body><template><td></td></tr><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td><tbody><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td><caption></caption><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td><colgroup></caption><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td></table><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><tr></tr><tbody><tr></tr></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+
+#data
+<body><template><tr></tr><caption><tr></tr></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+
+#data
+<body><template><tr></tr></table><tr></tr></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+
+#data
+<body><template><thead></thead><caption></caption><tbody></tbody></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <thead>
+| <caption>
+| <tbody>
+
+#data
+<body><template><thead></thead></table><tbody></tbody></template></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <thead>
+| <tbody>
+
+#data
+<body><template><div><tr></tr></div></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <div>
+
+#data
+<body><template><em>Hello</em></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <em>
+| "Hello"
+
+#data
+<body><template><!--comment--></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <!-- comment -->
+
+#data
+<body><template><style></style><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <style>
+| <td>
+
+#data
+<body><template><meta><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <meta>
+| <td>
+
+#data
+<body><template><link><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <link>
+| <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <template>
+| content
+| <tr>
+| <td>
+
+#data
+<body><table><colgroup><template><col></col></template></colgroup></table></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <template>
+| content
+| <col>
+
+#data
+<body a=b><template><div></div><body c=d><div></div></body></template></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| a="b"
+| <template>
+| content
+| <div>
+| <div>
+
+#data
+<html a=b><template><div><html b=c><span></template>
+#errors
+#document
+| <html>
+| a="b"
+| <head>
+| <template>
+| content
+| <div>
+| <span>
+| <body>
+
+#data
+<html a=b><template><col></col><html b=c><col></col></template>
+#errors
+#document
+| <html>
+| a="b"
+| <head>
+| <template>
+| content
+| <col>
+| <col>
+| <body>
+
+#data
+<html a=b><template><frame></frame><html b=c><frame></frame></template>
+#errors
+#document
+| <html>
+| a="b"
+| <head>
+| <template>
+| content
+| <body>
+
+#data
+<body><template><tr></tr><template></template><td></td></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <template>
+| content
+| <tr>
+| <td>
+
+#data
+<body><template><thead></thead><template><tr></tr></template><tr></tr><tfoot></tfoot></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <thead>
+| <template>
+| content
+| <tr>
+| <tbody>
+| <tr>
+| <tfoot>
+
+#data
+<body><template><template><b><template></template></template>text</template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <template>
+| content
+| <b>
+| <template>
+| content
+| "text"
+
+#data
+<body><template><col><colgroup>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col></colgroup>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col><colgroup></template></body>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col><div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col></div>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col>Hello
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><i><menu>Foo</i>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <i>
+| <menu>
+| <i>
+| "Foo"
+
+#data
+<body><template></div><div>Foo</div><template></template><tr></tr>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <div>
+| "Foo"
+| <template>
+| content
+
+#data
+<body><div><template></div><tr><td>Foo</td></tr></template>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| <tr>
+| <td>
+| "Foo"
+
+#data
+<template></figcaption><sub><table></table>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <sub>
+| <table>
+| <body>
+
+#data
+<template><template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <body>
+
+#data
+<template><div>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <div>
+| <body>
+
+#data
+<template><template><div>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <div>
+| <body>
+
+#data
+<template><template><table>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <table>
+| <body>
+
+#data
+<template><template><tbody>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <tbody>
+| <body>
+
+#data
+<template><template><tr>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <tr>
+| <body>
+
+#data
+<template><template><td>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <td>
+| <body>
+
+#data
+<template><template><caption>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <caption>
+| <body>
+
+#data
+<template><template><colgroup>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <colgroup>
+| <body>
+
+#data
+<template><template><col>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <col>
+| <body>
+
+#data
+<template><template><tbody><select>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <tbody>
+| <select>
+| <body>
+
+#data
+<template><template><table>Foo
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| "Foo"
+| <table>
+| <body>
+
+#data
+<template><template><table><div>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <div>
+| <table>
+| <body>
+
+#data
+<template><template><frame>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <body>
+
+#data
+<template><template><script>var i
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <script>
+| "var i"
+| <body>
+
+#data
+<template><template><style>var i
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <style>
+| "var i"
+| <body>
+
+#data
+<template><table></template><body><span>Foo
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <table>
+| <body>
+| <span>
+| "Foo"
+
+#data
+<template><td></template><body><span>Foo
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <td>
+| <body>
+| <span>
+| "Foo"
+
+#data
+<template><object></template><body><span>Foo
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <object>
+| <body>
+| <span>
+| "Foo"
+
+#data
+<template><svg><template>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <svg svg>
+| <svg template>
+| <body>
+
+#data
+<template><svg><foo><template><foreignObject><div></template><div>
+#errors
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <svg svg>
+| <svg foo>
+| <svg template>
+| <svg foreignObject>
+| <div>
+| <body>
+| <div>
+
+#data
+<dummy><template><span></dummy>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <dummy>
+| <template>
+| content
+| <span>
+
+#data
+<body><table><tr><td><select><template>Foo</template><caption>A</table>
+#errors
+(1,62): unexpected-caption-in-select-in-table
+(1,71): unexpected-table-end-in-caption
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| <template>
+| content
+| "Foo"
+| <caption>
+| "A"
+
+#data
+<body></body><template>
+#errors
+(1,23): template-after-body
+(1,24): eof-in-template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+
+#data
+<head></head><template>
+#errors
+(1,23): template-after-head
+(1,24): eof-in-template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <body>
+
+#data
+<head></head><template>Foo</template>
+#errors
+(1,23): template-after-head
+#document
+| <html>
+| <head>
+| <template>
+| content
+| "Foo"
+| <body>
+
+#data
+<body><form><template><form>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <template>
+| content
+| <form>
+
+#data
+<body><template><table><form>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <table>
+
+#data
+<body><template><form><form>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <form>
+| <form>
+
+#data
+<body><form><template><isindex>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <template>
+| content
+| <isindex>
+
+#data
+<body><form><template><isindex><form>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <template>
+| content
+| <isindex>
+| <form>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests1.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests1.dat
new file mode 100644
index 0000000000..f12e87178c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests1.dat
@@ -0,0 +1,1959 @@
+#data
+Test
+#errors
+(1,0): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<p>One<p>Two
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "One"
+| <p>
+| "Two"
+
+#data
+Line1<br>Line2<br>Line3<br>Line4
+#errors
+(1,0): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "Line1"
+| <br>
+| "Line2"
+| <br>
+| "Line3"
+| <br>
+| "Line4"
+
+#data
+<html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<head>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head><body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head><body></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head><body></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head><body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<head></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</head>
+#errors
+(1,7): expected-doctype-but-got-end-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</body>
+#errors
+(1,7): expected-doctype-but-got-end-tag element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</html>
+#errors
+(1,7): expected-doctype-but-got-end-tag element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<b><table><td><i></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,25): unexpected-cell-end-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<b><table><td></b><i></table>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,18): unexpected-end-tag
+(1,29): unexpected-cell-end-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+| "X"
+
+#data
+<h1>Hello<h2>World
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,13): unexpected-start-tag
+(1,18): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| "Hello"
+| <h2>
+| "World"
+
+#data
+<a><p>X<a>Y</a>Z</p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-implies-end-tag
+(1,10): adoption-agency-1.3
+(1,24): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+| "X"
+| <a>
+| "Y"
+| "Z"
+
+#data
+<b><button>foo</b>bar
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,18): adoption-agency-1.3
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <button>
+| <b>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html><span><button>foo</span>bar
+#errors
+(1,39): unexpected-end-tag
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <span>
+| <button>
+| "foobar"
+
+#data
+<p><b><div><marquee></p></b></div>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,28): unexpected-end-tag
+(1,34): end-tag-too-early
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <div>
+| <b>
+| <marquee>
+| <p>
+| "X"
+
+#data
+<script><div></script></div><title><p></title><p><p>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,28): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<div>"
+| <title>
+| "<p>"
+| <body>
+| <p>
+| <p>
+
+#data
+<!--><div>--<!-->
+#errors
+(1,5): incorrect-comment
+(1,10): expected-doctype-but-got-start-tag
+(1,17): incorrect-comment
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <!-- -->
+| <html>
+| <head>
+| <body>
+| <div>
+| "--"
+| <!-- -->
+
+#data
+<p><hr></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <hr>
+| <p>
+
+#data
+<select><b><option><select><option></b></select>X
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): unexpected-start-tag-in-select
+(1,27): unexpected-select-in-select
+(1,39): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,49): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+| "X"
+
+#data
+<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,35): unexpected-start-tag-implies-end-tag
+(1,40): unexpected-cell-end-tag
+(1,43): unexpected-start-tag-implies-table-voodoo
+(1,43): unexpected-start-tag-implies-end-tag
+(1,43): unexpected-end-tag
+(1,63): unexpected-start-tag-implies-end-tag
+(1,64): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| <table>
+| <a>
+| <a>
+| <b>
+| "X"
+| "C"
+| <a>
+| "Y"
+
+#data
+<a X>0<b>1<a Y>2
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-end-tag
+(1,15): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| x=""
+| "0"
+| <b>
+| "1"
+| <b>
+| <a>
+| y=""
+| "2"
+
+#data
+<!-----><font><div>hello<table>excite!<b>me!<th><i>please!</tr><!--X-->
+#errors
+(1,7): unexpected-dash-after-double-dash-in-comment
+(1,14): expected-doctype-but-got-start-tag
+(1,41): unexpected-start-tag-implies-table-voodoo
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-start-tag-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): unexpected-cell-in-table-body
+(1,63): unexpected-cell-end-tag
+(1,71): eof-in-table
+#document
+| <!-- - -->
+| <html>
+| <head>
+| <body>
+| <font>
+| <div>
+| "helloexcite!"
+| <b>
+| "me!"
+| <table>
+| <tbody>
+| <tr>
+| <th>
+| <i>
+| "please!"
+| <!-- X -->
+
+#data
+<!DOCTYPE html><li>hello<li>world<ul>how<li>do</ul>you</body><!--do-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <li>
+| "hello"
+| <li>
+| "world"
+| <ul>
+| "how"
+| <li>
+| "do"
+| "you"
+| <!-- do -->
+
+#data
+<!DOCTYPE html>A<option>B<optgroup>C<select>D</option>E
+#errors
+(1,54): unexpected-end-tag-in-select
+(1,55): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+| <option>
+| "B"
+| <optgroup>
+| "C"
+| <select>
+| "DE"
+
+#data
+<
+#errors
+(1,1): expected-tag-name
+(1,1): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "<"
+
+#data
+<#
+#errors
+(1,1): expected-tag-name
+(1,1): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "<#"
+
+#data
+</
+#errors
+(1,2): expected-closing-tag-but-got-eof
+(1,2): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "</"
+
+#data
+</#
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,3): expected-doctype-but-got-eof
+#document
+| <!-- # -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,2): expected-doctype-but-got-eof
+#document
+| <!-- ? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?#
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,3): expected-doctype-but-got-eof
+#document
+| <!-- ?# -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!
+#errors
+(1,2): expected-dashes-or-doctype
+(1,2): expected-doctype-but-got-eof
+#document
+| <!-- -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!#
+#errors
+(1,2): expected-dashes-or-doctype
+(1,3): expected-doctype-but-got-eof
+#document
+| <!-- # -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?COMMENT?>
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,11): expected-doctype-but-got-eof
+#document
+| <!-- ?COMMENT? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!COMMENT>
+#errors
+(1,2): expected-dashes-or-doctype
+(1,10): expected-doctype-but-got-eof
+#document
+| <!-- COMMENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+</ COMMENT >
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,12): expected-doctype-but-got-eof
+#document
+| <!-- COMMENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?COM--MENT?>
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,13): expected-doctype-but-got-eof
+#document
+| <!-- ?COM--MENT? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!COM--MENT>
+#errors
+(1,2): expected-dashes-or-doctype
+(1,12): expected-doctype-but-got-eof
+#document
+| <!-- COM--MENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+</ COM--MENT >
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,14): expected-doctype-but-got-eof
+#document
+| <!-- COM--MENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><style> EOF
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| " EOF"
+| <body>
+
+#data
+<!DOCTYPE html><script> <!-- </script> --> </script> EOF
+#errors
+(1,52): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| " <!-- "
+| " "
+| <body>
+| "--> EOF"
+
+#data
+<b><p></b>TEST
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <p>
+| <b>
+| "TEST"
+
+#data
+<p id=a><b><p id=b></b>TEST
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,19): unexpected-end-tag
+(1,23): adoption-agency-1.2
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="a"
+| <b>
+| <p>
+| id="b"
+| "TEST"
+
+#data
+<b id=a><p><b id=b></p></b>TEST
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+(1,27): adoption-agency-1.2
+(1,31): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| id="a"
+| <p>
+| <b>
+| id="b"
+| "TEST"
+
+#data
+<!DOCTYPE html><title>U-test</title><body><div><p>Test<u></p></div></body>
+#errors
+(1,61): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "U-test"
+| <body>
+| <div>
+| <p>
+| "Test"
+| <u>
+
+#data
+<!DOCTYPE html><font><table></font></table></font>
+#errors
+(1,35): unexpected-end-tag-implies-table-voodoo
+(1,35): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <table>
+
+#data
+<font><p>hello<b>cruel</font>world
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,29): adoption-agency-1.3
+(1,29): adoption-agency-1.3
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <font>
+| "hello"
+| <b>
+| "cruel"
+| <b>
+| "world"
+
+#data
+<b>Test</i>Test
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "TestTest"
+
+#data
+<b>A<cite>B<div>C
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| "C"
+
+#data
+<b>A<cite>B<div>C</cite>D
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,24): unexpected-end-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| "CD"
+
+#data
+<b>A<cite>B<div>C</b>D
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,21): adoption-agency-1.3
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| <b>
+| "C"
+| "D"
+
+#data
+
+#errors
+(1,0): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<DIV>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,5): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<DIV> abc
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc"
+
+#data
+<DIV> abc <B>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+
+#data
+<DIV> abc <B> def
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def"
+
+#data
+<DIV> abc <B> def <I>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+
+#data
+<DIV> abc <B> def <I> ghi
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi"
+
+#data
+<DIV> abc <B> def <I> ghi <P>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <p>
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <p>
+| " jkl"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <b>
+| " jkl "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <b>
+| " jkl "
+| " mno"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,47): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,51): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,56): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> stu
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,60): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr "
+| " stu"
+
+#data
+<test attribute---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+#errors
+(1,1040): expected-doctype-but-got-start-tag
+(1,1040): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <test>
+| attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------=""
+
+#data
+<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe
+#errors
+(1,15): expected-doctype-but-got-start-tag
+(1,39): unexpected-start-tag-implies-table-voodoo
+(1,39): unexpected-start-tag-implies-end-tag
+(1,39): unexpected-end-tag
+(1,45): foster-parenting-character-in-table
+(1,45): foster-parenting-character-in-table
+(1,68): foster-parenting-character-in-table
+(1,71): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "aba"
+| <a>
+| href="foo"
+| "br"
+| <a>
+| href="foo"
+| "x"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "aoe"
+
+#data
+<a href="blah">aba<table><tr><td><a href="foo">br</td></tr>x</table>aoe
+#errors
+(1,15): expected-doctype-but-got-start-tag
+(1,54): unexpected-cell-end-tag
+(1,71): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "abax"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "br"
+| "aoe"
+
+#data
+<table><a href="blah">aba<tr><td><a href="foo">br</td></tr>x</table>aoe
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): unexpected-start-tag-implies-table-voodoo
+(1,29): foster-parenting-character-in-table
+(1,29): foster-parenting-character-in-table
+(1,29): foster-parenting-character-in-table
+(1,54): unexpected-cell-end-tag
+(1,68): foster-parenting-character-in-table
+(1,71): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "aba"
+| <a>
+| href="blah"
+| "x"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "br"
+| <a>
+| href="blah"
+| "aoe"
+
+#data
+<a href=a>aa<marquee>aa<a href=b>bb</marquee>aa
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,45): end-tag-too-early
+(1,47): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="a"
+| "aa"
+| <marquee>
+| "aa"
+| <a>
+| href="b"
+| "bb"
+| "aa"
+
+#data
+<wbr><strike><code></strike><code><strike></code>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,28): adoption-agency-1.3
+(1,49): adoption-agency-1.3
+(1,49): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <wbr>
+| <strike>
+| <code>
+| <code>
+| <code>
+| <strike>
+
+#data
+<!DOCTYPE html><spacer>foo
+#errors
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <spacer>
+| "foo"
+
+#data
+<title><meta></title><link><title><meta></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<meta>"
+| <link>
+| <title>
+| "<meta>"
+| <body>
+
+#data
+<style><!--</style><meta><script>--><link></script>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <meta>
+| <script>
+| "--><link>"
+| <body>
+
+#data
+<head><meta></head><link>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,25): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <meta>
+| <link>
+| <body>
+
+#data
+<table><tr><tr><td><td><span><th><span>X</table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,33): unexpected-cell-end-tag
+(1,48): unexpected-cell-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <tr>
+| <td>
+| <td>
+| <span>
+| <th>
+| <span>
+| "X"
+
+#data
+<body><body><base><link><meta><title><p></title><body><p></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,12): unexpected-start-tag
+(1,54): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <base>
+| <link>
+| <meta>
+| <title>
+| "<p>"
+| <p>
+
+#data
+<textarea><p></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<p>"
+
+#data
+<p><image></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-treated-as
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <img>
+
+#data
+<a><table><a></table><p><a><div><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,13): unexpected-start-tag-implies-table-voodoo
+(1,13): unexpected-start-tag-implies-end-tag
+(1,13): adoption-agency-1.3
+(1,27): unexpected-start-tag-implies-end-tag
+(1,27): adoption-agency-1.2
+(1,32): unexpected-end-tag
+(1,35): unexpected-start-tag-implies-end-tag
+(1,35): adoption-agency-1.2
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <p>
+| <a>
+| <div>
+| <a>
+
+#data
+<head></p><meta><p>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,10): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <meta>
+| <body>
+| <p>
+
+#data
+<head></html><meta><p>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,19): expected-eof-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <meta>
+| <p>
+
+#data
+<b><table><td><i></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,25): unexpected-cell-end-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<b><table><td></b><i></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,18): unexpected-end-tag
+(1,29): unexpected-cell-end-tag
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<h1><h2>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,8): unexpected-start-tag
+(1,8): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| <h2>
+
+#data
+<a><p><a></a></p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,9): unexpected-start-tag-implies-end-tag
+(1,9): adoption-agency-1.3
+(1,21): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+| <a>
+
+#data
+<b><button></b></button></b>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+(1,28): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <button>
+| <b>
+
+#data
+<p><b><div><marquee></p></b></div>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,28): unexpected-end-tag
+(1,34): end-tag-too-early
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <div>
+| <b>
+| <marquee>
+| <p>
+
+#data
+<script></script></div><title></title><p><p>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| <title>
+| <body>
+| <p>
+| <p>
+
+#data
+<p><hr></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <hr>
+| <p>
+
+#data
+<select><b><option><select><option></b></select>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): unexpected-start-tag-in-select
+(1,27): unexpected-select-in-select
+(1,39): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+
+#data
+<html><head><title></title><body></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| <body>
+
+#data
+<a><table><td><a><table></table><a></tr><a></table><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,35): unexpected-start-tag-implies-end-tag
+(1,40): unexpected-cell-end-tag
+(1,43): unexpected-start-tag-implies-table-voodoo
+(1,43): unexpected-start-tag-implies-end-tag
+(1,43): unexpected-end-tag
+(1,54): unexpected-start-tag-implies-end-tag
+(1,54): adoption-agency-1.2
+(1,54): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| <table>
+| <a>
+| <a>
+
+#data
+<ul><li></li><div><li></div><li><li><div><li><address><li><b><em></b><li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,45): end-tag-too-early
+(1,58): end-tag-too-early
+(1,69): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| <li>
+| <li>
+| <li>
+| <div>
+| <li>
+| <address>
+| <li>
+| <b>
+| <em>
+| <li>
+
+#data
+<ul><li><ul></li><li>a</li></ul></li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,17): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <ul>
+| <li>
+| "a"
+
+#data
+<frameset><frame><frameset><frame></frameset><noframes></noframes></frameset>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+| <frameset>
+| <frame>
+| <noframes>
+
+#data
+<h1><table><td><h3></table><h3></h1>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,15): unexpected-cell-in-table-body
+(1,27): unexpected-cell-end-tag
+(1,31): unexpected-start-tag
+(1,36): end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <h3>
+| <h3>
+
+#data
+<table><colgroup><col><colgroup><col><col><col><colgroup><col><col><thead><tr><td></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| <colgroup>
+| <col>
+| <col>
+| <col>
+| <colgroup>
+| <col>
+| <col>
+| <thead>
+| <tr>
+| <td>
+
+#data
+<table><col><tbody><col><tr><col><td><col></table><col>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): unexpected-cell-in-table-body
+(1,55): unexpected-start-tag-ignored
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <td>
+| <colgroup>
+| <col>
+
+#data
+<table><colgroup><tbody><colgroup><tr><colgroup><td><colgroup></table><colgroup>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,52): unexpected-cell-in-table-body
+(1,80): unexpected-start-tag-ignored
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <tbody>
+| <colgroup>
+| <tbody>
+| <tr>
+| <colgroup>
+| <tbody>
+| <tr>
+| <td>
+| <colgroup>
+
+#data
+</strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
+#errors
+(1,9): expected-doctype-but-got-end-tag
+(1,9): unexpected-end-tag-before-html
+(1,13): unexpected-end-tag-before-html
+(1,18): unexpected-end-tag-before-html
+(1,22): unexpected-end-tag-before-html
+(1,26): unexpected-end-tag-before-html
+(1,35): unexpected-end-tag-before-html
+(1,39): unexpected-end-tag-before-html
+(1,47): unexpected-end-tag-before-html
+(1,52): unexpected-end-tag-before-html
+(1,58): unexpected-end-tag-before-html
+(1,64): unexpected-end-tag-before-html
+(1,72): unexpected-end-tag-before-html
+(1,79): unexpected-end-tag-before-html
+(1,88): unexpected-end-tag-before-html
+(1,93): unexpected-end-tag-before-html
+(1,98): unexpected-end-tag-before-html
+(1,103): unexpected-end-tag-before-html
+(1,108): unexpected-end-tag-before-html
+(1,113): unexpected-end-tag-before-html
+(1,118): unexpected-end-tag-before-html
+(1,130): unexpected-end-tag-after-body
+(1,130): unexpected-end-tag-treated-as
+(1,134): unexpected-end-tag
+(1,140): unexpected-end-tag
+(1,148): unexpected-end-tag
+(1,155): unexpected-end-tag
+(1,163): unexpected-end-tag
+(1,172): unexpected-end-tag
+(1,180): unexpected-end-tag
+(1,185): unexpected-end-tag
+(1,190): unexpected-end-tag
+(1,195): unexpected-end-tag
+(1,203): unexpected-end-tag
+(1,210): unexpected-end-tag
+(1,217): unexpected-end-tag
+(1,225): unexpected-end-tag
+(1,230): unexpected-end-tag
+(1,238): unexpected-end-tag
+(1,244): unexpected-end-tag
+(1,251): unexpected-end-tag
+(1,258): unexpected-end-tag
+(1,269): unexpected-end-tag
+(1,279): unexpected-end-tag
+(1,287): unexpected-end-tag
+(1,296): unexpected-end-tag
+(1,300): unexpected-end-tag
+(1,305): unexpected-end-tag
+(1,310): unexpected-end-tag
+(1,320): unexpected-end-tag
+(1,331): unexpected-end-tag
+(1,339): unexpected-end-tag
+(1,347): unexpected-end-tag
+(1,355): unexpected-end-tag
+(1,365): end-tag-too-early
+(1,378): end-tag-too-early
+(1,387): end-tag-too-early
+(1,393): end-tag-too-early
+(1,399): end-tag-too-early
+(1,404): end-tag-too-early
+(1,415): end-tag-too-early
+(1,425): end-tag-too-early
+(1,432): end-tag-too-early
+(1,437): end-tag-too-early
+(1,442): end-tag-too-early
+(1,447): unexpected-end-tag
+(1,454): unexpected-end-tag
+(1,460): unexpected-end-tag
+(1,467): unexpected-end-tag
+(1,476): end-tag-too-early
+(1,486): end-tag-too-early
+(1,495): end-tag-too-early
+(1,513): expected-eof-but-got-end-tag
+(1,513): unexpected-end-tag
+(1,520): unexpected-end-tag
+(1,529): unexpected-end-tag
+(1,537): unexpected-end-tag
+(1,547): unexpected-end-tag
+(1,557): unexpected-end-tag
+(1,568): unexpected-end-tag
+(1,579): unexpected-end-tag
+(1,590): unexpected-end-tag
+(1,599): unexpected-end-tag
+(1,611): unexpected-end-tag
+(1,622): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+| <p>
+
+#data
+<table><tr></strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-end-tag-implies-table-voodoo
+(1,20): unexpected-end-tag
+(1,24): unexpected-end-tag-implies-table-voodoo
+(1,24): unexpected-end-tag
+(1,29): unexpected-end-tag-implies-table-voodoo
+(1,29): unexpected-end-tag
+(1,33): unexpected-end-tag-implies-table-voodoo
+(1,33): unexpected-end-tag
+(1,37): unexpected-end-tag-implies-table-voodoo
+(1,37): unexpected-end-tag
+(1,46): unexpected-end-tag-implies-table-voodoo
+(1,46): unexpected-end-tag
+(1,50): unexpected-end-tag-implies-table-voodoo
+(1,50): unexpected-end-tag
+(1,58): unexpected-end-tag-implies-table-voodoo
+(1,58): unexpected-end-tag
+(1,63): unexpected-end-tag-implies-table-voodoo
+(1,63): unexpected-end-tag
+(1,69): unexpected-end-tag-implies-table-voodoo
+(1,69): end-tag-too-early
+(1,75): unexpected-end-tag-implies-table-voodoo
+(1,75): unexpected-end-tag
+(1,83): unexpected-end-tag-implies-table-voodoo
+(1,83): unexpected-end-tag
+(1,90): unexpected-end-tag-implies-table-voodoo
+(1,90): unexpected-end-tag
+(1,99): unexpected-end-tag-implies-table-voodoo
+(1,99): unexpected-end-tag
+(1,104): unexpected-end-tag-implies-table-voodoo
+(1,104): end-tag-too-early
+(1,109): unexpected-end-tag-implies-table-voodoo
+(1,109): end-tag-too-early
+(1,114): unexpected-end-tag-implies-table-voodoo
+(1,114): end-tag-too-early
+(1,119): unexpected-end-tag-implies-table-voodoo
+(1,119): end-tag-too-early
+(1,124): unexpected-end-tag-implies-table-voodoo
+(1,124): end-tag-too-early
+(1,129): unexpected-end-tag-implies-table-voodoo
+(1,129): end-tag-too-early
+(1,136): unexpected-end-tag-in-table-row
+(1,141): unexpected-end-tag-implies-table-voodoo
+(1,141): unexpected-end-tag-treated-as
+(1,145): unexpected-end-tag-implies-table-voodoo
+(1,145): unexpected-end-tag
+(1,151): unexpected-end-tag-implies-table-voodoo
+(1,151): unexpected-end-tag
+(1,159): unexpected-end-tag-implies-table-voodoo
+(1,159): unexpected-end-tag
+(1,166): unexpected-end-tag-implies-table-voodoo
+(1,166): unexpected-end-tag
+(1,174): unexpected-end-tag-implies-table-voodoo
+(1,174): unexpected-end-tag
+(1,183): unexpected-end-tag-implies-table-voodoo
+(1,183): unexpected-end-tag
+(1,196): unexpected-end-tag
+(1,201): unexpected-end-tag
+(1,206): unexpected-end-tag
+(1,214): unexpected-end-tag
+(1,221): unexpected-end-tag
+(1,228): unexpected-end-tag
+(1,236): unexpected-end-tag
+(1,241): unexpected-end-tag
+(1,249): unexpected-end-tag
+(1,255): unexpected-end-tag
+(1,262): unexpected-end-tag
+(1,269): unexpected-end-tag
+(1,280): unexpected-end-tag
+(1,290): unexpected-end-tag
+(1,298): unexpected-end-tag
+(1,307): unexpected-end-tag
+(1,311): unexpected-end-tag
+(1,316): unexpected-end-tag
+(1,321): unexpected-end-tag
+(1,331): unexpected-end-tag
+(1,342): unexpected-end-tag
+(1,350): unexpected-end-tag
+(1,358): unexpected-end-tag
+(1,366): unexpected-end-tag
+(1,376): end-tag-too-early
+(1,389): end-tag-too-early
+(1,398): end-tag-too-early
+(1,404): end-tag-too-early
+(1,410): end-tag-too-early
+(1,415): end-tag-too-early
+(1,426): end-tag-too-early
+(1,436): end-tag-too-early
+(1,443): end-tag-too-early
+(1,448): end-tag-too-early
+(1,453): end-tag-too-early
+(1,458): unexpected-end-tag
+(1,465): unexpected-end-tag
+(1,471): unexpected-end-tag
+(1,478): unexpected-end-tag
+(1,487): end-tag-too-early
+(1,497): end-tag-too-early
+(1,506): end-tag-too-early
+(1,524): expected-eof-but-got-end-tag
+(1,524): unexpected-end-tag
+(1,531): unexpected-end-tag
+(1,540): unexpected-end-tag
+(1,548): unexpected-end-tag
+(1,558): unexpected-end-tag
+(1,568): unexpected-end-tag
+(1,579): unexpected-end-tag
+(1,590): unexpected-end-tag
+(1,601): unexpected-end-tag
+(1,610): unexpected-end-tag
+(1,622): unexpected-end-tag
+(1,633): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+| <table>
+| <tbody>
+| <tr>
+| <p>
+
+#data
+<frameset>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,10): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests10.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests10.dat
new file mode 100644
index 0000000000..87d94786b1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests10.dat
@@ -0,0 +1,847 @@
+#data
+<!DOCTYPE html><svg></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!DOCTYPE html><svg></svg><![CDATA[a]]>
+#errors
+(1,28) expected-dashes-or-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <!-- [CDATA[a]] -->
+
+#data
+<!DOCTYPE html><body><svg></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!DOCTYPE html><body><select><svg></svg></select>
+#errors
+(1,34) unexpected-start-tag-in-select
+(1,40) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!DOCTYPE html><body><select><option><svg></svg></option></select>
+#errors
+(1,42) unexpected-start-tag-in-select
+(1,48) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!DOCTYPE html><body><table><svg></svg></table>
+#errors
+(1,33) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <table>
+
+#data
+<!DOCTYPE html><body><table><svg><g>foo</g></svg></table>
+#errors
+(1,33) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><svg><g>foo</g><g>bar</g></svg></table>
+#errors
+(1,33) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><tbody><svg><g>foo</g><g>bar</g></svg></tbody></table>
+#errors
+(1,40) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+| <tbody>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><svg><g>foo</g><g>bar</g></svg></tr></tbody></table>
+#errors
+(1,44) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg></td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg><p>baz</td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g></svg><p>baz</caption></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,65) unexpected-html-element-in-foreign-content
+(1,76) XXX-undefined-error
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g>baz</table><p>quux
+#errors
+(1,73) unexpected-end-tag
+(1,73) expected-one-end-tag-but-got-another
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,43) foster-parenting-start-tag
+(1,66) foster-parenting-start-tag
+(1,67) foster-parenting-character
+(1,68) foster-parenting-character
+(1,69) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+| <table>
+| <colgroup>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><tr><td><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,49) unexpected-start-tag-in-select
+(1,52) unexpected-start-tag-in-select
+(1,59) unexpected-end-tag-in-select
+(1,62) unexpected-start-tag-in-select
+(1,69) unexpected-end-tag-in-select
+(1,72) unexpected-start-tag-in-select
+(1,83) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| "foobarbaz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,36) unexpected-start-tag-implies-table-voodoo
+(1,41) unexpected-start-tag-in-select
+(1,44) unexpected-start-tag-in-select
+(1,51) unexpected-end-tag-in-select
+(1,54) unexpected-start-tag-in-select
+(1,61) unexpected-end-tag-in-select
+(1,64) unexpected-start-tag-in-select
+(1,75) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "foobarbaz"
+| <table>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body></body></html><svg><g>foo</g><g>bar</g><p>baz
+#errors
+(1,40) expected-eof-but-got-start-tag
+(1,63) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body></body><svg><g>foo</g><g>bar</g><p>baz
+#errors
+(1,33) unexpected-start-tag-after-body
+(1,56) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><frameset><svg><g></g><g></g><p><span>
+#errors
+(1,30) unexpected-start-tag-in-frameset
+(1,33) unexpected-start-tag-in-frameset
+(1,37) unexpected-end-tag-in-frameset
+(1,40) unexpected-start-tag-in-frameset
+(1,44) unexpected-end-tag-in-frameset
+(1,47) unexpected-start-tag-in-frameset
+(1,53) unexpected-start-tag-in-frameset
+(1,53) eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset></frameset><svg><g></g><g></g><p><span>
+#errors
+(1,41) unexpected-start-tag-after-frameset
+(1,44) unexpected-start-tag-after-frameset
+(1,48) unexpected-end-tag-after-frameset
+(1,51) unexpected-start-tag-after-frameset
+(1,55) unexpected-end-tag-after-frameset
+(1,58) unexpected-start-tag-after-frameset
+(1,64) unexpected-start-tag-after-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| <svg svg>
+| xlink href="foo"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo></g></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo />bar</svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+| "bar"
+
+#data
+<svg></path>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,12) unexpected-end-tag
+(1,12) unexpected-end-tag
+(1,12) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<div><svg></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,16) unexpected-end-tag
+(1,16) end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| "a"
+
+#data
+<div><svg><path></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,22) unexpected-end-tag
+(1,22) end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| "a"
+
+#data
+<div><svg><path></svg><path>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,22) unexpected-end-tag
+(1,28) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <path>
+
+#data
+<div><svg><path><foreignObject><math></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,43) unexpected-end-tag
+(1,43) end-tag-too-early
+(1,44) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <math math>
+| "a"
+
+#data
+<div><svg><path><foreignObject><p></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,40) end-tag-too-early
+(1,41) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <p>
+| "a"
+
+#data
+<!DOCTYPE html><svg><desc><div><svg><ul>a
+#errors
+(1,40) unexpected-html-element-in-foreign-content
+(1,41) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg desc>
+| <div>
+| <svg svg>
+| <ul>
+| "a"
+
+#data
+<!DOCTYPE html><svg><desc><svg><ul>a
+#errors
+(1,35) unexpected-html-element-in-foreign-content
+(1,36) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg desc>
+| <svg svg>
+| <ul>
+| "a"
+
+#data
+<!DOCTYPE html><p><svg><desc><p>
+#errors
+(1,32) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <svg svg>
+| <svg desc>
+| <p>
+
+#data
+<!DOCTYPE html><p><svg><title><p>
+#errors
+(1,33) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <svg svg>
+| <svg title>
+| <p>
+
+#data
+<div><svg><path><foreignObject><p></foreignObject><p>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,50) unexpected-end-tag
+(1,53) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <p>
+| <p>
+
+#data
+<math><mi><div><object><div><span></span></div></object></div></mi><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,71) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <div>
+| <object>
+| <div>
+| <span>
+| <math mi>
+
+#data
+<math><mi><svg><foreignObject><div><div></div></div></foreignObject></svg></mi><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,83) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <div>
+| <math mi>
+
+#data
+<svg><script></script><path>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,28) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg script>
+| <svg path>
+
+#data
+<table><svg></svg><tr>
+#errors
+(1,7) expected-doctype-but-got-start-tag
+(1,12) unexpected-start-tag-implies-table-voodoo
+(1,22) eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<math><mi><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <math mglyph>
+
+#data
+<math><mi><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <math malignmark>
+
+#data
+<math><mo><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mo>
+| <math mglyph>
+
+#data
+<math><mo><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mo>
+| <math malignmark>
+
+#data
+<math><mn><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| <math mglyph>
+
+#data
+<math><mn><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| <math malignmark>
+
+#data
+<math><ms><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math ms>
+| <math mglyph>
+
+#data
+<math><ms><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math ms>
+| <math malignmark>
+
+#data
+<math><mtext><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,21) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <math mglyph>
+
+#data
+<math><mtext><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,25) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <math malignmark>
+
+#data
+<math><annotation-xml><svg></svg></annotation-xml><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,54) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <math mi>
+
+#data
+<math><annotation-xml><svg><foreignObject><div><math><mi></mi></math><span></span></div></foreignObject><path></path></svg></annotation-xml><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,144) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <math math>
+| <math mi>
+| <span>
+| <svg path>
+| <math mi>
+
+#data
+<math><annotation-xml><svg><foreignObject><math><mi><svg></svg></mi><mo></mo></math><span></span></foreignObject><path></path></svg></annotation-xml><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,153) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <svg foreignObject>
+| <math math>
+| <math mi>
+| <svg svg>
+| <math mo>
+| <span>
+| <svg path>
+| <math mi>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat
new file mode 100644
index 0000000000..ad62cdf659
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests11.dat
@@ -0,0 +1,482 @@
+#data
+<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseConstant=""
+| edgeMode=""
+| externalresourcesrequired=""
+| filterUnits=""
+| filterres=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' DIFFUSECONSTANT='' EDGEMODE='' EXTERNALRESOURCESREQUIRED='' FILTERRES='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseConstant=""
+| edgeMode=""
+| externalresourcesrequired=""
+| filterUnits=""
+| filterres=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' contentscripttype='' contentstyletype='' diffuseconstant='' edgemode='' externalresourcesrequired='' filterres='' filterunits='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseConstant=""
+| edgeMode=""
+| externalresourcesrequired=""
+| filterUnits=""
+| filterres=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| attributename=""
+| attributetype=""
+| basefrequency=""
+| baseprofile=""
+| calcmode=""
+| clippathunits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseconstant=""
+| edgemode=""
+| externalresourcesrequired=""
+| filterres=""
+| filterunits=""
+| glyphref=""
+| gradienttransform=""
+| gradientunits=""
+| kernelmatrix=""
+| kernelunitlength=""
+| keypoints=""
+| keysplines=""
+| keytimes=""
+| lengthadjust=""
+| limitingconeangle=""
+| markerheight=""
+| markerunits=""
+| markerwidth=""
+| maskcontentunits=""
+| maskunits=""
+| numoctaves=""
+| pathlength=""
+| patterncontentunits=""
+| patterntransform=""
+| patternunits=""
+| pointsatx=""
+| pointsaty=""
+| pointsatz=""
+| preservealpha=""
+| preserveaspectratio=""
+| primitiveunits=""
+| refx=""
+| refy=""
+| repeatcount=""
+| repeatdur=""
+| requiredextensions=""
+| requiredfeatures=""
+| specularconstant=""
+| specularexponent=""
+| spreadmethod=""
+| startoffset=""
+| stddeviation=""
+| stitchtiles=""
+| surfacescale=""
+| systemlanguage=""
+| tablevalues=""
+| targetx=""
+| targety=""
+| textlength=""
+| viewbox=""
+| viewtarget=""
+| xchannelselector=""
+| ychannelselector=""
+| zoomandpan=""
+
+#data
+<!DOCTYPE html><body><svg><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><body><svg><altglyph /><altglyphdef /><altglyphitem /><animatecolor /><animatemotion /><animatetransform /><clippath /><feblend /><fecolormatrix /><fecomponenttransfer /><fecomposite /><feconvolvematrix /><fediffuselighting /><fedisplacementmap /><fedistantlight /><feflood /><fefunca /><fefuncb /><fefuncg /><fefuncr /><fegaussianblur /><feimage /><femerge /><femergenode /><femorphology /><feoffset /><fepointlight /><fespecularlighting /><fespotlight /><fetile /><feturbulence /><foreignobject /><glyphref /><lineargradient /><radialgradient /><textpath /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><BODY><SVG><ALTGLYPH /><ALTGLYPHDEF /><ALTGLYPHITEM /><ANIMATECOLOR /><ANIMATEMOTION /><ANIMATETRANSFORM /><CLIPPATH /><FEBLEND /><FECOLORMATRIX /><FECOMPONENTTRANSFER /><FECOMPOSITE /><FECONVOLVEMATRIX /><FEDIFFUSELIGHTING /><FEDISPLACEMENTMAP /><FEDISTANTLIGHT /><FEFLOOD /><FEFUNCA /><FEFUNCB /><FEFUNCG /><FEFUNCR /><FEGAUSSIANBLUR /><FEIMAGE /><FEMERGE /><FEMERGENODE /><FEMORPHOLOGY /><FEOFFSET /><FEPOINTLIGHT /><FESPECULARLIGHTING /><FESPOTLIGHT /><FETILE /><FETURBULENCE /><FOREIGNOBJECT /><GLYPHREF /><LINEARGRADIENT /><RADIALGRADIENT /><TEXTPATH /></SVG>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><body><math><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math altglyph>
+| <math altglyphdef>
+| <math altglyphitem>
+| <math animatecolor>
+| <math animatemotion>
+| <math animatetransform>
+| <math clippath>
+| <math feblend>
+| <math fecolormatrix>
+| <math fecomponenttransfer>
+| <math fecomposite>
+| <math feconvolvematrix>
+| <math fediffuselighting>
+| <math fedisplacementmap>
+| <math fedistantlight>
+| <math feflood>
+| <math fefunca>
+| <math fefuncb>
+| <math fefuncg>
+| <math fefuncr>
+| <math fegaussianblur>
+| <math feimage>
+| <math femerge>
+| <math femergenode>
+| <math femorphology>
+| <math feoffset>
+| <math fepointlight>
+| <math fespecularlighting>
+| <math fespotlight>
+| <math fetile>
+| <math feturbulence>
+| <math foreignobject>
+| <math glyphref>
+| <math lineargradient>
+| <math radialgradient>
+| <math textpath>
+
+#data
+<!DOCTYPE html><body><svg><solidColor /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg solidcolor>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests12.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests12.dat
new file mode 100644
index 0000000000..63107d277b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests12.dat
@@ -0,0 +1,62 @@
+#data
+<!DOCTYPE html><body><p>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+| <math math>
+| <math mtext>
+| <i>
+| "baz"
+| <math annotation-xml>
+| <svg svg>
+| <svg desc>
+| <b>
+| "eggs"
+| <svg g>
+| <svg foreignObject>
+| <p>
+| "spam"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <img>
+| <svg g>
+| "quux"
+| "bar"
+
+#data
+<!DOCTYPE html><body>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "foo"
+| <math math>
+| <math mtext>
+| <i>
+| "baz"
+| <math annotation-xml>
+| <svg svg>
+| <svg desc>
+| <b>
+| "eggs"
+| <svg g>
+| <svg foreignObject>
+| <p>
+| "spam"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <img>
+| <svg g>
+| "quux"
+| "bar"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests14.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests14.dat
new file mode 100644
index 0000000000..a08b7649eb
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests14.dat
@@ -0,0 +1,75 @@
+#data
+<!DOCTYPE html><html><body><xyz:abc></xyz:abc>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xyz:abc>
+
+#data
+<!DOCTYPE html><html><body><xyz:abc></xyz:abc><span></span>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xyz:abc>
+| <span>
+
+#data
+<!DOCTYPE html><html><html abc:def=gh><xyz:abc></xyz:abc>
+#errors
+(1,38): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| abc:def="gh"
+| <head>
+| <body>
+| <xyz:abc>
+
+#data
+<!DOCTYPE html><html xml:lang=bar><html xml:lang=foo>
+#errors
+(1,53): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| xml:lang="bar"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html 123=456>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| 123="456"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html 123=456><html 789=012>
+#errors
+(1,43): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| 123="456"
+| 789="012"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html><body 789=012>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| 789="012"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests15.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests15.dat
new file mode 100644
index 0000000000..93d06a8717
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests15.dat
@@ -0,0 +1,216 @@
+#data
+<!DOCTYPE html><p><b><i><u></p> <p>X
+#errors
+(1,31): unexpected-end-tag
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <i>
+| <u>
+| <b>
+| <i>
+| <u>
+| " "
+| <p>
+| "X"
+
+#data
+<p><b><i><u></p>
+<p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): unexpected-end-tag
+(2,4): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <i>
+| <u>
+| <b>
+| <i>
+| <u>
+| "
+"
+| <p>
+| "X"
+
+#data
+<!doctype html></html> <head>
+#errors
+(1,29): expected-eof-but-got-start-tag
+(1,29): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " "
+
+#data
+<!doctype html></body><meta>
+#errors
+(1,28): unexpected-start-tag-after-body
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+
+#data
+<html></html><!-- foo -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <!-- foo -->
+
+#data
+<!doctype html></body><title>X</title>
+#errors
+(1,29): unexpected-start-tag-after-body
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+
+#data
+<!doctype html><table> X<meta></table>
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,30): foster-parenting-start-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " X"
+| <meta>
+| <table>
+
+#data
+<!doctype html><table> x</table>
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x"
+| <table>
+
+#data
+<!doctype html><table> x </table>
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x "
+| <table>
+
+#data
+<!doctype html><table><tr> x</table>
+#errors
+(1,27): foster-parenting-character
+(1,28): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table>X<style> <tr>x </style> </table>
+#errors
+(1,23): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <style>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div>
+#errors
+(1,30): foster-parenting-start-tag
+(1,31): foster-parenting-character
+(1,32): foster-parenting-character
+(1,33): foster-parenting-character
+(1,37): foster-parenting-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| "foo"
+| <table>
+| " "
+| <tbody>
+| <tr>
+| <td>
+| "bar"
+| " "
+
+#data
+<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,7): unexpected-start-tag-ignored
+(1,15): unexpected-end-tag
+(1,23): unexpected-end-tag
+(1,33): unexpected-start-tag
+(1,99): expected-named-closing-tag-but-got-eof
+(1,99): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+| <frameset>
+| <frame>
+| <noframes>
+| "</frameset><noframes>"
+
+#data
+<!DOCTYPE html><object></html>
+#errors
+(1,30): expected-body-in-scope
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <object>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests16.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests16.dat
new file mode 100644
index 0000000000..1c57f14a32
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests16.dat
@@ -0,0 +1,2396 @@
+#data
+<!doctype html><script>
+#errors
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script>a
+#errors
+(1,24): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "a"
+| <body>
+
+#data
+<!doctype html><script><
+#errors
+(1,24): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<"
+| <body>
+
+#data
+<!doctype html><script></
+#errors
+(1,25): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</"
+| <body>
+
+#data
+<!doctype html><script></S
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</S"
+| <body>
+
+#data
+<!doctype html><script></SC
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SC"
+| <body>
+
+#data
+<!doctype html><script></SCR
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCR"
+| <body>
+
+#data
+<!doctype html><script></SCRI
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRI"
+| <body>
+
+#data
+<!doctype html><script></SCRIP
+#errors
+(1,30): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRIP"
+| <body>
+
+#data
+<!doctype html><script></SCRIPT
+#errors
+(1,31): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRIPT"
+| <body>
+
+#data
+<!doctype html><script></SCRIPT
+#errors
+(1,32): expected-attribute-name-but-got-eof
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script></s
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</s"
+| <body>
+
+#data
+<!doctype html><script></sc
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</sc"
+| <body>
+
+#data
+<!doctype html><script></scr
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scr"
+| <body>
+
+#data
+<!doctype html><script></scri
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scri"
+| <body>
+
+#data
+<!doctype html><script></scrip
+#errors
+(1,30): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scrip"
+| <body>
+
+#data
+<!doctype html><script></script
+#errors
+(1,31): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</script"
+| <body>
+
+#data
+<!doctype html><script></script
+#errors
+(1,32): expected-attribute-name-but-got-eof
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script><!
+#errors
+(1,25): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!"
+| <body>
+
+#data
+<!doctype html><script><!a
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!a"
+| <body>
+
+#data
+<!doctype html><script><!-
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!-"
+| <body>
+
+#data
+<!doctype html><script><!-a
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!-a"
+| <body>
+
+#data
+<!doctype html><script><!--
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+(1,27): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<!doctype html><script><!--a
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+(1,28): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--a"
+| <body>
+
+#data
+<!doctype html><script><!--<
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+(1,28): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<"
+| <body>
+
+#data
+<!doctype html><script><!--<a
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<a"
+| <body>
+
+#data
+<!doctype html><script><!--</
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--</"
+| <body>
+
+#data
+<!doctype html><script><!--</script
+#errors
+(1,35): expected-named-closing-tag-but-got-eof
+(1,35): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--</script"
+| <body>
+
+#data
+<!doctype html><script><!--</script
+#errors
+(1,36): expected-attribute-name-but-got-eof
+(1,36): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<!doctype html><script><!--<s
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<s"
+| <body>
+
+#data
+<!doctype html><script><!--<script
+#errors
+(1,34): expected-named-closing-tag-but-got-eof
+(1,34): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script"
+| <body>
+
+#data
+<!doctype html><script><!--<script
+#errors
+(1,35): eof-in-script-in-script
+(1,35): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script "
+| <body>
+
+#data
+<!doctype html><script><!--<script <
+#errors
+(1,36): eof-in-script-in-script
+(1,36): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script <"
+| <body>
+
+#data
+<!doctype html><script><!--<script <a
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script <a"
+| <body>
+
+#data
+<!doctype html><script><!--<script </
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </"
+| <body>
+
+#data
+<!doctype html><script><!--<script </s
+#errors
+(1,38): eof-in-script-in-script
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </s"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script
+#errors
+(1,43): eof-in-script-in-script
+(1,43): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script"
+| <body>
+
+#data
+<!doctype html><script><!--<script </scripta
+#errors
+(1,44): eof-in-script-in-script
+(1,44): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </scripta"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script
+#errors
+(1,44): expected-named-closing-tag-but-got-eof
+(1,44): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script>
+#errors
+(1,44): expected-named-closing-tag-but-got-eof
+(1,44): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script>"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script/
+#errors
+(1,44): expected-named-closing-tag-but-got-eof
+(1,44): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script/"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script <
+#errors
+(1,45): expected-named-closing-tag-but-got-eof
+(1,45): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script <a
+#errors
+(1,46): expected-named-closing-tag-but-got-eof
+(1,46): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <a"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </
+#errors
+(1,46): expected-named-closing-tag-but-got-eof
+(1,46): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script
+#errors
+(1,52): expected-named-closing-tag-but-got-eof
+(1,52): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </script"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script
+#errors
+(1,53): expected-attribute-name-but-got-eof
+(1,53): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script/
+#errors
+(1,53): unexpected-EOF-after-solidus-in-tag
+(1,53): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script -
+#errors
+(1,36): eof-in-script-in-script
+(1,36): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -"
+| <body>
+
+#data
+<!doctype html><script><!--<script -a
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -a"
+| <body>
+
+#data
+<!doctype html><script><!--<script -<
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -<"
+| <body>
+
+#data
+<!doctype html><script><!--<script --
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --"
+| <body>
+
+#data
+<!doctype html><script><!--<script --a
+#errors
+(1,38): eof-in-script-in-script
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --a"
+| <body>
+
+#data
+<!doctype html><script><!--<script --<
+#errors
+(1,38): eof-in-script-in-script
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --<"
+| <body>
+
+#data
+<!doctype html><script><!--<script -->
+#errors
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --><
+#errors
+(1,39): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --><"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></
+#errors
+(1,40): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --></"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script
+#errors
+(1,46): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --></script"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script
+#errors
+(1,47): expected-attribute-name-but-got-eof
+(1,47): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script/
+#errors
+(1,47): unexpected-EOF-after-solidus-in-tag
+(1,47): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script><\/script>--></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script><\/script>-->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></scr'+'ipt>--></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt>-->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>--><!--</script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>--><!--"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>-- ></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>-- >"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>- -></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- ->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>- - ></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- - >"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>-></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>->"
+| <body>
+
+#data
+<!doctype html><script><!--<script>--!></script>X
+#errors
+(1,49): expected-named-closing-tag-but-got-eof
+(1,49): unexpected-EOF-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script>--!></script>X"
+| <body>
+
+#data
+<!doctype html><script><!--<scr'+'ipt></script>--></script>
+#errors
+(1,59): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<scr'+'ipt>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><script><!--<script></scr'+'ipt></script>X
+#errors
+(1,57): expected-named-closing-tag-but-got-eof
+(1,57): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt></script>X"
+| <body>
+
+#data
+<!doctype html><style><!--<style></style>--></style>
+#errors
+(1,52): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--<style>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><style><!--</style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "X"
+
+#data
+<!doctype html><style><!--...</style>...--></style>
+#errors
+(1,51): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <body>
+| "...-->"
+
+#data
+<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
+| <body>
+| "X"
+
+#data
+<!doctype html><style><!--...<style><!--...--!></style>--></style>
+#errors
+(1,66): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--...<style><!--...--!>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><style><!--...</style><!-- --><style>@import ...</style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <!-- -->
+| <style>
+| "@import ..."
+| <body>
+
+#data
+<!doctype html><style>...<style><!--...</style><!-- --></style>
+#errors
+(1,63): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "...<style><!--..."
+| <!-- -->
+| <body>
+
+#data
+<!doctype html><style>...<!--[if IE]><style>...</style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "...<!--[if IE]><style>..."
+| <body>
+| "X"
+
+#data
+<!doctype html><title><!--<title></title>--></title>
+#errors
+(1,52): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "<!--<title>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><title>&lt;/title></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "</title>"
+| <body>
+
+#data
+<!doctype html><title>foo/title><link></head><body>X
+#errors
+(1,52): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "foo/title><link></head><body>X"
+| <body>
+
+#data
+<!doctype html><noscript><!--<noscript></noscript>--></noscript>
+#errors
+(1,64): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<!--<noscript>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "X"
+| <noscript>
+| "-->"
+
+#data
+<!doctype html><noscript><iframe></noscript>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<iframe>"
+| <body>
+| "X"
+
+#data
+<!doctype html><noframes><!--<noframes></noframes>--></noframes>
+#errors
+(1,64): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noframes>
+| "<!--<noframes>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><noframes><body><script><!--...</script></body></noframes></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noframes>
+| "<body><script><!--...</script></body>"
+| <body>
+
+#data
+<!doctype html><textarea><!--<textarea></textarea>--></textarea>
+#errors
+(1,64): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--<textarea>"
+| "-->"
+
+#data
+<!doctype html><textarea>&lt;/textarea></textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "</textarea>"
+
+#data
+<!doctype html><textarea>&lt;</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<"
+
+#data
+<!doctype html><textarea>a&lt;b</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "a<b"
+
+#data
+<!doctype html><iframe><!--<iframe></iframe>--></iframe>
+#errors
+(1,56): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "<!--<iframe>"
+| "-->"
+
+#data
+<!doctype html><iframe>...<!--X->...<!--/X->...</iframe>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "...<!--X->...<!--/X->..."
+
+#data
+<!doctype html><xmp><!--<xmp></xmp>--></xmp>
+#errors
+(1,44): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xmp>
+| "<!--<xmp>"
+| "-->"
+
+#data
+<!doctype html><style></style</style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "</style"
+| <body>
+
+#data
+<!doctype html><style></stylee</style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "</stylee"
+| <body>
+
+#data
+<!doctype html><noembed><!--<noembed></noembed>--></noembed>
+#errors
+(1,60): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <noembed>
+| "<!--<noembed>"
+| "-->"
+
+#data
+<script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,8): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script>a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,9): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "a"
+| <body>
+
+#data
+<script><
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,9): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<"
+| <body>
+
+#data
+<script></
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,10): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</"
+| <body>
+
+#data
+<script></S
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</S"
+| <body>
+
+#data
+<script></SC
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SC"
+| <body>
+
+#data
+<script></SCR
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCR"
+| <body>
+
+#data
+<script></SCRI
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRI"
+| <body>
+
+#data
+<script></SCRIP
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,15): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRIP"
+| <body>
+
+#data
+<script></SCRIPT
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRIPT"
+| <body>
+
+#data
+<script></SCRIPT
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,17): expected-attribute-name-but-got-eof
+(1,17): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script></s
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</s"
+| <body>
+
+#data
+<script></sc
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</sc"
+| <body>
+
+#data
+<script></scr
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</scr"
+| <body>
+
+#data
+<script></scri
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</scri"
+| <body>
+
+#data
+<script></scrip
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,15): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</scrip"
+| <body>
+
+#data
+<script></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</script"
+| <body>
+
+#data
+<script></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,17): expected-attribute-name-but-got-eof
+(1,17): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script><!
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,10): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!"
+| <body>
+
+#data
+<script><!a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!a"
+| <body>
+
+#data
+<script><!-
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!-"
+| <body>
+
+#data
+<script><!-a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!-a"
+| <body>
+
+#data
+<script><!--
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+(1,12): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<script><!--a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+(1,13): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--a"
+| <body>
+
+#data
+<script><!--<
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+(1,13): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<"
+| <body>
+
+#data
+<script><!--<a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+(1,14): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<a"
+| <body>
+
+#data
+<script><!--</
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+(1,14): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--</"
+| <body>
+
+#data
+<script><!--</script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,20): expected-named-closing-tag-but-got-eof
+(1,20): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--</script"
+| <body>
+
+#data
+<script><!--</script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,21): expected-attribute-name-but-got-eof
+(1,21): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<script><!--<s
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+(1,14): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<s"
+| <body>
+
+#data
+<script><!--<script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,19): expected-named-closing-tag-but-got-eof
+(1,19): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script"
+| <body>
+
+#data
+<script><!--<script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,20): eof-in-script-in-script
+(1,20): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script "
+| <body>
+
+#data
+<script><!--<script <
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,21): eof-in-script-in-script
+(1,21): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script <"
+| <body>
+
+#data
+<script><!--<script <a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script <a"
+| <body>
+
+#data
+<script><!--<script </
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </"
+| <body>
+
+#data
+<script><!--<script </s
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): eof-in-script-in-script
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </s"
+| <body>
+
+#data
+<script><!--<script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,28): eof-in-script-in-script
+(1,28): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script"
+| <body>
+
+#data
+<script><!--<script </scripta
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): eof-in-script-in-script
+(1,29): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </scripta"
+| <body>
+
+#data
+<script><!--<script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script>"
+| <body>
+
+#data
+<script><!--<script </script/
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script/"
+| <body>
+
+#data
+<script><!--<script </script <
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,30): expected-named-closing-tag-but-got-eof
+(1,30): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <"
+| <body>
+
+#data
+<script><!--<script </script <a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,31): expected-named-closing-tag-but-got-eof
+(1,31): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <a"
+| <body>
+
+#data
+<script><!--<script </script </
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,31): expected-named-closing-tag-but-got-eof
+(1,31): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </"
+| <body>
+
+#data
+<script><!--<script </script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,37): expected-named-closing-tag-but-got-eof
+(1,37): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </script"
+| <body>
+
+#data
+<script><!--<script </script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,38): expected-attribute-name-but-got-eof
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script </script/
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,38): unexpected-EOF-after-solidus-in-tag
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script </script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script -
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,21): eof-in-script-in-script
+(1,21): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -"
+| <body>
+
+#data
+<script><!--<script -a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -a"
+| <body>
+
+#data
+<script><!--<script --
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --"
+| <body>
+
+#data
+<script><!--<script --a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): eof-in-script-in-script
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --a"
+| <body>
+
+#data
+<script><!--<script -->
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --><
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,24): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --><"
+| <body>
+
+#data
+<script><!--<script --></
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,25): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --></"
+| <body>
+
+#data
+<script><!--<script --></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,31): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --></script"
+| <body>
+
+#data
+<script><!--<script --></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,32): expected-attribute-name-but-got-eof
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --></script/
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,32): unexpected-EOF-after-solidus-in-tag
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script><\/script>--></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script><\/script>-->"
+| <body>
+
+#data
+<script><!--<script></scr'+'ipt>--></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt>-->"
+| <body>
+
+#data
+<script><!--<script></script><script></script></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>"
+| <body>
+
+#data
+<script><!--<script></script><script></script>--><!--</script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>--><!--"
+| <body>
+
+#data
+<script><!--<script></script><script></script>-- ></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>-- >"
+| <body>
+
+#data
+<script><!--<script></script><script></script>- -></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- ->"
+| <body>
+
+#data
+<script><!--<script></script><script></script>- - ></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- - >"
+| <body>
+
+#data
+<script><!--<script></script><script></script>-></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>->"
+| <body>
+
+#data
+<script><!--<script>--!></script>X
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,34): expected-named-closing-tag-but-got-eof
+(1,34): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script>--!></script>X"
+| <body>
+
+#data
+<script><!--<scr'+'ipt></script>--></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,44): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<scr'+'ipt>"
+| <body>
+| "-->"
+
+#data
+<script><!--<script></scr'+'ipt></script>X
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,42): expected-named-closing-tag-but-got-eof
+(1,42): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt></script>X"
+| <body>
+
+#data
+<style><!--<style></style>--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--<style>"
+| <body>
+| "-->"
+
+#data
+<style><!--</style>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "X"
+
+#data
+<style><!--...</style>...--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,36): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <body>
+| "...-->"
+
+#data
+<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
+| <body>
+| "X"
+
+#data
+<style><!--...<style><!--...--!></style>--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,51): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--...<style><!--...--!>"
+| <body>
+| "-->"
+
+#data
+<style><!--...</style><!-- --><style>@import ...</style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <!-- -->
+| <style>
+| "@import ..."
+| <body>
+
+#data
+<style>...<style><!--...</style><!-- --></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,48): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "...<style><!--..."
+| <!-- -->
+| <body>
+
+#data
+<style>...<!--[if IE]><style>...</style>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "...<!--[if IE]><style>..."
+| <body>
+| "X"
+
+#data
+<title><!--<title></title>--></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<!--<title>"
+| <body>
+| "-->"
+
+#data
+<title>&lt;/title></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "</title>"
+| <body>
+
+#data
+<title>foo/title><link></head><body>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <title>
+| "foo/title><link></head><body>X"
+| <body>
+
+#data
+<noscript><!--<noscript></noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,49): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--<noscript>"
+| <body>
+| "-->"
+
+#data
+<noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "X"
+| <noscript>
+| "-->"
+
+#data
+<noscript><iframe></noscript>X
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <noscript>
+| "<iframe>"
+| <body>
+| "X"
+
+#data
+<noframes><!--<noframes></noframes>--></noframes>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,49): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <noframes>
+| "<!--<noframes>"
+| <body>
+| "-->"
+
+#data
+<noframes><body><script><!--...</script></body></noframes></html>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <noframes>
+| "<body><script><!--...</script></body>"
+| <body>
+
+#data
+<textarea><!--<textarea></textarea>--></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,49): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--<textarea>"
+| "-->"
+
+#data
+<textarea>&lt;/textarea></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "</textarea>"
+
+#data
+<iframe><!--<iframe></iframe>--></iframe>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,41): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "<!--<iframe>"
+| "-->"
+
+#data
+<iframe>...<!--X->...<!--/X->...</iframe>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "...<!--X->...<!--/X->..."
+
+#data
+<xmp><!--<xmp></xmp>--></xmp>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,29): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <xmp>
+| "<!--<xmp>"
+| "-->"
+
+#data
+<noembed><!--<noembed></noembed>--></noembed>
+#errors
+(1,9): expected-doctype-but-got-start-tag
+(1,45): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <noembed>
+| "<!--<noembed>"
+| "-->"
+
+#data
+<!doctype html><table>
+
+#errors
+(2,0): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| "
+"
+
+#data
+<!doctype html><table><td><span><font></span><span>
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,45): unexpected-end-tag
+(1,51): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <span>
+| <font>
+| <font>
+| <span>
+
+#data
+<!doctype html><form><table></form><form></table></form>
+#errors
+(1,35): unexpected-end-tag-implies-table-voodoo
+(1,35): unexpected-end-tag
+(1,41): unexpected-form-in-table
+(1,56): unexpected-end-tag
+(1,56): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <table>
+| <form>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests17.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests17.dat
new file mode 100644
index 0000000000..37a7be4187
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests17.dat
@@ -0,0 +1,180 @@
+#data
+<!doctype html><table><tbody><select><tr>
+#errors
+(1,37): unexpected-start-tag-implies-table-voodoo
+(1,41): unexpected-table-element-start-tag-in-select-in-table
+(1,41): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><tr><select><td>
+#errors
+(1,34): unexpected-start-tag-implies-table-voodoo
+(1,38): unexpected-table-element-start-tag-in-select-in-table
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<!doctype html><table><tr><td><select><td>
+#errors
+(1,42): unexpected-table-element-start-tag-in-select-in-table
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| <td>
+
+#data
+<!doctype html><table><tr><th><select><td>
+#errors
+(1,42): unexpected-table-element-start-tag-in-select-in-table
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <th>
+| <select>
+| <td>
+
+#data
+<!doctype html><table><caption><select><tr>
+#errors
+(1,43): unexpected-table-element-start-tag-in-select-in-table
+(1,43): XXX-undefined-error
+(1,43): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <select>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><select><tr>
+#errors
+(1,27): unexpected-start-tag-in-select
+(1,27): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><td>
+#errors
+(1,27): unexpected-start-tag-in-select
+(1,27): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><th>
+#errors
+(1,27): unexpected-start-tag-in-select
+(1,27): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><tbody>
+#errors
+(1,30): unexpected-start-tag-in-select
+(1,30): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><thead>
+#errors
+(1,30): unexpected-start-tag-in-select
+(1,30): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><tfoot>
+#errors
+(1,30): unexpected-start-tag-in-select
+(1,30): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><caption>
+#errors
+(1,32): unexpected-start-tag-in-select
+(1,32): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><table><tr></table>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| "a"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests18.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests18.dat
new file mode 100644
index 0000000000..926bccb387
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests18.dat
@@ -0,0 +1,322 @@
+#data
+<!doctype html><plaintext></plaintext>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><plaintext></plaintext>
+#errors
+(1,33): foster-parenting-start-tag
+(1,34): foster-parenting-character
+(1,35): foster-parenting-character
+(1,36): foster-parenting-character
+(1,37): foster-parenting-character
+(1,38): foster-parenting-character
+(1,39): foster-parenting-character
+(1,40): foster-parenting-character
+(1,41): foster-parenting-character
+(1,42): foster-parenting-character
+(1,43): foster-parenting-character
+(1,44): foster-parenting-character
+(1,45): foster-parenting-character
+(1,45): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+
+#data
+<!doctype html><table><tbody><plaintext></plaintext>
+#errors
+(1,40): foster-parenting-start-tag
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,52): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+
+#data
+<!doctype html><table><tbody><tr><plaintext></plaintext>
+#errors
+(1,44): foster-parenting-start-tag
+(1,45): foster-parenting-character
+(1,46): foster-parenting-character
+(1,47): foster-parenting-character
+(1,48): foster-parenting-character
+(1,49): foster-parenting-character
+(1,50): foster-parenting-character
+(1,51): foster-parenting-character
+(1,52): foster-parenting-character
+(1,53): foster-parenting-character
+(1,54): foster-parenting-character
+(1,55): foster-parenting-character
+(1,56): foster-parenting-character
+(1,56): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><td><plaintext></plaintext>
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,49): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><caption><plaintext></plaintext>
+#errors
+(1,54): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><tr><style></script></style>abc
+#errors
+(1,51): foster-parenting-character
+(1,52): foster-parenting-character
+(1,53): foster-parenting-character
+(1,53): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+| <style>
+| "</script>"
+
+#data
+<!doctype html><table><tr><script></style></script>abc
+#errors
+(1,52): foster-parenting-character
+(1,53): foster-parenting-character
+(1,54): foster-parenting-character
+(1,54): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+| <script>
+| "</style>"
+
+#data
+<!doctype html><table><caption><style></script></style>abc
+#errors
+(1,58): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <style>
+| "</script>"
+| "abc"
+
+#data
+<!doctype html><table><td><style></script></style>abc
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,53): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <style>
+| "</script>"
+| "abc"
+
+#data
+<!doctype html><select><script></style></script>abc
+#errors
+(1,51): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+
+#data
+<!doctype html><table><select><script></style></script>abc
+#errors
+(1,30): unexpected-start-tag-implies-table-voodoo
+(1,58): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+| <table>
+
+#data
+<!doctype html><table><tr><select><script></style></script>abc
+#errors
+(1,34): unexpected-start-tag-implies-table-voodoo
+(1,62): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><frameset></frameset><noframes>abc
+#errors
+(1,49): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+
+#data
+<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+| <!-- abc -->
+
+#data
+<!doctype html><frameset></frameset></html><noframes>abc
+#errors
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+
+#data
+<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+| <!-- abc -->
+
+#data
+<!doctype html><table><tr></tbody><tfoot>
+#errors
+(1,41): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <tfoot>
+
+#data
+<!doctype html><table><td><svg></svg>abc<td>
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,44): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| "abc"
+| <td>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests19.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests19.dat
new file mode 100644
index 0000000000..a1897774df
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests19.dat
@@ -0,0 +1,1454 @@
+#data
+<!doctype html><math><mn DefinitionUrl="foo">
+#errors
+(1,45): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| definitionURL="foo"
+
+#data
+<!doctype html><html></p><!--foo-->
+#errors
+(1,25): end-tag-after-implied-root
+#document
+| <!DOCTYPE html>
+| <html>
+| <!-- foo -->
+| <head>
+| <body>
+
+#data
+<!doctype html><head></head></p><!--foo-->
+#errors
+(1,32): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <!-- foo -->
+| <body>
+
+#data
+<!doctype html><body><p><pre>
+#errors
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <pre>
+
+#data
+<!doctype html><body><p><listing>
+#errors
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <listing>
+
+#data
+<!doctype html><p><plaintext>
+#errors
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <plaintext>
+
+#data
+<!doctype html><p><h1>
+#errors
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <h1>
+
+#data
+<!doctype html><isindex type="hidden">
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <isindex>
+| type="hidden"
+
+#data
+<!doctype html><ruby><p><rp>
+#errors
+(1,28): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <p>
+| <rp>
+
+#data
+<!doctype html><ruby><div><span><rp>
+#errors
+(1,36): XXX-undefined-error
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <span>
+| <rp>
+
+#data
+<!doctype html><ruby><div><p><rp>
+#errors
+(1,33): XXX-undefined-error
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <p>
+| <rp>
+
+#data
+<!doctype html><ruby><p><rt>
+#errors
+(1,28): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <p>
+| <rt>
+
+#data
+<!doctype html><ruby><div><span><rt>
+#errors
+(1,36): XXX-undefined-error
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <span>
+| <rt>
+
+#data
+<!doctype html><ruby><div><p><rt>
+#errors
+(1,33): XXX-undefined-error
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <p>
+| <rt>
+
+#data
+<html><ruby>a<rb>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rp>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rt>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rtc>b<rt>c<rb>d</ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rt>
+| "c"
+| <rb>
+| "d"
+
+#data
+<!doctype html><math/><foo>
+#errors
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <foo>
+
+#data
+<!doctype html><svg/><foo>
+#errors
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <foo>
+
+#data
+<!doctype html><div></body><!--foo-->
+#errors
+(1,27): expected-one-end-tag-but-got-another
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- foo -->
+
+#data
+<!doctype html><h1><div><h3><span></h1>foo
+#errors
+(1,39): end-tag-too-early
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <h1>
+| <div>
+| <h3>
+| <span>
+| "foo"
+
+#data
+<!doctype html><p></h3>foo
+#errors
+(1,23): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+
+#data
+<!doctype html><h3><li>abc</h2>foo
+#errors
+(1,31): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <h3>
+| <li>
+| "abc"
+| "foo"
+
+#data
+<!doctype html><table>abc<!--foo-->
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+(1,35): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <!-- foo -->
+
+#data
+<!doctype html><table> <!--foo-->
+#errors
+(1,34): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <!-- foo -->
+
+#data
+<!doctype html><table> b <!--foo-->
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+(1,35): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " b "
+| <table>
+| <!-- foo -->
+
+#data
+<!doctype html><select><option><option>
+#errors
+(1,39): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+
+#data
+<!doctype html><select><option></optgroup>
+#errors
+(1,42): unexpected-end-tag-in-select
+(1,42): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!doctype html><select><option></optgroup>
+#errors
+(1,42): unexpected-end-tag-in-select
+(1,42): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!doctype html><dd><optgroup><dd>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dd>
+| <optgroup>
+| <dd>
+
+#data
+<!doctype html><p><math><mi><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mi>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mo><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mo>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mn><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mn>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><ms><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math ms>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mtext><p><h1>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mtext>
+| <p>
+| <h1>
+
+#data
+<!doctype html><frameset></noframes>
+#errors
+(1,36): unexpected-end-tag-in-frameset
+(1,36): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html c=d><body></html><html a=b>
+#errors
+(1,48): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <body>
+
+#data
+<!doctype html><html c=d><frameset></frameset></html><html a=b>
+#errors
+(1,63): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html><!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <!-- foo -->
+
+#data
+<!doctype html><html><frameset></frameset></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!doctype html><html><frameset></frameset></html>abc
+#errors
+(1,50): expected-eof-but-got-char
+(1,51): expected-eof-but-got-char
+(1,52): expected-eof-but-got-char
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html><p>
+#errors
+(1,52): expected-eof-but-got-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html></p>
+#errors
+(1,53): expected-eof-but-got-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<html><frameset></frameset></html><!doctype html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,49): unexpected-doctype
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><body><frameset>
+#errors
+(1,31): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html><p><frameset><frame>
+#errors
+(1,28): unexpected-start-tag
+(1,35): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><p>a<frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "a"
+
+#data
+<!doctype html><p> <frameset><frame>
+#errors
+(1,29): unexpected-start-tag
+(1,36): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><pre><frameset>
+#errors
+(1,30): unexpected-start-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+
+#data
+<!doctype html><listing><frameset>
+#errors
+(1,34): unexpected-start-tag
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <listing>
+
+#data
+<!doctype html><li><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <li>
+
+#data
+<!doctype html><dd><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dd>
+
+#data
+<!doctype html><dt><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dt>
+
+#data
+<!doctype html><button><frameset>
+#errors
+(1,33): unexpected-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <button>
+
+#data
+<!doctype html><applet><frameset>
+#errors
+(1,33): unexpected-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <applet>
+
+#data
+<!doctype html><marquee><frameset>
+#errors
+(1,34): unexpected-start-tag
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <marquee>
+
+#data
+<!doctype html><object><frameset>
+#errors
+(1,33): unexpected-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <object>
+
+#data
+<!doctype html><table><frameset>
+#errors
+(1,32): unexpected-start-tag-implies-table-voodoo
+(1,32): unexpected-start-tag
+(1,32): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+
+#data
+<!doctype html><area><frameset>
+#errors
+(1,31): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <area>
+
+#data
+<!doctype html><basefont><frameset>
+#errors
+(1,35): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <basefont>
+| <frameset>
+
+#data
+<!doctype html><bgsound><frameset>
+#errors
+(1,34): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <bgsound>
+| <frameset>
+
+#data
+<!doctype html><br><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<!doctype html><embed><frameset>
+#errors
+(1,32): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <embed>
+
+#data
+<!doctype html><img><frameset>
+#errors
+(1,30): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+
+#data
+<!doctype html><input><frameset>
+#errors
+(1,32): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+
+#data
+<!doctype html><keygen><frameset>
+#errors
+(1,33): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <keygen>
+
+#data
+<!doctype html><wbr><frameset>
+#errors
+(1,30): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <wbr>
+
+#data
+<!doctype html><hr><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <hr>
+
+#data
+<!doctype html><textarea></textarea><frameset>
+#errors
+(1,46): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+
+#data
+<!doctype html><xmp></xmp><frameset>
+#errors
+(1,36): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xmp>
+
+#data
+<!doctype html><iframe></iframe><frameset>
+#errors
+(1,42): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+
+#data
+<!doctype html><select></select><frameset>
+#errors
+(1,42): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><svg></svg><frameset><frame>
+#errors
+(1,36): unexpected-start-tag
+(1,43): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><math></math><frameset><frame>
+#errors
+(1,38): unexpected-start-tag
+(1,45): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><svg><foreignObject><div> <frameset><frame>
+#errors
+(1,51): unexpected-start-tag
+(1,58): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><svg>a</svg><frameset><frame>
+#errors
+(1,37): unexpected-start-tag
+(1,44): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "a"
+
+#data
+<!doctype html><svg> </svg><frameset><frame>
+#errors
+(1,37): unexpected-start-tag
+(1,44): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<html>aaa<frameset></frameset>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,19): unexpected-start-tag
+(1,30): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "aaa"
+
+#data
+<html> a <frameset></frameset>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,19): unexpected-start-tag
+(1,30): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "a "
+
+#data
+<!doctype html><div><frameset>
+#errors
+(1,30): unexpected-start-tag
+(1,30): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><div><body><frameset>
+#errors
+(1,26): unexpected-start-tag
+(1,36): unexpected-start-tag
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<!doctype html><p><math></p>a
+#errors
+(1,28): unexpected-end-tag
+(1,28): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| "a"
+
+#data
+<!doctype html><p><math><mn><span></p>a
+#errors
+(1,38): unexpected-end-tag
+(1,39): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mn>
+| <span>
+| <p>
+| "a"
+
+#data
+<!doctype html><math></html>
+#errors
+(1,28): unexpected-end-tag
+(1,28): expected-one-end-tag-but-got-another
+(1,28): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!doctype html><meta charset="ascii">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| charset="ascii"
+| <body>
+
+#data
+<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| content="text/html;charset=ascii"
+| http-equiv="content-type"
+| <body>
+
+#data
+<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -->
+| <meta>
+| charset="utf8"
+| <body>
+
+#data
+<!doctype html><html a=b><head></head><html c=d>
+#errors
+(1,48): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <body>
+
+#data
+<!doctype html><image/>
+#errors
+(1,23): image-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+
+#data
+<!doctype html>a<i>b<table>c<b>d</i>e</b>f
+#errors
+(1,28): foster-parenting-character
+(1,31): foster-parenting-start-tag
+(1,32): foster-parenting-character
+(1,36): foster-parenting-end-tag
+(1,36): adoption-agency-1.3
+(1,37): foster-parenting-character
+(1,41): foster-parenting-end-tag
+(1,42): foster-parenting-character
+(1,42): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "a"
+| <i>
+| "bc"
+| <b>
+| "de"
+| "f"
+| <table>
+
+#data
+<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,29): foster-parenting-start-tag
+(1,30): foster-parenting-character
+(1,35): foster-parenting-start-tag
+(1,36): foster-parenting-character
+(1,39): foster-parenting-start-tag
+(1,40): foster-parenting-character
+(1,44): foster-parenting-end-tag
+(1,44): adoption-agency-1.3
+(1,44): adoption-agency-1.3
+(1,45): foster-parenting-character
+(1,49): foster-parenting-end-tag
+(1,49): adoption-agency-1.3
+(1,49): adoption-agency-1.3
+(1,50): foster-parenting-character
+(1,50): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+| <table>
+
+#data
+<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+(1,37): adoption-agency-1.3
+(1,37): adoption-agency-1.3
+(1,42): adoption-agency-1.3
+(1,42): adoption-agency-1.3
+(1,43): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+
+#data
+<!doctype html><table><i>a<b>b<div>c</i>
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,29): foster-parenting-start-tag
+(1,30): foster-parenting-character
+(1,35): foster-parenting-start-tag
+(1,36): foster-parenting-character
+(1,40): foster-parenting-end-tag
+(1,40): adoption-agency-1.3
+(1,40): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <i>
+| "c"
+| <table>
+
+#data
+<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,29): foster-parenting-start-tag
+(1,30): foster-parenting-character
+(1,35): foster-parenting-start-tag
+(1,36): foster-parenting-character
+(1,39): foster-parenting-start-tag
+(1,40): foster-parenting-character
+(1,44): foster-parenting-end-tag
+(1,44): adoption-agency-1.3
+(1,44): adoption-agency-1.3
+(1,45): foster-parenting-character
+(1,49): foster-parenting-end-tag
+(1,44): adoption-agency-1.3
+(1,44): adoption-agency-1.3
+(1,50): foster-parenting-character
+(1,50): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+| <table>
+
+#data
+<!doctype html><table><i>a<div>b<tr>c<b>d</i>e
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,31): foster-parenting-start-tag
+(1,32): foster-parenting-character
+(1,37): foster-parenting-character
+(1,40): foster-parenting-start-tag
+(1,41): foster-parenting-character
+(1,45): foster-parenting-end-tag
+(1,45): adoption-agency-1.3
+(1,46): foster-parenting-character
+(1,46): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <div>
+| "b"
+| <i>
+| "c"
+| <b>
+| "d"
+| <b>
+| "e"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><td><table><i>a<div>b<b>c</i>d
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,36): foster-parenting-start-tag
+(1,37): foster-parenting-character
+(1,42): foster-parenting-start-tag
+(1,43): foster-parenting-character
+(1,46): foster-parenting-start-tag
+(1,47): foster-parenting-character
+(1,51): foster-parenting-end-tag
+(1,51): adoption-agency-1.3
+(1,51): adoption-agency-1.3
+(1,52): foster-parenting-character
+(1,52): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+| "a"
+| <div>
+| <i>
+| "b"
+| <b>
+| "c"
+| <b>
+| "d"
+| <table>
+
+#data
+<!doctype html><body><bgsound>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <bgsound>
+
+#data
+<!doctype html><body><basefont>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <basefont>
+
+#data
+<!doctype html><a><b></a><basefont>
+#errors
+(1,25): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <basefont>
+
+#data
+<!doctype html><a><b></a><bgsound>
+#errors
+(1,25): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <bgsound>
+
+#data
+<!doctype html><figcaption><article></figcaption>a
+#errors
+(1,49): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <figcaption>
+| <article>
+| "a"
+
+#data
+<!doctype html><summary><article></summary>a
+#errors
+(1,43): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <summary>
+| <article>
+| "a"
+
+#data
+<!doctype html><p><a><plaintext>b
+#errors
+(1,32): unexpected-end-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <a>
+| <plaintext>
+| <a>
+| "b"
+
+#data
+<!DOCTYPE html><div>a<a></div>b<p>c</p>d
+#errors
+(1,30): end-tag-too-early
+(1,40): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| "a"
+| <a>
+| <a>
+| "b"
+| <p>
+| "c"
+| "d"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests2.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests2.dat
new file mode 100644
index 0000000000..b44fec4d76
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests2.dat
@@ -0,0 +1,821 @@
+#data
+<!DOCTYPE html>Test
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<textarea>test</div>test
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,24): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "test</div>test"
+
+#data
+<table><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,11): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><td>test</tbody></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "test"
+
+#data
+<frame>test
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,7): unexpected-start-tag-ignored
+#document
+| <html>
+| <head>
+| <body>
+| "test"
+
+#data
+<!DOCTYPE html><frameset>test
+#errors
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset> te st
+#errors
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html><frameset></frameset> te st
+#errors
+(1,29): unexpected-char-after-frameset
+(1,29): unexpected-char-after-frameset
+(1,29): unexpected-char-after-frameset
+(1,29): unexpected-char-after-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html><frameset><!DOCTYPE html>
+#errors
+(1,40): unexpected-doctype
+(1,40): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><font><p><b>test</font>
+#errors
+(1,38): adoption-agency-1.3
+(1,38): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <font>
+| <b>
+| "test"
+
+#data
+<!DOCTYPE html><dt><div><dd>
+#errors
+(1,28): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dt>
+| <div>
+| <dd>
+
+#data
+<script></x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</x"
+| <body>
+
+#data
+<table><plaintext><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): unexpected-start-tag-implies-table-voodoo
+(1,22): foster-parenting-character-in-table
+(1,22): foster-parenting-character-in-table
+(1,22): foster-parenting-character-in-table
+(1,22): foster-parenting-character-in-table
+(1,22): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "<td>"
+| <table>
+
+#data
+<plaintext></plaintext>
+#errors
+(1,11): expected-doctype-but-got-start-tag
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!DOCTYPE html><table><tr>TEST
+#errors
+(1,30): foster-parenting-character-in-table
+(1,30): foster-parenting-character-in-table
+(1,30): foster-parenting-character-in-table
+(1,30): foster-parenting-character-in-table
+(1,30): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "TEST"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4>
+#errors
+(1,37): unexpected-start-tag
+(1,53): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| t1="1"
+| t2="2"
+| t3="3"
+| t4="4"
+
+#data
+</b test
+#errors
+(1,8): eof-in-attribute-name
+(1,8): expected-doctype-but-got-eof
+#new-errors
+(1:9) eof-in-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html></b test<b &=&amp>X
+#errors
+(1,24): invalid-character-in-attribute-name
+(1,32): named-entity-without-semicolon
+(1,33): attributes-in-end-tag
+(1,33): unexpected-end-tag-before-html
+#new-errors
+(1:24) unexpected-character-in-attribute-name
+(1:33) missing-semicolon-after-character-reference
+(1:33) end-tag-with-attributes
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+
+#data
+<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt
+#errors
+(1,9): need-space-after-doctype
+(1,54): expected-named-closing-tag-but-got-eof
+#new-errors
+(1:10) missing-whitespace-before-doctype-name
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| type="text/x-foobar;baz"
+| "X</SCRipt"
+| <body>
+
+#data
+&
+#errors
+(1,1): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&"
+
+#data
+&#
+#errors
+(1,2): expected-numeric-entity
+(1,2): expected-doctype-but-got-chars
+#new-errors
+(1:3) absence-of-digits-in-numeric-character-reference
+#document
+| <html>
+| <head>
+| <body>
+| "&#"
+
+#data
+&#X
+#errors
+(1,3): expected-numeric-entity
+(1,3): expected-doctype-but-got-chars
+#new-errors
+(1:4) absence-of-digits-in-numeric-character-reference
+#document
+| <html>
+| <head>
+| <body>
+| "&#X"
+
+#data
+&#x
+#errors
+(1,3): expected-numeric-entity
+(1,3): expected-doctype-but-got-chars
+#new-errors
+(1:4) absence-of-digits-in-numeric-character-reference
+#document
+| <html>
+| <head>
+| <body>
+| "&#x"
+
+#data
+&#45
+#errors
+(1,4): numeric-entity-without-semicolon
+(1,4): expected-doctype-but-got-chars
+#new-errors
+(1:5) missing-semicolon-after-character-reference
+#document
+| <html>
+| <head>
+| <body>
+| "-"
+
+#data
+&x-test
+#errors
+(1,2): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&x-test"
+
+#data
+<!doctypehtml><p><li>
+#errors
+(1,9): need-space-after-doctype
+#new-errors
+(1:10) missing-whitespace-before-doctype-name
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <li>
+
+#data
+<!doctypehtml><p><dt>
+#errors
+(1,9): need-space-after-doctype
+#new-errors
+(1:10) missing-whitespace-before-doctype-name
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <dt>
+
+#data
+<!doctypehtml><p><dd>
+#errors
+(1,9): need-space-after-doctype
+#new-errors
+(1:10) missing-whitespace-before-doctype-name
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <dd>
+
+#data
+<!doctypehtml><p><form>
+#errors
+(1,9): need-space-after-doctype
+(1,23): expected-closing-tag-but-got-eof
+#new-errors
+(1:10) missing-whitespace-before-doctype-name
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <form>
+
+#data
+<!DOCTYPE html><p></P>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "X"
+
+#data
+&AMP
+#errors
+(1,4): named-entity-without-semicolon
+(1,4): expected-doctype-but-got-chars
+#new-errors
+(1:5) missing-semicolon-after-character-reference
+#document
+| <html>
+| <head>
+| <body>
+| "&"
+
+#data
+&AMp;
+#errors
+(1,3): expected-named-entity
+(1,3): expected-doctype-but-got-chars
+#new-errors
+(1:5) unknown-named-character-reference
+#document
+| <html>
+| <head>
+| <body>
+| "&AMp;"
+
+#data
+<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY>
+#errors
+(1,110): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly>
+
+#data
+<!DOCTYPE html>X</body>X
+#errors
+(1,24): unexpected-char-after-body
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "XX"
+
+#data
+<!DOCTYPE html><!-- X
+#errors
+(1,21): eof-in-comment
+#new-errors
+(1:22) eof-in-comment
+#document
+| <!DOCTYPE html>
+| <!-- X -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><table><caption>test TEST</caption><td>test
+#errors
+(1,54): unexpected-cell-in-table-body
+(1,58): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| "test TEST"
+| <tbody>
+| <tr>
+| <td>
+| "test"
+
+#data
+<!DOCTYPE html><select><option><optgroup>
+#errors
+(1,41): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <optgroup>
+
+#data
+<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option>
+#errors
+(1,68): unexpected-select-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+| <option>
+| <option>
+| <option>
+
+#data
+<!DOCTYPE html><select><optgroup><option><optgroup>
+#errors
+(1,51): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+| <option>
+| <optgroup>
+
+#data
+<!DOCTYPE html><datalist><option>foo</datalist>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <datalist>
+| <option>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html><font><input><input></font>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <input>
+| <input>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX -->
+#errors
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX
+#errors
+(1,29): eof-in-comment
+#new-errors
+(1:30) eof-in-comment
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX - XXX -->
+#errors
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+test
+test
+#errors
+(2,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "test
+test"
+
+#data
+<!DOCTYPE html><body><title>test</body></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "test</body>"
+
+#data
+<!DOCTYPE html><body><title>X</title><meta name=z><link rel=foo><style>
+x { content:"</style" } </style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+| <meta>
+| name="z"
+| <link>
+| rel="foo"
+| <style>
+| "
+x { content:"</style" } "
+
+#data
+<!DOCTYPE html><select><optgroup></optgroup></select>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+
+#data
+
+
+#errors
+(2,1): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html> <html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><script>
+</script> <title>x</title> </head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "
+"
+| " "
+| <title>
+| "x"
+| " "
+| <body>
+
+#data
+<!DOCTYPE html><html><body><html id=x>
+#errors
+(1,38): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html>X</body><html id="x">
+#errors
+(1,36): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+| "X"
+
+#data
+<!DOCTYPE html><head><html id=x>
+#errors
+(1,32): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html>X</html>X
+#errors
+(1,24): expected-eof-but-got-char
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "XX"
+
+#data
+<!DOCTYPE html>X</html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X "
+
+#data
+<!DOCTYPE html>X</html><p>X
+#errors
+(1,26): expected-eof-but-got-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <p>
+| "X"
+
+#data
+<!DOCTYPE html>X<p/x/y/z>
+#errors
+(1,19): unexpected-character-after-solidus-in-tag
+(1,21): unexpected-character-after-solidus-in-tag
+(1,23): unexpected-character-after-solidus-in-tag
+#new-errors
+(1:20) unexpected-solidus-in-tag
+(1:22) unexpected-solidus-in-tag
+(1:24) unexpected-solidus-in-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <p>
+| x=""
+| y=""
+| z=""
+
+#data
+<!DOCTYPE html><!--x--
+#errors
+(1,22): eof-in-comment-double-dash
+#new-errors
+(1:23) eof-in-comment
+#document
+| <!DOCTYPE html>
+| <!-- x -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><table><tr><td></p></table>
+#errors
+(1,34): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <p>
+
+#data
+<!DOCTYPE <!DOCTYPE HTML>><!--<!--x-->-->
+#errors
+(1,20): expected-space-or-right-bracket-in-doctype
+(1,25): unknown-doctype
+(1,35): unexpected-char-in-comment
+#new-errors
+(1:21) invalid-character-sequence-after-doctype-name
+(1:35) nested-comment
+#document
+| <!DOCTYPE <!doctype>
+| <html>
+| <head>
+| <body>
+| ">"
+| <!-- <!--x -->
+| "-->"
+
+#data
+<!doctype html><div><form></form><div></div></div>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <form>
+| <div>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests20.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests20.dat
new file mode 100644
index 0000000000..52c5acdc6e
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests20.dat
@@ -0,0 +1,516 @@
+#data
+<!doctype html><p><button><button>
+#errors
+(1,34): unexpected-start-tag-implies-end-tag
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <button>
+
+#data
+<!doctype html><p><button><address>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <address>
+
+#data
+<!doctype html><p><button><blockquote>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <blockquote>
+
+#data
+<!doctype html><p><button><menu>
+#errors
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <menu>
+
+#data
+<!doctype html><p><button><p>
+#errors
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <p>
+
+#data
+<!doctype html><p><button><ul>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <ul>
+
+#data
+<!doctype html><p><button><h1>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <h1>
+
+#data
+<!doctype html><p><button><h6>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <h6>
+
+#data
+<!doctype html><p><button><listing>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <listing>
+
+#data
+<!doctype html><p><button><pre>
+#errors
+(1,31): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <pre>
+
+#data
+<!doctype html><p><button><form>
+#errors
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <form>
+
+#data
+<!doctype html><p><button><li>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <li>
+
+#data
+<!doctype html><p><button><dd>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <dd>
+
+#data
+<!doctype html><p><button><dt>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <dt>
+
+#data
+<!doctype html><p><button><plaintext>
+#errors
+(1,37): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <plaintext>
+
+#data
+<!doctype html><p><button><table>
+#errors
+(1,33): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <table>
+
+#data
+<!doctype html><p><button><hr>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <hr>
+
+#data
+<!doctype html><p><button><xmp>
+#errors
+(1,31): expected-named-closing-tag-but-got-eof
+(1,31): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <xmp>
+
+#data
+<!doctype html><p><button></p>
+#errors
+(1,30): unexpected-end-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <p>
+
+#data
+<!doctype html><address><button></address>a
+#errors
+(1,42): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <address>
+| <button>
+| "a"
+
+#data
+<!doctype html><address><button></address>a
+#errors
+(1,42): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <address>
+| <button>
+| "a"
+
+#data
+<p><table></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-end-tag-implies-table-voodoo
+(1,14): unexpected-end-tag
+(1,14): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <p>
+| <table>
+
+#data
+<!doctype html><svg>
+#errors
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!doctype html><p><figcaption>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <figcaption>
+
+#data
+<!doctype html><p><summary>
+#errors
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <summary>
+
+#data
+<!doctype html><form><table><form>
+#errors
+(1,34): unexpected-form-in-table
+(1,34): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <table>
+
+#data
+<!doctype html><table><form><form>
+#errors
+(1,28): unexpected-form-in-table
+(1,34): unexpected-form-in-table
+(1,34): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <form>
+
+#data
+<!doctype html><table><form></table><form>
+#errors
+(1,28): unexpected-form-in-table
+(1,42): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <form>
+
+#data
+<!doctype html><svg><foreignObject><p>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+
+#data
+<!doctype html><svg><title>abc
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| "abc"
+
+#data
+<option><span><option>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <option>
+| <span>
+| <option>
+
+#data
+<option><option>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <option>
+| <option>
+
+#data
+<math><annotation-xml><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): unexpected-html-element-in-foreign-content
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <div>
+
+#data
+<math><annotation-xml encoding="application/svg+xml"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,58): unexpected-html-element-in-foreign-content
+(1,58): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="application/svg+xml"
+| <div>
+
+#data
+<math><annotation-xml encoding="application/xhtml+xml"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,60): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="application/xhtml+xml"
+| <div>
+
+#data
+<math><annotation-xml encoding="aPPlication/xhtmL+xMl"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,60): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="aPPlication/xhtmL+xMl"
+| <div>
+
+#data
+<math><annotation-xml encoding="text/html"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="text/html"
+| <div>
+
+#data
+<math><annotation-xml encoding="Text/htmL"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="Text/htmL"
+| <div>
+
+#data
+<math><annotation-xml encoding=" text/html "><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,50): unexpected-html-element-in-foreign-content
+(1,50): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding=" text/html "
+| <div>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests21.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests21.dat
new file mode 100644
index 0000000000..d384a55564
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests21.dat
@@ -0,0 +1,305 @@
+#data
+<svg><![CDATA[foo]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<math><![CDATA[foo]]>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| "foo"
+
+#data
+<div><![CDATA[foo]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,7): expected-dashes-or-doctype
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- [CDATA[foo]] -->
+
+#data
+<svg><![CDATA[foo
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<svg><![CDATA[foo
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<svg><![CDATA[
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,14): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<svg><![CDATA[]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<svg><![CDATA[]] >]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]] >"
+
+#data
+<svg><![CDATA[]] >]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]] >"
+
+#data
+<svg><![CDATA[]]
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]]"
+
+#data
+<svg><![CDATA[]
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]"
+
+#data
+<svg><![CDATA[]>a
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]>a"
+
+#data
+<!DOCTYPE html><svg><![CDATA[foo]]]>
+#errors
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo]"
+
+#data
+<!DOCTYPE html><svg><![CDATA[foo]]]]>
+#errors
+(1,37): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo]]"
+
+#data
+<!DOCTYPE html><svg><![CDATA[foo]]]]]>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo]]]"
+
+#data
+<svg><foreignObject><div><![CDATA[foo]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,27): expected-dashes-or-doctype
+(1,40): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <!-- [CDATA[foo]] -->
+
+#data
+<svg><![CDATA[<svg>]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+
+#data
+<svg><![CDATA[</svg>a]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,24): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "</svg>a"
+
+#data
+<svg><![CDATA[<svg>a
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>a"
+
+#data
+<svg><![CDATA[</svg>a
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "</svg>a"
+
+#data
+<svg><![CDATA[<svg>]]><path>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,28): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+| <svg path>
+
+#data
+<svg><![CDATA[<svg>]]></path>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,29): unexpected-end-tag
+(1,29): unexpected-end-tag
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+
+#data
+<svg><![CDATA[<svg>]]><!--path-->
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+| <!-- path -->
+
+#data
+<svg><![CDATA[<svg>]]>path
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>path"
+
+#data
+<svg><![CDATA[<!--svg-->]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<!--svg-->"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests22.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests22.dat
new file mode 100644
index 0000000000..31e6d9e331
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests22.dat
@@ -0,0 +1,190 @@
+#data
+<a><b><big><em><strong><div>X</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,33): adoption-agency-1.3
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <big>
+| <em>
+| <strong>
+| <big>
+| <em>
+| <strong>
+| <div>
+| <a>
+| "X"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8>A</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| "A"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9>A</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| <div>
+| id="9"
+| "A"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9><div id=10>A</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| <div>
+| id="9"
+| <div>
+| id="10"
+| "A"
+
+#data
+<cite><b><cite><i><cite><i><cite><i><div>X</b>TEST
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,46): adoption-agency-1.3
+(1,50): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <cite>
+| <b>
+| <cite>
+| <i>
+| <cite>
+| <i>
+| <cite>
+| <i>
+| <i>
+| <i>
+| <div>
+| <b>
+| "X"
+| "TEST"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests23.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests23.dat
new file mode 100644
index 0000000000..49e4a4ace5
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests23.dat
@@ -0,0 +1,168 @@
+#data
+<p><font size=4><font color=red><font size=4><font size=4><font size=4><font size=4><font size=4><font color=red><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,116): unexpected-end-tag
+(1,117): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| color="red"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| color="red"
+| <p>
+| <font>
+| color="red"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| color="red"
+| "X"
+
+#data
+<p><font size=4><font size=4><font size=4><font size=4><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,58): unexpected-end-tag
+(1,59): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><font size=4><font size=4><font size=4><font size="5"><font size=4><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,73): unexpected-end-tag
+(1,74): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><font size=4 id=a><font size=4 id=b><font size=4><font size=4><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,68): unexpected-end-tag
+(1,69): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| id="a"
+| size="4"
+| <font>
+| id="b"
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <p>
+| <font>
+| id="a"
+| size="4"
+| <font>
+| id="b"
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><b id=a><b id=a><b id=a><b><object><b id=a><b id=a>X</object><p>Y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,64): end-tag-too-early
+(1,67): unexpected-end-tag
+(1,68): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| <object>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| "X"
+| <p>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| "Y"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests24.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests24.dat
new file mode 100644
index 0000000000..f6dc7eb48a
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests24.dat
@@ -0,0 +1,79 @@
+#data
+<!DOCTYPE html>&NotEqualTilde;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "≂̸"
+
+#data
+<!DOCTYPE html>&NotEqualTilde;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "≂̸A"
+
+#data
+<!DOCTYPE html>&ThickSpace;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "âŸâ€Š"
+
+#data
+<!DOCTYPE html>&ThickSpace;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "âŸâ€ŠA"
+
+#data
+<!DOCTYPE html>&NotSubset;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "⊂⃒"
+
+#data
+<!DOCTYPE html>&NotSubset;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "⊂⃒A"
+
+#data
+<!DOCTYPE html>&Gopf;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "ð”¾"
+
+#data
+<!DOCTYPE html>&Gopf;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "ð”¾A"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests25.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests25.dat
new file mode 100644
index 0000000000..cbc00512b1
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests25.dat
@@ -0,0 +1,220 @@
+#data
+<!DOCTYPE html><body><foo>A
+#errors
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <foo>
+| "A"
+
+#data
+<!DOCTYPE html><body><area>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <area>
+| "A"
+
+#data
+<!DOCTYPE html><body><base>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <base>
+| "A"
+
+#data
+<!DOCTYPE html><body><basefont>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <basefont>
+| "A"
+
+#data
+<!DOCTYPE html><body><bgsound>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <bgsound>
+| "A"
+
+#data
+<!DOCTYPE html><body><br>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <br>
+| "A"
+
+#data
+<!DOCTYPE html><body><col>A
+#errors
+(1,26): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+
+#data
+<!DOCTYPE html><body><command>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <command>
+| "A"
+
+#data
+<!DOCTYPE html><body><embed>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <embed>
+| "A"
+
+#data
+<!DOCTYPE html><body><frame>A
+#errors
+(1,28): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+
+#data
+<!DOCTYPE html><body><hr>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <hr>
+| "A"
+
+#data
+<!DOCTYPE html><body><img>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+| "A"
+
+#data
+<!DOCTYPE html><body><input>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| "A"
+
+#data
+<!DOCTYPE html><body><keygen>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <keygen>
+| "A"
+
+#data
+<!DOCTYPE html><body><link>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <link>
+| "A"
+
+#data
+<!DOCTYPE html><body><meta>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+| "A"
+
+#data
+<!DOCTYPE html><body><param>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <param>
+| "A"
+
+#data
+<!DOCTYPE html><body><source>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <source>
+| "A"
+
+#data
+<!DOCTYPE html><body><track>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <track>
+| "A"
+
+#data
+<!DOCTYPE html><body><wbr>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <wbr>
+| "A"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests26.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests26.dat
new file mode 100644
index 0000000000..867bbeecd5
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests26.dat
@@ -0,0 +1,411 @@
+#data
+<!DOCTYPE html><body><a href='#1'><nobr>1<nobr></a><br><a href='#2'><nobr>2<nobr></a><br><a href='#3'><nobr>3<nobr></a>
+#errors
+(1,47): unexpected-start-tag-implies-end-tag
+(1,51): adoption-agency-1.3
+(1,74): unexpected-start-tag-implies-end-tag
+(1,74): adoption-agency-1.3
+(1,81): unexpected-start-tag-implies-end-tag
+(1,85): adoption-agency-1.3
+(1,108): unexpected-start-tag-implies-end-tag
+(1,108): adoption-agency-1.3
+(1,115): unexpected-start-tag-implies-end-tag
+(1,119): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| href="#1"
+| <nobr>
+| "1"
+| <nobr>
+| <nobr>
+| <br>
+| <a>
+| href="#2"
+| <a>
+| href="#2"
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| <br>
+| <a>
+| href="#3"
+| <a>
+| href="#3"
+| <nobr>
+| "3"
+| <nobr>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,37): unexpected-start-tag-implies-end-tag
+(1,41): adoption-agency-1.3
+(1,50): unexpected-start-tag-implies-end-tag
+(1,50): adoption-agency-1.3
+(1,57): unexpected-start-tag-implies-end-tag
+(1,61): adoption-agency-1.3
+(1,62): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,44): foster-parenting-start-tag
+(1,48): foster-parenting-end-tag
+(1,48): adoption-agency-1.3
+(1,51): foster-parenting-start-tag
+(1,57): foster-parenting-start-tag
+(1,57): nobr-already-in-scope
+(1,57): adoption-agency-1.2
+(1,58): foster-parenting-character
+(1,64): foster-parenting-start-tag
+(1,64): nobr-already-in-scope
+(1,68): foster-parenting-end-tag
+(1,68): adoption-agency-1.2
+(1,69): foster-parenting-character
+(1,69): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+| <table>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<table><tr><td><nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,56): unexpected-end-tag
+(1,65): unexpected-start-tag-implies-end-tag
+(1,65): adoption-agency-1.3
+(1,72): unexpected-start-tag-implies-end-tag
+(1,76): adoption-agency-1.3
+(1,77): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<div><nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,42): unexpected-start-tag-implies-end-tag
+(1,42): adoption-agency-1.3
+(1,46): adoption-agency-1.3
+(1,46): adoption-agency-1.3
+(1,55): unexpected-start-tag-implies-end-tag
+(1,55): adoption-agency-1.3
+(1,62): unexpected-start-tag-implies-end-tag
+(1,66): adoption-agency-1.3
+(1,67): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <div>
+| <b>
+| <nobr>
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr></b><div><i><nobr>2<nobr></i>3
+#errors
+(1,37): unexpected-start-tag-implies-end-tag
+(1,41): adoption-agency-1.3
+(1,55): unexpected-start-tag-implies-end-tag
+(1,55): adoption-agency-1.3
+(1,62): unexpected-start-tag-implies-end-tag
+(1,66): adoption-agency-1.3
+(1,67): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <div>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr><ins></b><i><nobr>
+#errors
+(1,37): unexpected-start-tag-implies-end-tag
+(1,46): adoption-agency-1.3
+(1,55): unexpected-start-tag-implies-end-tag
+(1,55): adoption-agency-1.3
+(1,55): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <ins>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<ins><nobr></b><i>2
+#errors
+(1,42): unexpected-start-tag-implies-end-tag
+(1,42): adoption-agency-1.3
+(1,46): adoption-agency-1.3
+(1,50): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <ins>
+| <nobr>
+| <nobr>
+| <i>
+| "2"
+
+#data
+<!DOCTYPE html><body><b>1<nobr></b><i><nobr>2</i>
+#errors
+(1,35): adoption-agency-1.3
+(1,44): unexpected-start-tag-implies-end-tag
+(1,44): adoption-agency-1.3
+(1,49): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| "1"
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+
+#data
+<p><code x</code></p>
+
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): invalid-character-in-attribute-name
+(1,12): unexpected-character-after-solidus-in-tag
+(1,21): unexpected-end-tag
+(2,0): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <code>
+| code=""
+| x<=""
+| <code>
+| code=""
+| x<=""
+| "
+"
+
+#data
+<!DOCTYPE html><svg><foreignObject><p><i></p>a
+#errors
+(1,45): unexpected-end-tag
+(1,46): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a
+#errors
+(1,60): unexpected-end-tag
+(1,61): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><math><mtext><p><i></p>a
+#errors
+(1,38): unexpected-end-tag
+(1,39): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a
+#errors
+(1,53): unexpected-end-tag
+(1,54): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><body><div><!/div>a
+#errors
+(1,28): expected-dashes-or-doctype
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- /div -->
+| "a"
+
+#data
+<button><p><button>
+#errors
+Line 1 Col 8 Unexpected start tag (button). Expected DOCTYPE.
+Line 1 Col 19 Unexpected start tag (button) implies end tag (button).
+Line 1 Col 19 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| <p>
+| <button>
+
+#data
+<!DOCTYPE html><html><frameset></frameset></html></frameset>
+#errors
+60: Stray end tag “framesetâ€.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><html><frameset></frameset></html>XXX</frameset>
+#errors
+52: Non-space character in page trailer.
+52: Non-space character in page trailer.
+52: Non-space character in page trailer.
+63: Stray end tag “framesetâ€.
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests3.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests3.dat
new file mode 100644
index 0000000000..423e2b3cab
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests3.dat
@@ -0,0 +1,306 @@
+#data
+<head></head><style></style>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,20): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <style>
+| <body>
+
+#data
+<head></head><script></script>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<head></head><!-- --><style></style><!-- --><script></script>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,28): unexpected-start-tag-out-of-my-head
+(1,52): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <style>
+| <script>
+| <!-- -->
+| <!-- -->
+| <body>
+
+#data
+<head></head><!-- -->x<style></style><!-- --><script></script>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <!-- -->
+| <body>
+| "x"
+| <style>
+| <!-- -->
+| <script>
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+foo</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+
+foo</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "
+foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+foo
+</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "foo
+"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x</pre><span>
+</span></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x"
+| <span>
+| "
+"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x
+y</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x
+y"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x<div>
+y</pre></body></html>
+#errors
+(2,7): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x"
+| <div>
+| "
+y"
+
+#data
+<!DOCTYPE html><pre>&#x0a;&#x0a;A</pre>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "
+A"
+
+#data
+<!DOCTYPE html><HTML><META><HEAD></HEAD></HTML>
+#errors
+(1,33): two-heads-are-not-better-than-one
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| <body>
+
+#data
+<!DOCTYPE html><HTML><HEAD><head></HEAD></HTML>
+#errors
+(1,33): two-heads-are-not-better-than-one
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<textarea>foo<span>bar</span><i>baz
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "foo<span>bar</span><i>baz"
+
+#data
+<title>foo<span>bar</em><i>baz
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <title>
+| "foo<span>bar</em><i>baz"
+| <body>
+
+#data
+<!DOCTYPE html><textarea>
+</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+
+#data
+<!DOCTYPE html><textarea>
+foo</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "foo"
+
+#data
+<!DOCTYPE html><textarea>
+
+foo</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "
+foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><ul><li><div><p><li></ul></body></html>
+#errors
+(1,60): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| <p>
+| <li>
+
+#data
+<!doctype html><nobr><nobr><nobr>
+#errors
+(1,27): unexpected-start-tag-implies-end-tag
+(1,33): unexpected-start-tag-implies-end-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <nobr>
+| <nobr>
+| <nobr>
+
+#data
+<!doctype html><nobr><nobr></nobr><nobr>
+#errors
+(1,27): unexpected-start-tag-implies-end-tag
+(1,40): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <nobr>
+| <nobr>
+| <nobr>
+
+#data
+<!doctype html><html><body><p><table></table></body></html>
+#errors
+Not known
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <table>
+
+#data
+<p><table></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <table>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests4.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests4.dat
new file mode 100644
index 0000000000..0a6174c36c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests4.dat
@@ -0,0 +1,58 @@
+#data
+direct div content
+#errors
+#document-fragment
+div
+#document
+| "direct div content"
+
+#data
+direct textarea content
+#errors
+#document-fragment
+textarea
+#document
+| "direct textarea content"
+
+#data
+textarea content with <em>pseudo</em> <foo>markup
+#errors
+#document-fragment
+textarea
+#document
+| "textarea content with <em>pseudo</em> <foo>markup"
+
+#data
+this is &#x0043;DATA inside a <style> element
+#errors
+#document-fragment
+style
+#document
+| "this is &#x0043;DATA inside a <style> element"
+
+#data
+</plaintext>
+#errors
+#document-fragment
+plaintext
+#document
+| "</plaintext>"
+
+#data
+setting html's innerHTML
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| "setting html's innerHTML"
+
+#data
+<title>setting head's innerHTML</title>
+#errors
+#document-fragment
+head
+#document
+| <title>
+| "setting head's innerHTML"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests5.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests5.dat
new file mode 100644
index 0000000000..4d5fcd7a79
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests5.dat
@@ -0,0 +1,197 @@
+#data
+<style> <!-- </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!-- "
+| <body>
+| "x"
+
+#data
+<style> <!-- </style> --> </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,34): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<style> <!--> </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!--> "
+| <body>
+| "x"
+
+#data
+<style> <!---> </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!---> "
+| <body>
+| "x"
+
+#data
+<iframe> <!---> </iframe>x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| " <!---> "
+| "x"
+
+#data
+<iframe> <!--- </iframe>->x</iframe> --> </iframe>x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,36): unexpected-end-tag
+(1,50): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| " <!--- "
+| "->x --> x"
+
+#data
+<script> <!-- </script> --> </script>x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,37): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<title> <!-- </title> --> </title>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,34): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <title>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<textarea> <!--- </textarea>->x</textarea> --> </textarea>x
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,42): unexpected-end-tag
+(1,58): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| " <!--- "
+| "->x --> x"
+
+#data
+<style> <!</-- </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!</-- "
+| <body>
+| "x"
+
+#data
+<p><xmp></xmp>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <xmp>
+
+#data
+<xmp> <!-- > --> </xmp>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <xmp>
+| " <!-- > --> "
+
+#data
+<title>&amp;</title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "&"
+| <body>
+
+#data
+<title><!--&amp;--></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<!--&-->"
+| <body>
+
+#data
+<title><!--</title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<!--"
+| <body>
+
+#data
+<noscript><!--</noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,39): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "-->"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests6.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests6.dat
new file mode 100644
index 0000000000..fedc64e938
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests6.dat
@@ -0,0 +1,662 @@
+#data
+<!doctype html></head> <head>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| " "
+| <body>
+
+#data
+<!doctype html><form><div></form><div>
+#errors
+(1,33): end-tag-too-early-ignored
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <div>
+| <div>
+
+#data
+<!doctype html><title>&amp;</title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "&"
+| <body>
+
+#data
+<!doctype html><title><!--&amp;--></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "<!--&-->"
+| <body>
+
+#data
+<!doctype>
+#errors
+(1,9): need-space-after-doctype
+(1,10): expected-doctype-name-but-got-right-bracket
+(1,10): unknown-doctype
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+
+#data
+<!---x
+#errors
+(1,6): eof-in-comment
+(1,6): expected-doctype-but-got-eof
+#document
+| <!-- -x -->
+| <html>
+| <head>
+| <body>
+
+#data
+<body>
+<div>
+#errors
+(1,6): unexpected-start-tag
+(2,5): expected-closing-tag-but-got-eof
+#document-fragment
+div
+#document
+| "
+"
+| <div>
+
+#data
+<frameset></frameset>
+foo
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,1): unexpected-char-after-frameset
+(2,2): unexpected-char-after-frameset
+(2,3): unexpected-char-after-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+<noframes>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,10): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+| <noframes>
+
+#data
+<frameset></frameset>
+<div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,5): unexpected-start-tag-after-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+</html>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+</div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,6): unexpected-end-tag-after-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<form><form>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,12): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+
+#data
+<button><button>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): unexpected-start-tag-implies-end-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| <button>
+
+#data
+<table><tr><td></th>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-end-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><caption><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): XXX-undefined-error
+(1,20): unexpected-cell-in-table-body
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><caption><div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+</caption><div>
+#errors
+(1,10): XXX-undefined-error
+(1,15): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <div>
+
+#data
+<table><caption><div></caption>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,31): expected-one-end-tag-but-got-another
+(1,31): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+<table><caption></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,24): end-table-tag-in-caption
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+
+#data
+</table><div>
+#errors
+(1,8): unexpected-end-tag
+(1,13): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <div>
+
+#data
+<table><caption></body></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+(1,29): unexpected-end-tag
+(1,40): unexpected-end-tag
+(1,47): unexpected-end-tag
+(1,55): unexpected-end-tag
+(1,60): unexpected-end-tag
+(1,68): unexpected-end-tag
+(1,73): unexpected-end-tag
+(1,81): unexpected-end-tag
+(1,86): unexpected-end-tag
+(1,86): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+
+#data
+<table><caption><div></div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+<table><tr><td></body></caption></col></colgroup></html>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): unexpected-end-tag
+(1,32): unexpected-end-tag
+(1,38): unexpected-end-tag
+(1,49): unexpected-end-tag
+(1,56): unexpected-end-tag
+(1,56): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+</table></tbody></tfoot></thead></tr><div>
+#errors
+(1,8): unexpected-end-tag
+(1,16): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,32): unexpected-end-tag
+(1,37): unexpected-end-tag
+(1,42): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <div>
+
+#data
+<table><colgroup>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): foster-parenting-character-in-table
+(1,19): foster-parenting-character-in-table
+(1,20): foster-parenting-character-in-table
+(1,20): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "foo"
+| <table>
+| <colgroup>
+
+#data
+foo<col>
+#errors
+(1,1): unexpected-character-in-colgroup
+(1,2): unexpected-character-in-colgroup
+(1,3): unexpected-character-in-colgroup
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<table><colgroup></col>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,23): no-end-tag
+(1,23): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+
+#data
+<frameset><div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-in-frameset
+(1,15): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</frameset><frame>
+#errors
+(1,11): unexpected-frameset-in-frameset-innerhtml
+#document-fragment
+frameset
+#document
+| <frame>
+
+#data
+<frameset></div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,16): unexpected-end-tag-in-frameset
+(1,16): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</body><div>
+#errors
+(1,7): unexpected-close-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <div>
+
+#data
+<table><tr><div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,16): unexpected-start-tag-implies-table-voodoo
+(1,16): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+</tr><td>
+#errors
+(1,5): unexpected-end-tag
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+</tbody></tfoot></thead><td>
+#errors
+(1,8): unexpected-end-tag
+(1,16): unexpected-end-tag
+(1,24): unexpected-end-tag
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<table><tr><div><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,16): foster-parenting-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<caption><col><colgroup><tbody><tfoot><thead><tr>
+#errors
+(1,9): unexpected-start-tag
+(1,14): unexpected-start-tag
+(1,24): unexpected-start-tag
+(1,31): unexpected-start-tag
+(1,38): unexpected-start-tag
+(1,45): unexpected-start-tag
+#document-fragment
+tbody
+#document
+| <tr>
+
+#data
+<table><tbody></thead>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): unexpected-end-tag-in-table-body
+(1,22): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+</table><tr>
+#errors
+(1,8): unexpected-end-tag
+#document-fragment
+tbody
+#document
+| <tr>
+
+#data
+<table><tbody></body></caption></col></colgroup></html></td></th></tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,21): unexpected-end-tag-in-table-body
+(1,31): unexpected-end-tag-in-table-body
+(1,37): unexpected-end-tag-in-table-body
+(1,48): unexpected-end-tag-in-table-body
+(1,55): unexpected-end-tag-in-table-body
+(1,60): unexpected-end-tag-in-table-body
+(1,65): unexpected-end-tag-in-table-body
+(1,70): unexpected-end-tag-in-table-body
+(1,70): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+<table><tbody></div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-end-tag-implies-table-voodoo
+(1,20): end-tag-too-early
+(1,20): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+<table><table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-start-tag-implies-end-tag
+(1,14): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <table>
+
+#data
+<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,30): unexpected-end-tag
+(1,41): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,56): unexpected-end-tag
+(1,61): unexpected-end-tag
+(1,69): unexpected-end-tag
+(1,74): unexpected-end-tag
+(1,82): unexpected-end-tag
+(1,87): unexpected-end-tag
+(1,87): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+
+#data
+</table><tr>
+#errors
+(1,8): unexpected-end-tag
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+<body></body></html>
+#errors
+(1,20): unexpected-end-tag-after-body-innerhtml
+#document-fragment
+html
+#document
+| <head>
+| <body>
+
+#data
+<html><frameset></frameset></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html></html>
+#errors
+(1,50): unknown-doctype element.
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "">
+| <html>
+| <head>
+| <body>
+
+#data
+<param><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<source><frameset></frameset>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,18): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<track><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</html><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-end-tag
+(1,17): expected-eof-but-got-start-tag
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</body><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-end-tag
+(1,17): unexpected-start-tag-after-body
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests7.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests7.dat
new file mode 100644
index 0000000000..f9471b9a34
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests7.dat
@@ -0,0 +1,402 @@
+#data
+<!doctype html><body><title>X</title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+
+#data
+<!doctype html><table><title>X</title></table>
+#errors
+(1,29): unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+| <table>
+
+#data
+<!doctype html><head></head><title>X</title>
+#errors
+(1,35): unexpected-start-tag-out-of-my-head
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "X"
+| <body>
+
+#data
+<!doctype html></head><title>X</title>
+#errors
+(1,29): unexpected-start-tag-out-of-my-head
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "X"
+| <body>
+
+#data
+<!doctype html><table><meta></table>
+#errors
+(1,28): unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+| <table>
+
+#data
+<!doctype html><table>X<tr><td><table> <meta></table></table>
+#errors
+(1,45): unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <meta>
+| <table>
+| " "
+
+#data
+<!doctype html><html> <head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html> <head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html><table><style> <tr>x </style> </table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <style>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><table><TBODY><script> <tr>x </script> </table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <script>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><p><applet><p>X</p></applet>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <applet>
+| <p>
+| "X"
+
+#data
+<!doctype html><listing>
+X</listing>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <listing>
+| "X"
+
+#data
+<!doctype html><select><input>X
+#errors
+(1,30): unexpected-input-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <input>
+| "X"
+
+#data
+<!doctype html><select><select>X
+#errors
+(1,31): unexpected-select-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+
+#data
+<!doctype html><table><input type=hidDEN></table>
+#errors
+(1,41): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table>X<input type=hidDEN></table>
+#errors
+(1,23): foster-parenting-character
+(1,42): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table> <input type=hidDEN></table>
+#errors
+(1,43): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table> <input type='hidDEN'></table>
+#errors
+(1,45): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table><input type=" hidden"><input type=hidDEN></table>
+#errors
+(1,44): unexpected-start-tag-implies-table-voodoo
+(1,63): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| type=" hidden"
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table><select>X<tr>
+#errors
+(1,30): unexpected-start-tag-implies-table-voodoo
+(1,35): unexpected-table-element-start-tag-in-select-in-table
+(1,35): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><select>X</select>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+
+#data
+<!DOCTYPE hTmL><html></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML><html></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<body>X</body></body>
+#errors
+(1,21): unexpected-end-tag-after-body
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| "X"
+
+#data
+<div><p>a</x> b
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): unexpected-end-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <p>
+| "a b"
+
+#data
+<table><tr><td><code></code> </table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <code>
+| " "
+
+#data
+<table><b><tr><td>aaa</td></tr>bbb</table>ccc
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,10): foster-parenting-start-tag
+(1,32): foster-parenting-character
+(1,33): foster-parenting-character
+(1,34): foster-parenting-character
+(1,45): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| "bbb"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "aaa"
+| <b>
+| "ccc"
+
+#data
+A<table><tr> B</tr> B</table>
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,13): foster-parenting-character
+(1,14): foster-parenting-character
+(1,20): foster-parenting-character
+(1,21): foster-parenting-character
+#document
+| <html>
+| <head>
+| <body>
+| "A B B"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+A<table><tr> B</tr> </em>C</table>
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,13): foster-parenting-character
+(1,14): foster-parenting-character
+(1,20): foster-parenting-character
+(1,25): unexpected-end-tag
+(1,26): foster-parenting-character
+#document
+| <html>
+| <head>
+| <body>
+| "A BC"
+| <table>
+| <tbody>
+| <tr>
+| " "
+
+#data
+<select><keygen>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): unexpected-input-in-select
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <keygen>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests8.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests8.dat
new file mode 100644
index 0000000000..93289f39c5
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests8.dat
@@ -0,0 +1,149 @@
+#data
+<div>
+<div></div>
+</span>x
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(3,7): unexpected-end-tag
+(3,8): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "
+"
+| <div>
+| "
+x"
+
+#data
+<div>x<div></div>
+</span>x
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(2,7): unexpected-end-tag
+(2,8): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "
+x"
+
+#data
+<div>x<div></div>x</span>x
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,25): unexpected-end-tag
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "xx"
+
+#data
+<div>x<div></div>y</span>z
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,25): unexpected-end-tag
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "yz"
+
+#data
+<table><div>x<div></div>x</span>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,12): foster-parenting-start-tag
+(1,13): foster-parenting-character
+(1,18): foster-parenting-start-tag
+(1,24): foster-parenting-end-tag
+(1,25): foster-parenting-start-tag
+(1,32): foster-parenting-end-tag
+(1,32): unexpected-end-tag
+(1,33): foster-parenting-character
+(1,33): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "xx"
+| <table>
+
+#data
+x<table>x
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,9): foster-parenting-character
+#document
+| <html>
+| <head>
+| <body>
+| "xx"
+| <table>
+
+#data
+x<table><table>x
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,15): unexpected-start-tag-implies-end-tag
+(1,16): foster-parenting-character
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <table>
+| "x"
+| <table>
+
+#data
+<b>a<div></div><div></b>y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,24): adoption-agency-1.3
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "a"
+| <div>
+| <div>
+| <b>
+| "y"
+
+#data
+<a><div><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+(1,15): adoption-agency-1.3
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <div>
+| <a>
+| <p>
+| <a>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests9.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests9.dat
new file mode 100644
index 0000000000..40651a0613
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests9.dat
@@ -0,0 +1,473 @@
+#data
+<!DOCTYPE html><math></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!DOCTYPE html><body><math></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!DOCTYPE html><math><mi>
+#errors
+(1,25) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+
+#data
+<!DOCTYPE html><math><annotation-xml><svg><u>
+#errors
+(1,45) unexpected-html-element-in-foreign-content
+(1,45) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <u>
+
+#data
+<!DOCTYPE html><body><select><math></math></select>
+#errors
+(1,35) unexpected-start-tag-in-select
+(1,42) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!DOCTYPE html><body><select><option><math></math></option></select>
+#errors
+(1,43) unexpected-start-tag-in-select
+(1,50) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!DOCTYPE html><body><table><math></math></table>
+#errors
+(1,34) unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <table>
+
+#data
+<!DOCTYPE html><body><table><math><mi>foo</mi></math></table>
+#errors
+(1,34) foster-parenting-start-token
+(1,39) foster-parenting-character
+(1,40) foster-parenting-character
+(1,41) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><math><mi>foo</mi><mi>bar</mi></math></table>
+#errors
+(1,34) foster-parenting-start-tag
+(1,39) foster-parenting-character
+(1,40) foster-parenting-character
+(1,41) foster-parenting-character
+(1,51) foster-parenting-character
+(1,52) foster-parenting-character
+(1,53) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><tbody><math><mi>foo</mi><mi>bar</mi></math></tbody></table>
+#errors
+(1,41) foster-parenting-start-tag
+(1,46) foster-parenting-character
+(1,47) foster-parenting-character
+(1,48) foster-parenting-character
+(1,58) foster-parenting-character
+(1,59) foster-parenting-character
+(1,60) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+| <tbody>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><math><mi>foo</mi><mi>bar</mi></math></tr></tbody></table>
+#errors
+(1,45) foster-parenting-start-tag
+(1,50) foster-parenting-character
+(1,51) foster-parenting-character
+(1,52) foster-parenting-character
+(1,62) foster-parenting-character
+(1,63) foster-parenting-character
+(1,64) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math></td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math><p>baz</td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi></math><p>baz</caption></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,70) unexpected-html-element-in-foreign-content
+(1,81) XXX-undefined-error
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi>baz</table><p>quux
+#errors
+(1,78) unexpected-end-tag
+(1,78) expected-one-end-tag-but-got-another
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><colgroup><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,44) foster-parenting-start-tag
+(1,49) foster-parenting-character
+(1,50) foster-parenting-character
+(1,51) foster-parenting-character
+(1,61) foster-parenting-character
+(1,62) foster-parenting-character
+(1,63) foster-parenting-character
+(1,71) unexpected-html-element-in-foreign-content
+(1,71) foster-parenting-start-tag
+(1,63) foster-parenting-character
+(1,63) foster-parenting-character
+(1,63) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+| <table>
+| <colgroup>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><tr><td><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,50) unexpected-start-tag-in-select
+(1,54) unexpected-start-tag-in-select
+(1,62) unexpected-end-tag-in-select
+(1,66) unexpected-start-tag-in-select
+(1,74) unexpected-end-tag-in-select
+(1,77) unexpected-start-tag-in-select
+(1,88) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| "foobarbaz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,36) unexpected-start-tag-implies-table-voodoo
+(1,42) unexpected-start-tag-in-select
+(1,46) unexpected-start-tag-in-select
+(1,54) unexpected-end-tag-in-select
+(1,58) unexpected-start-tag-in-select
+(1,66) unexpected-end-tag-in-select
+(1,69) unexpected-start-tag-in-select
+(1,80) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "foobarbaz"
+| <table>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body></body></html><math><mi>foo</mi><mi>bar</mi><p>baz
+#errors
+(1,41) expected-eof-but-got-start-tag
+(1,68) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body></body><math><mi>foo</mi><mi>bar</mi><p>baz
+#errors
+(1,34) unexpected-start-tag-after-body
+(1,61) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><frameset><math><mi></mi><mi></mi><p><span>
+#errors
+(1,31) unexpected-start-tag-in-frameset
+(1,35) unexpected-start-tag-in-frameset
+(1,40) unexpected-end-tag-in-frameset
+(1,44) unexpected-start-tag-in-frameset
+(1,49) unexpected-end-tag-in-frameset
+(1,52) unexpected-start-tag-in-frameset
+(1,58) unexpected-start-tag-in-frameset
+(1,58) eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset></frameset><math><mi></mi><mi></mi><p><span>
+#errors
+(1,42) unexpected-start-tag-after-frameset
+(1,46) unexpected-start-tag-after-frameset
+(1,51) unexpected-end-tag-after-frameset
+(1,55) unexpected-start-tag-after-frameset
+(1,60) unexpected-end-tag-after-frameset
+(1,63) unexpected-start-tag-after-frameset
+(1,69) unexpected-start-tag-after-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><body xlink:href=foo><math xlink:href=foo></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| <math math>
+| xlink href="foo"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo></mi></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo /></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo />bar</math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+| "bar"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests_innerHTML_1.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests_innerHTML_1.dat
new file mode 100644
index 0000000000..5ede639bcc
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tests_innerHTML_1.dat
@@ -0,0 +1,902 @@
+#data
+<body><span>
+#errors
+(1,6): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><body>
+#errors
+(1,12): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><body>
+#errors
+(1,12): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+div
+#document
+| <span>
+
+#data
+<body><span>
+#errors
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| <span>
+
+#data
+<frameset><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><frameset>
+#errors
+(1,16): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><frameset>
+#errors
+(1,16): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+div
+#document
+| <span>
+
+#data
+<frameset><span>
+#errors
+(1,16): unexpected-start-tag-in-frameset
+(1,16): eof-in-frameset
+#document-fragment
+html
+#document
+| <head>
+| <frameset>
+
+#data
+<table><tr>
+#errors
+(1,7): unexpected-start-tag
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+</table><tr>
+#errors
+(1,8): unexpected-end-tag
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+<a>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,3): eof-in-table
+#document-fragment
+table
+#document
+| <a>
+
+#data
+<a>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,3): eof-in-table
+#document-fragment
+table
+#document
+| <a>
+
+#data
+<a><caption>a
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,13): expected-closing-tag-but-got-eof
+#document-fragment
+table
+#document
+| <a>
+| <caption>
+| "a"
+
+#data
+<a><colgroup><col>
+#errors
+(1,3): foster-parenting-start-token
+(1,18): expected-closing-tag-but-got-eof
+#document-fragment
+table
+#document
+| <a>
+| <colgroup>
+| <col>
+
+#data
+<a><tbody><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+
+#data
+<a><tfoot><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <tfoot>
+| <tr>
+
+#data
+<a><thead><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <thead>
+| <tr>
+
+#data
+<a><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+
+#data
+<a><th>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+| <th>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table></table><tbody>
+#errors
+(1,22): unexpected-start-tag
+#document-fragment
+caption
+#document
+| <table>
+
+#data
+</table><span>
+#errors
+(1,8): unexpected-end-tag
+(1,14): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+<span></table>
+#errors
+(1,14): unexpected-end-tag
+(1,14): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+</caption><span>
+#errors
+(1,10): XXX-undefined-error
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+<span></caption><span>
+#errors
+(1,16): XXX-undefined-error
+(1,22): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><caption><span>
+#errors
+(1,15): unexpected-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><col><span>
+#errors
+(1,11): unexpected-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><colgroup><span>
+#errors
+(1,16): unexpected-start-tag
+(1,22): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><html><span>
+#errors
+(1,12): non-html-root
+(1,18): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tbody><span>
+#errors
+(1,13): unexpected-start-tag
+(1,19): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><td><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tfoot><span>
+#errors
+(1,13): unexpected-start-tag
+(1,19): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><thead><span>
+#errors
+(1,13): unexpected-start-tag
+(1,19): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><th><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tr><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span></table><span>
+#errors
+(1,14): unexpected-end-tag
+(1,20): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+</colgroup><col>
+#errors
+(1,11): XXX-undefined-error
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<a><col>
+#errors
+(1,3): XXX-undefined-error
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<caption><a>
+#errors
+(1,9): XXX-undefined-error
+(1,12): unexpected-start-tag-implies-table-voodoo
+(1,12): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<col><a>
+#errors
+(1,5): XXX-undefined-error
+(1,8): unexpected-start-tag-implies-table-voodoo
+(1,8): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<colgroup><a>
+#errors
+(1,10): XXX-undefined-error
+(1,13): unexpected-start-tag-implies-table-voodoo
+(1,13): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<tbody><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,10): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<tfoot><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,10): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<thead><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,10): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+</table><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): unexpected-start-tag-implies-table-voodoo
+(1,11): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<a><tr>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<td><table><tbody><a><tr>
+#errors
+(1,4): unexpected-cell-in-table-body
+(1,21): unexpected-start-tag-implies-table-voodoo
+(1,25): eof-in-table
+#document-fragment
+tbody
+#document
+| <tr>
+| <td>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+</tr><td>
+#errors
+(1,5): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<td><table><a><tr></tr><tr>
+#errors
+(1,14): unexpected-start-tag-implies-table-voodoo
+(1,27): eof-in-table
+#document-fragment
+tr
+#document
+| <td>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <tr>
+
+#data
+<caption><td>
+#errors
+(1,9): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<col><td>
+#errors
+(1,5): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<colgroup><td>
+#errors
+(1,10): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tbody><td>
+#errors
+(1,7): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tfoot><td>
+#errors
+(1,7): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<thead><td>
+#errors
+(1,7): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tr><td>
+#errors
+(1,4): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+</table><td>
+#errors
+(1,8): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<td><table></table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <table>
+| <td>
+
+#data
+<td><table></table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <table>
+| <td>
+
+#data
+<caption><a>
+#errors
+(1,9): XXX-undefined-error
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<col><a>
+#errors
+(1,5): XXX-undefined-error
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<colgroup><a>
+#errors
+(1,10): XXX-undefined-error
+(1,13): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tbody><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tfoot><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<th><a>
+#errors
+(1,4): XXX-undefined-error
+(1,7): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<thead><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tr><a>
+#errors
+(1,4): XXX-undefined-error
+(1,7): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</table><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tbody><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</td><a>
+#errors
+(1,5): unexpected-end-tag
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tfoot><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</thead><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</th><a>
+#errors
+(1,5): unexpected-end-tag
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tr><a>
+#errors
+(1,5): XXX-undefined-error
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<table><td><td>
+#errors
+(1,11): unexpected-cell-in-table-body
+(1,15): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <td>
+
+#data
+</select><option>
+#errors
+(1,9): XXX-undefined-error
+(1,17): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<input><option>
+#errors
+(1,7): unexpected-input-in-select
+(1,15): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<keygen><option>
+#errors
+(1,8): unexpected-input-in-select
+(1,16): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<textarea><option>
+#errors
+(1,10): unexpected-input-in-select
+(1,18): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+</html><!--abc-->
+#errors
+(1,7): unexpected-end-tag-after-body-innerhtml
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| <!-- abc -->
+
+#data
+</frameset><frame>
+#errors
+(1,11): unexpected-frameset-in-frameset-innerhtml
+#document-fragment
+frameset
+#document
+| <frame>
+
+#data
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
+
+#data
+<head></head><script></script>
+#errors
+21: “script†element between “head†and “bodyâ€.
+#document-fragment
+html
+#document
+| <head>
+| <script>
+| <body>
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tricky01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tricky01.dat
new file mode 100644
index 0000000000..f7065214ea
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/tricky01.dat
@@ -0,0 +1,334 @@
+#data
+<b><p>Bold </b> Not bold</p>
+Also not bold.
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <p>
+| <b>
+| "Bold "
+| " Not bold"
+| "
+Also not bold."
+
+#data
+<html>
+<font color=red><i>Italic and Red<p>Italic and Red </font> Just italic.</p> Italic only.</i> Plain
+<p>I should not be red. <font color=red>Red. <i>Italic and red.</p>
+<p>Italic and red. </i> Red.</font> I should not be red.</p>
+<b>Bold <i>Bold and italic</b> Only Italic </i> Plain
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(2,58): adoption-agency-1.3
+(3,67): unexpected-end-tag
+(4,23): adoption-agency-1.3
+(4,35): adoption-agency-1.3
+(5,30): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| color="red"
+| <i>
+| "Italic and Red"
+| <i>
+| <p>
+| <font>
+| color="red"
+| "Italic and Red "
+| " Just italic."
+| " Italic only."
+| " Plain
+"
+| <p>
+| "I should not be red. "
+| <font>
+| color="red"
+| "Red. "
+| <i>
+| "Italic and red."
+| <font>
+| color="red"
+| <i>
+| "
+"
+| <p>
+| <font>
+| color="red"
+| <i>
+| "Italic and red. "
+| " Red."
+| " I should not be red."
+| "
+"
+| <b>
+| "Bold "
+| <i>
+| "Bold and italic"
+| <i>
+| " Only Italic "
+| " Plain"
+
+#data
+<html><body>
+<p><font size="7">First paragraph.</p>
+<p>Second paragraph.</p></font>
+<b><p><i>Bold and Italic</b> Italic</p>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(2,38): unexpected-end-tag
+(4,28): adoption-agency-1.3
+(4,28): adoption-agency-1.3
+(4,39): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <p>
+| <font>
+| size="7"
+| "First paragraph."
+| <font>
+| size="7"
+| "
+"
+| <p>
+| "Second paragraph."
+| "
+"
+| <b>
+| <p>
+| <b>
+| <i>
+| "Bold and Italic"
+| <i>
+| " Italic"
+
+#data
+<html>
+<dl>
+<dt><b>Boo
+<dd>Goo?
+</dl>
+</html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(4,4): end-tag-too-early
+(5,5): end-tag-too-early
+(6,7): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| <dl>
+| "
+"
+| <dt>
+| <b>
+| "Boo
+"
+| <dd>
+| <b>
+| "Goo?
+"
+| <b>
+| "
+"
+
+#data
+<html><body>
+<label><a><div>Hello<div>World</div></a></label>
+</body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(2,40): adoption-agency-1.3
+(2,48): unexpected-end-tag
+(3,7): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <label>
+| <a>
+| <div>
+| <a>
+| "Hello"
+| <div>
+| "World"
+| "
+"
+
+#data
+<table><center> <font>a</center> <img> <tr><td> </td> </tr> </table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): foster-parenting-start-tag
+(1,16): foster-parenting-character
+(1,22): foster-parenting-start-tag
+(1,23): foster-parenting-character
+(1,32): foster-parenting-end-tag
+(1,32): end-tag-too-early
+(1,33): foster-parenting-character
+(1,38): foster-parenting-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <center>
+| " "
+| <font>
+| "a"
+| <font>
+| <img>
+| " "
+| <table>
+| " "
+| <tbody>
+| <tr>
+| <td>
+| " "
+| " "
+| " "
+
+#data
+<table><tr><p><a><p>You should see this text.
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-start-tag-implies-table-voodoo
+(1,17): unexpected-start-tag-implies-table-voodoo
+(1,20): unexpected-start-tag-implies-table-voodoo
+(1,20): closing-non-current-p-element
+(1,21): foster-parenting-character
+(1,22): foster-parenting-character
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+(1,26): foster-parenting-character
+(1,27): foster-parenting-character
+(1,28): foster-parenting-character
+(1,29): foster-parenting-character
+(1,30): foster-parenting-character
+(1,31): foster-parenting-character
+(1,32): foster-parenting-character
+(1,33): foster-parenting-character
+(1,34): foster-parenting-character
+(1,35): foster-parenting-character
+(1,36): foster-parenting-character
+(1,37): foster-parenting-character
+(1,38): foster-parenting-character
+(1,39): foster-parenting-character
+(1,40): foster-parenting-character
+(1,41): foster-parenting-character
+(1,42): foster-parenting-character
+(1,43): foster-parenting-character
+(1,44): foster-parenting-character
+(1,45): foster-parenting-character
+(1,45): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <a>
+| <p>
+| <a>
+| "You should see this text."
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<TABLE>
+<TR>
+<CENTER><CENTER><TD></TD></TR><TR>
+<FONT>
+<TABLE><tr></tr></TABLE>
+</P>
+<a></font><font></a>
+This page contains an insanely badly-nested tag sequence.
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(3,8): unexpected-start-tag-implies-table-voodoo
+(3,16): unexpected-start-tag-implies-table-voodoo
+(4,6): unexpected-start-tag-implies-table-voodoo
+(5,7): unexpected-start-tag-implies-end-tag
+(7,10): adoption-agency-1.3
+(7,20): adoption-agency-1.3
+(8,57): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <center>
+| <center>
+| <font>
+| "
+"
+| <table>
+| "
+"
+| <tbody>
+| <tr>
+| "
+"
+| <td>
+| <tr>
+| "
+"
+| <table>
+| <tbody>
+| <tr>
+| <font>
+| "
+"
+| <p>
+| "
+"
+| <a>
+| <a>
+| <font>
+| <font>
+| "
+This page contains an insanely badly-nested tag sequence."
+
+#data
+<html>
+<body>
+<b><nobr><div>This text is in a div inside a nobr</nobr>More text that should not be in the nobr, i.e., the
+nobr should have closed the div inside it implicitly. </b><pre>A pre tag outside everything else.</pre>
+</body>
+</html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(3,56): adoption-agency-1.3
+(4,58): adoption-agency-1.3
+(5,7): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <b>
+| <nobr>
+| <div>
+| <b>
+| <nobr>
+| "This text is in a div inside a nobr"
+| "More text that should not be in the nobr, i.e., the
+nobr should have closed the div inside it implicitly. "
+| <pre>
+| "A pre tag outside everything else."
+| "
+
+"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit01.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit01.dat
new file mode 100644
index 0000000000..c480accd95
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit01.dat
@@ -0,0 +1,705 @@
+#data
+Test
+#errors
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<div></div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<div>Test</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Test"
+
+#data
+<di
+#errors
+(1,3): eof-in-tag-name
+(1,3): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<div>Hello</div>
+<script>
+console.log("PASS");
+</script>
+<div>Bye</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Hello"
+| "
+"
+| <script>
+| "
+console.log("PASS");
+"
+| "
+"
+| <div>
+| "Bye"
+
+#data
+<div foo="bar">Hello</div>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo="bar"
+| "Hello"
+
+#data
+<div>Hello</div>
+<script>
+console.log("FOO<span>BAR</span>BAZ");
+</script>
+<div>Bye</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Hello"
+| "
+"
+| <script>
+| "
+console.log("FOO<span>BAR</span>BAZ");
+"
+| "
+"
+| <div>
+| "Bye"
+
+#data
+<foo bar="baz"></foo><potato quack="duck"></potato>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="baz"
+| <potato>
+| quack="duck"
+
+#data
+<foo bar="baz"><potato quack="duck"></potato></foo>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="baz"
+| <potato>
+| quack="duck"
+
+#data
+<foo></foo bar="baz"><potato></potato quack="duck">
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): attributes-in-end-tag
+(1,51): attributes-in-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| <potato>
+
+#data
+</ tttt>
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,8): expected-doctype-but-got-eof
+#document
+| <!-- tttt -->
+| <html>
+| <head>
+| <body>
+
+#data
+<div FOO ><img><img></div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo=""
+| <img>
+| <img>
+
+#data
+<p>Test</p<p>Test2</p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,13): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "TestTest2"
+
+#data
+<rdar://problem/6869687>
+#errors
+(1,7): unexpected-character-after-solidus-in-tag
+(1,8): unexpected-character-after-solidus-in-tag
+(1,16): unexpected-character-after-solidus-in-tag
+(1,24): expected-doctype-but-got-start-tag
+(1,24): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <rdar:>
+| 6869687=""
+| problem=""
+
+#data
+<A>test< /A>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,8): expected-tag-name
+(1,12): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "test< /A>"
+
+#data
+&lt;
+#errors
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "<"
+
+#data
+<body foo='bar'><body foo='baz' yo='mama'>
+#errors
+(1,16): expected-doctype-but-got-start-tag
+(1,42): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| foo="bar"
+| yo="mama"
+
+#data
+<body></br foo="bar"></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): attributes-in-end-tag
+(1,21): unexpected-end-tag-treated-as
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<bdy><br foo="bar"></body>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,26): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| <bdy>
+| <br>
+| foo="bar"
+
+#data
+<body></body></br foo="bar">
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,28): attributes-in-end-tag
+(1,28): unexpected-end-tag-after-body
+(1,28): unexpected-end-tag-treated-as
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<bdy></body><br foo="bar">
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,12): expected-one-end-tag-but-got-another
+(1,26): unexpected-start-tag-after-body
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <bdy>
+| <br>
+| foo="bar"
+
+#data
+<html><body></body></html><!-- Hi there -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <!-- Hi there -->
+
+#data
+<html><body></body></html>x<!-- Hi there -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): expected-eof-but-got-char
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+
+#data
+<html><body></body></html>x<!-- Hi there --></html><!-- Again -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): expected-eof-but-got-char
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+| <!-- Again -->
+
+#data
+<html><body></body></html>x<!-- Hi there --></body></html><!-- Again -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): expected-eof-but-got-char
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+| <!-- Again -->
+
+#data
+<html><body><ruby><div><rp>xx</rp></div></ruby></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): XXX-undefined-error
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <rp>
+| "xx"
+
+#data
+<html><body><ruby><div><rt>xx</rt></div></ruby></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): XXX-undefined-error
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <rt>
+| "xx"
+
+#data
+<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6-->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| <!-- 1 -->
+| <noframes>
+| "A"
+| <!-- 2 -->
+| <!-- 3 -->
+| <noframes>
+| "B"
+| <!-- 4 -->
+| <noframes>
+| "C"
+| <!-- 5 -->
+| <!-- 6 -->
+
+#data
+<select><option>A<select><option>B<select><option>C<select><option>D<select><option>E<select><option>F<select><option>G<select>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,25): unexpected-select-in-select
+(1,59): unexpected-select-in-select
+(1,93): unexpected-select-in-select
+(1,127): unexpected-select-in-select
+(1,127): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "A"
+| <option>
+| "B"
+| <select>
+| <option>
+| "C"
+| <option>
+| "D"
+| <select>
+| <option>
+| "E"
+| <option>
+| "F"
+| <select>
+| <option>
+| "G"
+
+#data
+<dd><dd><dt><dt><dd><li><li>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <dd>
+| <dd>
+| <dt>
+| <dt>
+| <dd>
+| <li>
+| <li>
+
+#data
+<div><b></div><div><nobr>a<nobr>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,14): end-tag-too-early
+(1,32): unexpected-start-tag-implies-end-tag
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <b>
+| <div>
+| <b>
+| <nobr>
+| "a"
+| <nobr>
+
+#data
+<head></head>
+<body></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| "
+"
+| <body>
+
+#data
+<head></head> <style></style>ddd
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <style>
+| " "
+| <body>
+| "ddd"
+
+#data
+<kbd><table></kbd><col><select><tr>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag-implies-table-voodoo
+(1,18): unexpected-end-tag
+(1,31): unexpected-start-tag-implies-table-voodoo
+(1,35): unexpected-table-element-start-tag-in-select-in-table
+(1,35): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <kbd>
+| <select>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+
+#data
+<kbd><table></kbd><col><select><tr></table><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag-implies-table-voodoo
+(1,18): unexpected-end-tag
+(1,31): unexpected-start-tag-implies-table-voodoo
+(1,35): unexpected-table-element-start-tag-in-select-in-table
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <kbd>
+| <select>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <div>
+
+#data
+<a><li><style></style><title></title></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,41): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <li>
+| <a>
+| <style>
+| <title>
+
+#data
+<font></p><p><meta><title></title></font>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,10): unexpected-end-tag
+(1,41): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <p>
+| <font>
+| <meta>
+| <title>
+
+#data
+<a><center><title></title><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,29): unexpected-start-tag-implies-end-tag
+(1,29): adoption-agency-1.3
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <center>
+| <a>
+| <title>
+| <a>
+
+#data
+<svg><title><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <div>
+
+#data
+<svg><title><rect><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <rect>
+| <div>
+
+#data
+<svg><title><svg><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,22): unexpected-html-element-in-foreign-content
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <svg svg>
+| <div>
+
+#data
+<img <="" FAIL>
+#errors
+(1,6): invalid-character-in-attribute-name
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <img>
+| <=""
+| fail=""
+
+#data
+<ul><li><div id='foo'/>A</li><li>B<div>C</div></li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,23): non-void-element-with-trailing-solidus
+(1,29): end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| id="foo"
+| "A"
+| <li>
+| "B"
+| <div>
+| "C"
+
+#data
+<svg><em><desc></em>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,9): unexpected-html-element-in-foreign-content
+(1,20): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <em>
+| <desc>
+
+#data
+<svg><tfoot></mi><td>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): unexpected-end-tag
+(1,17): unexpected-end-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg tfoot>
+| <svg td>
+
+#data
+<math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mrow>
+| <math mrow>
+| <math mn>
+| "1"
+| <math mi>
+| "a"
+
+#data
+<!doctype html><input type="hidden"><frameset>
+#errors
+(1,46): unexpected-start-tag
+(1,46): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><input type="button"><frameset>
+#errors
+(1,46): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| type="button"
diff --git a/parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit02.dat b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit02.dat
new file mode 100644
index 0000000000..647fcfd41f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_construction/webkit02.dat
@@ -0,0 +1,116 @@
+#data
+<foo bar=qux/>
+#errors
+(1,14): expected-doctype-but-got-start-tag
+(1,14): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="qux/"
+
+#data
+<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="status"
+| <noscript>
+| "<strong>A</strong>"
+| <span>
+| "B"
+
+#data
+<div><sarcasm><div></div></sarcasm></div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <sarcasm>
+| <div>
+
+#data
+<html><body><img src="" border="0" alt="><div>A</div></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,67): eof-in-attribute-value-double-quote
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<table><td></tbody>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,20): foster-parenting-character
+(1,20): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "A"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><td></thead>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,19): XXX-undefined-error
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+
+#data
+<table><td></tfoot>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,19): XXX-undefined-error
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+
+#data
+<table><thead><td></tbody>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): unexpected-cell-in-table-body
+(1,26): XXX-undefined-error
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <tr>
+| <td>
+| "A"
diff --git a/parser/htmlparser/tests/mochitest/invalidchar.xml b/parser/htmlparser/tests/mochitest/invalidchar.xml
new file mode 100644
index 0000000000..d4ad7f0571
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/invalidchar.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <fail> This is an invalid byte in UTF-8: ¿ </fail>
+</root>
diff --git a/parser/htmlparser/tests/mochitest/mochitest.ini b/parser/htmlparser/tests/mochitest/mochitest.ini
new file mode 100644
index 0000000000..77b31d4f4f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/mochitest.ini
@@ -0,0 +1,181 @@
+[DEFAULT]
+support-files =
+ bug_502091_iframe.html
+ file_bug102699.sjs
+ file_bug534293-slow.sjs
+ file_bug534293.sjs
+ file_bug543062.sjs
+ file_bug594730-1.html
+ file_bug594730-2.html
+ file_bug594730-3.html
+ file_bug594730-4.html
+ file_bug594730-5.html
+ file_bug594730-6.html
+ file_bug594730-7.html
+ file_bug594730-8.html
+ file_bug594730-9.html
+ file_bug642908.sjs
+ file_bug655682.sjs
+ file_bug672453_http_unsupported.html
+ file_bug672453_http_unsupported.html^headers^
+ file_bug672453_late_meta.html
+ file_bug672453_meta_non_superset.html
+ file_bug672453_meta_restart.html
+ file_bug672453_meta_unsupported.html
+ file_bug672453_meta_utf16.html
+ file_bug688580.js
+ file_bug672453_not_declared.html
+ file_bug672453_meta_userdefined.html
+ file_bug672453_xml_decl.html
+ file_bug672453_meta_after_head.html
+ file_bug672453_meta_replacement.html
+ file_bug672453_http_replacement.html
+ file_bug672453_http_replacement.html^headers^
+ file_bug672453_enc_error.html
+ file_bug672453_enc_error_inherited.html
+ file_bug672453_meta_speculation_fail.html
+ file_bug672453_xml_speculation_fail.html
+ file_bug716579-16.html
+ file_bug716579-16.html^headers^
+ file_bug716579-16.xhtml
+ file_bug716579-16.xhtml^headers^
+ file_bug716579-8.html
+ file_bug716579-8.html^headers^
+ file_bug716579-8.xhtml
+ file_bug716579-8.xhtml^headers^
+ file_bug717180.html
+ file_img_picture_preload.html
+ file_img_picture_preload.sjs
+ html5_tree_construction_exceptions.js
+ invalidchar.xml
+ parser_datreader.js
+ parser_web_testrunner.js
+ dir_bug534293/file_bug534293.sjs
+ html5lib_tree_construction/adoption01.dat
+ html5lib_tree_construction/adoption02.dat
+ html5lib_tree_construction/comments01.dat
+ html5lib_tree_construction/doctype01.dat
+ html5lib_tree_construction/domjs-unsafe.dat
+ html5lib_tree_construction/entities01.dat
+ html5lib_tree_construction/entities02.dat
+ html5lib_tree_construction/foreign-fragment.dat
+ html5lib_tree_construction/html5test-com.dat
+ html5lib_tree_construction/inbody01.dat
+ html5lib_tree_construction/isindex.dat
+ html5lib_tree_construction/pending-spec-changes.dat
+ html5lib_tree_construction/pending-spec-changes-plain-text-unsafe.dat
+ html5lib_tree_construction/plain-text-unsafe.dat
+ html5lib_tree_construction/scriptdata01.dat
+ html5lib_tree_construction/tables01.dat
+ html5lib_tree_construction/template.dat
+ html5lib_tree_construction/tests10.dat
+ html5lib_tree_construction/tests11.dat
+ html5lib_tree_construction/tests12.dat
+ html5lib_tree_construction/tests14.dat
+ html5lib_tree_construction/tests15.dat
+ html5lib_tree_construction/tests16.dat
+ html5lib_tree_construction/tests17.dat
+ html5lib_tree_construction/tests18.dat
+ html5lib_tree_construction/tests19.dat
+ html5lib_tree_construction/tests1.dat
+ html5lib_tree_construction/tests20.dat
+ html5lib_tree_construction/tests21.dat
+ html5lib_tree_construction/tests22.dat
+ html5lib_tree_construction/tests23.dat
+ html5lib_tree_construction/tests24.dat
+ html5lib_tree_construction/tests25.dat
+ html5lib_tree_construction/tests26.dat
+ html5lib_tree_construction/tests2.dat
+ html5lib_tree_construction/tests3.dat
+ html5lib_tree_construction/tests4.dat
+ html5lib_tree_construction/tests5.dat
+ html5lib_tree_construction/tests6.dat
+ html5lib_tree_construction/tests7.dat
+ html5lib_tree_construction/tests8.dat
+ html5lib_tree_construction/tests9.dat
+ html5lib_tree_construction/tests_innerHTML_1.dat
+ html5lib_tree_construction/tricky01.dat
+ html5lib_tree_construction/webkit01.dat
+ html5lib_tree_construction/webkit02.dat
+ html5lib_tree_construction/main-element.dat
+ html5lib_tree_construction/ruby.dat
+ html5lib_tree_construction/scripted/adoption01.dat
+ html5lib_tree_construction/scripted/webkit01.dat
+ html5lib_tree_construction/scripted/ark.dat
+ blue.png
+
+[test_base_csp_img.html]
+support-files =
+ blue.png
+ file_base_csp_img.sjs
+skip-if =
+ http3
+[test_base_header_csp_img.html]
+support-files =
+ blue.png
+ file_base_csp_img.sjs
+ test_base_header_csp_img.html^headers^
+skip-if =
+ http3
+[test_bug102699.html]
+[test_bug174351.html]
+[test_bug213517.html]
+[test_bug339350.xhtml]
+[test_bug358797.html]
+[test_bug396568.html]
+[test_bug418464.html]
+[test_bug460437.xhtml]
+skip-if =
+ (xorigin && debug)
+ http3
+[test_bug502091.html]
+[test_bug543062.html]
+[test_bug552938-2.html]
+[test_bug552938.html]
+[test_bug563322.xhtml]
+[test_bug566879.html]
+[test_bug594730.html]
+[test_bug613662.html]
+[test_bug613662.xhtml]
+skip-if = (xorigin && debug)
+[test_bug639362.html]
+[test_bug642908.html]
+[test_bug645115.html]
+[test_bug655682.html]
+skip-if =
+ http3
+[test_bug667533.html]
+[test_bug672453.html]
+skip-if =
+ http3
+[test_bug688580.html]
+[test_bug688580.xhtml]
+[test_bug709083.html]
+[test_bug715112.html]
+[test_bug715739.html]
+[test_bug716579.html]
+[test_bug717180.html]
+[test_bug1104732.html]
+support-files =
+ file_defer_bug1104732.js
+ file_async_bug1104732.sjs
+[test_compatmode.html]
+[test_html5_tree_construction.html]
+[test_html5_tree_construction_part2.html]
+[test_img_picture_preload.html]
+[test_xml_mislabeled.html]
+# Disabled test due to orange on Linux
+# test_bug568470.html
+# file_bug568470.sjs
+# file_bug568470-script.sjs
+# Disable test due to frequent orange on Mac
+# test_bug534293.html
+[test_bug1209658.html]
+[test_bug1364399.html]
+[test_bug1646140-1.html]
+[test_bug1646140-2.html]
+skip-if = headless # Bug 1685088
+[test_xml_parse_error.html]
+support-files =
+ file_xml_parse_error.js
+ file_xml_parse_error.xml
diff --git a/parser/htmlparser/tests/mochitest/parser_datreader.js b/parser/htmlparser/tests/mochitest/parser_datreader.js
new file mode 100644
index 0000000000..d3d3ea2c89
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/parser_datreader.js
@@ -0,0 +1,218 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * A test suite that runs WHATWG HTML parser tests.
+ * The tests are from html5lib.
+ *
+ * http://html5lib.googlecode.com/
+ */
+
+/**
+ * A few utility functions.
+ */
+function log(entry) {}
+
+function startsWith(s, s2) {
+ return s.indexOf(s2) == 0;
+}
+
+function trimString(s) {
+ return s.replace(/^\s+/, "").replace(/\s+$/, "");
+}
+
+/**
+ * Parses an individual testcase into an array containing the input
+ * string, a string representing the expected tree (DOM), and a list
+ * of error messages.
+ *
+ * @param A string containing a single testcase
+ */
+function parseTestcase(testcase) {
+ var lines = testcase.split("\n");
+
+ /* check that the first non-empty, non-comment line is #data */
+ for (let line of lines) {
+ if (!line || startsWith(line, "##")) {
+ continue;
+ }
+ if (line == "#data") {
+ break;
+ }
+ log(lines);
+ throw new Error("Unknown test format.");
+ }
+
+ var input = [];
+ var output = [];
+ var errors = [];
+ var fragment = [];
+ var currentList = input;
+ for (let line of lines) {
+ if (startsWith(line, "##todo")) {
+ todo(false, line.substring(6));
+ continue;
+ }
+ if (
+ !(
+ startsWith(line, "#error") ||
+ startsWith(line, "#document") ||
+ startsWith(line, "#document-fragment") ||
+ startsWith(line, "#data")
+ )
+ ) {
+ currentList.push(line);
+ } else if (line == "#errors") {
+ currentList = errors;
+ } else if (line == "#document") {
+ currentList = output;
+ } else if (line == "#document-fragment") {
+ currentList = fragment;
+ }
+ }
+ while (!output[output.length - 1]) {
+ output.pop(); // zap trailing blank lines
+ }
+ // logger.log(input.length, output.length, errors.length);
+ return [input.join("\n"), output.join("\n"), errors, fragment[0]];
+}
+
+/**
+ * A generator function that accepts a list of strings. Each list
+ * member corresponds to the contents of a ".dat" file from the
+ * html5lib test suite.
+ *
+ * @param The list of strings
+ */
+function* test_parser(testlist) {
+ for (var testgroup of testlist) {
+ var tests = testgroup.split("#data\n");
+ tests = tests.filter(test => test).map(test => "#data\n" + test);
+ for (var test of tests) {
+ yield parseTestcase(test);
+ }
+ }
+}
+
+/**
+ * Transforms a DOM document to a string matching the format in
+ * the test cases.
+ *
+ * @param the DOM document
+ */
+function docToTestOutput(doc) {
+ var walker = doc.createTreeWalker(doc, NodeFilter.SHOW_ALL, null);
+ return addLevels(walker, "", "| ").slice(0, -1); // remove the last newline
+}
+
+/**
+ * Creates a walker for a fragment that skips over the root node.
+ *
+ * @param an element
+ */
+function createFragmentWalker(elt) {
+ return elt.ownerDocument.createTreeWalker(
+ elt,
+ NodeFilter.SHOW_ALL,
+ function (node) {
+ return elt == node ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT;
+ }
+ );
+}
+
+/**
+ * Transforms the descendants of an element to a string matching the format
+ * in the test cases.
+ *
+ * @param an element
+ */
+function fragmentToTestOutput(elt) {
+ var walker = createFragmentWalker(elt);
+ return addLevels(walker, "", "| ").slice(0, -1); // remove the last newline
+}
+
+function addLevels(walker, buf, indent) {
+ if (walker.firstChild()) {
+ do {
+ buf += indent;
+ switch (walker.currentNode.nodeType) {
+ case Node.ELEMENT_NODE:
+ buf += "<";
+ var ns = walker.currentNode.namespaceURI;
+ if ("http://www.w3.org/1998/Math/MathML" == ns) {
+ buf += "math ";
+ } else if ("http://www.w3.org/2000/svg" == ns) {
+ buf += "svg ";
+ } else if ("http://www.w3.org/1999/xhtml" != ns) {
+ buf += "otherns ";
+ }
+ buf += walker.currentNode.localName + ">";
+ if (walker.currentNode.hasAttributes()) {
+ var valuesByName = {};
+ var attrs = walker.currentNode.attributes;
+ for (let i = 0; i < attrs.length; ++i) {
+ var localName = attrs[i].localName;
+ var name;
+ var attrNs = attrs[i].namespaceURI;
+ if (null == attrNs) {
+ name = localName;
+ } else if ("http://www.w3.org/XML/1998/namespace" == attrNs) {
+ name = "xml " + localName;
+ } else if ("http://www.w3.org/1999/xlink" == attrNs) {
+ name = "xlink " + localName;
+ } else if ("http://www.w3.org/2000/xmlns/" == attrNs) {
+ name = "xmlns " + localName;
+ } else {
+ name = "otherns " + localName;
+ }
+ valuesByName[name] = attrs[i].value;
+ }
+ var keys = Object.keys(valuesByName).sort();
+ for (let i = 0; i < keys.length; ++i) {
+ buf +=
+ "\n" +
+ indent +
+ " " +
+ keys[i] +
+ '="' +
+ valuesByName[keys[i]] +
+ '"';
+ }
+ }
+ break;
+ case Node.DOCUMENT_TYPE_NODE:
+ buf += "<!DOCTYPE " + walker.currentNode.name;
+ if (walker.currentNode.publicId || walker.currentNode.systemId) {
+ buf += ' "';
+ buf += walker.currentNode.publicId;
+ buf += '" "';
+ buf += walker.currentNode.systemId;
+ buf += '"';
+ }
+ buf += ">";
+ break;
+ case Node.COMMENT_NODE:
+ buf += "<!-- " + walker.currentNode.nodeValue + " -->";
+ break;
+ case Node.TEXT_NODE:
+ buf += '"' + walker.currentNode.nodeValue + '"';
+ break;
+ }
+ buf += "\n";
+ // In the case of template elements, children do not get inserted as
+ // children of the template element, instead they are inserted
+ // as children of the template content (which is a document fragment).
+ if (walker.currentNode.constructor.name === "HTMLTemplateElement") {
+ buf += indent + " content\n";
+ // Walk through the template content.
+ var templateWalker = createFragmentWalker(walker.currentNode.content);
+ buf = addLevels(templateWalker, buf, indent + " ");
+ }
+ buf = addLevels(walker, buf, indent + " ");
+ } while (walker.nextSibling());
+ walker.parentNode();
+ }
+ return buf;
+}
diff --git a/parser/htmlparser/tests/mochitest/parser_web_testrunner.js b/parser/htmlparser/tests/mochitest/parser_web_testrunner.js
new file mode 100644
index 0000000000..45df6ea2c6
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/parser_web_testrunner.js
@@ -0,0 +1,149 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Runs html5lib-formatted test cases in the browser. Requires SimpleTest.
+ *
+ * Define an array named parserDatFiles before loading this script,
+ * and it will load each of those dat files into an array, then run
+ * the test parser on each and run the tests by assigning the input
+ * data to an iframe's url.
+ *
+ * Your test document should have an element with id "display" and
+ * an iframe with id "testframe".
+ */
+
+/* import-globals-from ./parser_datreader.js */
+/* import-globals-from ./html5_tree_construction_exceptions.js */
+/* globals parserDatFiles */
+
+var functionsToRunAsync = [];
+
+window.addEventListener(
+ "message",
+ function (event) {
+ if (event.source == window && event.data == "async-run") {
+ event.stopPropagation();
+ var fn = functionsToRunAsync.shift();
+ fn();
+ }
+ },
+ true
+);
+
+function asyncRun(fn) {
+ functionsToRunAsync.push(fn);
+ window.postMessage("async-run", "*");
+}
+
+function writeErrorSummary(input, expected, got, isTodo) {
+ if (isTodo) {
+ $("display").appendChild(createEl("h2", null, "Unexpected Success:"));
+ } else {
+ $("display").appendChild(createEl("h2", null, "Unexpected Failure:"));
+ }
+ $("display").appendChild(createEl("br"));
+ $("display").appendChild(createEl("span", null, "Matched: "));
+ $("display").appendChild(document.createTextNode("" + (expected == got)));
+ var pre = createEl("pre");
+ pre.appendChild(document.createTextNode("Input: \n" + input, "\n-\n"));
+ pre.appendChild(document.createTextNode("Expected:\n" + expected, "\n-\n"));
+ pre.appendChild(document.createTextNode("Output:\n" + got + "\n-\n"));
+ $("display").appendChild(pre);
+ $("display").appendChild(createEl("hr"));
+}
+
+/**
+ * Control will bounce back and forth between nextTest() and the
+ * event handler returned by makeTestChecker() or the callback returned by
+ * makeFragmentTestChecker() until the 'testcases' iterator is spent.
+ */
+function makeTestChecker(input, expected, errors) {
+ return function (e) {
+ var domAsString = docToTestOutput(e.target.contentDocument);
+ if (html5Exceptions[input]) {
+ todo_is(domAsString, expected, "HTML5 expected success.");
+ if (domAsString == expected) {
+ writeErrorSummary(input, expected, domAsString, true);
+ }
+ } else {
+ is(domAsString, expected, "HTML5 expected success.");
+ if (domAsString != expected) {
+ writeErrorSummary(input, expected, domAsString, false);
+ }
+ }
+ nextTest(e.target);
+ };
+}
+
+function makeFragmentTestChecker(input, expected, errors, fragment, testframe) {
+ return function () {
+ var context;
+ if (fragment.startsWith("svg ")) {
+ context = document.createElementNS(
+ "http://www.w3.org/2000/svg",
+ fragment.substring(4)
+ );
+ } else if (fragment.startsWith("math ")) {
+ context = document.createElementNS(
+ "http://www.w3.org/1998/Math/MathML",
+ fragment.substring(5)
+ );
+ } else {
+ context = document.createElementNS(
+ "http://www.w3.org/1999/xhtml",
+ fragment
+ );
+ }
+ // eslint-disable-next-line no-unsanitized/property
+ context.innerHTML = input;
+ var domAsString = fragmentToTestOutput(context);
+ is(domAsString, expected, "HTML5 expected success. " + new Date());
+ if (domAsString != expected) {
+ writeErrorSummary(input, expected, domAsString, false);
+ }
+ nextTest(testframe);
+ };
+}
+
+var testcases;
+function nextTest(testframe) {
+ var { done, value } = testcases.next();
+ if (done) {
+ SimpleTest.finish();
+ return;
+ }
+ var [input, output, errors, fragment] = value;
+ if (fragment) {
+ asyncRun(
+ makeFragmentTestChecker(input, output, errors, fragment, testframe)
+ );
+ } else {
+ testframe.onload = makeTestChecker(input, output, errors);
+ testframe.srcdoc = input;
+ }
+}
+
+var testFileContents = [];
+function loadNextTestFile() {
+ var datFile = parserDatFiles.shift();
+ if (datFile) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function () {
+ if (this.readyState == 4) {
+ testFileContents.push(this.responseText);
+ loadNextTestFile();
+ }
+ };
+ xhr.open("GET", "html5lib_tree_construction/" + datFile);
+ xhr.send();
+ } else {
+ testcases = test_parser(testFileContents);
+ nextTest($("testframe"));
+ }
+}
+
+addLoadEvent(loadNextTestFile);
+SimpleTest.waitForExplicitFinish();
diff --git a/parser/htmlparser/tests/mochitest/test_base_csp_img.html b/parser/htmlparser/tests/mochitest/test_base_csp_img.html
new file mode 100644
index 0000000000..d17a99c657
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_base_csp_img.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Base with base-uri CSP</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <!-- Set CSP -->
+ <meta http-equiv="Content-Security-Policy" content="base-uri 'self';">
+
+ <!-- Base should be ignored -->
+ <base href="http://example.org/">
+</head>
+<body>
+
+<img src="/tests/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs?image" width=10 height=10>
+
+<script>
+add_task(async function() {
+ let response = await fetch(
+ "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs?result"
+ );
+ let hosts = await response.json();
+
+ is(hosts.length, 1, "One host");
+ is(hosts[0], "mochi.test", "Host was not influenced by base");
+
+ info("finished");
+});
+</script>
+
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_base_header_csp_img.html b/parser/htmlparser/tests/mochitest/test_base_header_csp_img.html
new file mode 100644
index 0000000000..f0becc4080
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_base_header_csp_img.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Base with base-uri CSP header</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <!-- Base should be ignored -->
+ <base href="http://example.org/">
+</head>
+<body>
+
+<img src="/tests/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs?image" width=10 height=10>
+
+<script>
+add_task(async function() {
+ let response = await fetch(
+ "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_base_csp_img.sjs?result"
+ );
+ let hosts = await response.json();
+
+ is(hosts.length, 1, "One host");
+ is(hosts[0], "mochi.test", "Host was not influenced by base");
+
+ info("finished");
+});
+</script>
+
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_base_header_csp_img.html^headers^ b/parser/htmlparser/tests/mochitest/test_base_header_csp_img.html^headers^
new file mode 100644
index 0000000000..3c02326419
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_base_header_csp_img.html^headers^
@@ -0,0 +1 @@
+Content-Security-Policy: base-uri 'self';
diff --git a/parser/htmlparser/tests/mochitest/test_bug102699.html b/parser/htmlparser/tests/mochitest/test_bug102699.html
new file mode 100644
index 0000000000..f7d88910cf
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug102699.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=102699
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 102699</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=102699">Mozilla Bug 102699</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 102699 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var p = new DOMParser();
+
+var d = p.parseFromString(
+'<meta charset="windows-1252">' +
+"\u003cscript>" +
+'document.documentElement.setAttribute("data-fail", "FAIL");' +
+"\u003c/script>" +
+'\u003cscript src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs">\u003c/script>' +
+'\u003cscript src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs" defer>\u003c/script>' +
+'\u003cscript src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs" async>\u003c/script>' +
+'<link type="stylesheet" href="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs">' +
+'<body onload=\'document.documentElement.setAttribute("data-fail", "FAIL");\'>' +
+'<img src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs">' +
+'<iframe src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs"></iframe>' +
+'<video poster="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs" src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs"></video>' +
+'<object data="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug102699.sjs"></object>' +
+'<noscript><div></div></noscript>"', "text/html");
+
+is(d.createElement("div").tagName, "DIV", "The created document should have HTML nature.");
+
+is(d.getElementsByTagName("div").length, 1, "There should be one div.");
+
+is(d.contentType, "text/html", "contentType should be text/html");
+
+is(d.characterSet, "UTF-8", "Expected the <meta> to be ignored.");
+
+is(d.compatMode, "BackCompat", "Should be in the quirks mode.");
+
+var scripts = d.getElementsByTagName("script");
+is(scripts.length, 4, "Unexpected number of scripts.");
+while (scripts.length) {
+ // These should not run when moved to another doc
+ document.body.appendChild(scripts[0]);
+}
+var s = document.createElement("script");
+s.src = "file_bug102699.sjs?report=1";
+document.body.appendChild(s);
+
+function continueAfterReport() {
+ ok(!d.documentElement.hasAttribute("data-fail"), "Should not have a data-fail attribute.");
+
+ d = p.parseFromString("<!DOCTYPE html>", "text/html");
+ is(d.compatMode, "CSS1Compat", "Should be in the standards mode.");
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug1104732.html b/parser/htmlparser/tests/mochitest/test_bug1104732.html
new file mode 100644
index 0000000000..7a77e5936d
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug1104732.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1104732
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1104732</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1104732 **/
+
+ // Expected order of the values of the "state" variable:
+ // Test starting
+ // defer
+ // DOMContentLoaded
+ // load
+
+ // In the meantime, the async script load should happen before load.
+ // Ideally, we would want to assert that it happens after DOMContentLoaded,
+ // because it shouldn't be holding up DOMContentLoaded, but there is
+ // no *guarantee* that this is the case, so we cannot assert it.
+
+ var state = "Test starting";
+ var asyncState = "not loaded";
+ SimpleTest.waitForExplicitFinish();
+ is(document.readyState, "loading", "Document should have been loading.");
+ document.addEventListener("DOMContentLoaded", function() {
+ is(document.readyState, "interactive", "readyState should be interactive during DOMContentLoaded.");
+ is(state, "defer", "Bad state upon DOMContentLoaded");
+ state = "DOMContentLoaded";
+ // This doesn't work (see above), but we can't "todo" this assertion either, because
+ // it will sometimes be the case...
+ // isnot(asyncState, "loaded", "Async script should not have delayed domcontentloaded");
+ });
+ window.addEventListener("load", function() {
+ is(document.readyState, "complete", "readyState should be complete during load.");
+ is(state, "DOMContentLoaded", "Bad state upon load");
+ state = "load";
+ is(asyncState, "loaded", "Async script should be loaded upon document load event");
+ SimpleTest.finish();
+ });
+ </script>
+ <script defer src="file_defer_bug1104732.js"></script>
+ <script async src="file_async_bug1104732.sjs"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1104732">Mozilla Bug 1104732</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug1209658.html b/parser/htmlparser/tests/mochitest/test_bug1209658.html
new file mode 100644
index 0000000000..3ef27d1925
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug1209658.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1209658
+-->
+<head>
+ <title>Test for Bug 1209658</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1209658">Mozilla Bug 1209658</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function loaded() {
+ for (var iframe of document.querySelectorAll("iframe")) {
+ is(SpecialPowers.wrap(iframe).contentWindow.location.href, iframe.src, "should load correct URL");
+ is(SpecialPowers.wrap(iframe).contentDocument.body.textContent, '{"<p>Hello</p>": null}',
+ iframe.getAttribute("mimeType") + " should be treated as text");
+ }
+ SimpleTest.finish();
+});
+</script>
+<iframe src="data:text/json,{&quot;<p>Hello</p>&quot;:%20null}"
+ mimeType="text/json"></iframe>
+<!-- Totally not valid VTT data, but doesn't matter for our purposes here -->
+<iframe src="data:text/vtt,{&quot;<p>Hello</p>&quot;:%20null}"
+ mimeType="text/vtt"></iframe>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug1364399.html b/parser/htmlparser/tests/mochitest/test_bug1364399.html
new file mode 100644
index 0000000000..84d9a38aed
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug1364399.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1364399
+-->
+<head>
+ <title>Test for Bug 1364399</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1364399">Mozilla Bug 1364399</a>
+<p id="display"></p>
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1364399 **/
+// Non-data: version at dom/base/test/test_bug518104.html
+SimpleTest.waitForExplicitFinish();
+
+function done() {
+ // document.write should have gotten ignored due to the
+ // ignore-destructive-writes counter. Then document.close should
+ // have gotten ignored due to the parser still being not-script-created.
+ var iframe = document.getElementById("iframe");
+ var divs = iframe.contentWindow.document.getElementsByTagName("div").length;
+ is(divs, 2, "<div>s are still there.");
+ var ps = iframe.contentWindow.document.getElementsByTagName("p").length;
+ is(ps, 0, "<p> did not get written.");
+ SimpleTest.finish();
+}
+
+</script>
+<div id="content" style="display: none">
+ <iframe id='iframe' srcdoc="
+ <div></div><div></div>
+ <script defer src='data:application/javascript,document.write(&quot;<p></p>&quot;);parent.done();document.close();'></script>">
+ </iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug1646140-1.html b/parser/htmlparser/tests/mochitest/test_bug1646140-1.html
new file mode 100644
index 0000000000..8592d0d17f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug1646140-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<div id="div">
+<script>
+/* globals div svgRanScript */
+SimpleTest.waitForExplicitFinish();
+
+window.svgRanScript = false;
+const o = new MutationObserver(mutations => {
+ o.disconnect();
+ setTimeout(() => {
+ ok(!svgRanScript, "svg onload must not fire");
+ SimpleTest.finish();
+ });
+});
+o.observe(div, {childList: true});
+const p = (new DOMParser()).parseFromString("<svg onload=\"window.svgRanScript=true\"></svg>", "text/html");
+div.appendChild(p.body);
+</script>
diff --git a/parser/htmlparser/tests/mochitest/test_bug1646140-2.html b/parser/htmlparser/tests/mochitest/test_bug1646140-2.html
new file mode 100644
index 0000000000..11c370d401
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug1646140-2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<div id="div" contenteditable></div>
+<script>
+/* globals div svgRanScript */
+window.svgRanScript = false;
+document.addEventListener("copy", ev => {
+ ev.preventDefault();
+ ev.clipboardData.setData('text/html', "<svg><style><svg/onload=\"window.svgRanScript=true\">");
+});
+const o = new MutationObserver(mutations => {
+ o.disconnect();
+ setTimeout(() => {
+ ok(!svgRanScript, "svg onload must not fire");
+ SimpleTest.finish()
+ });
+});
+o.observe(div, {childList: true});
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(() => {
+ getSelection().collapse(div);
+ SpecialPowers.doCommand(window, "cmd_copy");
+ SpecialPowers.doCommand(window, "cmd_paste");
+});
+</script>
diff --git a/parser/htmlparser/tests/mochitest/test_bug174351.html b/parser/htmlparser/tests/mochitest/test_bug174351.html
new file mode 100644
index 0000000000..a370d9fefc
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug174351.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=174351
+-->
+<head>
+ <title>Test for Bug 174351</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=174351">Mozilla Bug 174351</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ var iframe = document.createElement("iframe");
+ iframe.src = "invalidchar.xml";
+ iframe.onload = function() {
+ var doc = document.getElementById("test").childNodes[1].contentDocument;
+ ok(doc.documentElement.tagName != "root", "Since XML has invalid enconding, must throw error");
+ };
+
+ document.getElementById("test").appendChild(iframe);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug213517.html b/parser/htmlparser/tests/mochitest/test_bug213517.html
new file mode 100644
index 0000000000..b5bb5afa74
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug213517.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=213517
+-->
+<head>
+ <meta charset="x-user-defined">
+ <title>Test for Bug 213517</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 213517 **/
+
+ is(document.characterSet, "windows-1252", "x-user-defined in <meta> should have gotten mapped to windows-1252");
+
+
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=213517">Mozilla Bug 213517</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug339350.xhtml b/parser/htmlparser/tests/mochitest/test_bug339350.xhtml
new file mode 100644
index 0000000000..6c16e56cb7
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug339350.xhtml
@@ -0,0 +1,61 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+Tests by Sam Ruby - WTFPL License (http://sam.zoy.org/wtfpl/)
+
+http://www.intertwingly.net/blog/2006/10/03/Firefox-XHTML-innerHTML-quirk#comments
+https://bugzilla.mozilla.org/show_bug.cgi?id=339350
+-->
+<head>
+ <!-- XHTML needs the packed version -->
+ <script src="/tests/SimpleTest/SimpleTest.js"/>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=339350">Mozilla Bug 339350</a>
+<div style="display: none">
+ <table border="1" cellspacing="0">
+ <thead>
+ <th></th>
+ <th>plain</th>
+ <th>brackets</th>
+ <th>braces</th>
+ </thead>
+
+ <tr>
+ <th>innerHTML</th>
+ <td><div id="i1"/></td>
+ <td style="background:yellow"><div id="i2"/></td>
+ <td><div id="i3"/></td>
+ </tr>
+ <tr>
+ <th>textNode</th>
+ <td><div id="t1"/></td>
+ <td><div id="t2"/></td>
+ <td><div id="t3"/></td>
+ </tr>
+ </table>
+</div>
+<pre id="test">
+<script type="text/javascript">
+/* eslint-disable no-unsanitized/property */
+var text1 = "foo bar";
+var text2 = "foo [bar]";
+var text3 = "foo {bar}";
+
+// This is the long way to write this stuff,
+// you can use MochiKit functions too
+document.getElementById("i1").innerHTML = text1;
+document.getElementById("i2").innerHTML = text2;
+document.getElementById("i3").innerHTML = text3;
+
+document.getElementById("t1").appendChild(document.createTextNode(text1));
+document.getElementById("t2").appendChild(document.createTextNode(text2));
+document.getElementById("t3").appendChild(document.createTextNode(text3));
+
+<!-- The is() function is one way to add a test -->
+is(document.getElementById("i2").innerHTML, text2, "XHTML innerHTML with trailing brackets ']]'");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug358797.html b/parser/htmlparser/tests/mochitest/test_bug358797.html
new file mode 100644
index 0000000000..f142c42c88
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug358797.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=358797
+-->
+<head>
+ <title>Test for Bug 358797</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=358797">Mozilla Bug 358797</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 358797 **/
+
+var range = document.createRange();
+range.selectNode(document.firstChild);
+var cf = range.createContextualFragment("<span></span>");
+ok(cf != null,
+ "range.createContextualFragment() should work when range node is DocType");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug396568.html b/parser/htmlparser/tests/mochitest/test_bug396568.html
new file mode 100644
index 0000000000..d4152e7971
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug396568.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=396568
+-->
+<head>
+ <title>Test for Bug 396568</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <!--These script tags are part of the test, complete with indentation!-->
+ <script language="javascript"
+
+
+
+
+
+
+
+ type="text/javascript"></script>
+ <script language="javascript"
+ type="text/javascript"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=396568">Mozilla Bug 396568</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 396568 **/
+
+ var reached = false;
+ try {
+ // eslint-disable-next-line no-undef
+ noSuchIdentifier;
+ reached = true;
+ } catch (e) {
+ is(e.lineNumber, 37, "Unexpected line number"); // this line number is dependent on the line number of noSuchIdentifier
+ }
+ is(reached, false, "Exception needed to be thrown");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug418464.html b/parser/htmlparser/tests/mochitest/test_bug418464.html
new file mode 100644
index 0000000000..c9c6f585e3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug418464.html
@@ -0,0 +1,43 @@
+<form name="formGo" method="post">
+ <input type="hidden">
+</form>
+<script>
+ var form1 = document.formGo;
+</script>
+<form name="formGo2" method="post">
+ <input type="Hidden">
+</form>
+<script>
+ var form2 = document.formGo2;
+</script>
+ <!-- NOTE: The forms and scripts above this comment _must_ come first in this file-->
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=418464
+-->
+<head>
+ <title>Test for Bug 418464</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418464">Mozilla Bug 418464</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 418464 **/
+ is(form1 instanceof HTMLFormElement, true,
+ "Should have a form here");
+ is(form2 instanceof HTMLFormElement, true,
+ "Should have a form here");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug460437.xhtml b/parser/htmlparser/tests/mochitest/test_bug460437.xhtml
new file mode 100644
index 0000000000..c6fd25d0b3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug460437.xhtml
@@ -0,0 +1,40 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=460437
+-->
+<head>
+ <title>Test for Bug 460437</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=460437">Mozilla Bug 460437</a>
+<p id="display"><b id="test460437">orig</b></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+/* eslint-disable no-unsanitized/property */
+<![CDATA[
+
+SimpleTest.expectAssertions(1);
+
+/** Test for Bug 460437 **/
+
+var s = "<i>invalid</i";
+try {
+ document.getElementById("test460437").innerHTML = s;
+} catch (e) {
+}
+is(document.getElementById("test460437").innerHTML, "", "setting invalid innerHTML should clear it");
+s = "<i>valid</i>";
+document.getElementById("test460437").innerHTML = s;
+is(document.getElementById("test460437").innerHTML, "<i xmlns=\"http://www.w3.org/1999/xhtml\">valid</i>", "failed to set valid innerHTML");
+
+
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug502091.html b/parser/htmlparser/tests/mochitest/test_bug502091.html
new file mode 100644
index 0000000000..e6c318e7c6
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug502091.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=502091
+
+Adding a <meta> element by writing to innerHTML should work correctly.
+-->
+<head>
+ <title>Test for Bug 502091</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=502091">Mozilla Bug 502091</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<div id="test">
+<script class="testbody" type="text/javascript">
+ function $(id) { return document.getElementById(id); }
+
+ var iframe = document.createElement("iframe");
+ iframe.setAttribute("id", "iframe");
+ iframe.src = "bug_502091_iframe.html";
+ iframe.onload = function() {
+ var div = $("iframe").contentDocument.getElementById("testdiv");
+ var meta = div.getElementsByTagName("meta");
+ is(meta.length, 1, "meta element not added to div");
+ };
+ $("test").appendChild(iframe);
+
+</script>
+</div>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug534293.html b/parser/htmlparser/tests/mochitest/test_bug534293.html
new file mode 100644
index 0000000000..62a9605dcd
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug534293.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=534293
+-->
+<head>
+ <title>Test for Bug 534293</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug534293-slow.sjs"></script>
+ <base href="dir_bug534293/">
+ <script src="file_bug534293.sjs"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=534293">Mozilla Bug 534293</a>
+
+<script src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug534293.sjs?report=1"></script>
+<script src="http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/dir_bug534293/file_bug534293.sjs?report=1"></script>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug543062.html b/parser/htmlparser/tests/mochitest/test_bug543062.html
new file mode 100644
index 0000000000..8a966df383
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug543062.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=543062
+-->
+<head>
+ <title>Test for Bug 543062</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=543062">Mozilla Bug 543062</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+document.write("\u003Cscript src='file_bug543062.sjs?first'>\u003C/script>\u003Cscript src='file_bug543062.sjs?second'>\u003C/script>");
+document.write("\u003Cscript src='file_bug543062.sjs?third'>\u003C/script>");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug552938-2.html b/parser/htmlparser/tests/mochitest/test_bug552938-2.html
new file mode 100644
index 0000000000..87996765d0
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug552938-2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=552938
+-->
+<head>
+ <title>Test for Bug 552938</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload='runTest();'>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=552938">Mozilla Bug 552938</a>
+<script>
+var svgLoadFired = false;
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <svg>
+ <script>
+ document.getElementsByTagName("svg")[0].addEventListener("SVGLoad",
+ function() { svgLoadFired = true; });
+ </script>
+ </svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 552938 **/
+function runTest() {
+ ok(svgLoadFired, "The SVG load event should have fired.");
+ SimpleTest.finish();
+}
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug552938.html b/parser/htmlparser/tests/mochitest/test_bug552938.html
new file mode 100644
index 0000000000..77d96691a6
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug552938.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=552938
+-->
+<head>
+ <title>Test for Bug 552938</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload='runTest();'>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=552938">Mozilla Bug 552938</a>
+<script>
+var svgLoadFired = false;
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <svg onload="svgLoadFired = true;"></svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 552938 **/
+function runTest() {
+ ok(svgLoadFired, "The SVG load event should have fired.");
+ SimpleTest.finish();
+}
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug563322.xhtml b/parser/htmlparser/tests/mochitest/test_bug563322.xhtml
new file mode 100644
index 0000000000..35239cb69a
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug563322.xhtml
@@ -0,0 +1,33 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=563322
+-->
+<head>
+ <title>Test for Bug 563322</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=563322">Mozilla Bug 563322</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 563322 **/
+
+var div = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
+div.innerHTML = "<script>ok(false, 'Script ran but should not have')</script><script>ok(false, 'Script ran but should not have')</script>";
+
+document.getElementById("content").appendChild(div);
+
+ok(true, "Keep the harness happy");
+
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug566879.html b/parser/htmlparser/tests/mochitest/test_bug566879.html
new file mode 100644
index 0000000000..1704100bfd
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug566879.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=566879
+-->
+<head>
+ <title>Test for Bug 566879</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload='runTest();'>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566879">Mozilla Bug 566879</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<form>
+<input type=text id=textfield name=textfield>
+<input type=checkbox id=checkbox name=checkbox>
+<input type=radio id=radio1 name=radio>
+<input type=radio id=radio2 name=radio>
+<textarea name=textarea id=textarea></textarea>
+<select name=select id=select>
+<option value=foo>Foo</option>
+<option value=bar selected>Bar</option>
+</select>
+</form>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var initialState;
+
+function runTest() {
+ initialState = document.getElementById("content").innerHTML;
+ document.getElementById("textfield").value = "foo";
+ document.getElementById("checkbox").checked = true;
+ document.getElementById("radio2").checked = true;
+ document.getElementById("textarea").value = "foo";
+ document.getElementById("select").value = "foo";
+ setTimeout(continuation1, 1);
+}
+
+function continuation1() {
+ // eslint-disable-next-line no-unsanitized/property
+ document.getElementById("content").innerHTML = initialState;
+ setTimeout(continuation2, 1);
+}
+
+function continuation2() {
+ is(document.getElementById("textfield").value, "", "The text field should have gone back to its initial state.");
+ ok(!document.getElementById("checkbox").checked, "The checkbox should have gone back to its initial state.");
+ ok(!document.getElementById("radio2").checked, "The second radio button should have gone back to its initial state.");
+ is(document.getElementById("textarea").value, "", "The text area should have gone back to its initial state.");
+ is(document.getElementById("select").value, "bar", "The select should have gone back to its initial state.");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug568470.html b/parser/htmlparser/tests/mochitest/test_bug568470.html
new file mode 100644
index 0000000000..fc8f26f5d4
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug568470.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=568470
+-->
+<head>
+ <title>Test for Bug 568470</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=568470">Mozilla Bug 568470</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 568470 **/
+SimpleTest.waitForExplicitFinish();
+
+// assuming the test runs in less than a year...
+var time = new Date().getTime() + 1000 * 60 * 60 * 24 * 365;
+
+var interval = setInterval(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ if (iframe) {
+ var doc = iframe.contentDocument;
+ if (doc) {
+ if (doc.getElementById("flushable")) {
+ time = new Date();
+ clearInterval(interval);
+ }
+ }
+ }
+}, 25);
+
+function finish() {
+ clearInterval(interval);
+ var elapsed = new Date().getTime() - time;
+ ok(elapsed > 350,
+ "Content flush time and parse end time not enough apart.");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+<div id="content" style="display: none">
+ <iframe onload="finish();" src="file_bug568470.sjs"></iframe>
+</div>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug594730.html b/parser/htmlparser/tests/mochitest/test_bug594730.html
new file mode 100644
index 0000000000..5042c8ae32
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug594730.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=594730
+-->
+<head>
+ <title>Test for Bug 594730</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=594730">Mozilla Bug 594730</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<iframe src=file_bug594730-1.html></iframe>
+<iframe src=file_bug594730-2.html></iframe>
+<iframe src=file_bug594730-3.html></iframe>
+<iframe src=file_bug594730-4.html></iframe>
+<iframe src=file_bug594730-5.html></iframe>
+<iframe src=file_bug594730-6.html></iframe>
+<iframe src=file_bug594730-7.html></iframe>
+<iframe src=file_bug594730-8.html></iframe>
+<iframe src=file_bug594730-9.html></iframe>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug613662.html b/parser/htmlparser/tests/mochitest/test_bug613662.html
new file mode 100644
index 0000000000..a35f52e453
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug613662.html
@@ -0,0 +1,132 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613662
+-->
+<head>
+ <title>Test for Bug 613662</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613662">Mozilla Bug 613662</a>
+<p id="display"></p><div id="content" style="display: none"></div><div id="content2" style="display: none"></div><pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 613662 **/
+
+function testPositions(node) {
+ node.insertAdjacentHTML("beforeBegin", "\u003Cscript>ok(false, 'script should not have run');\u003C/script><i></i>");
+ is(node.previousSibling.localName, "i", "Should have had <i> as previous sibling");
+ node.insertAdjacentHTML("Afterbegin", "<b></b>\u003Cscript>ok(false, 'script should not have run');\u003C/script>");
+ is(node.firstChild.localName, "b", "Should have had <b> as first child");
+ node.insertAdjacentHTML("BeforeEnd", "\u003Cscript>ok(false, 'script should not have run');\u003C/script><u></u>");
+ is(node.lastChild.localName, "u", "Should have had <u> as last child");
+ node.insertAdjacentHTML("afterend", "<a></a>\u003Cscript>ok(false, 'script should not have run');\u003C/script>");
+ is(node.nextSibling.localName, "a", "Should have had <a> as next sibling");
+}
+
+var content = document.getElementById("content");
+testPositions(content); // without next sibling
+testPositions(content); // test again when there's next sibling
+
+try {
+ content.insertAdjacentHTML("bar", "foo");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "SyntaxError", "insertAdjacentHTML should throw SyntaxError");
+ is(e.code, 12, "insertAdjacentHTML should throw SYNTAX_ERR");
+}
+
+var parent = document.createElement("div");
+var child = document.createElement("div");
+
+try {
+ child.insertAdjacentHTML("Beforebegin", "foo");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "NoModificationAllowedError", "insertAdjacentHTML should throw NoModificationAllowedError");
+ is(e.code, 7, "insertAdjacentHTML should throw NO_MODIFICATION_ALLOWED_ERR");
+}
+
+try {
+ child.insertAdjacentHTML("AfterEnd", "foo");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "NoModificationAllowedError", "insertAdjacentHTML should throw NoModificationAllowedError");
+ is(e.code, 7, "insertAdjacentHTML should throw NO_MODIFICATION_ALLOWED_ERR");
+}
+
+child.insertAdjacentHTML("afterBegin", "foo"); // mustn't throw
+child.insertAdjacentHTML("beforeend", "foo"); // mustn't throw
+
+parent.appendChild(child);
+testPositions(child); // node not in tree but has parent
+
+content.appendChild(parent); // must not run scripts
+
+try {
+ document.documentElement.insertAdjacentHTML("afterend", "<div></div>");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "NoModificationAllowedError", "insertAdjacentHTML should throw NoModificationAllowedError");
+ is(e.code, 7, "insertAdjacentHTML should throw NO_MODIFICATION_ALLOWED_ERR");
+}
+
+var content2 = document.getElementById("content2");
+
+var events = [
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+];
+
+function mutationEventListener(evt) {
+ var expected = events.shift();
+ is(evt.type, expected[0], "Unexpected mutation type");
+ is(evt.relatedNode, expected[1], "Unexpected related node");
+}
+/*
+document.addEventListener("DOMSubtreeModified", mutationEventListener, false);
+document.addEventListener("DOMNodeInserted", mutationEventListener, false);
+document.addEventListener("DOMNodeRemoved", mutationEventListener, false);
+document.addEventListener("DOMNodeRemovedFromDocument", mutationEventListener, false);
+document.addEventListener("DOMNodeInsertedIntoDocument", mutationEventListener, false);
+document.addEventListener("DOMAttrModified", mutationEventListener, false);
+document.addEventListener("DOMCharacterDataModified", mutationEventListener, false);
+
+testPositions(content2); // without next sibling
+testPositions(content2); // test again when there's next sibling
+
+is(events.length, 0, "Not all expected events fired.");
+*/
+// HTML only
+document.body.insertAdjacentHTML("afterend", "<p>");
+document.head.insertAdjacentHTML("beforebegin", "<p>");
+is(document.getElementsByTagName("head").length, 1, "Should still have one head");
+is(document.getElementsByTagName("body").length, 1, "Should still have one body");
+
+</script>
+</pre>
+</body></html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug613662.xhtml b/parser/htmlparser/tests/mochitest/test_bug613662.xhtml
new file mode 100644
index 0000000000..b6a5c63670
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug613662.xhtml
@@ -0,0 +1,137 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613662
+-->
+<head>
+ <title>Test for Bug 613662</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613662">Mozilla Bug 613662</a>
+<p id="display"></p><div id="content" style="display: none"></div><div id="content2" style="display: none"></div><pre id="test">
+<script type="application/javascript"><![CDATA[
+
+SimpleTest.expectAssertions(1);
+
+/** Test for Bug 613662 **/
+
+function testPositions(node) {
+ node.insertAdjacentHTML("beforeBegin", "\u003Cscript>ok(false, 'script should not have run');\u003C/script><i></i>");
+ is(node.previousSibling.localName, "i", "Should have had <i> as previous sibling");
+ node.insertAdjacentHTML("Afterbegin", "<b></b>\u003Cscript>ok(false, 'script should not have run');\u003C/script>");
+ is(node.firstChild.localName, "b", "Should have had <b> as first child");
+ node.insertAdjacentHTML("BeforeEnd", "\u003Cscript>ok(false, 'script should not have run');\u003C/script><u></u>");
+ is(node.lastChild.localName, "u", "Should have had <u> as last child");
+ node.insertAdjacentHTML("afterend", "<a></a>\u003Cscript>ok(false, 'script should not have run');\u003C/script>");
+ is(node.nextSibling.localName, "a", "Should have had <a> as next sibling");
+}
+
+var content = document.getElementById("content");
+testPositions(content); // without next sibling
+testPositions(content); // test again when there's next sibling
+
+try {
+ content.insertAdjacentHTML("bar", "foo");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "SyntaxError", "insertAdjacentHTML should throw SyntaxError");
+ is(e.code, 12, "insertAdjacentHTML should throw SYNTAX_ERR");
+}
+
+var parent = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
+var child = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
+
+try {
+ child.insertAdjacentHTML("Beforebegin", "foo");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "NoModificationAllowedError", "insertAdjacentHTML should throw NoModificationAllowedError");
+ is(e.code, 7, "insertAdjacentHTML should throw NO_MODIFICATION_ALLOWED_ERR");
+}
+
+try {
+ child.insertAdjacentHTML("AfterEnd", "foo");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "NoModificationAllowedError", "insertAdjacentHTML should throw NoModificationAllowedError");
+ is(e.code, 7, "insertAdjacentHTML should throw NO_MODIFICATION_ALLOWED_ERR");
+}
+
+child.insertAdjacentHTML("afterBegin", "foo"); // mustn't throw
+child.insertAdjacentHTML("beforeend", "foo"); // mustn't throw
+
+parent.appendChild(child);
+testPositions(child); // node not in tree but has parent
+
+content.appendChild(parent); // must not run scripts
+
+try {
+ document.documentElement.insertAdjacentHTML("afterend", "<div></div>");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "NoModificationAllowedError", "insertAdjacentHTML should throw NoModificationAllowedError");
+ is(e.code, 7, "insertAdjacentHTML should throw NO_MODIFICATION_ALLOWED_ERR");
+}
+
+var content2 = document.getElementById("content2");
+
+var events = [
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMNodeInserted", content2 ],
+ [ "DOMSubtreeModified", null ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMNodeInserted", document.body ],
+ [ "DOMSubtreeModified", null ],
+];
+
+function mutationEventListener(evt) {
+ var expected = events.shift();
+ is(evt.type, expected[0], "Unexpected mutation type");
+ is(evt.relatedNode, expected[1], "Unexpected related node");
+}
+
+document.addEventListener("DOMSubtreeModified", mutationEventListener);
+document.addEventListener("DOMNodeInserted", mutationEventListener);
+document.addEventListener("DOMNodeRemoved", mutationEventListener);
+document.addEventListener("DOMNodeRemovedFromDocument", mutationEventListener);
+document.addEventListener("DOMNodeInsertedIntoDocument", mutationEventListener);
+document.addEventListener("DOMAttrModified", mutationEventListener);
+document.addEventListener("DOMCharacterDataModified", mutationEventListener);
+
+testPositions(content2); // without next sibling
+testPositions(content2); // test again when there's next sibling
+
+is(events.length, 0, "Not all expected events fired.");
+
+// XML-only:
+try {
+ content.insertAdjacentHTML("beforeend", "<p>");
+ ok(false, "insertAdjacentHTML should have thrown");
+} catch (e) {
+ is(e.name, "SyntaxError", "insertAdjacentHTML should throw SyntaxError");
+ is(e.code, 12, "insertAdjacentHTML should throw SYNTAX_ERR");
+}
+
+]]></script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug639362.html b/parser/htmlparser/tests/mochitest/test_bug639362.html
new file mode 100644
index 0000000000..665f3c7910
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug639362.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=639362
+-->
+<head>
+ <title>Test for Bug 639362</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=639362">Mozilla Bug 639362</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function loaded(iframe) {
+ is(SpecialPowers.wrap(iframe).contentWindow.location.href, iframe.src, "should load correct URL");
+ is(SpecialPowers.wrap(iframe).contentDocument.body.textContent, "CACHE MANIFEST", "text/cache-manifest should be treated as text");
+ SimpleTest.finish();
+}
+</script>
+<iframe src="data:text/cache-manifest,CACHE MANIFEST" onload="loaded(this);"></iframe>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug642908.html b/parser/htmlparser/tests/mochitest/test_bug642908.html
new file mode 100644
index 0000000000..10fd735363
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug642908.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=642908
+-->
+<head>
+ <title>Test for Bug 642908</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="loaded();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=642908">Mozilla Bug 642908</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+document.write("\u003Cscript src='data:text/javascript,1;'>\u003C/script>");
+document.write("<noscript><img src='file_bug642908.sjs'></noscript>");
+
+function loaded() {
+ var s = document.createElement("script");
+ s.src = "file_bug642908.sjs?report=1";
+ document.body.appendChild(s);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug645115.html b/parser/htmlparser/tests/mochitest/test_bug645115.html
new file mode 100644
index 0000000000..74f4e8be4f
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug645115.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=645115
+-->
+<head>
+ <title>Test for Bug 645115</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=645115">Mozilla Bug 645115</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 645115 **/
+var div = document.createElement("div");
+div.innerHTML = "\u003Cscript>ok(false, 'innerHTML script ran');\u003C/script>\u003Cscript>";
+document.getElementById("content").appendChild(div);
+
+ok(true, "Keep the test harness happy.");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_bug655682.html b/parser/htmlparser/tests/mochitest/test_bug655682.html
new file mode 100644
index 0000000000..7011d3044c
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug655682.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=655682
+-->
+<head>
+ <title>Test for Bug 655682</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=655682">Mozilla Bug 655682</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe src=file_bug655682.sjs></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 655682 **/
+
+var gotOnload = false;
+var finishedTesting = false;
+
+function tryFinishTest() {
+ if (gotOnload && finishedTesting) {
+ SimpleTest.finish();
+ }
+}
+
+addLoadEvent(function() {
+ // Hit the event loop again just to make sure that we're not ending the test
+ // before all activity we care about is done.
+ SimpleTest.executeSoon(function() {
+ gotOnload = true;
+ tryFinishTest();
+ });
+});
+
+var tdsSeen = 0;
+
+var triggeredSecondTd = false;
+
+var iframe = document.getElementsByTagName("iframe")[0];
+
+SimpleTest.waitForExplicitFinish();
+
+function probe() {
+ var tds = iframe.contentDocument.getElementsByTagName("td").length;
+ switch (tds) {
+ case 0:
+ setTimeout(probe, 0);
+ return;
+ case 1:
+ tdsSeen = tds;
+ if (!triggeredSecondTd) {
+ triggeredSecondTd = true;
+ var script = document.createElement("script");
+ script.src = "file_bug655682.sjs?trigger=1";
+ document.head.appendChild(script);
+ }
+ setTimeout(probe, 0);
+ return;
+ case 2:
+ is(tdsSeen, 1, "Should have seen one td before seeing two.");
+ finishedTesting = true;
+ tryFinishTest();
+ return;
+ default:
+ ok(false, "Wrong number of tds");
+ SimpleTest.finish();
+ }
+}
+
+setTimeout(probe, 0);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug667533.html b/parser/htmlparser/tests/mochitest/test_bug667533.html
new file mode 100644
index 0000000000..c531d4cec3
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug667533.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=667533
+-->
+<head>
+ <title>Test for Bug 667533</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=667533">Mozilla Bug 667533</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function loaded(iframe) {
+ is(SpecialPowers.wrap(iframe).contentWindow.location.href, iframe.src, "should load correct URL");
+ is(SpecialPowers.wrap(iframe).contentDocument.body.textContent, '{"<p>Hello</p>": null}', "application/json should be treated as text");
+ SimpleTest.finish();
+}
+</script>
+<iframe src="data:application/json,{&quot;<p>Hello</p>&quot;:%20null}" onload="loaded(this);"></iframe>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug672453.html b/parser/htmlparser/tests/mochitest/test_bug672453.html
new file mode 100644
index 0000000000..312757cb58
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug672453.html
@@ -0,0 +1,131 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=672453
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 672453</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=672453"
+ >Mozilla Bug 672453</a>
+<iframe></iframe>
+<script>
+/** Test for Bug 672453 **/
+
+var tests = [
+ "file_bug672453_not_declared.html",
+ "file_bug672453_xml_decl.html",
+ "file_bug672453_late_meta.html",
+ "file_bug672453_meta_restart.html",
+ "file_bug672453_meta_after_head.html",
+ "file_bug672453_meta_unsupported.html",
+ "file_bug672453_http_unsupported.html",
+ "file_bug672453_meta_utf16.html",
+ "file_bug672453_meta_non_superset.html",
+ "file_bug672453_meta_userdefined.html",
+ "file_bug672453_meta_replacement.html",
+ "file_bug672453_http_replacement.html",
+ "file_bug672453_enc_error.html",
+ "file_bug672453_enc_error_inherited.html",
+ "file_bug672453_meta_speculation_fail.html",
+ "file_bug672453_xml_speculation_fail.html",
+];
+
+// The general idea here is that encoding substitutions or failures to declare the encoding
+// (except when inherited or, not tested here, all-ASCII) are errors and ineffeciencies
+// or risks about things failing under further editing (i.e. meta after head but within
+// the extended scan zone) are warnings.
+
+var expectedErrors = [
+ { errorMessage: "The character encoding of a framed document was not declared. The document may appear different if viewed without the document framing it.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html",
+ lineNumber: 0,
+ isWarning: true },
+ { errorMessage: "The character encoding of an HTML document was declared using the XML declaration syntax. This is non-conforming, and declaring the encoding using a meta tag at the start of the head part is more efficient.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_xml_decl.html",
+ lineNumber: 1,
+ isWarning: true },
+ { errorMessage: "A meta tag attempting to declare the character encoding declaration was found too late, and the encoding of the parent document was used instead. The meta tag needs to be moved to the start of the head part of the document.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html",
+ lineNumber: 1028,
+ isWarning: false },
+ { errorMessage: "A meta tag attempting to declare the character encoding declaration was found too late, and the encoding of the parent document was used instead. The meta tag needs to be moved to the start of the head part of the document.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html",
+ lineNumber: 1028,
+ isWarning: false },
+ { errorMessage: "The meta tag declaring the character encoding of the document should be moved to start of the head part of the document.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_after_head.html",
+ lineNumber: 7,
+ isWarning: true },
+ { errorMessage: "An unsupported character encoding was declared for the HTML document using a meta tag. The declaration was ignored.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html",
+ lineNumber: 1,
+ isWarning: false },
+ { errorMessage: "An unsupported character encoding was declared on the transfer protocol level. The declaration was ignored.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html",
+ lineNumber: 0,
+ isWarning: false },
+ { errorMessage: "A meta tag was used to declare the character encoding as UTF-16. This was interpreted as an UTF-8 declaration instead.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html",
+ lineNumber: 1,
+ isWarning: false },
+ { errorMessage: "An unsupported character encoding was declared for the HTML document using a meta tag. The declaration was ignored.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html",
+ lineNumber: 1,
+ isWarning: false },
+ { errorMessage: "A meta tag was used to declare the character encoding as x-user-defined. This was interpreted as a windows-1252 declaration instead for compatibility with intentionally mis-encoded legacy fonts. This site should migrate to Unicode.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_userdefined.html",
+ lineNumber: 1,
+ isWarning: false },
+ { errorMessage: "A meta tag was used to declare an encoding that is a cross-site scripting hazard. The replacement encoding was used instead.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_replacement.html",
+ lineNumber: 0,
+ isWarning: false },
+ { errorMessage: "An encoding that is a cross-site scripting hazard was declared on the transfer protocol level. The replacement encoding was used instead.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_http_replacement.html",
+ lineNumber: 0,
+ isWarning: false },
+ { errorMessage: "The byte stream was erroneous according to the character encoding that was declared. The character encoding declaration may be incorrect.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_enc_error.html",
+ lineNumber: 0,
+ isWarning: false },
+ { errorMessage: "The byte stream was erroneous according to the character encoding that was inherited from the parent document. The character encoding needs to be declared in the Content-Type HTTP header, using a meta tag, or using a byte order mark.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_enc_error_inherited.html",
+ lineNumber: 0,
+ isWarning: false },
+ { errorMessage: "The start of the document was reparsed, because there were non-ASCII characters before the meta tag that declared the encoding. The meta should be the first child of head without non-ASCII comments before.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_speculation_fail.html",
+ lineNumber: 5,
+ isWarning: true },
+ { errorMessage: "The start of the document was reparsed, because there were non-ASCII characters in the part of the document that was unsuccessfully searched for a meta tag before falling back to the XML declaration syntax. A meta tag at the start of the head part should be used instead of the XML declaration syntax.",
+ sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_xml_speculation_fail.html",
+ lineNumber: 10,
+ isWarning: true },
+];
+
+SimpleTest.waitForExplicitFinish();
+
+window.onload = function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+
+ function runNextTest() {
+ var url = tests.shift();
+ if (!url) {
+ SimpleTest.endMonitorConsole();
+ return;
+ }
+ iframe.src = url;
+ }
+ iframe.onload = runNextTest;
+
+ SimpleTest.monitorConsole(SimpleTest.finish, expectedErrors);
+ runNextTest();
+};
+</script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug688580.html b/parser/htmlparser/tests/mochitest/test_bug688580.html
new file mode 100644
index 0000000000..1d18cc5f78
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug688580.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=688580
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 688580</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 688580 **/
+
+ // Expected order:
+ // Test starting
+ // readyState interactive
+ // defer
+ // DOMContentLoaded
+ // readyState complete
+ // load
+
+ var state = "Test starting";
+ var readyStateCall = 0;
+ SimpleTest.waitForExplicitFinish();
+ is(document.readyState, "loading", "Document should have been loading.");
+ document.addEventListener("DOMContentLoaded", function() {
+ is(document.readyState, "interactive", "readyState should be interactive during DOMContentLoaded.");
+ is(state, "defer", "Bad state upon DOMContentLoaded");
+ state = "DOMContentLoaded";
+ });
+ document.addEventListener("readystatechange", function() {
+ readyStateCall++;
+ if (readyStateCall == 1) {
+ is(document.readyState, "interactive", "readyState should have changed to interactive.");
+ is(state, "Test starting", "Bad state upon first readystatechange.");
+ state = "readyState interactive";
+ } else if (readyStateCall == 2) {
+ is(document.readyState, "complete", "readyState should have changed to complete.");
+ is(state, "DOMContentLoaded", "Bad state upon second readystatechange.");
+ state = "readyState complete";
+ } else {
+ ok(false, "Too many readystatechanges");
+ }
+ });
+ window.addEventListener("load", function() {
+ is(document.readyState, "complete", "readyState should be complete during load.");
+ is(state, "readyState complete", "Bad state upon load");
+ state = "load";
+ SimpleTest.finish();
+ });
+ </script>
+ <script defer src="file_bug688580.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=688580">Mozilla Bug 688580</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug688580.xhtml b/parser/htmlparser/tests/mochitest/test_bug688580.xhtml
new file mode 100644
index 0000000000..a4046dfa76
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug688580.xhtml
@@ -0,0 +1,62 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=688580
+-->
+<head>
+ <title>Test for Bug 688580</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 688580 **/
+
+ // Expected order:
+ // Test starting
+ // readyState interactive
+ // defer
+ // DOMContentLoaded
+ // readyState complete
+ // load
+
+ var state = "Test starting";
+ var readyStateCall = 0;
+ SimpleTest.waitForExplicitFinish();
+ is(document.readyState, "loading", "Document should have been loading.");
+ document.addEventListener("DOMContentLoaded", function() {
+ is(document.readyState, "interactive", "readyState should be interactive during DOMContentLoaded.");
+ is(state, "defer", "Bad state upon DOMContentLoaded");
+ state = "DOMContentLoaded";
+ });
+ document.addEventListener("readystatechange", function() {
+ readyStateCall++;
+ if (readyStateCall == 1) {
+ is(document.readyState, "interactive", "readyState should have changed to interactive.");
+ is(state, "Test starting", "Bad state upon first readystatechange.");
+ state = "readyState interactive";
+ } else if (readyStateCall == 2) {
+ is(document.readyState, "complete", "readyState should have changed to complete.");
+ is(state, "DOMContentLoaded", "Bad state upon second readystatechange.");
+ state = "readyState complete";
+ } else {
+ ok(false, "Too many readystatechanges");
+ }
+ });
+ window.addEventListener("load", function() {
+ is(document.readyState, "complete", "readyState should be complete during load.");
+ is(state, "readyState complete", "Bad state upon load");
+ state = "load";
+ SimpleTest.finish();
+ });
+ </script>
+ <script defer="" src="file_bug688580.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=688580">Mozilla Bug 688580</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug709083.html b/parser/htmlparser/tests/mochitest/test_bug709083.html
new file mode 100644
index 0000000000..74f39c38d5
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug709083.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=709083
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 709083</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=709083">Mozilla Bug 709083</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<video muted>
+<script type="application/javascript">
+
+/** Test for Bug 709083 **/
+
+ok(document.getElementsByTagName("video")[0].muted, "Should be muted already.");
+
+</script>
+</video>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug715112.html b/parser/htmlparser/tests/mochitest/test_bug715112.html
new file mode 100644
index 0000000000..1b81f2da2a
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug715112.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=715112
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 715112</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=715112">Mozilla Bug 715112</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 715112 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var expected = [
+ "First",
+ "Second",
+];
+
+function log(str) {
+ is(str, expected.shift(), "Unexpected log string.");
+}
+
+var w = window.open();
+w.document.open();
+w.document.addEventListener("DOMContentLoaded", function() {
+ is(expected.length, 0, "Not all expected messages were logged.");
+ is(w.document.getElementsByTagName("script").length, 3, "The document should have 3 scripts.");
+ w.close();
+ SimpleTest.finish();
+});
+w.document.write("\u003cscript>opener.log('First');\u003c/script>");
+w.document.write("\u003cscript>document.close();\u003c/script>");
+w.document.write("\u003cscript>opener.log('Second');\u003c/script>");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug715739.html b/parser/htmlparser/tests/mochitest/test_bug715739.html
new file mode 100644
index 0000000000..914459c2ce
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug715739.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=715739
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 715739</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="tick()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=715739">Mozilla Bug 715739</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 715739 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var runNumber = 0;
+
+function textChildren(node) {
+ var s = "";
+ var n = node.firstChild;
+ while (n) {
+ if (n.nodeType == Node.TEXT_NODE) {
+ s += n.nodeValue;
+ }
+ n = n.nextSibling;
+ }
+ return s;
+}
+
+var f, d;
+
+function tick() {
+ runNumber++;
+ f = document.getElementsByTagName("iframe")[0];
+ d = f.contentDocument;
+ var text;
+
+ if (runNumber == 1) {
+ frames[1].setTimeout(`
+ var d = parent.d;
+ var f = parent.f;
+ d.open();
+ f.addEventListener("load", parent.tick);
+ d.write("X");
+ d.write("\u003cscript>document.write('Y');\u003c/script>");
+ d.write("Z");
+ d.close();
+ `);
+ return;
+ }
+
+ if (runNumber == 2) {
+ text = textChildren(d.body);
+ is(text, "XYZ", "Wrong text before reload.");
+ f.contentWindow.location.reload();
+ return;
+ }
+
+ if (runNumber == 3) {
+ text = textChildren(d.body);
+ is(text, "ABC", "Wrong text after reload.");
+ SimpleTest.finish();
+ }
+}
+
+// We want to trigger a document.open/write with a different window as the
+// entry global. Let's give that window a blob URL so we don't have to set up
+// extra helper files.
+var blob = new Blob(["ABC"], { type: "text/html" });
+var blobURL = URL.createObjectURL(blob);
+
+</script>
+</pre>
+<div id="content" style="display: none">
+ <iframe></iframe>
+ <iframe></iframe>
+</div>
+<script>
+ document.querySelectorAll("iframe")[1].src = blobURL;
+</script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug716579.html b/parser/htmlparser/tests/mochitest/test_bug716579.html
new file mode 100644
index 0000000000..32ae13a611
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug716579.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=716579
+-->
+<head>
+ <meta charset="windows-1251">
+ <title>Test for Bug 716579</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=716579">Mozilla Bug 716579</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 716579 **/
+
+var html8 = "FAIL";
+var html16 = "FAIL";
+var xml8 = "FAIL";
+var xml16 = "FAIL";
+
+SimpleTest.waitForExplicitFinish();
+
+window.onload = function() {
+ is(html8, "\u20AC", "HTML UTF-8 failed.");
+ is(html16, "\u20AC", "HTML UTF-16 failed.");
+ is(xml8, "\u20AC", "XML UTF-8 failed.");
+ is(xml16, "\u20AC", "XML UTF-16 failed.");
+ SimpleTest.finish();
+};
+
+</script>
+</pre>
+<div id="content" style="display: none">
+<iframe src="file_bug716579-8.html"></iframe>
+<iframe src="file_bug716579-16.html"></iframe>
+<iframe src="file_bug716579-8.xhtml"></iframe>
+<iframe src="file_bug716579-16.xhtml"></iframe>
+</div>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_bug717180.html b/parser/htmlparser/tests/mochitest/test_bug717180.html
new file mode 100644
index 0000000000..7351264562
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_bug717180.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=717180
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 717180</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717180">Mozilla Bug 717180</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 717180 **/
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener("load", function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ var d = iframe.contentDocument;
+ d.open();
+ iframe.addEventListener("load", function() {
+ is(iframe.contentDocument.body.textContent, "SUCCESS\n", "Wrong text");
+ SimpleTest.finish();
+ });
+ d.write("\u003Cscript>");
+ d.write("window.location = 'file_bug717180.html';");
+ d.write("\u003C/script>");
+ d.write("FAIL");
+ d.close();
+ is(iframe.contentDocument.body, null, "The document should not have a body right now.");
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_compatmode.html b/parser/htmlparser/tests/mochitest/test_compatmode.html
new file mode 100644
index 0000000000..82121b2fd6
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_compatmode.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <title>Mochitest for DOCTYPE parsing</title>
+
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=363883">Mozilla Bug 363883</a>
+
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var doctypes = [
+/* from bug 363883 */
+"BackCompat", "<!DOCTYPE>",
+"BackCompat", "<!DOCTYPEz>",
+"BackCompat", "<! DOCTYPE>",
+"BackCompat", "<!zDOCTYPE>",
+"CSS1Compat", "<!DOCTYPEHTML>",
+"BackCompat", "<!DOCTYPEz HTML>",
+"CSS1Compat", "<!DOCTYPE HTML>",
+"BackCompat", "<!zDOCTYPE HTML>",
+"BackCompat", "<!DOCTYPE HTMLz>",
+"BackCompat", "<!DOCTYPE zHTML>",
+"BackCompat", "<!DOCTYPE XHTML>",
+"BackCompat", "<!DOCTYPE zzHTML>",
+"BackCompat", "<!DOCTYPEzHTML>",
+"BackCompat", "<!DOCTYPEzzHTML>",
+"BackCompat", '<!DOCTYPE "bla">',
+"BackCompat", '<!DOCTYPE HTML "bla">',
+"BackCompat", '<!DOCTYPE HTML "html">',
+"BackCompat", "<!DOCTYPE PUBLIC>",
+"BackCompat", '<!DOCTYPE PUBLIC "bla">',
+"BackCompat", '<!DOCTYPE PUBLIC "html">',
+"CSS1Compat", '<!DOCTYPE HTML PUBLIC "bla">',
+"BackCompat", '<!DOCTYPE HTML PUBLIC "html">',
+"BackCompat", '<!DOCTYPEz HTML PUBLIC "html">',
+"BackCompat", '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//en">',
+"BackCompat", '<!DOCTYPEz HTML PUBLIC "-//IETF//DTD HTML 3.2//en">',
+"BackCompat", '<!DOCTYPE HTMLz PUBLIC "DTD HTML 3.2">',
+"BackCompat", '<!DOCTYPE "DTD HTML 3.2">',
+/* end from bug 363883 */
+// from bug 502600
+"BackCompat", '<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">',
+];
+
+window.addEventListener("message", verifyResult);
+
+function verifyResult(event) {
+ let i = event.data.index;
+ let curFrame = document.getElementById("test" + i);
+ let mode = SpecialPowers.wrap(curFrame).contentDocument.compatMode;
+ is(mode, doctypes[i], doctypes[i + 1]);
+ if (i == doctypes.length - 2) {
+ window.removeEventListener("message", verifyResult);
+ SimpleTest.finish();
+ }
+}
+
+// //
+// Insert a hidden iframe into the document, with the src
+// containing the test doctype. The iframe's onload
+// function is set to call the test's verification step.
+//
+function insert_iframe(index, doctype) {
+ var elm = document.createElement("iframe");
+ elm.setAttribute("id", "test" + index);
+ elm.setAttribute("src", "data:text/html," + doctype +
+ '<html><body onload="parent.postMessage({index:' + index + '},\'*\');"></body>');
+ elm.setAttribute("style", "display:none");
+ document.getElementsByTagName("body")[0].appendChild(elm);
+}
+
+// //
+// Iterate over the tests
+//
+function doTest() {
+ for (var i = 0; i < doctypes.length; i += 2) {
+ insert_iframe(i, doctypes[i + 1]);
+ }
+}
+
+// //
+// Run the compatbility mode tests.
+//
+SimpleTest.waitForExplicitFinish();
+doTest();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_html5_tree_construction.html b/parser/htmlparser/tests/mochitest/test_html5_tree_construction.html
new file mode 100644
index 0000000000..fe755a7248
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_html5_tree_construction.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=366936
+-->
+<head>
+ <meta charset=utf-8>
+ <title>Test for Bug 366936</title>
+ <script type="text/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css"
+ href="/tests/SimpleTest/test.css" />
+ <script type="application/javascript"
+ src="parser_datreader.js"></script>
+ <script type="application/javascript"
+ src="html5_tree_construction_exceptions.js"></script>
+ <script class="testbody" type="application/javascript">
+ var parserDatFiles = ["adoption01.dat",
+ "adoption02.dat",
+ "comments01.dat",
+ "doctype01.dat",
+ "domjs-unsafe.dat",
+ "entities01.dat",
+ "entities02.dat",
+ "html5test-com.dat",
+ "inbody01.dat",
+ "isindex.dat",
+ "pending-spec-changes.dat",
+ "pending-spec-changes-plain-text-unsafe.dat",
+ "plain-text-unsafe.dat",
+ "scripted/adoption01.dat",
+ "scripted/webkit01.dat",
+ "scripted/ark.dat",
+ "scriptdata01.dat",
+ "tables01.dat",
+ "template.dat",
+ "tests10.dat",
+ "tests11.dat",
+ "tests12.dat",
+ "tests14.dat",
+ "tests15.dat",
+ "tests16.dat"];
+
+ </script>
+ <script type="application/javascript"
+ src="parser_web_testrunner.js"></script>
+</head>
+<body>
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=366936"
+ target="_blank">Mozilla Bug 366936</a>
+<div id="content">
+<iframe src="" id="testframe"></iframe>
+</div>
+See https://github.com/html5lib/html5lib-tests for original test data<br>
+<div id="display">
+
+</div>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_html5_tree_construction_part2.html b/parser/htmlparser/tests/mochitest/test_html5_tree_construction_part2.html
new file mode 100644
index 0000000000..fa64788fc0
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_html5_tree_construction_part2.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=366936
+-->
+<head>
+ <meta charset=utf-8>
+ <title>Test for Bug 366936</title>
+ <script type="text/javascript"
+ src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css"
+ href="/tests/SimpleTest/test.css" />
+ <script type="application/javascript"
+ src="parser_datreader.js"></script>
+ <script type="application/javascript"
+ src="html5_tree_construction_exceptions.js"></script>
+ <script class="testbody" type="application/javascript">
+ var parserDatFiles = ["tests17.dat",
+ "tests18.dat",
+ "tests19.dat",
+ "tests1.dat",
+ "tests20.dat",
+ "tests21.dat",
+ "tests22.dat",
+ "tests23.dat",
+ "tests24.dat",
+ "tests25.dat",
+ "tests26.dat",
+ "tests2.dat",
+ "tests3.dat",
+ "tests4.dat",
+ "tests5.dat",
+ "tests6.dat",
+ "tests7.dat",
+ "tests8.dat",
+ "tests9.dat",
+ "tests_innerHTML_1.dat",
+ "tricky01.dat",
+ "webkit01.dat",
+ "webkit02.dat",
+ "main-element.dat",
+ "foreign-fragment.dat",
+ "ruby.dat"];
+ </script>
+ <script type="application/javascript"
+ src="parser_web_testrunner.js"></script>
+</head>
+<body>
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=366936"
+ target="_blank">Mozilla Bug 366936</a>
+<div id="content">
+<iframe src="" id="testframe"></iframe>
+</div>
+See https://github.com/html5lib/html5lib-tests for original test data<br>
+<div id="display">
+
+</div>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/mochitest/test_img_picture_preload.html b/parser/htmlparser/tests/mochitest/test_img_picture_preload.html
new file mode 100644
index 0000000000..295993060b
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_img_picture_preload.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1067345
+-->
+<head>
+ <title>Test for Bug 1067345</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <script>
+ // Ensure srcset/picture are enabled, re-run the test at different DPI
+ // levels to ensure preload step does the right responsive image selection
+
+ SimpleTest.waitForExplicitFinish();
+
+ var testDPIs = [ "1.0", "0.5", "2.0", "1.5" ];
+ var iframe = document.createElement("iframe");
+
+ // These accessed by child frame
+ var currentDPI;
+
+ document.body.appendChild(iframe);
+
+ SpecialPowers.pushPrefEnv({"set": [ [ "dom.image.srcset.enabled", true ],
+ [ "dom.image.picture.enabled", true ]] },
+ function() {
+ // Reset the sjs helper so repeat runs work
+ resetRequests();
+ setTimeout(nextTest, 0);
+ });
+
+ function resetRequests() {
+ // Ask the SJS to reset requests
+ var request = new XMLHttpRequest();
+ request.open("GET", "./file_img_picture_preload.sjs?reset", false);
+ request.send(null);
+ is(request.status, 200, "Sending reset to helper should succeed");
+ // Script responds with pre-reset request count
+ var previousRequests = +request.responseText;
+
+ return previousRequests;
+ }
+
+ // Called when iframe is finished
+ function childTestFinished(requestsMade) {
+ setTimeout(function() {
+ // Reset sjs, ensure no new requests appeared after test finished
+ var requestsCleared = resetRequests();
+ is(requestsCleared, requestsMade,
+ "Should not have recorded new requests after test iteration completed");
+
+ setTimeout(nextTest, 0);
+ }, 0);
+ }
+
+ function nextTest() {
+ // Re-run test for each DPI level
+ if (testDPIs.length) {
+ currentDPI = testDPIs.pop();
+ info("Starting test for DPI: " + currentDPI);
+ // To avoid spurious image loads being reported when the resolution changes,
+ // load an intermediate iframe.
+ iframe.src = "about:blank";
+ iframe.addEventListener("load", function() {
+ SpecialPowers.pushPrefEnv({"set": [ [ "layout.css.devPixelsPerPx", currentDPI ]] },
+ function() {
+ // Make sure we trigger a layout flush so that the frame is sized
+ // appropriately after the DPI changes.
+ iframe.getBoundingClientRect();
+ // Clear image cache for next run (we don't try to validate cached items
+ // in preload).
+ SpecialPowers.Cc["@mozilla.org/image/tools;1"]
+ .getService(SpecialPowers.Ci.imgITools)
+ .getImgCacheForDocument(iframe.contentDocument)
+ .clearCache(false);
+ iframe.src = "./file_img_picture_preload.html?" + currentDPI;
+ });
+ }, {once: true});
+ } else {
+ SimpleTest.finish();
+ }
+ }
+ </script>
+
+</body>
+</html>
diff --git a/parser/htmlparser/tests/mochitest/test_xml_mislabeled.html b/parser/htmlparser/tests/mochitest/test_xml_mislabeled.html
new file mode 100644
index 0000000000..0865647389
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_xml_mislabeled.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html><meta charset=utf-8>
+<title>Test for mislabeled or unlabeled XML entities with U+xxD8</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+<body>
+<script class="testbody">
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+
+var declaredEncodings = [null, "utf-8", "uTf-8", "UTF-8", "utf-16", "uTf-16", "UTF-16"];
+var actualEncodings = ["utf-8", "utf-16be", "utf-16le"];
+var i = 0, j = 0;
+testxhr(declaredEncodings[i], actualEncodings[j]);
+
+function testxhr(declaredEncoding, actualEncoding) {
+ // utf-16 XML requres the BOM
+ var bom = actualEncoding.startsWith("utf-16") ? "\uFEFF" : "";
+ var xmlDecl = declaredEncoding ? '<?xml version="1.0" encoding="' + declaredEncoding + '" ?>\n' : "";
+ // The test string need to contain U+xxD8 (bug 860180)
+ var xmlString = bom + xmlDecl + "<test>testãƒãƒ’フヘホ</test>";
+ var xml = new TextEncoder(actualEncoding).encode(xmlString);
+ var description = declaredEncoding ? " labeled with " + declaredEncoding : " without XML declaration";
+ if (!declaredEncoding || actualEncoding !== declaredEncoding.toLowerCase()) {
+ description += " but actually encoded with " + actualEncoding;
+ }
+ var xhr = new XMLHttpRequest();
+ var url = URL.createObjectURL(new Blob([xml], {type: "text/xml"}));
+ xhr.open("GET", url);
+ xhr.send();
+ xhr.onload = xhr.onerror = function(e) {
+ URL.revokeObjectURL(url);
+ is(e.type, "load", "xhr loading should succeed for XML" + description);
+ is(xhr.responseXML.documentElement.textContent, "testãƒãƒ’フヘホ",
+ "response should be available for XML" + description);
+ testiframe(description, xml);
+ };
+}
+
+function testiframe(description, xml) {
+ var iframe = document.createElement("iframe");
+ var url = URL.createObjectURL(new Blob([xml], {type: "text/xml"}));
+ iframe.src = url;
+ iframe.onload = iframe.onerror = function(e) {
+ URL.revokeObjectURL(url);
+ is(e.type, "load", "iframe loading should succeed for XML" + description);
+ is(iframe.contentDocument.documentElement.textContent, "testãƒãƒ’フヘホ",
+ "iframe content should be available for XML" + description);
+ if (++i >= declaredEncodings.length) {
+ i = 0;
+ if (++j >= actualEncodings.length) {
+ SimpleTest.finish();
+ return;
+ }
+ }
+ testxhr(declaredEncodings[i], actualEncodings[j]);
+ };
+ document.body.appendChild(iframe);
+}
+</script>
+<div id="display"></div>
+</body>
diff --git a/parser/htmlparser/tests/mochitest/test_xml_parse_error.html b/parser/htmlparser/tests/mochitest/test_xml_parse_error.html
new file mode 100644
index 0000000000..5c023ecfbd
--- /dev/null
+++ b/parser/htmlparser/tests/mochitest/test_xml_parse_error.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title><!-- TODO: insert title here --></title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <script>
+ function getExpectedError(string, filename=location.href) {
+ let lines = string.split(/\r\n|\r|\n/);
+ let line, column;
+ let errorLine;
+ for (line = 0; line < lines.length; ++line) {
+ errorLine = lines[line];
+ // The error starts at the opening '<' of '<b>'.
+ column = errorLine.search("<<b>") + 1;
+ if (column > 0) {
+ // Line and column are 1-based.
+ line += 1;
+ column += 1;
+ break;
+ }
+ }
+
+ let expectedError = `XML Parsing Error: not well-formed
+Location: ${filename}
+Line Number ${line}, Column ${column}:${errorLine}
+${"^".padStart(column, "-")}`;
+ return expectedError;
+ }
+
+ function getParseError(string) {
+ let error = new window.DOMParser()
+ .parseFromString(string, "text/xml")
+ .getElementsByTagName("parsererror")[0].textContent;
+ return [error, getExpectedError(string)];
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest() {
+ let [error, expectedError] = getParseError("<p>Not a <<b>well-formed</b> xml string</p>");
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ [error, expectedError] = getParseError("<p>Not \na <<b>well-formed</b> xml string</p>");
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ [error, expectedError] = getParseError("<p>Not \na <<b>well-formed</b> xml string</p>");
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ [error, expectedError] = getParseError("<p>Not a <<b>well-fo\nrmed</b> xml string</p>");
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ [error, expectedError] = getParseError(`<p>Not ${' '.repeat(512)} a <<b>well-formed</b> xml string</p>`);
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ [error, expectedError] = getParseError(`<p>${' '.repeat(505)}<br>${' '.repeat(512)}<<b>Not a well-formed</b> xml string</p>`);
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ [error, expectedError] = getParseError(`<p>${' '.repeat(2048)}<br>${' '.repeat(512)}<<b>Not a well-formed</b> xml string</p>`);
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ fetch("file_xml_parse_error.xml").then(response => response.text()).then(string => {
+ let doc = document.getElementById("frame").contentDocument;
+ error = doc.documentElement.textContent;
+ expectedError = getExpectedError(string, doc.location);
+ is(error, expectedError, "Check that parsererror contains the right data.");
+
+ SimpleTest.finish();
+ });
+ }
+ </script>
+</head>
+<body onload="runTest()">
+<p id="display"><iframe id="frame" src="file_xml_parse_error.xml"></iframe></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/after-1kb-ref.html b/parser/htmlparser/tests/reftest/after-1kb-ref.html
new file mode 100644
index 0000000000..edb0ae9c72
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-1kb-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>In <code>head</code>, after first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-1kb.html b/parser/htmlparser/tests/reftest/after-1kb.html
new file mode 100644
index 0000000000..01eedca187
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-1kb.html
@@ -0,0 +1,955 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/after-1kb-ref.html">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<meta charset="windows-1251">
+</head>
+<body>
+<p>In <code>head</code>, after first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-bogus-after-1kb-ref.html b/parser/htmlparser/tests/reftest/after-bogus-after-1kb-ref.html
new file mode 100644
index 0000000000..c6f129a89e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-bogus-after-1kb-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>After <code>bogus</code>, before <code>head</code> end tag, after first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-bogus-after-1kb.html b/parser/htmlparser/tests/reftest/after-bogus-after-1kb.html
new file mode 100644
index 0000000000..f44fda1e6d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-bogus-after-1kb.html
@@ -0,0 +1,933 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/after-bogus-after-1kb-ref.html">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<bogus><meta charset="windows-1251">
+</head>
+<body>
+<p>After <code>bogus</code>, before <code>head</code> end tag, after first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-bogus-ref.html b/parser/htmlparser/tests/reftest/after-bogus-ref.html
new file mode 100644
index 0000000000..f8080e60aa
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-bogus-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta after <code>bogus</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-bogus.html b/parser/htmlparser/tests/reftest/after-bogus.html
new file mode 100644
index 0000000000..7eeedde7af
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-bogus.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/after-bogus-ref.html">
+<bogus><meta charset="windows-1251">
+</head>
+<body>
+<p>Meta after <code>bogus</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-after-1kb-crlf-ref.html b/parser/htmlparser/tests/reftest/after-head-after-1kb-crlf-ref.html
new file mode 100644
index 0000000000..868a9639bf
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-after-1kb-crlf-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>After <code>head</code>, before <code>body</code>, after first kilobyte, with a CRLF in the first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-after-1kb-crlf.html b/parser/htmlparser/tests/reftest/after-head-after-1kb-crlf.html
new file mode 100644
index 0000000000..10a6d1c3d7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-after-1kb-crlf.html
@@ -0,0 +1,927 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/after-head-after-1kb-crlf-ref.html">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</head>
+<meta charset="windows-1251">
+<body>
+<p>After <code>head</code>, before <code>body</code>, after first kilobyte, with a CRLF in the first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-after-1kb-ref.html b/parser/htmlparser/tests/reftest/after-head-after-1kb-ref.html
new file mode 100644
index 0000000000..bde4745b26
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-after-1kb-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>After <code>head</code>, before <code>body</code>, after first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-after-1kb.html b/parser/htmlparser/tests/reftest/after-head-after-1kb.html
new file mode 100644
index 0000000000..d514fdfbff
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-after-1kb.html
@@ -0,0 +1,933 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/after-head-after-1kb-ref.html">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</head>
+<meta charset="windows-1251">
+<body>
+<p>After <code>head</code>, before <code>body</code>, after first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-in-1kb-crlf-ref.html b/parser/htmlparser/tests/reftest/after-head-in-1kb-crlf-ref.html
new file mode 100644
index 0000000000..0676d7374e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-in-1kb-crlf-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>After <code>head</code>, before <code>body</code>, within first kilobyte, with a CRLF in the first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-in-1kb-crlf.html b/parser/htmlparser/tests/reftest/after-head-in-1kb-crlf.html
new file mode 100644
index 0000000000..e5c95e7036
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-in-1kb-crlf.html
@@ -0,0 +1,932 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/after-head-in-1kb-crlf-ref.html">
+</head>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<meta charset="windows-1251">
+<body>
+<p>After <code>head</code>, before <code>body</code>, within first kilobyte, with a CRLF in the first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-in-1kb-ref.html b/parser/htmlparser/tests/reftest/after-head-in-1kb-ref.html
new file mode 100644
index 0000000000..75fc2dd618
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-in-1kb-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>After <code>head</code>, before <code>body</code>, within first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/after-head-in-1kb.html b/parser/htmlparser/tests/reftest/after-head-in-1kb.html
new file mode 100644
index 0000000000..e73522d373
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/after-head-in-1kb.html
@@ -0,0 +1,938 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/after-head-in-1kb-ref.html">
+</head>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<meta charset="windows-1251">
+<body>
+<p>After <code>head</code>, before <code>body</code>, within first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/baseline-ref.html b/parser/htmlparser/tests/reftest/baseline-ref.html
new file mode 100644
index 0000000000..21b939efe0
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/baseline-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Normal meta.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/baseline.html b/parser/htmlparser/tests/reftest/baseline.html
new file mode 100644
index 0000000000..40bce2f63f
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/baseline.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/baseline-ref.html">
+<meta charset="windows-1251">
+</head>
+<body>
+<p>Normal meta.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/bug1153920-1-ref.html b/parser/htmlparser/tests/reftest/bug1153920-1-ref.html
new file mode 100644
index 0000000000..6c7e8fb13c
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1153920-1-ref.html
@@ -0,0 +1,4 @@
+<html><head><meta name="viewport" content="width=device-width"><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span>&lt;<span class="start-tag">a</span> <span class="attribute-name">href</span>='<a class="attribute-value" href="?a=b&amp;c=d&amp;a0b=c&amp;copy=1&amp;noti=n&amp;not=in&amp;notin=%26%238713%3B%AC&amp;;&amp;%20&amp;">?a=b<span><span>&amp;</span>c</span>=d<span><span>&amp;</span>a</span>0b=c<span><span>&amp;</span>copy</span>=1<span><span>&amp;</span>noti</span>=n<span><span>&amp;</span>not</span>=in<span><span>&amp;</span>notin</span>=<span class="entity"><span>&amp;</span>notin;</span><span class="entity"><span>&amp;</span>not;</span><span><span>&amp;</span></span>;<span><span>&amp;</span></span> <span><span>&amp;</span></span></a>'&gt;</span><span>Link</span><span>&lt;/<span class="end-tag">a</span>&gt;</span><span>
+<span id="line3"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Text: ?a=b<span><span>&amp;</span>c</span>=d<span><span>&amp;</span>a</span>0b=c<span class="error entity" title="Named character reference was not terminated by a semicolon. (Or “&amp;†should have been escaped as “&amp;amp;â€.)"><span>&amp;</span>copy</span>=1<span class="error entity" title="Named character reference was not terminated by a semicolon. (Or “&amp;†should have been escaped as “&amp;amp;â€.)"><span>&amp;</span>noti</span>=n<span class="error entity" title="Named character reference was not terminated by a semicolon. (Or “&amp;†should have been escaped as “&amp;amp;â€.)"><span>&amp;</span>not</span>=in<span class="error entity" title="Named character reference was not terminated by a semicolon. (Or “&amp;†should have been escaped as “&amp;amp;â€.)"><span>&amp;</span>notin</span>=<span class="entity"><span>&amp;</span>notin;</span><span class="entity"><span>&amp;</span>not;</span><span><span>&amp;</span></span>;<span><span>&amp;</span></span> <span><span>&amp;</span></span></span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line4"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/bug1153920-1.html b/parser/htmlparser/tests/reftest/bug1153920-1.html
new file mode 100644
index 0000000000..f36b2b0581
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1153920-1.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<a href='?a=b&c=d&a0b=c&copy=1&noti=n&not=in&notin=&notin;&not;&;& &'>Link</a>
+<p>Text: ?a=b&c=d&a0b=c&copy=1&noti=n&not=in&notin=&notin;&not;&;& &</p>
diff --git a/parser/htmlparser/tests/reftest/bug1319410-1-ref.html b/parser/htmlparser/tests/reftest/bug1319410-1-ref.html
new file mode 100644
index 0000000000..abce6d8540
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1319410-1-ref.html
@@ -0,0 +1,6 @@
+<html><head><meta name="viewport" content="width=device-width"><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span class="comment">&lt;!-- -- --&gt;</span><span>
+<span id="line3"></span></span><span class="error comment" title="Saw “<!--†within a comment. Probable cause: Nested comment (not allowed).">&lt;!-- &lt;!-- --&gt;</span><span> --&gt;
+<span id="line4"></span></span><span class="error comment" title="Premature end of comment. Use “-->†to end a comment properly.">&lt;!--&gt;</span><span>
+<span id="line5"></span></span><span class="comment">&lt;!--&lt;!--&gt;
+<span id="line6"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/bug1319410-1.html b/parser/htmlparser/tests/reftest/bug1319410-1.html
new file mode 100644
index 0000000000..04363210af
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1319410-1.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<!-- -- -->
+<!-- <!-- --> -->
+<!-->
+<!--<!-->
diff --git a/parser/htmlparser/tests/reftest/bug1636607-1-ref.html b/parser/htmlparser/tests/reftest/bug1636607-1-ref.html
new file mode 100644
index 0000000000..b5e24f87a7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1636607-1-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<style>
+div { border: medium solid blue }
+span { background: #9090ff; }
+span.test::before {
+ white-space: pre;
+ content: "\A";
+}
+</style>
+<p>This document is in <span id="mode"></span> mode.</p>
+<p>This is a test for the line height quirk which is present in limited-quirks mode <b>and</b> quirks mode:</p>
+<div><span style="font-size: 50%">hello<br>hello</span></div>
+<p>This is a test for the hashless hex color quirk which is present in quirks mode <b>only</b>:</p>
+<div style="background-color: 9090ff">test</div>
+
+<script>
+document.getElementById("mode").innerText = document.compatMode;
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug1636607-1.html b/parser/htmlparser/tests/reftest/bug1636607-1.html
new file mode 100644
index 0000000000..af2c2cb3e8
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1636607-1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//FR" "http://www.w3.org/TR/html4/loose.dtd">
+<style>
+div { border: medium solid blue }
+span { background: #9090ff; }
+span.test::before {
+ white-space: pre;
+ content: "\A";
+}
+</style>
+<p>This document is in <span id="mode"></span> mode.</p>
+<p>This is a test for the line height quirk which is present in limited-quirks mode <b>and</b> quirks mode:</p>
+<div><span style="font-size: 50%">hello<br>hello</span></div>
+<p>This is a test for the hashless hex color quirk which is present in quirks mode <b>only</b>:</p>
+<div style="background-color: 9090ff">test</div>
+
+<script>
+document.getElementById("mode").innerText = document.compatMode;
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug1636607-2-ref.html b/parser/htmlparser/tests/reftest/bug1636607-2-ref.html
new file mode 100644
index 0000000000..e82fd73824
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1636607-2-ref.html
@@ -0,0 +1,17 @@
+<style>
+div { border: medium solid blue }
+span { background: #9090ff; }
+span.test::before {
+ white-space: pre;
+ content: "\A";
+}
+</style>
+<p>This document is in <span id="mode"></span> mode.</p>
+<p>This is a test for the line height quirk which is present in limited-quirks mode <b>and</b> quirks mode:</p>
+<div><span style="font-size: 50%">hello<br>hello</span></div>
+<p>This is a test for the hashless hex color quirk which is present in quirks mode <b>only</b>:</p>
+<div style="background-color: 9090ff">test</div>
+
+<script>
+document.getElementById("mode").innerText = document.compatMode;
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug1636607-2.html b/parser/htmlparser/tests/reftest/bug1636607-2.html
new file mode 100644
index 0000000000..f551df5ac1
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1636607-2.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//FR">
+<style>
+div { border: medium solid blue }
+span { background: #9090ff; }
+span.test::before {
+ white-space: pre;
+ content: "\A";
+}
+</style>
+<p>This document is in <span id="mode"></span> mode.</p>
+<p>This is a test for the line height quirk which is present in limited-quirks mode <b>and</b> quirks mode:</p>
+<div><span style="font-size: 50%">hello<br>hello</span></div>
+<p>This is a test for the hashless hex color quirk which is present in quirks mode <b>only</b>:</p>
+<div style="background-color: 9090ff">test</div>
+
+<script>
+document.getElementById("mode").innerText = document.compatMode;
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug1650087-1-ref.html b/parser/htmlparser/tests/reftest/bug1650087-1-ref.html
new file mode 100644
index 0000000000..284f097100
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1650087-1-ref.html
@@ -0,0 +1,8 @@
+<html><head><meta name="viewport" content="width=device-width"><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span>&lt;<span class="start-tag">template</span>&gt;</span><span></span><span>&lt;<span class="start-tag">td</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">template</span>&gt;</span><span>
+<span id="line3"></span></span><span>&lt;<span class="start-tag">template</span>&gt;</span><span></span><span>&lt;<span class="start-tag">tr</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">template</span>&gt;</span><span>
+<span id="line4"></span></span><span>&lt;<span class="start-tag">template</span>&gt;</span><span></span><span>&lt;<span class="start-tag">thead</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">template</span>&gt;</span><span>
+<span id="line5"></span></span><span>&lt;<span class="start-tag">template</span>&gt;</span><span></span><span>&lt;<span class="start-tag">tbody</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">template</span>&gt;</span><span>
+<span id="line6"></span></span><span>&lt;<span class="start-tag">template</span>&gt;</span><span></span><span>&lt;<span class="start-tag">tfoot</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">template</span>&gt;</span><span>
+<span id="line7"></span></span><span>&lt;<span class="start-tag">template</span>&gt;</span><span></span><span>&lt;<span class="start-tag">colgroup</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">template</span>&gt;</span><span>
+<span id="line8"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/bug1650087-1.html b/parser/htmlparser/tests/reftest/bug1650087-1.html
new file mode 100644
index 0000000000..c5b92f1615
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1650087-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<template><td></template>
+<template><tr></template>
+<template><thead></template>
+<template><tbody></template>
+<template><tfoot></template>
+<template><colgroup></template>
diff --git a/parser/htmlparser/tests/reftest/bug1726374-1-ref.html b/parser/htmlparser/tests/reftest/bug1726374-1-ref.html
new file mode 100644
index 0000000000..1bd351963d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1726374-1-ref.html
@@ -0,0 +1,2 @@
+<html><head><meta name="viewport" content="width=device-width"><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span></span><span class="comment">&lt;!-- a &lt;!--&gt;</span><span>b
+<span id="line2"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/bug1726374-1.html b/parser/htmlparser/tests/reftest/bug1726374-1.html
new file mode 100644
index 0000000000..edcb3952c5
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1726374-1.html
@@ -0,0 +1 @@
+<!DOCTYPE html><!-- a <!-->b
diff --git a/parser/htmlparser/tests/reftest/bug1749522-1-ref.txt b/parser/htmlparser/tests/reftest/bug1749522-1-ref.txt
new file mode 100644
index 0000000000..c95d7230fd
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1749522-1-ref.txt
@@ -0,0 +1,3 @@
+<script>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+To jest test kodowania znaków. W przypadku niektórych języków, które używają znaków łacińskich, potrzebujemy więcej danych, aby podjąć decyzję.
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug1749522-1.txt b/parser/htmlparser/tests/reftest/bug1749522-1.txt
new file mode 100644
index 0000000000..3520d89838
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug1749522-1.txt
@@ -0,0 +1,3 @@
+<script>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+To jest test kodowania znaków. W przypadku niektórych jêzyków, które u¿ywaj¹ znaków ³aciñskich, potrzebujemy wiêcej danych, aby podj¹æ decyzjê.
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug482921-1-ref.html b/parser/htmlparser/tests/reftest/bug482921-1-ref.html
new file mode 100644
index 0000000000..71c0f91c08
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug482921-1-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="wrap highlight"><pre id><span class="doctype">&lt;!DOCTYPE html&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">html</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">head</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">title</span>&gt;</span><span>Title</span><span>&lt;/<span class="end-tag">title</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">script</span>&gt;</span>
+<span id></span>var lt = "&lt;";
+<span id></span>&lt;!--
+<span id></span>var s = "&lt;script&gt;foo&lt;/script&gt;";
+<span id></span>--&gt;
+<span id></span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span></span><span class="comment">&lt;!-- Comment. --&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">style</span>&gt;</span>
+<span id></span>/* &lt;/foo&gt; */
+<span id></span><span>&lt;/<span class="end-tag">style</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">head</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">body</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Entity: <span class="entity"><span>&amp;</span>amp; </span></span><span>&lt;/<span class="end-tag">p</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">iframe</span>&gt;</span>&lt;img&gt;<span>&lt;/<span class="end-tag">iframe</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">noscript</span>&gt;</span>&lt;p&gt;Not para&lt;/p&gt;<span>&lt;/<span class="end-tag">noscript</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">svg</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">title</span>&gt;</span><span></span><span class="cdata">&lt;![CDATA[bar]]&gt;</span><span></span><span>&lt;/<span class="end-tag">title</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span class="comment">&lt;!-- this is a comment --&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">svg</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">body</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">html</span>&gt;</span>
+<span id></span>
+</pre>
+<!-- View source CSS matches the <pre id> and <span id> elements and produces line numbers. -->
diff --git a/parser/htmlparser/tests/reftest/bug482921-1.html b/parser/htmlparser/tests/reftest/bug482921-1.html
new file mode 100644
index 0000000000..ca603844f2
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug482921-1.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Title</title>
+<script>
+var lt = "<";
+<!--
+var s = "<script>foo</script>";
+-->
+</script><!-- Comment. -->
+<style>
+/* </foo> */
+</style>
+</head>
+<body>
+<p>Entity: &amp; </p>
+<iframe><img></iframe>
+<noscript><p>Not para</p></noscript>
+<svg>
+<title><![CDATA[bar]]></title>
+<script><!-- this is a comment --></script>
+</svg>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/bug482921-2-ref.html b/parser/htmlparser/tests/reftest/bug482921-2-ref.html
new file mode 100644
index 0000000000..d764c70bca
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug482921-2-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="wrap highlight"><pre id><span class="pi">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
+<span id></span><span class="pi">&lt;?foo bar?&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">html</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">head</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">title</span>&gt;</span><span>Title</span><span>&lt;/<span class="end-tag">title</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">script</span>&gt;</span>
+<span id></span>var s = "<span>&lt;<span class="start-tag">script</span>&gt;</span><span>foo</span><span>&lt;/<span class="end-tag">script</span>&gt;</span>";
+<span id></span><span class="comment">&lt;!--
+<span id></span>var s = "&lt;script&gt;foo&lt;/script&gt;";
+<span id></span>--&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span></span>
+<span id></span><span>&lt;<span class="start-tag">style</span>&gt;</span>
+<span id></span>/* <span>&lt;<span class="start-tag">foo</span><span>/</span>&gt;</span> */
+<span id></span><span>&lt;/<span class="end-tag">style</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">head</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">body</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Entity: <span class="entity"><span>&amp;</span>amp; </span></span><span>&lt;/<span class="end-tag">p</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">iframe</span>&gt;</span><span></span><span>&lt;<span class="start-tag">img</span>&gt;</span><span>&lt;/<span class="end-tag">iframe</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">noscript</span>&gt;</span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Not para</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>&lt;/<span class="end-tag">noscript</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">svg</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">title</span>&gt;</span><span></span><span class="cdata">&lt;![CDATA[bar]]&gt;</span><span></span><span>&lt;/<span class="end-tag">title</span>&gt;</span>
+<span id></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span class="comment">&lt;!-- this is a comment --&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">svg</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">body</span>&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">html</span>&gt;</span>
+<span id></span>
+</pre>
+<!-- View source CSS matches the <pre id> and <span id> elements and produces line numbers. -->
diff --git a/parser/htmlparser/tests/reftest/bug482921-2.xhtml b/parser/htmlparser/tests/reftest/bug482921-2.xhtml
new file mode 100644
index 0000000000..4d3f0b6a73
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug482921-2.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<?foo bar?>
+<html>
+<head>
+<title>Title</title>
+<script>
+var s = "<script>foo</script>";
+<!--
+var s = "<script>foo</script>";
+-->
+</script>
+<style>
+/* <foo/> */
+</style>
+</head>
+<body>
+<p>Entity: &amp; </p>
+<iframe><img></iframe>
+<noscript><p>Not para</p></noscript>
+<svg>
+<title><![CDATA[bar]]></title>
+<script><!-- this is a comment --></script>
+</svg>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/bug535530-1-ref.html b/parser/htmlparser/tests/reftest/bug535530-1-ref.html
new file mode 100644
index 0000000000..22d0dc0b0b
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug535530-1-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html><meta charset=utf-8>
+XX&amp;XX XX&amp;nXX XX&amp;noXX XX¬XX XX¬iXX XX¬inXX XX&amp;;XX XX&amp;n;XX XX&amp;no;XX XX¬XX XX¬i;XX XX∉XX
diff --git a/parser/htmlparser/tests/reftest/bug535530-1.html b/parser/htmlparser/tests/reftest/bug535530-1.html
new file mode 100644
index 0000000000..63f2d8782e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug535530-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+XX&XX
+XX&nXX
+XX&noXX
+XX&notXX
+XX&notiXX
+XX&notinXX
+XX&;XX
+XX&n;XX
+XX&no;XX
+XX&not;XX
+XX&noti;XX
+XX&notin;XX
+
diff --git a/parser/htmlparser/tests/reftest/bug535530-2-ref.html b/parser/htmlparser/tests/reftest/bug535530-2-ref.html
new file mode 100644
index 0000000000..174e94dc8b
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug535530-2-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="wrap highlight"><pre id><span class="doctype">&lt;!DOCTYPE html&gt;</span>
+<span id></span>XX&amp;XX
+<span id></span>XX&amp;nXX
+<span id></span>XX&amp;noXX
+<span id></span>XX<span class="error entity">&amp;not</span>XX
+<span id></span>XX<span class="error entity">&amp;noti</span>XX
+<span id></span>XX<span class="error entity">&amp;notin</span>XX
+<span id></span>XX&amp;;XX
+<span id></span>XX<span class="error">&amp;</span>n;XX
+<span id></span>XX<span class="error">&amp;</span>no;XX
+<span id></span>XX<span class="entity">&amp;not;</span>XX
+<span id></span>XX<span class="error entity">&amp;noti</span>;XX
+<span id></span>XX<span class="entity">&amp;notin;</span>XX
+<span id></span>
+<span id></span>
+</pre>
+<!-- View source CSS matches the <pre id> and <span id> elements and produces line numbers. -->
diff --git a/parser/htmlparser/tests/reftest/bug535530-2.html b/parser/htmlparser/tests/reftest/bug535530-2.html
new file mode 100644
index 0000000000..63f2d8782e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug535530-2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+XX&XX
+XX&nXX
+XX&noXX
+XX&notXX
+XX&notiXX
+XX&notinXX
+XX&;XX
+XX&n;XX
+XX&no;XX
+XX&not;XX
+XX&noti;XX
+XX&notin;XX
+
diff --git a/parser/htmlparser/tests/reftest/bug566280-1-ref.html b/parser/htmlparser/tests/reftest/bug566280-1-ref.html
new file mode 100644
index 0000000000..6585cac38f
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug566280-1-ref.html
@@ -0,0 +1,2 @@
+<body>hello world
+
diff --git a/parser/htmlparser/tests/reftest/bug566280-1.html b/parser/htmlparser/tests/reftest/bug566280-1.html
new file mode 100644
index 0000000000..3aa60caf34
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug566280-1.html
Binary files differ
diff --git a/parser/htmlparser/tests/reftest/bug569229-1-ref.xml b/parser/htmlparser/tests/reftest/bug569229-1-ref.xml
new file mode 100644
index 0000000000..652f1d7da8
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug569229-1-ref.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" standalone="yes" ?>
+<html xmlns="http://www.w3.org/1999/xhtml"><p>abcd</p></html>
diff --git a/parser/htmlparser/tests/reftest/bug569229-1.xml b/parser/htmlparser/tests/reftest/bug569229-1.xml
new file mode 100644
index 0000000000..2e1ff75603
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug569229-1.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" standalone="yes" ?>
+<!DOCTYPE html [
+ <!ENTITY inner "<script src='script.js'></script><p>abcd</p>">
+ <!ENTITY outer "&inner;">
+]>
+<html xmlns="http://www.w3.org/1999/xhtml">&outer;</html>
diff --git a/parser/htmlparser/tests/reftest/bug577418-1-ref.html b/parser/htmlparser/tests/reftest/bug577418-1-ref.html
new file mode 100644
index 0000000000..ff773d5364
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug577418-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<style>
+html {
+ background-color: lime;
+}
+</style>
diff --git a/parser/htmlparser/tests/reftest/bug577418-1.html b/parser/htmlparser/tests/reftest/bug577418-1.html
new file mode 100644
index 0000000000..cfd53be0a8
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug577418-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html style="width:100%;height:100%;margin:0;border:0;overflow:hidden">
+<body style="width:100%;height:100%;margin:0;border:0;overflow:hidden">
+<svg style="width:100%;height:100%">
+ <rect height="100%" width="100%" fill="red"/>
+ <foreignObject>
+ <html>
+ <body>
+ </body>
+ </html>
+ </foreignObject>
+ <rect height="100%" width="100%" fill="lime"/>
+</svg>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/bug582788-1-ref.html b/parser/htmlparser/tests/reftest/bug582788-1-ref.html
new file mode 100644
index 0000000000..c1f684807a
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug582788-1-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>Not ISO-10646</title>
+</head>
+<body>
+<p>Not ISO-10646</p>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug582788-1.html b/parser/htmlparser/tests/reftest/bug582788-1.html
new file mode 100644
index 0000000000..ee31b3de9d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug582788-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-10646">
+<title>Not ISO-10646</title>
+</head>
+<body>
+<p>Not ISO-10646</p>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug582940-1-ref.html b/parser/htmlparser/tests/reftest/bug582940-1-ref.html
new file mode 100644
index 0000000000..7209c8e69e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug582940-1-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<head>
+<meta charset=utf-8>
+<title>Fragment nav</title>
+<script>
+function loaded() {
+ document.documentElement.removeAttribute("class");
+}
+</script>
+</head>
+<body onload='setTimeout(loaded, 10);'>
+<iframe src="frame582940-ref.html#ref"></iframe>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug582940-1.html b/parser/htmlparser/tests/reftest/bug582940-1.html
new file mode 100644
index 0000000000..fd721a8bc3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug582940-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<head>
+<meta charset=utf-8>
+<title>Fragment nav</title>
+<script>
+function loaded() {
+ document.documentElement.removeAttribute("class");
+}
+</script>
+</head>
+<body onload='setTimeout(loaded, 10);'>
+<iframe src="frame582940.html#ref%20ref"></iframe>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug592656-1-ref.html b/parser/htmlparser/tests/reftest/bug592656-1-ref.html
new file mode 100644
index 0000000000..824d815633
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug592656-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>document.write() from script-inserted inline scripts and script@onload</title>
+</head>
+<body>
+1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/bug592656-1.html b/parser/htmlparser/tests/reftest/bug592656-1.html
new file mode 100644
index 0000000000..769f62f648
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug592656-1.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>document.write() from script-inserted inline scripts and script@onload</title>
+</head>
+<body>
+1
+<script>
+function write(num) {
+ document.write(num + " ");
+}
+function scriptload() {
+ document.write("\u003Cscript src='data:text/javascript,write(9)'>\u003C/script> 10 \u003Cscript>write(11)\u003C/script>");
+ write(12);
+}
+function scripterror() {
+ document.write("\u003Cscript src='data:text/javascript,write(16)'>\u003C/script> 17 \u003Cscript>write(18)\u003C/script>");
+ write(19);
+}
+write(2);
+document.write("\u003Cscript src='data:text/javascript,write(3)'>\u003C/script> 4 \u003Cscript>write(5)\u003C/script>");
+var s = document.createElement("script");
+s.textContent = "write(6)";
+document.body.appendChild(s);
+write(7);
+document.write("\u003Cscript src='data:text/javascript,write(8)' onload='scriptload()'>\u003C/script> 13 \u003Cscript>write(14)\u003C/script>");
+write(15);
+document.write(`\u003Cscript src='nosuchscriptoutthere.js' onload='write("fail")' onerror='scripterror()'>\u003C/script> 20 \u003Cscript>write(21)\u003C/script>`);
+write(22);
+</script>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/bug599320-1-ref.html b/parser/htmlparser/tests/reftest/bug599320-1-ref.html
new file mode 100644
index 0000000000..bb48fe5d25
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug599320-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset=utf-8>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>UTF-16 doc</title>
+</head>
+<body>
+<h1>UTF-16 doc</h1>
+
+<p>Euro sign: €</p>
+<p>iframe:</p>
+<iframe src=frame599320-1-ref.html width=300 height=400></iframe>
+
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug599320-1.html b/parser/htmlparser/tests/reftest/bug599320-1.html
new file mode 100644
index 0000000000..590e9126c3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug599320-1.html
Binary files differ
diff --git a/parser/htmlparser/tests/reftest/bug608373-1-ref.html b/parser/htmlparser/tests/reftest/bug608373-1-ref.html
new file mode 100644
index 0000000000..69fec47d0f
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug608373-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+ <iframe src="data:text/html,TEXT"></iframe>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug608373-1.html b/parser/htmlparser/tests/reftest/bug608373-1.html
new file mode 100644
index 0000000000..7bc47552f7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug608373-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<head>
+<script>
+function write() {
+ document.getElementsByTagName("iframe")[0].contentDocument.write('\u003Cscript src="data:text/javascript,var i = 0;">\u003C\/script>TEXT\u003Cscript>parent.document.documentElement.removeAttribute("class");\u003c/script>');
+}
+</script>
+</head>
+<body onload="write();">
+ <iframe></iframe>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/bug659763-1-ref.html b/parser/htmlparser/tests/reftest/bug659763-1-ref.html
new file mode 100644
index 0000000000..99429bf4e7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-1-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src="data:text/html,<i>foo</i>"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug659763-1.html b/parser/htmlparser/tests/reftest/bug659763-1.html
new file mode 100644
index 0000000000..46dbde092e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<iframe></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var doc = iframe.contentDocument;
+doc.open("text/plain");
+doc.write("<i>foo</i>");
+doc.close();
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug659763-2-ref.html b/parser/htmlparser/tests/reftest/bug659763-2-ref.html
new file mode 100644
index 0000000000..99429bf4e7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-2-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src="data:text/html,<i>foo</i>"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug659763-2.html b/parser/htmlparser/tests/reftest/bug659763-2.html
new file mode 100644
index 0000000000..c6152193aa
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-2.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<iframe></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var doc = iframe.contentDocument;
+doc.open("TEXT/PLAIN");
+doc.write("<i>foo</i>");
+doc.close();
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug659763-3-ref.html b/parser/htmlparser/tests/reftest/bug659763-3-ref.html
new file mode 100644
index 0000000000..99429bf4e7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-3-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src="data:text/html,<i>foo</i>"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug659763-3.html b/parser/htmlparser/tests/reftest/bug659763-3.html
new file mode 100644
index 0000000000..bd2ed094bc
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-3.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<iframe></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var doc = iframe.contentDocument;
+doc.open("foo/bar");
+doc.write("<i>foo</i>");
+doc.close();
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug659763-4-ref.html b/parser/htmlparser/tests/reftest/bug659763-4-ref.html
new file mode 100644
index 0000000000..99429bf4e7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-4-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src="data:text/html,<i>foo</i>"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug659763-4.html b/parser/htmlparser/tests/reftest/bug659763-4.html
new file mode 100644
index 0000000000..5317186351
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-4.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<iframe></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var doc = iframe.contentDocument;
+doc.open("text/html");
+doc.write("<i>foo</i>");
+doc.close();
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug659763-5-ref.html b/parser/htmlparser/tests/reftest/bug659763-5-ref.html
new file mode 100644
index 0000000000..99429bf4e7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-5-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src="data:text/html,<i>foo</i>"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug659763-5.html b/parser/htmlparser/tests/reftest/bug659763-5.html
new file mode 100644
index 0000000000..23e9fd8e6f
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-5.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<iframe></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var doc = iframe.contentDocument;
+doc.open();
+doc.write("<i>foo</i>");
+doc.close();
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug659763-6-ref.html b/parser/htmlparser/tests/reftest/bug659763-6-ref.html
new file mode 100644
index 0000000000..99429bf4e7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-6-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<iframe src="data:text/html,<i>foo</i>"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug659763-6.html b/parser/htmlparser/tests/reftest/bug659763-6.html
new file mode 100644
index 0000000000..f0a5ea8d3f
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug659763-6.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<iframe></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var doc = iframe.contentDocument;
+doc.open("TEXT/HTML");
+doc.write("<i>foo</i>");
+doc.close();
+</script>
diff --git a/parser/htmlparser/tests/reftest/bug673094-1-ref.html b/parser/htmlparser/tests/reftest/bug673094-1-ref.html
new file mode 100644
index 0000000000..f8f8ce5939
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug673094-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>bidi in attribute</title>
+</head>
+<body>
+<p>Persian <a href="http://en.wiktionary.org/wiki/%D9%81%D8%A7%D8%B1%D8%B3%DB%8C" title="wikt:Ùارسی‎" >Ùارسی</a></p>
+</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/bug673094-1.html b/parser/htmlparser/tests/reftest/bug673094-1.html
new file mode 100644
index 0000000000..2fbdbfb10d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug673094-1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>bidi in attribute</title>
+</head>
+<body>
+<p>Persian <a href="http://en.wiktionary.org/wiki/%D9%81%D8%A7%D8%B1%D8%B3%DB%8C" title="wikt:Ùارسی" >Ùارسی</a></p>
+</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/bug696651-1-ref.html b/parser/htmlparser/tests/reftest/bug696651-1-ref.html
new file mode 100644
index 0000000000..02f59b7ae6
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug696651-1-ref.html
@@ -0,0 +1 @@
+<!DOCTYPE html>CcBbAa
diff --git a/parser/htmlparser/tests/reftest/bug696651-1.html b/parser/htmlparser/tests/reftest/bug696651-1.html
new file mode 100644
index 0000000000..50a9135aa3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug696651-1.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body><script>document.write("\u003cscript>document.write(\"\\u003cscript src='bug696651-external.js'>\\u003c/script>B\"); document.write(\"b\");\u003c/script>A"); document.write("a");</script>
diff --git a/parser/htmlparser/tests/reftest/bug696651-2-ref.html b/parser/htmlparser/tests/reftest/bug696651-2-ref.html
new file mode 100644
index 0000000000..7999785c09
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug696651-2-ref.html
@@ -0,0 +1 @@
+<!DOCTYPE html><iframe src="data:text/html,<!DOCTYPE html>CcBbAa"></iframe>
diff --git a/parser/htmlparser/tests/reftest/bug696651-2.html b/parser/htmlparser/tests/reftest/bug696651-2.html
new file mode 100644
index 0000000000..2d3515b6af
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug696651-2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<body>
+<iframe></iframe>
+<script>
+var doc = document.getElementsByTagName("iframe")[0].contentDocument;
+doc.open(); doc.write("\u003cscript>document.write(\"\\u003cscript src='bug696651-external.js'>\\u003c/script>B\"); document.write(\"b\");\u003c/script>A"); doc.write("a"); doc.close();</script>
diff --git a/parser/htmlparser/tests/reftest/bug696651-external.js b/parser/htmlparser/tests/reftest/bug696651-external.js
new file mode 100644
index 0000000000..c1c2a8f788
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug696651-external.js
@@ -0,0 +1 @@
+document.write("C"); document.write("c");
diff --git a/parser/htmlparser/tests/reftest/bug700260-1-ref.html b/parser/htmlparser/tests/reftest/bug700260-1-ref.html
new file mode 100644
index 0000000000..0ba4495a09
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug700260-1-ref.html
@@ -0,0 +1,3 @@
+ 1
+ 2
+ 3
diff --git a/parser/htmlparser/tests/reftest/bug700260-1.html b/parser/htmlparser/tests/reftest/bug700260-1.html
new file mode 100644
index 0000000000..37d3008347
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug700260-1.html
@@ -0,0 +1,3 @@
+ 1
+ 2
+ 3
diff --git a/parser/htmlparser/tests/reftest/bug704667-1-ref.html b/parser/htmlparser/tests/reftest/bug704667-1-ref.html
new file mode 100644
index 0000000000..a7a939f3a4
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug704667-1-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="wrap highlight"><pre id><span class="error comment">&lt;!--&gt;</span> <span class="error comment">&lt;!X&gt;</span>
+<span id></span>
+</pre>
+<!-- View source CSS matches the <pre id> and <span id> elements and produces line numbers. -->
diff --git a/parser/htmlparser/tests/reftest/bug704667-1.html b/parser/htmlparser/tests/reftest/bug704667-1.html
new file mode 100644
index 0000000000..553c62b309
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug704667-1.html
@@ -0,0 +1 @@
+<!--> <!X>
diff --git a/parser/htmlparser/tests/reftest/bug731234-1-ref.html b/parser/htmlparser/tests/reftest/bug731234-1-ref.html
new file mode 100644
index 0000000000..897b73ea1b
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug731234-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="wrap highlight"><pre id><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id></span></span><span>&lt;<span class="start-tag">body</span>&gt;</span><span>
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span> &gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>
+<span id></span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>=<a class="attribute-value">bar</a>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>="<a class="attribute-value">bar</a>"&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span>&lt;/<span class="end-tag">script</span> &gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span>&lt;/<span class="end-tag">script</span>
+<span id></span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>=<a class="attribute-value">bar</a>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>="<a class="attribute-value">bar</a>"&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- -</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- --</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script&gt; </span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript &lt;/script&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script &gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script foo&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script foo=bar&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script foo="bar"&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span>
+</pre>
+<!-- View source CSS matches the <pre id> and <span id> elements and produces line numbers. -->
diff --git a/parser/htmlparser/tests/reftest/bug731234-1.html b/parser/htmlparser/tests/reftest/bug731234-1.html
new file mode 100644
index 0000000000..313e44cca7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug731234-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+<script></script>X
+<script></script >X
+<script></script
+>X
+<script></script foo>X
+<script></script foo=bar>X
+<script></script foo="bar">X
+<script><!--</script>X
+<script><!-- </script>X
+<script><!-- </script >X
+<script><!-- </script
+>X
+<script><!-- </script foo>X
+<script><!-- </script foo=bar>X
+<script><!-- </script foo="bar">X
+<script><!-- -</script>X
+<script><!-- --</script>X
+<script><!-- --></script>X
+<script><!--<script> </script> </script>X
+<script><!--<script> </script> --></script>X
+<script><!--<script </script> --></script>X
+<script><!--<script> </script > --></script>X
+<script><!--<script> </script foo> --></script>X
+<script><!--<script> </script foo=bar> --></script>X
+<script><!--<script> </script foo="bar"> --></script>X
diff --git a/parser/htmlparser/tests/reftest/bug820508-1-ref.html b/parser/htmlparser/tests/reftest/bug820508-1-ref.html
new file mode 100644
index 0000000000..e624b16885
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug820508-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<title>main { display: block; }</title>
+<style>div {
+ border: 2px solid blue;
+}</style>
+<div>foo</div><div>bar</div>
diff --git a/parser/htmlparser/tests/reftest/bug820508-1.html b/parser/htmlparser/tests/reftest/bug820508-1.html
new file mode 100644
index 0000000000..60eabee67d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug820508-1.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<title>main { display: block; }</title>
+<style>main {
+ border: 2px solid blue;
+}</style>
+<main>foo</main><main>bar</main>
diff --git a/parser/htmlparser/tests/reftest/bug910588-1-ref.html b/parser/htmlparser/tests/reftest/bug910588-1-ref.html
new file mode 100644
index 0000000000..46133dd2c4
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug910588-1-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="-moz-tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span></span><span>&lt;<span class="start-tag">table</span>&gt;</span><span></span><span title="Start tag “input†seen in “tableâ€." class="error">&lt;<span class="start-tag">input</span> <span class="attribute-name">type</span>=<a class="attribute-value">hidden</a>&gt;</span><span></span><span>&lt;/<span class="end-tag">table</span>&gt;</span><span>
+<span id="line2"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/bug910588-1.html b/parser/htmlparser/tests/reftest/bug910588-1.html
new file mode 100644
index 0000000000..d0f5958582
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug910588-1.html
@@ -0,0 +1 @@
+<!DOCTYPE html><table><input type=hidden></table>
diff --git a/parser/htmlparser/tests/reftest/document-write-ref.html b/parser/htmlparser/tests/reftest/document-write-ref.html
new file mode 100644
index 0000000000..9902cf77d1
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/document-write-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta from <code>document.write</code> (with concatenation in the middle of <code>charset</code> to require execution for effect).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/document-write.html b/parser/htmlparser/tests/reftest/document-write.html
new file mode 100644
index 0000000000..b70a15c567
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/document-write.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/document-write-ref.html">
+<script>document.write('<meta char' + 'set="windows-1251">');</script>
+</head>
+<body>
+<p>Meta from <code>document.write</code> (with concatenation in the middle of <code>charset</code> to require execution for effect).</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/frame582940-ref.html b/parser/htmlparser/tests/reftest/frame582940-ref.html
new file mode 100644
index 0000000000..ac665679b5
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/frame582940-ref.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Fragment nav</title>
+</head>
+<body>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p><a name='ref'>Ref!</a></p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/frame582940.html b/parser/htmlparser/tests/reftest/frame582940.html
new file mode 100644
index 0000000000..646b7d5a71
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/frame582940.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Fragment nav</title>
+</head>
+<body>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p><a name='ref%20ref'>Ref!</a></p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+<p>Filler</p>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/frame599320-1-ref.html b/parser/htmlparser/tests/reftest/frame599320-1-ref.html
new file mode 100644
index 0000000000..735c368f8b
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/frame599320-1-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset=utf-8>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>Non-UTF-16 doc</title>
+</head>
+<body>
+<h1>Non-UTF-16 doc</h1>
+
+<p>Euro sign: €</p>
+
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/frame599320-1.html b/parser/htmlparser/tests/reftest/frame599320-1.html
new file mode 100644
index 0000000000..145ee94ba8
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/frame599320-1.html
@@ -0,0 +1,1092 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<!-- More than 1 KB of space -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<meta charset=utf-8>
+<meta content="width=device-width, initial-scale=1" name="viewport">
+<title>Non-UTF-16 doc</title>
+</head>
+<body>
+<h1>Non-UTF-16 doc</h1>
+
+<p>Euro sign: €</p>
+<script>
+window.onload = function() {
+ window.requestAnimationFrame(function() {
+ parent.document.documentElement.removeAttribute("class");
+ });
+}
+</script>
+</body>
+</html>
+
diff --git a/parser/htmlparser/tests/reftest/in-comment-ref.html b/parser/htmlparser/tests/reftest/in-comment-ref.html
new file mode 100644
index 0000000000..94b2016e0d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-comment-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta inside comment.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-comment.html b/parser/htmlparser/tests/reftest/in-comment.html
new file mode 100644
index 0000000000..65828a1872
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-comment.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-comment-ref.html">
+<!--<meta charset="windows-1251">-->
+</head>
+<body>
+<p>Meta inside comment.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb-ref.html b/parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb-ref.html
new file mode 100644
index 0000000000..12e9b93626
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>noscript</code> after <code>template</code> (which is also inside the <code>noscript</code>) after 1kb of padding following the template.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb.html b/parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb.html
new file mode 100644
index 0000000000..d22e83aaa7
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-after-template-after-1kb.html
@@ -0,0 +1,894 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-after-template-after-1kb-ref.html">
+<noscript><template></template>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<meta charset="windows-1251"></noscript>
+</head>
+<body>
+<p>Meta in <code>noscript</code> after <code>template</code> (which is also inside the <code>noscript</code>) after 1kb of padding following the template.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-after-template-ref.html b/parser/htmlparser/tests/reftest/in-noscript-after-template-ref.html
new file mode 100644
index 0000000000..27defe54c0
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-after-template-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>noscript</code> after <code>template</code> (which is also inside the <code>noscript</code>).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-after-template.html b/parser/htmlparser/tests/reftest/in-noscript-after-template.html
new file mode 100644
index 0000000000..71ef9144e0
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-after-template.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-after-template-ref.html">
+<noscript><template></template><meta charset="windows-1251"></noscript>
+</head>
+<body>
+<p>Meta in <code>noscript</code> after <code>template</code> (which is also inside the <code>noscript</code>).</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-ncr-ref.html b/parser/htmlparser/tests/reftest/in-noscript-ncr-ref.html
new file mode 100644
index 0000000000..3581ab68db
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-ncr-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta with NCR in the encoding label in <code>noscript</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-ncr.html b/parser/htmlparser/tests/reftest/in-noscript-ncr.html
new file mode 100644
index 0000000000..645f151b26
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-ncr.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-ncr-ref.html">
+<noscript><meta charset="&#119;indows-1251"></noscript>
+</head>
+<body>
+<p>Meta with NCR in the encoding label in <code>noscript</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript-ref.html b/parser/htmlparser/tests/reftest/in-noscript-ref.html
new file mode 100644
index 0000000000..9bb9f24b88
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>noscript</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-noscript.html b/parser/htmlparser/tests/reftest/in-noscript.html
new file mode 100644
index 0000000000..e76054d618
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-noscript.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-noscript-ref.html">
+<noscript><meta charset="windows-1251"></noscript>
+</head>
+<body>
+<p>Meta in <code>noscript</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-object-ref.html b/parser/htmlparser/tests/reftest/in-object-ref.html
new file mode 100644
index 0000000000..3f52d0efe9
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-object-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>object</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-object.html b/parser/htmlparser/tests/reftest/in-object.html
new file mode 100644
index 0000000000..32535b8eba
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-object.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/in-object-ref.html">
+<object><meta charset="windows-1251"></object>
+</head>
+<body>
+<p>Meta in <code>object</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-script-ref.html b/parser/htmlparser/tests/reftest/in-script-ref.html
new file mode 100644
index 0000000000..bbb63fd931
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-script-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>script</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-script.html b/parser/htmlparser/tests/reftest/in-script.html
new file mode 100644
index 0000000000..0c18a4435e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-script.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-script-ref.html">
+<script><meta charset="windows-1251"></script>
+</head>
+<body>
+<p>Meta in <code>script</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-style-ref.html b/parser/htmlparser/tests/reftest/in-style-ref.html
new file mode 100644
index 0000000000..9669146eb5
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-style-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>style</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-style.html b/parser/htmlparser/tests/reftest/in-style.html
new file mode 100644
index 0000000000..69d8fa429c
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-style.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-style-ref.html">
+<style><meta charset="windows-1251"></style>
+</head>
+<body>
+<p>Meta in <code>style</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt-ref.html b/parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt-ref.html
new file mode 100644
index 0000000000..2868f47fc2
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<svg></svg>
+<p>In SVG in CDATA after greater-than sign in the CDATA (after head).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt.html b/parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt.html
new file mode 100644
index 0000000000..56783b7afc
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-svg-in-cdata-after-gt.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-svg-in-cdata-after-gt-ref.html">
+</head>
+<body>
+<svg><![CDATA[><meta charset="windows-1251">]]></svg>
+<p>In SVG in CDATA after greater-than sign in the CDATA (after head).</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-svg-in-cdata-ref.html b/parser/htmlparser/tests/reftest/in-svg-in-cdata-ref.html
new file mode 100644
index 0000000000..1d17d2720b
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-svg-in-cdata-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<svg></svg>
+<p>In SVG in CDATA (after head).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-svg-in-cdata.html b/parser/htmlparser/tests/reftest/in-svg-in-cdata.html
new file mode 100644
index 0000000000..d1c4ca12b3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-svg-in-cdata.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-svg-in-cdata-ref.html">
+</head>
+<body>
+<svg><![CDATA[<meta charset="windows-1251">]]></svg>
+<p>In SVG in CDATA (after head).</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-svg-ref.html b/parser/htmlparser/tests/reftest/in-svg-ref.html
new file mode 100644
index 0000000000..c9e41aa177
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-svg-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<svg></svg>
+<p>In SVG (after head).</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-svg.html b/parser/htmlparser/tests/reftest/in-svg.html
new file mode 100644
index 0000000000..cb29164289
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-svg.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/in-svg-ref.html">
+</head>
+<body>
+<svg><meta charset="windows-1251"></svg>
+<p>In SVG (after head).</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-template-after-1kb-ref.html b/parser/htmlparser/tests/reftest/in-template-after-1kb-ref.html
new file mode 100644
index 0000000000..df20eba39b
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-template-after-1kb-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+<p>In <code>template</code>, before <code>head</code> end tag, after first kilobyte.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-template-after-1kb.html b/parser/htmlparser/tests/reftest/in-template-after-1kb.html
new file mode 100644
index 0000000000..ae77decea2
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-template-after-1kb.html
@@ -0,0 +1,1046 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-template-after-1kb-ref.html">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<template><meta charset="windows-1251"></template>
+</head>
+<body>
+<p>In <code>template</code>, before <code>head</code> end tag, after first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-template-ref.html b/parser/htmlparser/tests/reftest/in-template-ref.html
new file mode 100644
index 0000000000..83c0e93072
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-template-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Meta in <code>template</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-template.html b/parser/htmlparser/tests/reftest/in-template.html
new file mode 100644
index 0000000000..264affc269
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-template.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/in-template-ref.html">
+<template><meta charset="windows-1251"></template>
+</head>
+<body>
+<p>Meta in <code>template</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-title-ref.html b/parser/htmlparser/tests/reftest/in-title-ref.html
new file mode 100644
index 0000000000..5fb8a05f2d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-title-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+<title><meta charset="windows-1251"></title>
+</head>
+<body>
+<p>Meta in <code>title</code>.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/in-title.html b/parser/htmlparser/tests/reftest/in-title.html
new file mode 100644
index 0000000000..7b72c48dd8
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/in-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/in-title-ref.html">
+<title><meta charset="windows-1251"></title>
+</head>
+<body>
+<p>Meta in <code>title</code>.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/incomplete-xml-decl-ref.html b/parser/htmlparser/tests/reftest/incomplete-xml-decl-ref.html
new file mode 100644
index 0000000000..201fe664d5
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/incomplete-xml-decl-ref.html
@@ -0,0 +1,2 @@
+<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>incomplete-xml-decl.xml</title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="pi">&lt;?xml
+<span id="line2"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/incomplete-xml-decl.xml b/parser/htmlparser/tests/reftest/incomplete-xml-decl.xml
new file mode 100644
index 0000000000..1b345b6c84
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/incomplete-xml-decl.xml
@@ -0,0 +1 @@
+<?xml
diff --git a/parser/htmlparser/tests/reftest/ncr-ref.html b/parser/htmlparser/tests/reftest/ncr-ref.html
new file mode 100644
index 0000000000..1d25b4d23d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/ncr-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>NCR in encoding label.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/ncr.html b/parser/htmlparser/tests/reftest/ncr.html
new file mode 100644
index 0000000000..9f8b7308ad
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/ncr.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/ncr-ref.html">
+<meta charset="&#119;indows-1251">
+</head>
+<body>
+<p>NCR in encoding label.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/non-ascii-in-comment-before-ref.html b/parser/htmlparser/tests/reftest/non-ascii-in-comment-before-ref.html
new file mode 100644
index 0000000000..bd2acd274c
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/non-ascii-in-comment-before-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+</head>
+<body>
+<p>Normal meta. Non-ASCII in comment before.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/non-ascii-in-comment-before.html b/parser/htmlparser/tests/reftest/non-ascii-in-comment-before.html
new file mode 100644
index 0000000000..148c6544a3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/non-ascii-in-comment-before.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/non-ascii-in-comment-before-ref.html">
+<!-- æ -->
+<meta charset="windows-1251">
+</head>
+<body>
+<p>Normal meta. Non-ASCII in comment before.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/non-ascii-in-title-before-ref.html b/parser/htmlparser/tests/reftest/non-ascii-in-title-before-ref.html
new file mode 100644
index 0000000000..4f54732432
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/non-ascii-in-title-before-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+<title>ж</title>
+</head>
+<body>
+<p>Normal meta. Non-ASCII in title before.</p>
+<p>Test: ж</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/non-ascii-in-title-before.html b/parser/htmlparser/tests/reftest/non-ascii-in-title-before.html
new file mode 100644
index 0000000000..aac0ca94c1
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/non-ascii-in-title-before.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/non-ascii-in-title-before-ref.html">
+<title>æ</title>
+<meta charset="windows-1251">
+</head>
+<body>
+<p>Normal meta. Non-ASCII in title before.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/reftest.list b/parser/htmlparser/tests/reftest/reftest.list
new file mode 100644
index 0000000000..52b5bc45b0
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/reftest.list
@@ -0,0 +1,73 @@
+== bug535530-1.html bug535530-1-ref.html
+== view-source:bug535530-2.html bug535530-2-ref.html
+== bug566280-1.html bug566280-1-ref.html
+== bug569229-1.xml bug569229-1-ref.xml
+== bug577418-1.html bug577418-1-ref.html
+== bug582788-1.html bug582788-1-ref.html
+fuzzy(0-2,0-5) skip-if(OSX) == bug582940-1.html bug582940-1-ref.html
+== bug592656-1.html bug592656-1-ref.html
+fuzzy(0-1,0-5) == bug599320-1.html bug599320-1-ref.html
+fuzzy(0-2,0-5) == bug608373-1.html bug608373-1-ref.html
+fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azureSkia,0-73,0-1) == view-source:bug482921-1.html bug482921-1-ref.html
+== view-source:bug482921-2.xhtml bug482921-2-ref.html
+fuzzy(0-2,0-5) == bug659763-1.html bug659763-1-ref.html
+fuzzy(0-1,0-5) == bug659763-2.html bug659763-2-ref.html
+fuzzy(0-1,0-5) == bug659763-3.html bug659763-3-ref.html
+fuzzy(0-2,0-3) == bug659763-4.html bug659763-4-ref.html
+fuzzy(0-1,0-5) == bug659763-5.html bug659763-5-ref.html
+fuzzy(0-1,0-5) == bug659763-6.html bug659763-6-ref.html
+== view-source:bug673094-1.html view-source:bug673094-1-ref.html
+== bug696651-1.html bug696651-1-ref.html
+== bug696651-2.html bug696651-2-ref.html
+== view-source:bug700260-1.html view-source:bug700260-1-ref.html
+== view-source:bug704667-1.html bug704667-1-ref.html
+== view-source:bug731234-1.html bug731234-1-ref.html
+== bug820508-1.html bug820508-1-ref.html
+== view-source:bug910588-1.html bug910588-1-ref.html
+== bug1636607-1.html bug1636607-1-ref.html
+== bug1636607-2.html bug1636607-2-ref.html
+== view-source:bug1319410-1.html bug1319410-1-ref.html
+== view-source:bug1650087-1.html bug1650087-1-ref.html
+== view-source:bug1726374-1.html bug1726374-1-ref.html
+== view-source:bug1153920-1.html bug1153920-1-ref.html
+== after-1kb.html after-1kb-ref.html
+!= after-bogus-after-1kb.html after-bogus-after-1kb-ref.html
+== after-bogus.html after-bogus-ref.html
+!= after-head-after-1kb-crlf.html after-head-after-1kb-crlf-ref.html
+!= after-head-after-1kb.html after-head-after-1kb-ref.html
+== after-head-in-1kb-crlf.html after-head-in-1kb-crlf-ref.html
+== after-head-in-1kb.html after-head-in-1kb-ref.html
+== baseline.html baseline-ref.html
+!= document-write.html document-write-ref.html
+!= in-comment.html in-comment-ref.html
+!= in-noscript-after-template-after-1kb.html in-noscript-after-template-after-1kb-ref.html
+!= in-noscript-after-template.html in-noscript-after-template-ref.html
+!= in-noscript.html in-noscript-ref.html
+!= in-noscript-ncr.html in-noscript-ncr-ref.html
+== in-object.html in-object-ref.html
+!= in-script.html in-script-ref.html
+!= in-style.html in-style-ref.html
+== in-svg.html in-svg-ref.html
+!= in-svg-in-cdata-after-gt.html in-svg-in-cdata-after-gt-ref.html
+!= in-svg-in-cdata.html in-svg-in-cdata-ref.html
+!= in-template-after-1kb.html in-template-after-1kb-ref.html
+== in-template.html in-template-ref.html
+!= in-title.html in-title-ref.html
+== ncr.html ncr-ref.html
+== non-ascii-in-comment-before.html non-ascii-in-comment-before-ref.html
+== non-ascii-in-title-before.html non-ascii-in-title-before-ref.html
+== view-source:xml-1.xml xml-ref.html
+HTTP(..) == view-source:xml-trickle-1.sjs xml-ref.html
+HTTP(..) == view-source:xml-trickle-2.sjs xml-ref.html
+HTTP(..) == view-source:xml-trickle-3.sjs xml-ref.html
+HTTP(..) == view-source:xml-trickle-4.sjs xml-utf-ref.html
+HTTP(..) == view-source:xml-trickle-5.sjs xml-utf-ref.html
+HTTP(..) == view-source:xml-trickle-6.sjs xml-utf-ref.html
+skip-if(Android) HTTP(..) == view-source:vs-after-head-in-1kb.html vs-after-head-in-1kb-ref.html # Skipped on Android due to inconsistent scrollbar display
+HTTP(..) != view-source:vs-after-head-after-1kb.html vs-after-head-after-1kb-ref.html
+HTTP(..) == view-source:vs-non-ascii-in-comment-before.html vs-non-ascii-in-comment-before-ref.html
+HTTP(..) == view-source:vs-non-ascii-in-comment-before.sjs vs-non-ascii-in-comment-before-ref.html
+== view-source:xml-without-tags.xml xml-without-tags-ref.html
+== view-source:incomplete-xml-decl.xml incomplete-xml-decl-ref.html
+== view-source:view-source-bom.html view-source-bom-ref.html
+skip-if(Android) == bug1749522-1.txt bug1749522-1-ref.txt # Skipped on Android due to suspicion of harness bug
diff --git a/parser/htmlparser/tests/reftest/view-source-bom-ref.html b/parser/htmlparser/tests/reftest/view-source-bom-ref.html
new file mode 100644
index 0000000000..0ed26be850
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/view-source-bom-ref.html
@@ -0,0 +1,10 @@
+<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>view-source-bom.html</title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span>&lt;<span class="start-tag">html</span>&gt;</span><span>
+<span id="line3"></span></span><span>&lt;<span class="start-tag">head</span>&gt;</span><span>
+<span id="line4"></span> </span><span>&lt;<span class="start-tag">title</span>&gt;</span><span>UTF-8 file with a BOM</span><span>&lt;/<span class="end-tag">title</span>&gt;</span><span>
+<span id="line5"></span></span><span>&lt;/<span class="end-tag">head</span>&gt;</span><span>
+<span id="line6"></span></span><span>&lt;<span class="start-tag">body</span>&gt;</span><span>
+<span id="line7"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>UTF-8 file with a BOM. Euro sign: €</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line8"></span></span><span>&lt;/<span class="end-tag">body</span>&gt;</span><span>
+<span id="line9"></span></span><span>&lt;/<span class="end-tag">html</span>&gt;</span><span>
+<span id="line10"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/view-source-bom.html b/parser/htmlparser/tests/reftest/view-source-bom.html
new file mode 100644
index 0000000000..d10d94fbee
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/view-source-bom.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>UTF-8 file with a BOM</title>
+</head>
+<body>
+<p>UTF-8 file with a BOM. Euro sign: €</p>
+</body>
+</html>
diff --git a/parser/htmlparser/tests/reftest/vs-after-head-after-1kb-ref.html b/parser/htmlparser/tests/reftest/vs-after-head-after-1kb-ref.html
new file mode 100644
index 0000000000..5a721755b1
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-after-head-after-1kb-ref.html
@@ -0,0 +1,11 @@
+<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>vs-after-head-after-1kb.html</title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span>&lt;<span class="start-tag">head</span>&gt;</span><span>
+<span id="line3"></span></span><span>&lt;<span class="start-tag">link</span> <span class="attribute-name">rel</span>="<a class="attribute-value">mismatch</a>" <span class="attribute-name">href</span>="<a class="attribute-value" href="view-source:references/after-head-after-1kb-ref.html">references/after-head-after-1kb-ref.html</a>"&gt;</span><span>
+<span id="line4"></span> </span><span>&lt;/<span class="end-tag">head</span>&gt;</span><span>
+<span id="line5"></span></span><span class="error" title="“meta†element between “head†and “bodyâ€.">&lt;<span class="start-tag">meta</span> <span class="attribute-name">charset</span>="<a class="attribute-value">windows-1251</a>"&gt;</span><span>
+<span id="line6"></span></span><span>&lt;<span class="start-tag">body</span>&gt;</span><span>
+<span id="line7"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>After </span><span>&lt;<span class="start-tag">code</span>&gt;</span><span>head</span><span>&lt;/<span class="end-tag">code</span>&gt;</span><span>, before </span><span>&lt;<span class="start-tag">code</span>&gt;</span><span>body</span><span>&lt;/<span class="end-tag">code</span>&gt;</span><span>, after first kilobyte.</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line8"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Test: ж</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line9"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>If <span class="entity"><span>&amp;</span>#x0436;</span>, meta takes effect</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line10"></span></span><span>&lt;/<span class="end-tag">body</span>&gt;</span><span>
+<span id="line11"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/vs-after-head-after-1kb.html b/parser/htmlparser/tests/reftest/vs-after-head-after-1kb.html
new file mode 100644
index 0000000000..6637a2a8c5
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-after-head-after-1kb.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<head>
+<link rel="mismatch" href="references/after-head-after-1kb-ref.html">
+ </head>
+<meta charset="windows-1251">
+<body>
+<p>After <code>head</code>, before <code>body</code>, after first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/vs-after-head-in-1kb-ref.html b/parser/htmlparser/tests/reftest/vs-after-head-in-1kb-ref.html
new file mode 100644
index 0000000000..706c20da6e
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-after-head-in-1kb-ref.html
@@ -0,0 +1,12 @@
+<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>vs-after-head-in-1kb.html</title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span>&lt;<span class="start-tag">head</span>&gt;</span><span>
+<span id="line3"></span></span><span>&lt;<span class="start-tag">link</span> <span class="attribute-name">rel</span>="<a class="attribute-value">match</a>" <span class="attribute-name">href</span>="<a class="attribute-value" href="view-source:references/after-head-in-1kb-ref.html">references/after-head-in-1kb-ref.html</a>"&gt;</span><span>
+<span id="line4"></span></span><span>&lt;/<span class="end-tag">head</span>&gt;</span><span>
+<span id="line5"></span>
+<span id="line6"></span></span><span class="error" title="“meta†element between “head†and “bodyâ€.">&lt;<span class="start-tag">meta</span> <span class="attribute-name">charset</span>="<a class="attribute-value">windows-1251</a>"&gt;</span><span>
+<span id="line7"></span></span><span>&lt;<span class="start-tag">body</span>&gt;</span><span>
+<span id="line8"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>After </span><span>&lt;<span class="start-tag">code</span>&gt;</span><span>head</span><span>&lt;/<span class="end-tag">code</span>&gt;</span><span>, before </span><span>&lt;<span class="start-tag">code</span>&gt;</span><span>body</span><span>&lt;/<span class="end-tag">code</span>&gt;</span><span>, within first kilobyte.</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line9"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Test: ж</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line10"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>If <span class="entity"><span>&amp;</span>#x0436;</span>, meta takes effect</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line11"></span></span><span>&lt;/<span class="end-tag">body</span>&gt;</span><span>
+<span id="line12"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/vs-after-head-in-1kb.html b/parser/htmlparser/tests/reftest/vs-after-head-in-1kb.html
new file mode 100644
index 0000000000..af63f06acb
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-after-head-in-1kb.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/after-head-in-1kb-ref.html">
+</head>
+
+<meta charset="windows-1251">
+<body>
+<p>After <code>head</code>, before <code>body</code>, within first kilobyte.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before-ref.html b/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before-ref.html
new file mode 100644
index 0000000000..66f0338658
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before-ref.html
@@ -0,0 +1,12 @@
+<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>vs-non-ascii-in-comment-before.html</title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id="line2"></span></span><span>&lt;<span class="start-tag">head</span>&gt;</span><span>
+<span id="line3"></span></span><span>&lt;<span class="start-tag">link</span> <span class="attribute-name">rel</span>="<a class="attribute-value">match</a>" <span class="attribute-name">href</span>="<a class="attribute-value" href="view-source:references/non-ascii-in-comment-before-ref.html">references/non-ascii-in-comment-before-ref.html</a>"&gt;</span><span>
+<span id="line4"></span></span><span class="comment">&lt;!-- ж --&gt;</span><span>
+<span id="line5"></span></span><span>&lt;<span class="start-tag">meta</span> <span class="attribute-name">charset</span>="<a class="attribute-value">windows-1251</a>"&gt;</span><span>
+<span id="line6"></span></span><span>&lt;/<span class="end-tag">head</span>&gt;</span><span>
+<span id="line7"></span></span><span>&lt;<span class="start-tag">body</span>&gt;</span><span>
+<span id="line8"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Normal meta. Non-ASCII in comment before.</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line9"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Test: ж</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line10"></span></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>If <span class="entity"><span>&amp;</span>#x0436;</span>, meta takes effect</span><span>&lt;/<span class="end-tag">p</span>&gt;</span><span>
+<span id="line11"></span></span><span>&lt;/<span class="end-tag">body</span>&gt;</span><span>
+<span id="line12"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.html b/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.html
new file mode 100644
index 0000000000..148c6544a3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<head>
+<link rel="match" href="references/non-ascii-in-comment-before-ref.html">
+<!-- æ -->
+<meta charset="windows-1251">
+</head>
+<body>
+<p>Normal meta. Non-ASCII in comment before.</p>
+<p>Test: æ</p>
+<p>If &#x0436;, meta takes effect</p>
+</body>
diff --git a/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.sjs b/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.sjs
new file mode 100644
index 0000000000..12b1919ff8
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/vs-non-ascii-in-comment-before.sjs
@@ -0,0 +1,16 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "text/html", false);
+ response.write('<!DOCTYPE html>\n<head>\n<link rel="match" href="references/non-ascii-in-comment-before-ref.html">\n<!-- \u00E6 -->\n');
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write('<meta charset="windows-1251">\n</head>\n<body>\n<p>Normal meta. Non-ASCII in comment before.</p>\n<p>Test: \u00E6</p>\n<p>If &#x0436;, meta takes effect</p>\n</body>\n');
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
diff --git a/parser/htmlparser/tests/reftest/xml-1.xml b/parser/htmlparser/tests/reftest/xml-1.xml
new file mode 100644
index 0000000000..a6ac350ad3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-1.xml
@@ -0,0 +1 @@
+<?xml version='1.0' encoding='windows-1251'?><root>æ</root>
diff --git a/parser/htmlparser/tests/reftest/xml-ref.html b/parser/htmlparser/tests/reftest/xml-ref.html
new file mode 100644
index 0000000000..3bf58fb763
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-ref.html
@@ -0,0 +1,2 @@
+<html><meta charset="utf-8"><head><meta name="viewport" content="width=device-width"><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="pi">&lt;?xml version='1.0' encoding='windows-1251'?&gt;</span><span></span><span>&lt;<span class="start-tag">root</span>&gt;</span><span>ж</span><span>&lt;/<span class="end-tag">root</span>&gt;</span><span>
+<span id="line2"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/xml-trickle-1.sjs b/parser/htmlparser/tests/reftest/xml-trickle-1.sjs
new file mode 100644
index 0000000000..eaec0e37fc
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-trickle-1.sjs
@@ -0,0 +1,17 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("?xml version='1.0' encoding='windows-1251'?><root>\u00E6</root>\n");
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
diff --git a/parser/htmlparser/tests/reftest/xml-trickle-2.sjs b/parser/htmlparser/tests/reftest/xml-trickle-2.sjs
new file mode 100644
index 0000000000..04c1354fa3
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-trickle-2.sjs
@@ -0,0 +1,17 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<?");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("xml version='1.0' encoding='windows-1251'?><root>\u00E6</root>\n");
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
diff --git a/parser/htmlparser/tests/reftest/xml-trickle-3.sjs b/parser/htmlparser/tests/reftest/xml-trickle-3.sjs
new file mode 100644
index 0000000000..e601f69038
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-trickle-3.sjs
@@ -0,0 +1,21 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<?");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("xml");
+ response.bodyOutputStream.flush();
+ timer.initWithCallback(function() {
+ response.write(" version='1.0' encoding='windows-1251'?><root>\u00E6</root>\n");
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
diff --git a/parser/htmlparser/tests/reftest/xml-trickle-4.sjs b/parser/htmlparser/tests/reftest/xml-trickle-4.sjs
new file mode 100644
index 0000000000..0ac01d84da
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-trickle-4.sjs
@@ -0,0 +1,17 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("?xml version='1.0'?><root>\u00D0\u00B6</root>\n");
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
diff --git a/parser/htmlparser/tests/reftest/xml-trickle-5.sjs b/parser/htmlparser/tests/reftest/xml-trickle-5.sjs
new file mode 100644
index 0000000000..815295ac30
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-trickle-5.sjs
@@ -0,0 +1,17 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<?");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("xml version='1.0'?><root>\u00D0\u00B6</root>\n");
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
diff --git a/parser/htmlparser/tests/reftest/xml-trickle-6.sjs b/parser/htmlparser/tests/reftest/xml-trickle-6.sjs
new file mode 100644
index 0000000000..9e96687d19
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-trickle-6.sjs
@@ -0,0 +1,21 @@
+var timer; // Place timer in global scope to avoid it getting GC'ed prematurely
+
+function handleRequest(request, response)
+{
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Content-Type", "application/xml", false);
+ response.write("<?");
+ response.bodyOutputStream.flush();
+ response.processAsync();
+ timer = Components.classes["@mozilla.org/timer;1"]
+ .createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback(function() {
+ response.write("xml");
+ response.bodyOutputStream.flush();
+ timer.initWithCallback(function() {
+ response.write(" version='1.0'?><root>\u00D0\u00B6</root>\n");
+ response.finish();
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ }, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
diff --git a/parser/htmlparser/tests/reftest/xml-utf-ref.html b/parser/htmlparser/tests/reftest/xml-utf-ref.html
new file mode 100644
index 0000000000..98a3100b24
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-utf-ref.html
@@ -0,0 +1,2 @@
+<html><meta charset="utf-8"><head><meta name="viewport" content="width=device-width"><title></title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span></span><span class="pi">&lt;?xml version='1.0'?&gt;</span><span></span><span>&lt;<span class="start-tag">root</span>&gt;</span><span>ж</span><span>&lt;/<span class="end-tag">root</span>&gt;</span><span>
+<span id="line2"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/xml-without-tags-ref.html b/parser/htmlparser/tests/reftest/xml-without-tags-ref.html
new file mode 100644
index 0000000000..d853e67634
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-without-tags-ref.html
@@ -0,0 +1,2 @@
+<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>xml-without-tags.xml</title><link rel="stylesheet" type="text/css" href="resource://content-accessible/viewsource.css"></head><body id="viewsource" class="highlight" style="tab-size: 4"><pre id="line1"><span>ill-formed
+<span id="line2"></span></span></pre></body></html>
diff --git a/parser/htmlparser/tests/reftest/xml-without-tags.xml b/parser/htmlparser/tests/reftest/xml-without-tags.xml
new file mode 100644
index 0000000000..ddc2f2135d
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/xml-without-tags.xml
@@ -0,0 +1 @@
+ill-formed
diff --git a/parser/moz.build b/parser/moz.build
new file mode 100644
index 0000000000..729ecf9190
--- /dev/null
+++ b/parser/moz.build
@@ -0,0 +1,14 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "DOM: HTML Parser")
+
+DIRS += ["expat", "prototype", "xml", "htmlparser", "html"]
+
+EXPORTS += [
+ "nsCharsetSource.h",
+]
diff --git a/parser/nsCharsetSource.h b/parser/nsCharsetSource.h
new file mode 100644
index 0000000000..0590883688
--- /dev/null
+++ b/parser/nsCharsetSource.h
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsCharsetSource_h_
+#define nsCharsetSource_h_
+
+// note: the value order defines the priority; higher numbers take priority
+enum nsCharsetSource {
+ kCharsetUninitialized,
+ kCharsetFromFallback,
+ kCharsetFromDocTypeDefault, // This and up confident for XHR
+ // Start subdividing source for telemetry purposes
+ kCharsetFromInitialAutoDetectionASCII,
+ kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8,
+ kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic,
+ kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content,
+ kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD,
+ // End subdividing source for telemetry purposes
+ kCharsetFromParentFrame, // Same-origin parent takes precedence over detector
+ // to avoid breaking tests. (Also, the HTML spec
+ // says so.)
+ kCharsetFromXmlDeclaration,
+ kCharsetFromMetaTag,
+ kCharsetFromChannel,
+ kCharsetFromOtherComponent,
+ kCharsetFromInitialUserForcedAutoDetection,
+ // Start subdividing source for telemetry purposes
+ // Deliberately no Final version of ASCII
+ kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII,
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic,
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII,
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content,
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII,
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD,
+ kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII,
+ kCharsetFromFinalAutoDetectionFile,
+ // End subdividing source for telemetry purposes
+ kCharsetFromFinalUserForcedAutoDetection,
+ kCharsetFromXmlDeclarationUtf16, // This one is overridden by
+ // kCharsetFromChannel
+ kCharsetFromByteOrderMark,
+ kCharsetFromUtf8OnlyMime, // For JSON, WebVTT and such
+ kCharsetFromBuiltIn, // resource: URLs
+};
+
+#endif /* nsCharsetSource_h_ */
diff --git a/parser/prototype/PrototypeDocumentParser.cpp b/parser/prototype/PrototypeDocumentParser.cpp
new file mode 100644
index 0000000000..c07a35b892
--- /dev/null
+++ b/parser/prototype/PrototypeDocumentParser.cpp
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#include "PrototypeDocumentParser.h"
+
+#include "nsXULPrototypeCache.h"
+#include "nsXULContentSink.h"
+#include "nsXULPrototypeDocument.h"
+#include "mozilla/Encoding.h"
+#include "nsCharsetSource.h"
+#include "nsParser.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/URL.h"
+#include "mozilla/dom/PrototypeDocumentContentSink.h"
+
+using namespace mozilla::dom;
+
+namespace mozilla {
+namespace parser {
+
+PrototypeDocumentParser::PrototypeDocumentParser(nsIURI* aDocumentURI,
+ dom::Document* aDocument)
+ : mDocumentURI(aDocumentURI),
+ mDocument(aDocument),
+ mPrototypeAlreadyLoaded(false),
+ mIsComplete(false) {}
+
+PrototypeDocumentParser::~PrototypeDocumentParser() {}
+
+NS_INTERFACE_TABLE_HEAD(PrototypeDocumentParser)
+ NS_INTERFACE_TABLE(PrototypeDocumentParser, nsIParser, nsIStreamListener,
+ nsIRequestObserver)
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(PrototypeDocumentParser)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PrototypeDocumentParser)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PrototypeDocumentParser)
+
+NS_IMPL_CYCLE_COLLECTION(PrototypeDocumentParser, mDocumentURI, mOriginalSink,
+ mDocument, mStreamListener, mCurrentPrototype)
+
+NS_IMETHODIMP_(void)
+PrototypeDocumentParser::SetContentSink(nsIContentSink* aSink) {
+ MOZ_ASSERT(aSink, "sink cannot be null!");
+ mOriginalSink = static_cast<PrototypeDocumentContentSink*>(aSink);
+ MOZ_ASSERT(mOriginalSink);
+
+ aSink->SetParser(this);
+}
+
+NS_IMETHODIMP_(nsIContentSink*)
+PrototypeDocumentParser::GetContentSink() { return mOriginalSink; }
+
+nsIStreamListener* PrototypeDocumentParser::GetStreamListener() { return this; }
+
+NS_IMETHODIMP_(bool)
+PrototypeDocumentParser::IsComplete() { return mIsComplete; }
+
+NS_IMETHODIMP
+PrototypeDocumentParser::Parse(nsIURI* aURL) {
+ // Look in the chrome cache: we've got this puppy loaded
+ // already.
+ nsXULPrototypeDocument* proto =
+ IsChromeURI(mDocumentURI)
+ ? nsXULPrototypeCache::GetInstance()->GetPrototype(mDocumentURI)
+ : nullptr;
+
+ // We don't abort on failure here because there are too many valid
+ // cases that can return failure, and the null-ness of |proto| is enough
+ // to trigger the fail-safe parse-from-disk solution. Example failure cases
+ // (for reference) include:
+ //
+ // NS_ERROR_NOT_AVAILABLE: the URI cannot be found in the startup cache,
+ // parse from disk
+ // other: the startup cache file could not be found, probably
+ // due to being accessed before a profile has been selected (e.g.
+ // loading chrome for the profile manager itself). This must be
+ // parsed from disk.
+ nsresult rv;
+ if (proto) {
+ mCurrentPrototype = proto;
+
+ // Set up the right principal on the document.
+ mDocument->SetPrincipals(proto->DocumentPrincipal(),
+ proto->DocumentPrincipal());
+ } else {
+ // It's just a vanilla document load. Create a parser to deal
+ // with the stream n' stuff.
+
+ nsCOMPtr<nsIParser> parser;
+ // Get the document's principal
+ nsCOMPtr<nsIPrincipal> principal = mDocument->NodePrincipal();
+ rv =
+ PrepareToLoadPrototype(mDocumentURI, principal, getter_AddRefs(parser));
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(parser, &rv);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "parser doesn't support nsIStreamListener");
+ if (NS_FAILED(rv)) return rv;
+
+ mStreamListener = listener;
+
+ parser->Parse(mDocumentURI);
+ }
+
+ // If we're racing with another document to load proto, wait till the
+ // load has finished loading before trying build the document.
+ // Either the nsXULContentSink finishing to load the XML or
+ // the nsXULPrototypeDocument completing deserialization will trigger the
+ // OnPrototypeLoadDone callback.
+ // If the prototype is already loaded, OnPrototypeLoadDone will be called
+ // in OnStopRequest.
+ RefPtr<PrototypeDocumentParser> self = this;
+ rv = mCurrentPrototype->AwaitLoadDone(
+ [self]() { self->OnPrototypeLoadDone(); }, &mPrototypeAlreadyLoaded);
+ if (NS_FAILED(rv)) return rv;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PrototypeDocumentParser::OnStartRequest(nsIRequest* request) {
+ if (mStreamListener) {
+ return mStreamListener->OnStartRequest(request);
+ }
+ // There's already a prototype cached, so return cached here so the original
+ // request will be aborted. Either OnStopRequest or the prototype load
+ // finishing will notify the content sink that we're done loading the
+ // prototype.
+ return NS_ERROR_PARSED_DATA_CACHED;
+}
+
+NS_IMETHODIMP
+PrototypeDocumentParser::OnStopRequest(nsIRequest* request, nsresult aStatus) {
+ if (mStreamListener) {
+ return mStreamListener->OnStopRequest(request, aStatus);
+ }
+ if (mPrototypeAlreadyLoaded) {
+ return this->OnPrototypeLoadDone();
+ }
+ // The prototype will handle calling OnPrototypeLoadDone when it is ready.
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PrototypeDocumentParser::OnDataAvailable(nsIRequest* request,
+ nsIInputStream* aInStr,
+ uint64_t aSourceOffset,
+ uint32_t aCount) {
+ if (mStreamListener) {
+ return mStreamListener->OnDataAvailable(request, aInStr, aSourceOffset,
+ aCount);
+ }
+ MOZ_ASSERT_UNREACHABLE("Cached prototype doesn't receive data");
+ return NS_ERROR_UNEXPECTED;
+}
+
+nsresult PrototypeDocumentParser::OnPrototypeLoadDone() {
+ MOZ_ASSERT(!mIsComplete, "Should not be called more than once.");
+ mIsComplete = true;
+
+ RefPtr<PrototypeDocumentContentSink> sink = mOriginalSink;
+ RefPtr<nsXULPrototypeDocument> prototype = mCurrentPrototype;
+ return sink->OnPrototypeLoadDone(prototype);
+}
+
+nsresult PrototypeDocumentParser::PrepareToLoadPrototype(
+ nsIURI* aURI, nsIPrincipal* aDocumentPrincipal, nsIParser** aResult) {
+ nsresult rv;
+
+ // Create a new prototype document.
+ rv = NS_NewXULPrototypeDocument(getter_AddRefs(mCurrentPrototype));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mCurrentPrototype->InitPrincipal(aURI, aDocumentPrincipal);
+ if (NS_FAILED(rv)) {
+ mCurrentPrototype = nullptr;
+ return rv;
+ }
+
+ // Store the new prototype right away so if there are multiple requests
+ // for the same document they all get the same prototype.
+ if (IsChromeURI(mDocumentURI) &&
+ nsXULPrototypeCache::GetInstance()->IsEnabled()) {
+ nsXULPrototypeCache::GetInstance()->PutPrototype(mCurrentPrototype);
+ }
+
+ mDocument->SetPrincipals(aDocumentPrincipal, aDocumentPrincipal);
+
+ // Create a XUL content sink, a parser, and kick off a load for
+ // the document.
+ RefPtr<XULContentSinkImpl> sink = new XULContentSinkImpl();
+
+ rv = sink->Init(mDocument, mCurrentPrototype);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to initialize datasource sink");
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIParser> parser = new nsParser();
+
+ parser->SetCommand(eViewNormal);
+
+ parser->SetDocumentCharset(UTF_8_ENCODING, kCharsetFromDocTypeDefault);
+ parser->SetContentSink(sink); // grabs a reference to the parser
+
+ parser.forget(aResult);
+ return NS_OK;
+}
+
+} // namespace parser
+} // namespace mozilla
diff --git a/parser/prototype/PrototypeDocumentParser.h b/parser/prototype/PrototypeDocumentParser.h
new file mode 100644
index 0000000000..3e7935bffc
--- /dev/null
+++ b/parser/prototype/PrototypeDocumentParser.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_parser_PrototypeDocumentParser_h
+#define mozilla_parser_PrototypeDocumentParser_h
+
+#include "nsCycleCollectionParticipant.h"
+#include "nsIContentSink.h"
+#include "nsIParser.h"
+#include "nsXULPrototypeDocument.h"
+
+class nsIExpatSink;
+
+namespace mozilla {
+namespace dom {
+class PrototypeDocumentContentSink;
+} // namespace dom
+} // namespace mozilla
+
+namespace mozilla {
+namespace parser {
+
+// The PrototypeDocumentParser is more of a stub than a real parser. It is
+// responsible for loading an nsXULPrototypeDocument either from the startup
+// cache or creating a new prototype from the original source if a cached
+// version does not exist. Once the parser finishes loading the prototype it
+// will notify the content sink.
+class PrototypeDocumentParser final : public nsIParser,
+ public nsIStreamListener {
+ public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+
+ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PrototypeDocumentParser, nsIParser)
+
+ explicit PrototypeDocumentParser(nsIURI* aDocumentURI,
+ dom::Document* aDocument);
+
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+
+ // Start nsIParser
+ // Ideally, this would just implement nsBaseParser since most of these are
+ // stubs, but Document.h expects an nsIParser.
+ NS_IMETHOD_(void) SetContentSink(nsIContentSink* aSink) override;
+
+ NS_IMETHOD_(nsIContentSink*) GetContentSink() override;
+
+ NS_IMETHOD_(void) GetCommand(nsCString& aCommand) override {}
+
+ NS_IMETHOD_(void) SetCommand(const char* aCommand) override {}
+
+ NS_IMETHOD_(void) SetCommand(eParserCommands aParserCommand) override {}
+
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding,
+ int32_t aSource,
+ bool aForceAutoDetection) override {}
+
+ virtual nsIStreamListener* GetStreamListener() override;
+
+ NS_IMETHOD ContinueInterruptedParsing() override {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ NS_IMETHOD_(void) BlockParser() override {}
+
+ NS_IMETHOD_(void) UnblockParser() override {}
+
+ NS_IMETHOD_(void) ContinueInterruptedParsingAsync() override {}
+
+ NS_IMETHOD_(bool) IsParserEnabled() override { return true; }
+
+ NS_IMETHOD_(bool) IsComplete() override;
+
+ NS_IMETHOD Parse(nsIURI* aURL) override;
+
+ NS_IMETHOD Terminate() override { return NS_ERROR_NOT_IMPLEMENTED; }
+
+ virtual bool IsInsertionPointDefined() override { return false; }
+
+ void IncrementScriptNestingLevel() final {}
+
+ void DecrementScriptNestingLevel() final {}
+
+ bool HasNonzeroScriptNestingLevel() const final { return false; }
+
+ virtual bool IsScriptCreated() override { return false; }
+
+ // End nsIParser
+
+ private:
+ virtual ~PrototypeDocumentParser();
+
+ protected:
+ nsresult PrepareToLoadPrototype(nsIURI* aURI,
+ nsIPrincipal* aDocumentPrincipal,
+ nsIParser** aResult);
+
+ // This is invoked whenever the prototype for this document is loaded
+ // and should be walked, regardless of whether the XUL cache is
+ // disabled, whether the protototype was loaded, whether the
+ // prototype was loaded from the cache or created by parsing the
+ // actual XUL source, etc.
+ nsresult OnPrototypeLoadDone();
+
+ nsCOMPtr<nsIURI> mDocumentURI;
+ RefPtr<dom::PrototypeDocumentContentSink> mOriginalSink;
+ RefPtr<dom::Document> mDocument;
+
+ // The XML parser that data is forwarded to when the prototype does not exist
+ // and must be parsed from disk.
+ nsCOMPtr<nsIStreamListener> mStreamListener;
+
+ // The current prototype that we are walking to construct the
+ // content model.
+ RefPtr<nsXULPrototypeDocument> mCurrentPrototype;
+
+ // True if there was a prototype in the cache and it finished loading
+ // already.
+ bool mPrototypeAlreadyLoaded;
+
+ // True after the parser has notified the content sink that it is done.
+ bool mIsComplete;
+};
+
+} // namespace parser
+} // namespace mozilla
+
+#endif // mozilla_parser_PrototypeDocumentParser_h
diff --git a/parser/prototype/moz.build b/parser/prototype/moz.build
new file mode 100644
index 0000000000..4a2ea437a8
--- /dev/null
+++ b/parser/prototype/moz.build
@@ -0,0 +1,24 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "XML")
+
+EXPORTS.mozilla.parser += [
+ "PrototypeDocumentParser.h",
+]
+
+
+UNIFIED_SOURCES += [
+ "PrototypeDocumentParser.cpp",
+]
+
+FINAL_LIBRARY = "xul"
+
+LOCAL_INCLUDES += [
+ "../htmlparser",
+ "/dom/xul",
+]
diff --git a/parser/xml/moz.build b/parser/xml/moz.build
new file mode 100644
index 0000000000..2612106e3a
--- /dev/null
+++ b/parser/xml/moz.build
@@ -0,0 +1,10 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "DOM: HTML Parser")
+
+TEST_DIRS += ["test"]
diff --git a/parser/xml/test/moz.build b/parser/xml/test/moz.build
new file mode 100644
index 0000000000..96dbb88c3d
--- /dev/null
+++ b/parser/xml/test/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Note: set the test module's name to test_<yourmodule>
+XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.ini"]
diff --git a/parser/xml/test/unit/CC-BY-LICENSE b/parser/xml/test/unit/CC-BY-LICENSE
new file mode 100644
index 0000000000..d0ce194dc0
--- /dev/null
+++ b/parser/xml/test/unit/CC-BY-LICENSE
@@ -0,0 +1,59 @@
+Creative Commons Attribution 3.0 Unported License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
+
+1. Definitions
+
+ "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
+ "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
+ "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
+ "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
+ "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
+ "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
+ "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
+ "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
+ "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
+
+ to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
+ to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
+ to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
+ to Distribute and Publicly Perform Adaptations.
+
+ For the avoidance of doubt:
+ Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
+ Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and,
+ Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
+
+ You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(b), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(b), as requested.
+ If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4 (b) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
+ Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
+ Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
+
+8. Miscellaneous
+
+ Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
+ Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
+ If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+ No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
+ This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
+ The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
diff --git a/parser/xml/test/unit/results.js b/parser/xml/test/unit/results.js
new file mode 100644
index 0000000000..d5b638275e
--- /dev/null
+++ b/parser/xml/test/unit/results.js
@@ -0,0 +1,924 @@
+// vectors by the html5security project (https://code.google.com/p/html5security/ & Creative Commons 3.0 BY), see CC-BY-LICENSE for the full license
+
+var vectors = [
+ {
+ data: '<form id="test"></form><button form="test" formaction="javascript:alert(1)">X</button>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<meta charset="x-imap4-modified-utf7">&ADz&AGn&AG0&AEf&ACA&AHM&AHI&AGO&AD0&AGn&ACA&AG8Abg&AGUAcgByAG8AcgA9AGEAbABlAHIAdAAoADEAKQ&ACAAPABi',
+ sanitized:
+ "<html><head></head><body>&amp;ADz&amp;AGn&amp;AG0&amp;AEf&amp;ACA&amp;AHM&amp;AHI&amp;AGO&amp;AD0&amp;AGn&amp;ACA&amp;AG8Abg&amp;AGUAcgByAG8AcgA9AGEAbABlAHIAdAAoADEAKQ&amp;ACAAPABi</body></html>",
+ },
+ {
+ data: '<meta charset="x-imap4-modified-utf7">&<script&S1&TS&1>alert&A7&(1)&R&UA;&&<&A9&11/script&X&>',
+ sanitized:
+ "<html><head></head><body>&amp;alert&amp;A7&amp;(1)&amp;R&amp;UA;&amp;&amp;&lt;&amp;A9&amp;11/script&amp;X&amp;&gt;</body></html>",
+ },
+ {
+ data: "0?<script>Worker(\"#\").onmessage=message=>eval(message.data)</script> :postMessage(importScripts('data:;base64,cG9zdE1lc3NhZ2UoJ2FsZXJ0KDEpJyk'))",
+ sanitized:
+ "<html><head></head><body>0? :postMessage(importScripts('data:;base64,cG9zdE1lc3NhZ2UoJ2FsZXJ0KDEpJyk'))</body></html>",
+ },
+ {
+ data: "<script>crypto.generateCRMFRequest('CN=0',0,0,null,'alert(1)',384,null,'rsa-dual-use')</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<script>({set/**/$($){_/**/setter=$,_=1}}).$=alert</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<input onfocus=write(1) autofocus>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<input onblur=write(1) autofocus><input autofocus>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<a style=\"-o-link:'javascript:alert(1)';-o-link-source:current\">X</a>",
+ sanitized: "<html><head></head><body><a>X</a></body></html>",
+ },
+ {
+ data: "<video poster=javascript:alert(1)//></video>",
+ sanitized:
+ '<html><head></head><body><video controls="controls"></video></body></html>',
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg"><g onload="javascript:alert(1)"></g></svg>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<body onscroll=alert(1)><br><br><br><br><br><br>...<br><br><br><br><input autofocus>",
+ sanitized:
+ "<html><head></head><body><br><br><br><br><br><br>...<br><br><br><br></body></html>",
+ },
+ {
+ data: '<x repeat="template" repeat-start="999999">0<y repeat="template" repeat-start="999999">1</y></x>',
+ sanitized: "<html><head></head><body>01</body></html>",
+ },
+ {
+ data: "<input pattern=^((a+.)a)+$ value=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<script>({0:#0=alert/#0#/#0#(0)})</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "X<x style=`behavior:url(#default#time2)` onbegin=`write(1)` >",
+ sanitized: "<html><head></head><body>X</body></html>",
+ },
+ {
+ data: '<?xml-stylesheet href="javascript:alert(1)"?><root/>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<script xmlns="http://www.w3.org/1999/xhtml">&#x61;l&#x65;rt&#40;1)</script>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<meta charset="x-mac-farsi">�script �alert(1)//�/script �',
+ sanitized:
+ "<html><head></head><body>�script �alert(1)//�/script �</body></html>",
+ },
+ {
+ data: "<script>ReferenceError.prototype.__defineGetter__('name', function(){alert(1)}),x</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<script>Object.__noSuchMethod__ = Function,[{}][0].constructor._('alert(1)')()</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<input onblur=focus() autofocus><input>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<form id=test onforminput=alert(1)><input></form><button form=test onformchange=alert(2)>X</button>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "1<set/xmlns=`urn:schemas-microsoft-com:time` style=`beh&#x41vior:url(#default#time2)` attributename=`innerhtml` to=`&lt;img/src=&quot;x&quot;onerror=alert(1)&gt;`>",
+ sanitized: "<html><head></head><body>1</body></html>",
+ },
+ {
+ data: '<script src="#">{alert(1)}</script>;1',
+ sanitized: "<html><head></head><body>;1</body></html>",
+ },
+ {
+ data: "+ADw-html+AD4APA-body+AD4APA-div+AD4-top secret+ADw-/div+AD4APA-/body+AD4APA-/html+AD4-.toXMLString().match(/.*/m),alert(RegExp.input);",
+ sanitized:
+ "<html><head></head><body>+ADw-html+AD4APA-body+AD4APA-div+AD4-top secret+ADw-/div+AD4APA-/body+AD4APA-/html+AD4-.toXMLString().match(/.*/m),alert(RegExp.input);</body></html>",
+ },
+ {
+ data: "<style>p[foo=bar{}*{-o-link:'javascript:alert(1)'}{}*{-o-link-source:current}*{background:red}]{background:green};</style>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "1<animate/xmlns=urn:schemas-microsoft-com:time style=behavior:url(#default#time2) attributename=innerhtml values=&lt;img/src=&quot;.&quot;onerror=alert(1)&gt;>",
+ sanitized: "<html><head></head><body>1</body></html>",
+ },
+ {
+ data: "<link rel=stylesheet href=data:,*%7bx:expression(write(1))%7d",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<style>@import "data:,*%7bx:expression(write(1))%7D";</style>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<frameset onload=alert(1)>",
+ sanitized: "<html><head></head></html>",
+ },
+ {
+ data: '<table background="javascript:alert(1)"></table>',
+ sanitized: "<html><head></head><body><table></table></body></html>",
+ },
+ {
+ data: '<a style="pointer-events:none;position:absolute;"><a style="position:absolute;" onclick="alert(1);">XXX</a></a><a href="javascript:alert(2)">XXX</a>',
+ sanitized:
+ "<html><head></head><body><a></a><a>XXX</a><a>XXX</a></body></html>",
+ },
+ {
+ data: "1<vmlframe xmlns=urn:schemas-microsoft-com:vml style=behavior:url(#default#vml);position:absolute;width:100%;height:100% src=test.vml#xss></vmlframe>",
+ sanitized: "<html><head></head><body>1</body></html>",
+ },
+ {
+ data: "1<a href=#><line xmlns=urn:schemas-microsoft-com:vml style=behavior:url(#default#vml);position:absolute href=javascript:alert(1) strokecolor=white strokeweight=1000px from=0 to=1000 /></a>",
+ sanitized: '<html><head></head><body>1<a href="#"></a></body></html>',
+ },
+ {
+ data: '<a style="behavior:url(#default#AnchorClick);" folder="javascript:alert(1)">XXX</a>',
+ sanitized: "<html><head></head><body><a>XXX</a></body></html>",
+ },
+ {
+ data: '<!--<img src="--><img src=x onerror=alert(1)//">',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<comment><img src="</comment><img src=x onerror=alert(1)//">',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<!-- up to Opera 11.52, FF 3.6.28 -->\r\n<![><img src="]><img src=x onerror=alert(1)//">\r\n\r\n<!-- IE9+, FF4+, Opera 11.60+, Safari 4.0.4+, GC7+ -->\r\n<svg><![CDATA[><image xlink:href="]]><img src=xx:x onerror=alert(2)//"></svg>',
+ sanitized:
+ '<html><head></head><body><img>\n\n\n&gt;&lt;image xlink:href="<img></body></html>',
+ },
+ {
+ data: '<style><img src="</style><img src=x onerror=alert(1)//">',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<li style=list-style:url() onerror=alert(1)></li>\n<div style=content:url(data:image/svg+xml,%3Csvg/%3E);visibility:hidden onload=alert(1)></div>",
+ sanitized: "<html><head></head><body><li></li>\n<div></div></body></html>",
+ },
+ {
+ data: '<head><base href="javascript://"/></head><body><a href="/. /,alert(1)//#">XXX</a></body>',
+ sanitized: "<html><head></head><body><a>XXX</a></body></html>",
+ },
+ {
+ data: '<?xml version="1.0" standalone="no"?>\r\n<html xmlns="http://www.w3.org/1999/xhtml">\r\n<head>\r\n<style type="text/css">\r\n@font-face {font-family: y; src: url("font.svg#x") format("svg");} body {font: 100px "y";}\r\n</style>\r\n</head>\r\n<body>Hello</body>\r\n</html>',
+ sanitized: "<html><head>\n\n</head>\n<body>Hello\n</body></html>",
+ },
+ {
+ data: "<style>*[{}@import'test.css?]{color: green;}</style>X",
+ sanitized: "<html><head></head><body>X</body></html>",
+ },
+ {
+ data: "<div style=\"font-family:'foo[a];color:red;';\">XXX</div>",
+ sanitized: "<html><head></head><body><div>XXX</div></body></html>",
+ },
+ {
+ data: '<div style="font-family:foo}color=red;">XXX</div>',
+ sanitized: "<html><head></head><body><div>XXX</div></body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<SCRIPT FOR=document EVENT=onreadystatechange>alert(1)</SCRIPT>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<OBJECT CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83"><PARAM NAME="DataURL" VALUE="javascript:alert(1)"></OBJECT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></embed>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<x style="behavior:url(test.sct)">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<xml id="xss" src="test.htc"></xml>\r\n<label dataformatas="html" datasrc="#xss" datafld="payload"></label>',
+ sanitized: "<html><head></head><body>\n<label></label></body></html>",
+ },
+ {
+ data: "<script>[{'a':Object.prototype.__defineSetter__('b',function(){alert(arguments[0])}),'b':['secret']}]</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<video><source onerror="alert(1)">',
+ sanitized:
+ '<html><head></head><body><video controls="controls"><source></video></body></html>',
+ },
+ {
+ data: '<video onerror="alert(1)"><source></source></video>',
+ sanitized:
+ '<html><head></head><body><video controls="controls"><source></video></body></html>',
+ },
+ {
+ data: "<b <script>alert(1)//</script>0</script></b>",
+ sanitized: "<html><head></head><body><b>alert(1)//0</b></body></html>",
+ },
+ {
+ data: "<b><script<b></b><alert(1)</script </b></b>",
+ sanitized: "<html><head></head><body><b></b></body></html>",
+ },
+ {
+ data: '<div id="div1"><input value="``onmouseover=alert(1)"></div> <div id="div2"></div><script>document.getElementById("div2").innerHTML = document.getElementById("div1").innerHTML;</script>',
+ sanitized:
+ '<html><head></head><body><div id="div1"></div> <div id="div2"></div></body></html>',
+ },
+ {
+ data: '<div style="[a]color[b]:[c]red">XXX</div>',
+ sanitized: "<html><head></head><body><div>XXX</div></body></html>",
+ },
+ {
+ data: '<div style="\\63&#9\\06f&#10\\0006c&#12\\00006F&#13\\R:\\000072 Ed;color\\0\\bla:yellow\\0\\bla;col\\0\\00 \\&#xA0or:blue;">XXX</div>',
+ sanitized: "<html><head></head><body><div>XXX</div></body></html>",
+ },
+ {
+ data: "<!-- IE 6-8 -->\r\n<x '=\"foo\"><x foo='><img src=x onerror=alert(1)//'>\r\n\r\n<!-- IE 6-9 -->\r\n<! '=\"foo\"><x foo='><img src=x onerror=alert(2)//'>\r\n<? '=\"foo\"><x foo='><img src=x onerror=alert(3)//'>",
+ sanitized: "<html><head></head><body>\n\n\n\n</body></html>",
+ },
+ {
+ data: '<embed src="javascript:alert(1)"></embed> // O10.10�, OM10.0�, GC6�, FF\r\n<img src="javascript:alert(2)">\r\n<image src="javascript:alert(2)"> // IE6, O10.10�, OM10.0�\r\n<script src="javascript:alert(3)"></script> // IE6, O11.01�, OM10.1�',
+ sanitized:
+ "<html><head></head><body> // O10.10�, OM10.0�, GC6�, FF\n<img>\n<img> // IE6, O10.10�, OM10.0�\n // IE6, O11.01�, OM10.1�</body></html>",
+ },
+ {
+ data: '<!DOCTYPE x[<!ENTITY x SYSTEM "http://html5sec.org/test.xxe">]><y>&x;</y>',
+ sanitized:
+ "<!DOCTYPE x[<!entity>\n<html><head></head><body>]&gt;&amp;x;</body></html>",
+ },
+ {
+ data: '<svg onload="javascript:alert(1)" xmlns="http://www.w3.org/2000/svg"></svg>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<?xml version=\"1.0\"?>\n<?xml-stylesheet type=\"text/xsl\" href=\"data:,%3Cxsl:transform version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' id='xss'%3E%3Cxsl:output method='html'/%3E%3Cxsl:template match='/'%3E%3Cscript%3Ealert(1)%3C/script%3E%3C/xsl:template%3E%3C/xsl:transform%3E\"?>\n<root/>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<!DOCTYPE x [\r\n\t<!ATTLIST img xmlns CDATA "http://www.w3.org/1999/xhtml" src CDATA "xx:x"\r\n onerror CDATA "alert(1)"\r\n onload CDATA "alert(2)">\r\n]><img />',
+ sanitized:
+ "<!DOCTYPE x>\n<html><head></head><body>]&gt;<img></body></html>",
+ },
+ {
+ data: '<doc xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/1999/xhtml">\r\n\t<html:style /><x xlink:href="javascript:alert(1)" xlink:type="simple">XXX</x>\r\n</doc>',
+ sanitized: "<html><head></head><body>\n\tXXX\n</body></html>",
+ },
+ {
+ data: '<card xmlns="http://www.wapforum.org/2001/wml"><onevent type="ontimer"><go href="javascript:alert(1)"/></onevent><timer value="1"/></card>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<div style=width:1px;filter:glow onfilterchange=alert(1)>x</div>",
+ sanitized: "<html><head></head><body><div>x</div></body></html>",
+ },
+ {
+ data: "<// style=x:expression\\28write(1)\\29>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<form><button formaction="javascript:alert(1)">X</button>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<event-source src="event.php" onload="alert(1)">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<a href="javascript:alert(1)"><event-source src="data:application/x-dom-event-stream,Event:click%0Adata:XXX%0A%0A" /></a>',
+ sanitized: "<html><head></head><body><a></a></body></html>",
+ },
+ {
+ data: "<script<{alert(1)}/></script </>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<?xml-stylesheet type="text/css"?><!DOCTYPE x SYSTEM "test.dtd"><x>&x;</x>',
+ sanitized:
+ '<!DOCTYPE x SYSTEM "test.dtd">\n<html><head></head><body>&amp;x;</body></html>',
+ },
+ {
+ data: '<?xml-stylesheet type="text/css"?><root style="x:expression(write(1))"/>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<?xml-stylesheet type="text/xsl" href="#"?><img xmlns="x-schema:test.xdr"/>',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<object allowscriptaccess="always" data="test.swf"></object>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<style>*{x:EXPRESSION(write(1))}</style>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<x xmlns:xlink="http://www.w3.org/1999/xlink" xlink:actuate="onLoad" xlink:href="javascript:alert(1)" xlink:type="simple"/>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<?xml-stylesheet type="text/css" href="data:,*%7bx:expression(write(2));%7d"?>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<x:template xmlns:x="http://www.wapforum.org/2001/wml" x:ontimer="$(x:unesc)j$(y:escape)a$(z:noecs)v$(x)a$(y)s$(z)cript$x:alert(1)"><x:timer value="1"/></x:template>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<x xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load" ev:handler="javascript:alert(1)//#x"/>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<x xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load" ev:handler="test.evt#x"/>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<body oninput=alert(1)><input autofocus>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg">\n<a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="javascript:alert(1)"><rect width="1000" height="1000" fill="white"/></a>\n</svg>',
+ sanitized: "<html><head></head><body>\n\n</body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\n\n<animation xlink:href="javascript:alert(1)"/>\n<animation xlink:href="data:text/xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' onload=\'alert(1)\'%3E%3C/svg%3E"/>\n\n<image xlink:href="data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' onload=\'alert(1)\'%3E%3C/svg%3E"/>\n\n<foreignObject xlink:href="javascript:alert(1)"/>\n<foreignObject xlink:href="data:text/xml,%3Cscript xmlns=\'http://www.w3.org/1999/xhtml\'%3Ealert(1)%3C/script%3E"/>\n\n</svg>',
+ sanitized: "<html><head></head><body>\n\n\n\n\n\n\n\n\n\n</body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg">\n<set attributeName="onmouseover" to="alert(1)"/>\n<animate attributeName="onunload" to="alert(1)"/>\n</svg>',
+ sanitized: "<html><head></head><body>\n\n\n</body></html>",
+ },
+ {
+ data: '<!-- Up to Opera 10.63 -->\r\n<div style=content:url(test2.svg)></div>\r\n\r\n<!-- Up to Opera 11.64 - see link below -->\r\n\r\n<!-- Up to Opera 12.x -->\r\n<div style="background:url(test5.svg)">PRESS ENTER</div>',
+ sanitized:
+ "<html><head></head><body><div></div>\n\n\n\n\n<div>PRESS ENTER</div></body></html>",
+ },
+ {
+ data: '[A]\n<? foo="><script>alert(1)</script>">\n<! foo="><script>alert(1)</script>">\n</ foo="><script>alert(1)</script>">\n[B]\n<? foo="><x foo=\'?><script>alert(1)</script>\'>">\n[C]\n<! foo="[[[x]]"><x foo="]foo><script>alert(1)</script>">\n[D]\n<% foo><x foo="%><script>alert(1)</script>">',
+ sanitized:
+ '<html><head></head><body>[A]\n"&gt;\n"&gt;\n"&gt;\n[B]\n"&gt;\n[C]\n\n[D]\n&lt;% foo&gt;</body></html>',
+ },
+ {
+ data: '<div style="background:url(http://foo.f/f oo/;color:red/*/foo.jpg);">X</div>',
+ sanitized: "<html><head></head><body><div>X</div></body></html>",
+ },
+ {
+ data: '<div style="list-style:url(http://foo.f)\\20url(javascript:alert(1));">X</div>',
+ sanitized: "<html><head></head><body><div>X</div></body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg">\n<handler xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load">alert(1)</handler>\n</svg>',
+ sanitized: "<html><head></head><body>\nalert(1)\n</body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\n<feImage>\n<set attributeName="xlink:href" to="data:image/svg+xml;charset=utf-8;base64,\nPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxzY3JpcHQ%2BYWxlcnQoMSk8L3NjcmlwdD48L3N2Zz4NCg%3D%3D"/>\n</feImage>\n</svg>',
+ sanitized: "<html><head></head><body>\n\n\n\n</body></html>",
+ },
+ {
+ data: "<iframe src=mhtml:http://html5sec.org/test.html!xss.html></iframe>\n<iframe src=mhtml:http://html5sec.org/test.gif!xss.html></iframe>",
+ sanitized: "<html><head></head><body>\n</body></html>",
+ },
+ {
+ data: "<!-- IE 5-9 -->\r\n<div id=d><x xmlns=\"><iframe onload=alert(1)\"></div>\n<script>d.innerHTML+='';</script>\r\n\r\n<!-- IE 10 in IE5-9 Standards mode -->\r\n<div id=d><x xmlns='\"><iframe onload=alert(2)//'></div>\n<script>d.innerHTML+='';</script>",
+ sanitized:
+ '<html><head></head><body><div id="d"></div>\n\n\n\n<div id="d"></div>\n</body></html>',
+ },
+ {
+ data: '<div id=d><div style="font-family:\'sans\\27\\2F\\2A\\22\\2A\\2F\\3B color\\3Ared\\3B\'">X</div></div>\n<script>with(document.getElementById("d"))innerHTML=innerHTML</script>',
+ sanitized:
+ '<html><head></head><body><div id="d"><div>X</div></div>\n</body></html>',
+ },
+ {
+ data: "XXX<style>\r\n\r\n*{color:gre/**/en !/**/important} /* IE 6-9 Standards mode */\r\n\r\n<!--\r\n--><!--*{color:red} /* all UA */\r\n\r\n*{background:url(xx:x //**/\\red/*)} /* IE 6-7 Standards mode */\r\n\r\n</style>",
+ sanitized: "<html><head></head><body>XXX</body></html>",
+ },
+ {
+ data: '<img[a][b]src=x[d]onerror[c]=[e]"alert(1)">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<a href="[a]java[b]script[c]:alert(1)">XXX</a>',
+ sanitized: "<html><head></head><body><a>XXX</a></body></html>",
+ },
+ {
+ data: '<img src="x` `<script>alert(1)</script>"` `>',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<script>history.pushState(0,0,'/i/am/somewhere_else');</script>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg" id="foo">\r\n<x xmlns="http://www.w3.org/2001/xml-events" event="load" observer="foo" handler="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%3Chandler%20xml%3Aid%3D%22bar%22%20type%3D%22application%2Fecmascript%22%3E alert(1) %3C%2Fhandler%3E%0A%3C%2Fsvg%3E%0A#bar"/>\r\n</svg>',
+ sanitized: "<html><head></head><body>\n\n</body></html>",
+ },
+ {
+ data: '<iframe src="data:image/svg-xml,%1F%8B%08%00%00%00%00%00%02%03%B3)N.%CA%2C(Q%A8%C8%CD%C9%2B%B6U%CA())%B0%D2%D7%2F%2F%2F%D7%2B7%D6%CB%2FJ%D77%B4%B4%B4%D4%AF%C8(%C9%CDQ%B2K%CCI-*%D10%D4%B4%D1%87%E8%B2%03"></iframe>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<img src onerror /" \'"= alt=alert(1)//">',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<title onpropertychange=alert(1)></title><title title=></title>",
+ sanitized:
+ '<html><head><title></title><title title=""></title></head><body></body></html>',
+ },
+ {
+ data: '<!-- IE 5-8 standards mode -->\r\n<a href=http://foo.bar/#x=`y></a><img alt="`><img src=xx:x onerror=alert(1)></a>">\r\n\r\n<!-- IE 5-9 standards mode -->\r\n<!a foo=x=`y><img alt="`><img src=xx:x onerror=alert(2)//">\r\n<?a foo=x=`y><img alt="`><img src=xx:x onerror=alert(3)//">',
+ sanitized:
+ '<html><head></head><body><a href="http://foo.bar/#x=`y"></a><img alt="`&gt;&lt;img src=xx:x onerror=alert(1)&gt;&lt;/a&gt;">\n\n\n<img alt="`&gt;&lt;img src=xx:x onerror=alert(2)//">\n<img alt="`&gt;&lt;img src=xx:x onerror=alert(3)//"></body></html>',
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg">\n<a id="x"><rect fill="white" width="1000" height="1000"/></a>\n<rect fill="white" style="clip-path:url(test3.svg#a);fill:url(#b);filter:url(#c);marker:url(#d);mask:url(#e);stroke:url(#f);"/>\n</svg>',
+ sanitized: "<html><head></head><body>\n\n\n</body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg">\r\n<path d="M0,0" style="marker-start:url(test4.svg#a)"/>\r\n</svg>',
+ sanitized: "<html><head></head><body>\n\n</body></html>",
+ },
+ {
+ data: '<div style="background:url(/f#[a]oo/;color:red/*/foo.jpg);">X</div>',
+ sanitized: "<html><head></head><body><div>X</div></body></html>",
+ },
+ {
+ data: '<div style="font-family:foo{bar;background:url(http://foo.f/oo};color:red/*/foo.jpg);">X</div>',
+ sanitized: "<html><head></head><body><div>X</div></body></html>",
+ },
+ {
+ data: '<div id="x">XXX</div>\n<style>\n\n#x{font-family:foo[bar;color:green;}\n\n#y];color:red;{}\n\n</style>',
+ sanitized: '<html><head></head><body><div id="x">XXX</div>\n</body></html>',
+ },
+ {
+ data: "<x style=\"background:url('x[a];color:red;/*')\">XXX</x>",
+ sanitized: "<html><head></head><body>XXX</body></html>",
+ },
+ {
+ data: "<!--[if]><script>alert(1)</script -->\r\n<!--[if<img src=x onerror=alert(2)//]> -->",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<div id="x">x</div>\n<xml:namespace prefix="t">\n<import namespace="t" implementation="#default#time2">\n<t:set attributeName="innerHTML" targetElement="x" to="&lt;img&#11;src=x:x&#11;onerror&#11;=alert(1)&gt;">',
+ sanitized:
+ '<html><head></head><body><div id="x">x</div>\n\n\n</body></html>',
+ },
+ {
+ data: '<a href="http://attacker.org">\n\t<iframe src="http://example.org/"></iframe>\n</a>',
+ sanitized:
+ '<html><head></head><body><a href="http://attacker.org">\n\t\n</a></body></html>',
+ },
+ {
+ data: '<div draggable="true" ondragstart="event.dataTransfer.setData(\'text/plain\',\'malicious code\');">\n\t<h1>Drop me</h1>\n</div>\n\n<iframe src="http://www.example.org/dropHere.html"></iframe>',
+ sanitized:
+ '<html><head></head><body><div draggable="true">\n\t<h1>Drop me</h1>\n</div>\n\n</body></html>',
+ },
+ {
+ data: '<iframe src="view-source:http://www.example.org/" frameborder="0" style="width:400px;height:180px"></iframe>\n\n<textarea type="text" cols="50" rows="10"></textarea>',
+ sanitized:
+ '<html><head></head><body>\n\n<textarea type="text" cols="50" rows="10"></textarea></body></html>',
+ },
+ {
+ data: "<script>\nfunction makePopups(){\n\tfor (i=1;i<6;i++) {\n\t\twindow.open('popup.html','spam'+i,'width=50,height=50');\n\t}\n}\n</script>\n\n<body>\n<a href=\"#\" onclick=\"makePopups()\">Spam</a>",
+ sanitized:
+ '<html><head>\n\n</head><body>\n<a href="#">Spam</a></body></html>',
+ },
+ {
+ data: '<html xmlns="http://www.w3.org/1999/xhtml"\nxmlns:svg="http://www.w3.org/2000/svg">\n<body style="background:gray">\n<iframe src="http://example.com/" style="width:800px; height:350px; border:none; mask: url(#maskForClickjacking);"/>\n<svg:svg>\n<svg:mask id="maskForClickjacking" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">\n\t<svg:rect x="0.0" y="0.0" width="0.373" height="0.3" fill="white"/>\n\t<svg:circle cx="0.45" cy="0.7" r="0.075" fill="white"/>\n</svg:mask>\n</svg:svg>\n</body>\n</html>',
+ sanitized:
+ '<html><head></head><body>\n\n&lt;svg:svg&gt;\n&lt;svg:mask id="maskForClickjacking" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox"&gt;\n\t&lt;svg:rect x="0.0" y="0.0" width="0.373" height="0.3" fill="white"/&gt;\n\t&lt;svg:circle cx="0.45" cy="0.7" r="0.075" fill="white"/&gt;\n&lt;/svg:mask&gt;\n&lt;/svg:svg&gt;\n&lt;/body&gt;\n&lt;/html&gt;</body></html>',
+ },
+ {
+ data: '<iframe sandbox="allow-same-origin allow-forms allow-scripts" src="http://example.org/"></iframe>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<span class=foo>Some text</span>\n<a class=bar href="http://www.example.org">www.example.org</a>\n\n<script src="http://code.jquery.com/jquery-1.4.4.js"></script>\n<script>\n$("span.foo").click(function() {\nalert(\'foo\');\n$("a.bar").click();\n});\n$("a.bar").click(function() {\nalert(\'bar\');\nlocation="http://html5sec.org";\n});\n</script>',
+ sanitized:
+ '<html><head></head><body><span class="foo">Some text</span>\n<a class="bar" href="http://www.example.org">www.example.org</a>\n\n\n</body></html>',
+ },
+ {
+ data: '<script src="/\\example.com\\foo.js"></script> // Safari 5.0, Chrome 9, 10\n<script src="\\\\example.com\\foo.js"></script> // Safari 5.0',
+ sanitized:
+ "<html><head> </head><body>// Safari 5.0, Chrome 9, 10\n // Safari 5.0</body></html>",
+ },
+ {
+ data: '<?xml version="1.0"?>\r\n<?xml-stylesheet type="text/xml" href="#stylesheet"?>\r\n<!DOCTYPE doc [\r\n<!ATTLIST xsl:stylesheet\r\n id ID #REQUIRED>]>\r\n<svg xmlns="http://www.w3.org/2000/svg">\r\n <xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\r\n <xsl:template match="/">\r\n <iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(1)"></iframe>\r\n </xsl:template>\r\n </xsl:stylesheet>\r\n <circle fill="red" r="40"></circle>\r\n</svg>',
+ sanitized:
+ "<!DOCTYPE doc>\n<html><head></head><body>]&gt;\n\n \n \n \n \n \n \n</body></html>",
+ },
+ {
+ data: '<object id="x" classid="clsid:CB927D12-4FF7-4a9e-A169-56E4B8A75598"></object>\r\n<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" onqt_error="alert(1)" style="behavior:url(#x);"><param name=postdomevents /></object>',
+ sanitized: "<html><head></head><body>\n</body></html>",
+ },
+ {
+ data: '<svg xmlns="http://www.w3.org/2000/svg" id="x">\r\n<listener event="load" handler="#y" xmlns="http://www.w3.org/2001/xml-events" observer="x"/>\r\n<handler id="y">alert(1)</handler>\r\n</svg>',
+ sanitized: "<html><head></head><body>\n\nalert(1)\n</body></html>",
+ },
+ {
+ data: "<svg><style>&lt;img/src=x onerror=alert(1)// </b>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<svg>\n<image style='filter:url(\"data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22><script>parent.alert(1)</script></svg>\")'>\n<!--\nSame effect with\n<image filter='...'>\n-->\n</svg>",
+ sanitized: "<html><head></head><body>\n\n\n</body></html>",
+ },
+ {
+ data: '<math href="javascript:alert(1)">CLICKME</math>\r\n\r\n<math>\r\n<!-- up to FF 13 -->\r\n<maction actiontype="statusline#http://google.com" xlink:href="javascript:alert(2)">CLICKME</maction>\r\n\r\n<!-- FF 14+ -->\r\n<maction actiontype="statusline" xlink:href="javascript:alert(3)">CLICKME<mtext>http://http://google.com</mtext></maction>\r\n</math>',
+ sanitized:
+ '<html><head></head><body><math>CLICKME</math>\n\n<math>\n\n<maction actiontype="statusline#http://google.com">CLICKME</maction>\n\n\n<maction actiontype="statusline">CLICKME<mtext>http://http://google.com</mtext></maction>\n</math></body></html>',
+ },
+ {
+ data: "<b>drag and drop one of the following strings to the drop box:</b>\r\n<br/><hr/>\r\njAvascript:alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie);//\r\n<br/><hr/>\r\nfeed:javascript:alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie);//\r\n<br/><hr/>\r\nfeed:data:text/html,&#x3c;script>alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie)&#x3c;/script>&#x3c;b>\r\n<br/><hr/>\r\nfeed:feed:javAscript:javAscript:feed:alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie);//\r\n<br/><hr/>\r\n<div id=\"dropbox\" style=\"height: 360px;width: 500px;border: 5px solid #000;position: relative;\" ondragover=\"event.preventDefault()\">+ Drop Box +</div>",
+ sanitized:
+ "<html><head></head><body><b>drag and drop one of the following strings to the drop box:</b>\n<br><hr>\njAvascript:alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie);//\n<br><hr>\nfeed:javascript:alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie);//\n<br><hr>\nfeed:data:text/html,&lt;script&gt;alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie)&lt;/script&gt;&lt;b&gt;\n<br><hr>\nfeed:feed:javAscript:javAscript:feed:alert('Top Page Location: '+document.location+' Host Page Cookies: '+document.cookie);//\n<br><hr>\n<div id=\"dropbox\">+ Drop Box +</div></body></html>",
+ },
+ {
+ data: '<!doctype html>\r\n<form>\r\n<label>type a,b,c,d - watch the network tab/traffic (JS is off, latest NoScript)</label>\r\n<br>\r\n<input name="secret" type="password">\r\n</form>\r\n<!-- injection --><svg height="50px">\r\n<image xmlns:xlink="http://www.w3.org/1999/xlink">\r\n<set attributeName="xlink:href" begin="accessKey(a)" to="//example.com/?a" />\r\n<set attributeName="xlink:href" begin="accessKey(b)" to="//example.com/?b" />\r\n<set attributeName="xlink:href" begin="accessKey(c)" to="//example.com/?c" />\r\n<set attributeName="xlink:href" begin="accessKey(d)" to="//example.com/?d" />\r\n</image>\r\n</svg>',
+ sanitized:
+ "<!DOCTYPE html>\n<html><head></head><body>\n<label>type a,b,c,d - watch the network tab/traffic (JS is off, latest NoScript)</label>\n<br>\n\n\n\n\n\n\n\n\n\n</body></html>",
+ },
+ {
+ data: "<!-- `<img/src=xx:xx onerror=alert(1)//--!>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<xmp>\r\n<%\r\n</xmp>\r\n<img alt='%></xmp><img src=xx:x onerror=alert(1)//'>\r\n\r\n<script>\r\nx='<%'\r\n</script> %>/\r\nalert(2)\r\n</script>\r\n\r\nXXX\r\n<style>\r\n*['<!--']{}\r\n</style>\r\n-->{}\r\n*{color:red}</style>",
+ sanitized:
+ '<html><head></head><body>\n&lt;%\n\n<img alt="%&gt;&lt;/xmp&gt;&lt;img src=xx:x onerror=alert(1)//">\n\n %&gt;/\nalert(2)\n\n\nXXX\n\n--&gt;{}\n*{color:red}</body></html>',
+ },
+ {
+ data: '<form action="" method="post">\r\n<input name="username" value="admin" />\r\n<input name="password" type="password" value="secret" />\r\n<input name="injected" value="injected" dirname="password" />\r\n<input type="submit">\r\n</form>',
+ sanitized: "<html><head></head><body>\n\n\n\n\n</body></html>",
+ },
+ {
+ data: "<SCRIPT>alert('XSS');</SCRIPT>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "'';!--\"<XSS>=&{()}",
+ sanitized: "<html><head></head><body>'';!--\"=&amp;{()}</body></html>",
+ },
+ {
+ data: "<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<IMG SRC=\"javascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=javascript:alert('XSS')>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=JaVaScRiPt:alert('XSS')>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=javascript:alert(&quot;XSS&quot;)>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=`javascript:alert(\"RSnake says, 'XSS'\")`>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "SRC=&#10<IMG 6;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>",
+ sanitized: "<html><head></head><body>SRC=\n<img></body></html>",
+ },
+ {
+ data: "<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=\"javascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=\"jav&#x09;ascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=\"jav&#x0A;ascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=\"jav&#x0D;ascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG SRC=\" &#14; javascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<IMG SRC=\"javascript:alert('XSS')\"",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<SCRIPT>a=/XSS/",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "\\\";alert('XSS');//",
+ sanitized: "<html><head></head><body>\\\";alert('XSS');//</body></html>",
+ },
+ {
+ data: '<INPUT TYPE="IMAGE" SRC="javascript:alert(\'XSS\');">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<BODY BACKGROUND=\"javascript:alert('XSS')\">",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<BODY ONLOAD=alert('XSS')>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<IMG DYNSRC=\"javascript:alert('XSS')\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<IMG LOWSRC=\"javascript:alert('XSS')\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<BGSOUND SRC=\"javascript:alert('XSS');\">",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<BR SIZE=\"&{alert('XSS')}\">",
+ sanitized: "<html><head></head><body><br></body></html>",
+ },
+ {
+ data: '<LAYER SRC="http://ha.ckers.org/scriptlet.html"></LAYER>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<LINK REL="stylesheet" HREF="javascript:alert(\'XSS\');">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<STYLE>BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</STYLE>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<IMG SRC='vbscript:msgbox(\"XSS\")'>",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<IMG SRC="mocha:[code]">',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<IMG SRC="livescript:[code]">',
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: '<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert(\'XSS\');">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<META HTTP-EQUIV="Link" Content="<javascript:alert(\'XSS\')>; REL=stylesheet">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(\'XSS\');">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<IFRAME SRC=\"javascript:alert('XSS');\"></IFRAME>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<FRAMESET><FRAME SRC=\"javascript:alert('XSS');\"></FRAMESET>",
+ sanitized: "<html><head></head></html>",
+ },
+ {
+ data: "<TABLE BACKGROUND=\"javascript:alert('XSS')\">",
+ sanitized: "<html><head></head><body><table></table></body></html>",
+ },
+ {
+ data: "<DIV STYLE=\"background-image: url(javascript:alert('XSS'))\">",
+ sanitized: "<html><head></head><body><div></div></body></html>",
+ },
+ {
+ data: "<DIV STYLE=\"background-image: url(&#1;javascript:alert('XSS'))\">",
+ sanitized: "<html><head></head><body><div></div></body></html>",
+ },
+ {
+ data: "<DIV STYLE=\"width: expression(alert('XSS'));\">",
+ sanitized: "<html><head></head><body><div></div></body></html>",
+ },
+ {
+ data: "<STYLE>@im\\port'\\ja\\vasc\\ript:alert(\"XSS\")';</STYLE>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<IMG STYLE=\"xss:expr/*XSS*/ession(alert('XSS'))\">",
+ sanitized: "<html><head></head><body><img></body></html>",
+ },
+ {
+ data: "<XSS STYLE=\"xss:expression(alert('XSS'))\">",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: 'exp/*<XSS STYLE=\'no\\xss:noxss("*//*");',
+ sanitized: "<html><head></head><body>exp/*</body></html>",
+ },
+ {
+ data: "<STYLE TYPE=\"text/javascript\">alert('XSS');</STYLE>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<STYLE>.XSS{background-image:url(\"javascript:alert('XSS')\");}</STYLE><A CLASS=XSS></A>",
+ sanitized: '<html><head></head><body><a class="XSS"></a></body></html>',
+ },
+ {
+ data: '<STYLE type="text/css">BODY{background:url("javascript:alert(\'XSS\')")}</STYLE>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<BASE HREF=\"javascript:alert('XSS');//\">",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert('XSS')></OBJECT>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "getURL(\"javascript:alert('XSS')\")",
+ sanitized:
+ "<html><head></head><body>getURL(\"javascript:alert('XSS')\")</body></html>",
+ },
+ {
+ data: 'a="get";',
+ sanitized: '<html><head></head><body>a="get";</body></html>',
+ },
+ {
+ data: "<!--<value><![CDATA[<XML ID=I><X><C><![CDATA[<IMG SRC=\"javas<![CDATA[cript:alert('XSS');\">",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<XML SRC="http://ha.ckers.org/xsstest.xml" ID=I></XML>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<HTML><BODY>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<SCRIPT SRC="http://ha.ckers.org/xss.jpg"></SCRIPT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<!--#exec cmd=\"/bin/echo '<SCRIPT SRC'\"--><!--#exec cmd=\"/bin/echo '=http://ha.ckers.org/xss.js></SCRIPT>'\"-->",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<? echo('<SCR)';",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<META HTTP-EQUIV="Set-Cookie" Content="USERID=&lt;SCRIPT&gt;alert(\'XSS\')&lt;/SCRIPT&gt;">',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<HEAD><META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-7"> </HEAD>+ADw-SCRIPT+AD4-alert(\'XSS\');+ADw-/SCRIPT+AD4-',
+ sanitized:
+ "<html><head> </head><body>+ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4-</body></html>",
+ },
+ {
+ data: '<SCRIPT a=">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<SCRIPT a=">" \'\' SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<SCRIPT "a=\'>\'" SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<SCRIPT a=`>` SRC="http://ha.ckers.org/xss.js"></SCRIPT>',
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: '<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC',
+ sanitized: "<html><head></head><body>PT SRC</body></html>",
+ },
+ {
+ data: "",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<dialog>allowed</dialog>",
+ sanitized:
+ "<html><head></head><body><dialog>allowed</dialog></body></html>",
+ },
+ {
+ data: "<main>allowed</main>",
+ sanitized: "<html><head></head><body><main>allowed</main></body></html>",
+ },
+ {
+ data: "<picture>allowed</picture>",
+ sanitized:
+ "<html><head></head><body><picture>allowed</picture></body></html>",
+ },
+ {
+ data: "<template>allowed</template>",
+ sanitized:
+ "<html><head><template>allowed</template></head><body></body></html>",
+ },
+ {
+ // traverse into HTML template elements
+ data: '<template><img src="x" onerror="alert(1)"></template>',
+ sanitized:
+ "<html><head><template><img></template></head><body></body></html>",
+ },
+ {
+ // do not traverse into SVG template elements (that's not a thing)
+ data: "<svg><template></template></svg>",
+ sanitized: "<html><head></head><body></body></html>",
+ },
+ {
+ data: "<svg><use href='http://example.com/test.svg'></svg>",
+ flags: 1, // ParserUtils.SanitizerAllowStyle
+ sanitized: "<html><head></head><body><svg><use></use></svg></body></html>",
+ },
+ {
+ // fragments that reference the same document are allowed.
+ data: "<svg><use href='#x'></svg>",
+ flags: 1, // ParserUtils.SanitizerAllowStyle
+ sanitized:
+ '<html><head></head><body><svg><use href="#x"></use></svg></body></html>',
+ },
+ {
+ data: '<svg><use xlink:href="http://example/#baz"/></svg>',
+ flags: 1, // ParserUtils.SanitizerAllowStyl,
+ sanitized: "<html><head></head><body><svg><use></use></svg></body></html>",
+ },
+];
diff --git a/parser/xml/test/unit/test_sanitizer.js b/parser/xml/test/unit/test_sanitizer.js
new file mode 100644
index 0000000000..814940578d
--- /dev/null
+++ b/parser/xml/test/unit/test_sanitizer.js
@@ -0,0 +1,53 @@
+const { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+if (AppConstants.platform != "android") {
+ // We load HTML documents, which try to track link state, which requires
+ // the history service, which requires a profile.
+ do_get_profile();
+}
+
+function run_test() {
+ // vectors by the html5security project (https://code.google.com/p/html5security/ & Creative Commons 3.0 BY), see CC-BY-LICENSE for the full license
+ load("results.js"); // gives us a `vectors' array
+ /* import-globals-from ./results.js */
+
+ if (AppConstants.platform != "android") {
+ // xpcshell tests are weird. They fake shutdown after the test finishes. This upsets this test
+ // because it will try to create the history service to check for visited state on the links
+ // we're parsing.
+ // Creating the history service midway through shutdown breaks.
+ // We can't catch this in the history component because we're not *actually* shutting down,
+ // and so the app startup's service's `shuttingDown` bool is false, even though normally that
+ // is set to true *before* profile-change-teardown notifications are fired.
+ // To work around this, just force the history service to be created earlier:
+
+ let { PlacesUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PlacesUtils.sys.mjs"
+ );
+ Assert.ok(
+ PlacesUtils.history.databaseStatus <= 1,
+ "ensure places database is successfully initialized."
+ );
+ }
+
+ var ParserUtils = Cc["@mozilla.org/parserutils;1"].getService(
+ Ci.nsIParserUtils
+ );
+ var sanitizeFlags =
+ ParserUtils.SanitizerCidEmbedsOnly |
+ ParserUtils.SanitizerDropForms |
+ ParserUtils.SanitizerDropNonCSSPresentation;
+ // flags according to
+ // http://mxr.mozilla.org/comm-central/source/mailnews/mime/src/mimemoz2.cpp#2218
+ // and default settings
+
+ for (var item in vectors) {
+ let { data, sanitized, flags } = vectors[item];
+ if (!flags) {
+ flags = sanitizeFlags;
+ }
+ var out = ParserUtils.sanitize(data, flags);
+ Assert.equal(sanitized, out);
+ }
+}
diff --git a/parser/xml/test/unit/test_sanitizer_style.js b/parser/xml/test/unit/test_sanitizer_style.js
new file mode 100644
index 0000000000..6f00295cda
--- /dev/null
+++ b/parser/xml/test/unit/test_sanitizer_style.js
@@ -0,0 +1,125 @@
+const { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+
+if (AppConstants.platform != "android") {
+ // We load HTML documents, which try to track link state, which requires
+ // the history service, which requires a profile.
+ do_get_profile();
+}
+
+const kTestCases = [
+ {
+ // bug 1602843
+ data: `@font-face { font-family: 'ab<\\/style><img src onerror=alert(1)>'}`,
+ sanitized: `@font-face { font-family: 'ab<\\/style><img src onerror=alert(1)>'}`,
+ },
+ {
+ // bug 1680084
+ data: `<!--
+/* Font Definitions */
+@font-face
+ {font-family:"Cambria Math";
+ panose-1:2 4 5 3 5 4 6 3 2 4;}
+@font-face
+ {font-family:"Yu Gothic";
+ panose-1:2 11 4 0 0 0 0 0 0 0;}
+@font-face
+ {font-family:"Yu Gothic";
+ panose-1:2 11 4 0 0 0 0 0 0 0;}
+/* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {margin:0mm;
+ text-align:justify;
+ text-justify:inter-ideograph;
+ font-size:10.5pt;
+ font-family:"Yu Gothic";}
+span.17
+ {mso-style-type:personal-compose;
+ font-family:"Yu Gothic";
+ color:windowtext;}
+.MsoChpDefault
+ {mso-style-type:export-only;
+ font-family:"Yu Gothic";}
+/* Page Definitions */
+@page WordSection1
+ {size:612.0pt 792.0pt;
+ margin:99.25pt 30.0mm 30.0mm 30.0mm;}
+div.WordSection1
+ {page:WordSection1}
+-->`,
+ sanitized: `@font-face
+ {font-family:"Cambria Math";
+ panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
+ {font-family:"Yu Gothic";
+ panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
+ {font-family:"Yu Gothic";
+ panose-1:2 11 4 0 0 0 0 0 0 0;}p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {margin:0mm;
+ text-align:justify;
+ text-justify:inter-ideograph;
+ font-size:10.5pt;
+ font-family:"Yu Gothic";}.MsoChpDefault
+ {mso-style-type:export-only;
+ font-family:"Yu Gothic";}div.WordSection1
+ {page:WordSection1}`,
+ },
+];
+
+const kConditionalCSSTestCases = [
+ {
+ data: `#foo { display: none } @media (min-width: 300px) { #bar { display: none } }`,
+ sanitized: `#foo { display: none }`,
+ },
+ {
+ data: `@media (min-width: 300px) { #bar { display: none } }`,
+ sanitized: ``,
+ },
+];
+
+function run_test() {
+ if (AppConstants.platform != "android") {
+ // xpcshell tests are weird. They fake shutdown after the test finishes. This upsets this test
+ // because it will try to create the history service to check for visited state on the links
+ // we're parsing.
+ // Creating the history service midway through shutdown breaks.
+ // We can't catch this in the history component because we're not *actually* shutting down,
+ // and so the app startup's service's `shuttingDown` bool is false, even though normally that
+ // is set to true *before* profile-change-teardown notifications are fired.
+ // To work around this, just force the history service to be created earlier:
+
+ let { PlacesUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PlacesUtils.sys.mjs"
+ );
+ Assert.ok(
+ PlacesUtils.history.databaseStatus <= 1,
+ "ensure places database is successfully initialized."
+ );
+ }
+
+ var ParserUtils = Cc["@mozilla.org/parserutils;1"].getService(
+ Ci.nsIParserUtils
+ );
+ var sanitizeFlags =
+ ParserUtils.SanitizerDropForms |
+ ParserUtils.SanitizerDropNonCSSPresentation |
+ ParserUtils.SanitizerAllowStyle;
+
+ for (let { data, sanitized } of kTestCases) {
+ let out = ParserUtils.sanitize(`<style>${data}</style>`, sanitizeFlags);
+ info(out);
+ Assert.equal(
+ `<html><head><style>${sanitized}</style></head><body></body></html>`,
+ out
+ );
+ }
+
+ for (let { data, sanitized } of kConditionalCSSTestCases) {
+ let out = ParserUtils.removeConditionalCSS(`<style>${data}</style>`);
+ info(out);
+ Assert.equal(
+ `<html><head><style>${sanitized}</style></head><body></body></html>`,
+ out
+ );
+ }
+}
diff --git a/parser/xml/test/unit/xpcshell.ini b/parser/xml/test/unit/xpcshell.ini
new file mode 100644
index 0000000000..4ae9918864
--- /dev/null
+++ b/parser/xml/test/unit/xpcshell.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+head =
+support-files = results.js
+
+[test_sanitizer.js]
+[test_sanitizer_style.js]