Modernize and tighten up HTMLDocumentParser
[WebKit-https.git] / Source / WebCore / html / parser / HTMLTreeBuilder.cpp
1 /*
2  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3  * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GOOGLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "HTMLTreeBuilder.h"
29
30 #include "DocumentFragment.h"
31 #include "HTMLDocument.h"
32 #include "HTMLDocumentParser.h"
33 #include "HTMLFormControlElement.h"
34 #include "HTMLFormElement.h"
35 #include "HTMLOptGroupElement.h"
36 #include "HTMLParserIdioms.h"
37 #include "LocalizedStrings.h"
38 #include "NotImplemented.h"
39 #include "XLinkNames.h"
40 #include "XMLNSNames.h"
41 #include "XMLNames.h"
42 #include <wtf/NeverDestroyed.h>
43 #include <wtf/unicode/CharacterNames.h>
44
45 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
46 #include "TelephoneNumberDetector.h"
47 #endif
48
49 namespace WebCore {
50
51 using namespace HTMLNames;
52
53 namespace {
54
55 inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
56 {
57     return isHTMLSpace(character) || character == replacementCharacter;
58 }
59
60 }
61
62 static inline TextPosition uninitializedPositionValue1()
63 {
64     return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber::first());
65 }
66
67 static inline bool isAllWhitespace(const String& string)
68 {
69     return string.isAllSpecialCharacters<isHTMLSpace>();
70 }
71
72 static inline bool isAllWhitespaceOrReplacementCharacters(const String& string)
73 {
74     return string.isAllSpecialCharacters<isHTMLSpaceOrReplacementCharacter>();
75 }
76
77 static bool isNumberedHeaderTag(const AtomicString& tagName)
78 {
79     return tagName == h1Tag
80         || tagName == h2Tag
81         || tagName == h3Tag
82         || tagName == h4Tag
83         || tagName == h5Tag
84         || tagName == h6Tag;
85 }
86
87 static bool isCaptionColOrColgroupTag(const AtomicString& tagName)
88 {
89     return tagName == captionTag || tagName == colTag || tagName == colgroupTag;
90 }
91
92 static bool isTableCellContextTag(const AtomicString& tagName)
93 {
94     return tagName == thTag || tagName == tdTag;
95 }
96
97 static bool isTableBodyContextTag(const AtomicString& tagName)
98 {
99     return tagName == tbodyTag || tagName == tfootTag || tagName == theadTag;
100 }
101
102 static bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
103 {
104     return tagName == bTag
105         || tagName == bigTag
106         || tagName == codeTag
107         || tagName == emTag
108         || tagName == fontTag
109         || tagName == iTag
110         || tagName == sTag
111         || tagName == smallTag
112         || tagName == strikeTag
113         || tagName == strongTag
114         || tagName == ttTag
115         || tagName == uTag;
116 }
117
118 static bool isNonAnchorFormattingTag(const AtomicString& tagName)
119 {
120     return tagName == nobrTag || isNonAnchorNonNobrFormattingTag(tagName);
121 }
122
123 // https://html.spec.whatwg.org/multipage/syntax.html#formatting
124 static bool isFormattingTag(const AtomicString& tagName)
125 {
126     return tagName == aTag || isNonAnchorFormattingTag(tagName);
127 }
128
129 class HTMLTreeBuilder::ExternalCharacterTokenBuffer {
130 public:
131     explicit ExternalCharacterTokenBuffer(AtomicHTMLToken& token)
132         : m_text(token.characters(), token.charactersLength())
133         , m_isAll8BitData(token.isAll8BitData())
134     {
135         ASSERT(!isEmpty());
136     }
137
138     explicit ExternalCharacterTokenBuffer(const String& string)
139         : m_text(string)
140         , m_isAll8BitData(m_text.is8Bit())
141     {
142         ASSERT(!isEmpty());
143     }
144
145     ~ExternalCharacterTokenBuffer()
146     {
147         ASSERT(isEmpty());
148     }
149
150     bool isEmpty() const { return m_text.isEmpty(); }
151
152     bool isAll8BitData() const { return m_isAll8BitData; }
153
154     void skipAtMostOneLeadingNewline()
155     {
156         ASSERT(!isEmpty());
157         if (m_text[0] == '\n')
158             m_text = m_text.substring(1);
159     }
160
161     void skipLeadingWhitespace()
162     {
163         skipLeading<isHTMLSpace>();
164     }
165
166     String takeLeadingWhitespace()
167     {
168         return takeLeading<isHTMLSpace>();
169     }
170
171     void skipLeadingNonWhitespace()
172     {
173         skipLeading<isNotHTMLSpace>();
174     }
175
176     String takeRemaining()
177     {
178         String result = makeString(m_text);
179         m_text = StringView();
180         return result;
181     }
182
183     void giveRemainingTo(StringBuilder& recipient)
184     {
185         recipient.append(m_text);
186         m_text = StringView();
187     }
188
189     String takeRemainingWhitespace()
190     {
191         ASSERT(!isEmpty());
192         Vector<LChar, 8> whitespace;
193         do {
194             UChar character = m_text[0];
195             if (isHTMLSpace(character))
196                 whitespace.append(character);
197             m_text = m_text.substring(1);
198         } while (!m_text.isEmpty());
199
200         // Returning the null string when there aren't any whitespace
201         // characters is slightly cleaner semantically because we don't want
202         // to insert a text node (as opposed to inserting an empty text node).
203         if (whitespace.isEmpty())
204             return String();
205
206         return String::adopt(whitespace);
207     }
208
209 private:
210     template<bool characterPredicate(UChar)> void skipLeading()
211     {
212         ASSERT(!isEmpty());
213         while (characterPredicate(m_text[0])) {
214             m_text = m_text.substring(1);
215             if (m_text.isEmpty())
216                 return;
217         }
218     }
219
220     template<bool characterPredicate(UChar)> String takeLeading()
221     {
222         ASSERT(!isEmpty());
223         StringView start = m_text;
224         skipLeading<characterPredicate>();
225         if (start.length() == m_text.length())
226             return String();
227         return makeString(start.substring(0, start.length() - m_text.length()));
228     }
229
230     String makeString(StringView stringView) const
231     {
232         if (stringView.is8Bit() || !isAll8BitData())
233             return stringView.toString();
234         return String::make8BitFrom16BitSource(stringView.characters16(), stringView.length());
235     }
236
237     StringView m_text;
238     bool m_isAll8BitData;
239 };
240
241 inline bool HTMLTreeBuilder::isParsingTemplateContents() const
242 {
243 #if ENABLE(TEMPLATE_ELEMENT)
244     return m_tree.openElements()->hasTemplateInHTMLScope();
245 #else
246     return false;
247 #endif
248 }
249
250 inline bool HTMLTreeBuilder::isParsingFragmentOrTemplateContents() const
251 {
252     return isParsingFragment() || isParsingTemplateContents();
253 }
254
255 HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, HTMLDocument& document, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
256     : m_parser(parser)
257     , m_options(options)
258     , m_tree(document, parserContentPolicy, options.maximumDOMTreeDepth)
259     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
260 {
261 #if !ASSERT_DISABLED
262     m_destructionProhibited = false;
263 #endif
264 }
265
266 HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, DocumentFragment& fragment, Element& contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
267     : m_parser(parser)
268     , m_options(options)
269     , m_fragmentContext(fragment, contextElement)
270     , m_tree(fragment, parserContentPolicy, options.maximumDOMTreeDepth)
271     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
272 {
273     ASSERT(isMainThread());
274
275     // https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments
276     // For efficiency, we skip step 5 ("Let root be a new html element with no attributes") and instead use the DocumentFragment as a root node.
277     m_tree.openElements()->pushRootNode(HTMLStackItem::create(&fragment, HTMLStackItem::ItemForDocumentFragmentNode));
278
279 #if ENABLE(TEMPLATE_ELEMENT)
280     if (contextElement.hasTagName(templateTag))
281         m_templateInsertionModes.append(InsertionMode::TemplateContents);
282 #endif
283
284     resetInsertionModeAppropriately();
285
286     m_tree.setForm(is<HTMLFormElement>(contextElement) ? &downcast<HTMLFormElement>(contextElement) : HTMLFormElement::findClosestFormAncestor(contextElement));
287
288 #if !ASSERT_DISABLED
289     m_destructionProhibited = false;
290 #endif
291 }
292
293 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
294 {
295 }
296
297 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element& contextElement)
298     : m_fragment(&fragment)
299 {
300     ASSERT(!fragment.hasChildNodes());
301     m_contextElementStackItem = HTMLStackItem::create(&contextElement, HTMLStackItem::ItemForContextElement);
302 }
303
304 inline Element& HTMLTreeBuilder::FragmentParsingContext::contextElement() const
305 {
306     return *contextElementStackItem().element();
307 }
308
309 inline HTMLStackItem& HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem() const
310 {
311     ASSERT(m_fragment);
312     return *m_contextElementStackItem;
313 }
314
315 RefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
316 {
317     ASSERT(!m_destroyed);
318
319     if (!m_scriptToProcess)
320         return nullptr;
321
322     // Unpause ourselves, callers may pause us again when processing the script.
323     // The HTML5 spec is written as though scripts are executed inside the tree builder.
324     // We pause the parser to exit the tree builder, and then resume before running scripts.
325     scriptStartPosition = m_scriptToProcessStartPosition;
326     m_scriptToProcessStartPosition = uninitializedPositionValue1();
327     return WTF::move(m_scriptToProcess);
328 }
329
330 void HTMLTreeBuilder::constructTree(AtomicHTMLToken& token)
331 {
332 #if !ASSERT_DISABLED
333     ASSERT(!m_destroyed);
334     ASSERT(!m_destructionProhibited);
335     m_destructionProhibited = true;
336 #endif
337
338     if (shouldProcessTokenInForeignContent(token))
339         processTokenInForeignContent(token);
340     else
341         processToken(token);
342
343     bool inForeignContent = !m_tree.isEmpty()
344         && !adjustedCurrentStackItem().isInHTMLNamespace()
345         && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
346         && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
347
348     m_parser.tokenizer().setForceNullCharacterReplacement(m_insertionMode == InsertionMode::Text || inForeignContent);
349     m_parser.tokenizer().setShouldAllowCDATA(inForeignContent);
350
351 #if !ASSERT_DISABLED
352     m_destructionProhibited = false;
353 #endif
354
355     m_tree.executeQueuedTasks();
356     // The tree builder might have been destroyed as an indirect result of executing the queued tasks.
357 }
358
359 void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
360 {
361     switch (token.type()) {
362     case HTMLToken::Uninitialized:
363         ASSERT_NOT_REACHED();
364         break;
365     case HTMLToken::DOCTYPE:
366         m_shouldSkipLeadingNewline = false;
367         processDoctypeToken(token);
368         break;
369     case HTMLToken::StartTag:
370         m_shouldSkipLeadingNewline = false;
371         processStartTag(token);
372         break;
373     case HTMLToken::EndTag:
374         m_shouldSkipLeadingNewline = false;
375         processEndTag(token);
376         break;
377     case HTMLToken::Comment:
378         m_shouldSkipLeadingNewline = false;
379         processComment(token);
380         return;
381     case HTMLToken::Character:
382         processCharacter(token);
383         break;
384     case HTMLToken::EndOfFile:
385         m_shouldSkipLeadingNewline = false;
386         processEndOfFile(token);
387         break;
388     }
389 }
390
391 void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token)
392 {
393     ASSERT(token.type() == HTMLToken::DOCTYPE);
394     if (m_insertionMode == InsertionMode::Initial) {
395         m_tree.insertDoctype(&token);
396         m_insertionMode = InsertionMode::BeforeHTML;
397         return;
398     }
399     if (m_insertionMode == InsertionMode::InTableText) {
400         defaultForInTableText();
401         processDoctypeToken(token);
402         return;
403     }
404     parseError(token);
405 }
406
407 void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, Vector<Attribute>&& attributes)
408 {
409     // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
410     AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), WTF::move(attributes));
411     processStartTag(fakeToken);
412 }
413
414 void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName)
415 {
416     AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName);
417     processEndTag(fakeToken);
418 }
419
420 void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
421 {
422     // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
423     processFakeEndTag(tagName.localName());
424 }
425
426 void HTMLTreeBuilder::processFakeCharacters(const String& characters)
427 {
428     ASSERT(!characters.isEmpty());
429     ExternalCharacterTokenBuffer buffer(characters);
430     processCharacterBuffer(buffer);
431 }
432
433 void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
434 {
435     if (!m_tree.openElements()->inButtonScope(pTag.localName()))
436         return;
437     AtomicHTMLToken endP(HTMLToken::EndTag, pTag.localName());
438     processEndTag(endP);
439 }
440
441 Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token)
442 {
443     Vector<Attribute> attributes = token.attributes();
444     for (int i = attributes.size() - 1; i >= 0; --i) {
445         const QualifiedName& name = attributes.at(i).name();
446         if (name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr))
447             attributes.remove(i);
448     }
449
450     attributes.append(Attribute(nameAttr, isindexTag.localName()));
451     return attributes;
452 }
453
454 void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken& token)
455 {
456     ASSERT(token.type() == HTMLToken::StartTag);
457     ASSERT(token.name() == isindexTag);
458     parseError(token);
459     if (m_tree.form() && !isParsingTemplateContents())
460         return;
461     notImplemented(); // Acknowledge self-closing flag
462     processFakeStartTag(formTag);
463     Attribute* actionAttribute = token.getAttributeItem(actionAttr);
464     if (actionAttribute)
465         m_tree.form()->setAttribute(actionAttr, actionAttribute->value());
466     processFakeStartTag(hrTag);
467     processFakeStartTag(labelTag);
468     Attribute* promptAttribute = token.getAttributeItem(promptAttr);
469     if (promptAttribute)
470         processFakeCharacters(promptAttribute->value());
471     else
472         processFakeCharacters(searchableIndexIntroduction());
473     processFakeStartTag(inputTag, attributesForIsindexInput(token));
474     notImplemented(); // This second set of characters may be needed by non-english locales.
475     processFakeEndTag(labelTag);
476     processFakeStartTag(hrTag);
477     processFakeEndTag(formTag);
478 }
479
480 namespace {
481
482 bool isLi(const HTMLStackItem& item)
483 {
484     return item.hasTagName(liTag);
485 }
486
487 bool isDdOrDt(const HTMLStackItem& item)
488 {
489     return item.hasTagName(ddTag) || item.hasTagName(dtTag);
490 }
491
492 }
493
494 template <bool shouldClose(const HTMLStackItem&)> void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken& token)
495 {
496     m_framesetOk = false;
497     for (auto* nodeRecord = m_tree.openElements()->topRecord(); ; nodeRecord = nodeRecord->next()) {
498         HTMLStackItem& item = *nodeRecord->stackItem();
499         if (shouldClose(item)) {
500             ASSERT(item.isElementNode());
501             processFakeEndTag(item.localName());
502             break;
503         }
504         if (item.isSpecialNode() && !item.hasTagName(addressTag) && !item.hasTagName(divTag) && !item.hasTagName(pTag))
505             break;
506     }
507     processFakePEndTagIfPInButtonScope();
508     m_tree.insertHTMLElement(&token);
509 }
510
511 template <typename TableQualifiedName> static HashMap<AtomicString, QualifiedName> createCaseMap(const TableQualifiedName* const names[], unsigned length)
512 {
513     HashMap<AtomicString, QualifiedName> map;
514     for (unsigned i = 0; i < length; ++i) {
515         const QualifiedName& name = *names[i];
516         const AtomicString& localName = name.localName();
517         AtomicString loweredLocalName = localName.lower();
518         if (loweredLocalName != localName)
519             map.add(loweredLocalName, name);
520     }
521     return map;
522 }
523
524 static void adjustSVGTagNameCase(AtomicHTMLToken& token)
525 {
526     static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(SVGNames::getSVGTags(), SVGNames::SVGTagsCount);
527     const QualifiedName& casedName = map.get().get(token.name());
528     if (casedName.localName().isNull())
529         return;
530     token.setName(casedName.localName());
531 }
532
533 static inline void adjustAttributes(HashMap<AtomicString, QualifiedName>& map, AtomicHTMLToken& token)
534 {
535     for (auto& attribute : token.attributes()) {
536         const QualifiedName& casedName = map.get(attribute.localName());
537         if (!casedName.localName().isNull())
538             attribute.parserSetName(casedName);
539     }
540 }
541
542 template<const QualifiedName* const* attributesTable(), unsigned attributesTableLength> static void adjustAttributes(AtomicHTMLToken& token)
543 {
544     static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(attributesTable(), attributesTableLength);
545     adjustAttributes(map, token);
546 }
547
548 static inline void adjustSVGAttributes(AtomicHTMLToken& token)
549 {
550     adjustAttributes<SVGNames::getSVGAttrs, SVGNames::SVGAttrsCount>(token);
551 }
552
553 static inline void adjustMathMLAttributes(AtomicHTMLToken& token)
554 {
555     adjustAttributes<MathMLNames::getMathMLAttrs, MathMLNames::MathMLAttrsCount>(token);
556 }
557
558 static void addNamesWithPrefix(HashMap<AtomicString, QualifiedName>& map, const AtomicString& prefix, const QualifiedName* const names[], unsigned length)
559 {
560     for (unsigned i = 0; i < length; ++i) {
561         const QualifiedName& name = *names[i];
562         const AtomicString& localName = name.localName();
563         map.add(prefix + ':' + localName, QualifiedName(prefix, localName, name.namespaceURI()));
564     }
565 }
566
567 static HashMap<AtomicString, QualifiedName> createForeignAttributesMap()
568 {
569     HashMap<AtomicString, QualifiedName> map;
570
571     addNamesWithPrefix(map, xlinkAtom, XLinkNames::getXLinkAttrs(), XLinkNames::XLinkAttrsCount);
572     addNamesWithPrefix(map, xmlAtom, XMLNames::getXMLAttrs(), XMLNames::XMLAttrsCount);
573
574     map.add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
575     map.add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom, XMLNSNames::xmlnsNamespaceURI));
576
577     return map;
578 }
579
580 static void adjustForeignAttributes(AtomicHTMLToken& token)
581 {
582     static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createForeignAttributesMap();
583     adjustAttributes(map, token);
584 }
585
586 void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
587 {
588     ASSERT(token.type() == HTMLToken::StartTag);
589     if (token.name() == htmlTag) {
590         processHtmlStartTagForInBody(token);
591         return;
592     }
593     if (token.name() == baseTag
594         || token.name() == basefontTag
595         || token.name() == bgsoundTag
596         || token.name() == commandTag
597         || token.name() == linkTag
598         || token.name() == metaTag
599         || token.name() == noframesTag
600         || token.name() == scriptTag
601         || token.name() == styleTag
602         || token.name() == titleTag) {
603         bool didProcess = processStartTagForInHead(token);
604         ASSERT_UNUSED(didProcess, didProcess);
605         return;
606     }
607     if (token.name() == bodyTag) {
608         parseError(token);
609         bool fragmentOrTemplateCase = !m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement();
610 #if ENABLE(TEMPLATE_ELEMENT)
611         fragmentOrTemplateCase = fragmentOrTemplateCase || m_tree.openElements()->hasTemplateInHTMLScope();
612 #endif
613         if (fragmentOrTemplateCase) {
614             ASSERT(isParsingFragmentOrTemplateContents());
615             return;
616         }
617         m_framesetOk = false;
618         m_tree.insertHTMLBodyStartTagInBody(&token);
619         return;
620     }
621     if (token.name() == framesetTag) {
622         parseError(token);
623         if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
624             ASSERT(isParsingFragmentOrTemplateContents());
625             return;
626         }
627         if (!m_framesetOk)
628             return;
629         m_tree.openElements()->bodyElement()->remove(ASSERT_NO_EXCEPTION);
630         m_tree.openElements()->popUntil(m_tree.openElements()->bodyElement());
631         m_tree.openElements()->popHTMLBodyElement();
632         ASSERT(m_tree.openElements()->top() == m_tree.openElements()->htmlElement());
633         m_tree.insertHTMLElement(&token);
634         m_insertionMode = InsertionMode::InFrameset;
635         return;
636     }
637     if (token.name() == addressTag
638         || token.name() == articleTag
639         || token.name() == asideTag
640         || token.name() == blockquoteTag
641         || token.name() == centerTag
642         || token.name() == detailsTag
643         || token.name() == dirTag
644         || token.name() == divTag
645         || token.name() == dlTag
646         || token.name() == fieldsetTag
647         || token.name() == figcaptionTag
648         || token.name() == figureTag
649         || token.name() == footerTag
650         || token.name() == headerTag
651         || token.name() == hgroupTag
652         || token.name() == mainTag
653         || token.name() == menuTag
654         || token.name() == navTag
655         || token.name() == olTag
656         || token.name() == pTag
657         || token.name() == sectionTag
658         || token.name() == summaryTag
659         || token.name() == ulTag) {
660         processFakePEndTagIfPInButtonScope();
661         m_tree.insertHTMLElement(&token);
662         return;
663     }
664     if (isNumberedHeaderTag(token.name())) {
665         processFakePEndTagIfPInButtonScope();
666         if (m_tree.currentStackItem()->isNumberedHeaderElement()) {
667             parseError(token);
668             m_tree.openElements()->pop();
669         }
670         m_tree.insertHTMLElement(&token);
671         return;
672     }
673     if (token.name() == preTag || token.name() == listingTag) {
674         processFakePEndTagIfPInButtonScope();
675         m_tree.insertHTMLElement(&token);
676         m_shouldSkipLeadingNewline = true;
677         m_framesetOk = false;
678         return;
679     }
680     if (token.name() == formTag) {
681         if (m_tree.form() && !isParsingTemplateContents()) {
682             parseError(token);
683             return;
684         }
685         processFakePEndTagIfPInButtonScope();
686         m_tree.insertHTMLFormElement(&token);
687         return;
688     }
689     if (token.name() == liTag) {
690         processCloseWhenNestedTag<isLi>(token);
691         return;
692     }
693     if (token.name() == ddTag || token.name() == dtTag) {
694         processCloseWhenNestedTag<isDdOrDt>(token);
695         return;
696     }
697     if (token.name() == plaintextTag) {
698         processFakePEndTagIfPInButtonScope();
699         m_tree.insertHTMLElement(&token);
700         m_parser.tokenizer().setState(HTMLTokenizer::PLAINTEXTState);
701         return;
702     }
703     if (token.name() == buttonTag) {
704         if (m_tree.openElements()->inScope(buttonTag)) {
705             parseError(token);
706             processFakeEndTag(buttonTag);
707             processStartTag(token); // FIXME: Could we just fall through here?
708             return;
709         }
710         m_tree.reconstructTheActiveFormattingElements();
711         m_tree.insertHTMLElement(&token);
712         m_framesetOk = false;
713         return;
714     }
715     if (token.name() == aTag) {
716         Element* activeATag = m_tree.activeFormattingElements()->closestElementInScopeWithName(aTag.localName());
717         if (activeATag) {
718             parseError(token);
719             processFakeEndTag(aTag);
720             m_tree.activeFormattingElements()->remove(activeATag);
721             if (m_tree.openElements()->contains(activeATag))
722                 m_tree.openElements()->remove(activeATag);
723         }
724         m_tree.reconstructTheActiveFormattingElements();
725         m_tree.insertFormattingElement(&token);
726         return;
727     }
728     if (isNonAnchorNonNobrFormattingTag(token.name())) {
729         m_tree.reconstructTheActiveFormattingElements();
730         m_tree.insertFormattingElement(&token);
731         return;
732     }
733     if (token.name() == nobrTag) {
734         m_tree.reconstructTheActiveFormattingElements();
735         if (m_tree.openElements()->inScope(nobrTag)) {
736             parseError(token);
737             processFakeEndTag(nobrTag);
738             m_tree.reconstructTheActiveFormattingElements();
739         }
740         m_tree.insertFormattingElement(&token);
741         return;
742     }
743     if (token.name() == appletTag || token.name() == embedTag || token.name() == objectTag) {
744         if (!pluginContentIsAllowed(m_tree.parserContentPolicy()))
745             return;
746     }
747     if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
748         m_tree.reconstructTheActiveFormattingElements();
749         m_tree.insertHTMLElement(&token);
750         m_tree.activeFormattingElements()->appendMarker();
751         m_framesetOk = false;
752         return;
753     }
754     if (token.name() == tableTag) {
755         if (!m_tree.inQuirksMode() && m_tree.openElements()->inButtonScope(pTag))
756             processFakeEndTag(pTag);
757         m_tree.insertHTMLElement(&token);
758         m_framesetOk = false;
759         m_insertionMode = InsertionMode::InTable;
760         return;
761     }
762     if (token.name() == imageTag) {
763         parseError(token);
764         // Apparently we're not supposed to ask.
765         token.setName(imgTag.localName());
766         // Note the fall through to the imgTag handling below!
767     }
768     if (token.name() == areaTag
769         || token.name() == brTag
770         || token.name() == embedTag
771         || token.name() == imgTag
772         || token.name() == keygenTag
773         || token.name() == wbrTag) {
774         m_tree.reconstructTheActiveFormattingElements();
775         m_tree.insertSelfClosingHTMLElement(&token);
776         m_framesetOk = false;
777         return;
778     }
779     if (token.name() == inputTag) {
780         Attribute* typeAttribute = token.getAttributeItem(typeAttr);
781         m_tree.reconstructTheActiveFormattingElements();
782         m_tree.insertSelfClosingHTMLElement(&token);
783         if (!typeAttribute || !equalIgnoringCase(typeAttribute->value(), "hidden"))
784             m_framesetOk = false;
785         return;
786     }
787     if (token.name() == paramTag
788         || token.name() == sourceTag
789         || token.name() == trackTag) {
790         m_tree.insertSelfClosingHTMLElement(&token);
791         return;
792     }
793     if (token.name() == hrTag) {
794         processFakePEndTagIfPInButtonScope();
795         m_tree.insertSelfClosingHTMLElement(&token);
796         m_framesetOk = false;
797         return;
798     }
799     if (token.name() == isindexTag) {
800         processIsindexStartTagForInBody(token);
801         return;
802     }
803     if (token.name() == textareaTag) {
804         m_tree.insertHTMLElement(&token);
805         m_shouldSkipLeadingNewline = true;
806         m_parser.tokenizer().setState(HTMLTokenizer::RCDATAState);
807         m_originalInsertionMode = m_insertionMode;
808         m_framesetOk = false;
809         m_insertionMode = InsertionMode::Text;
810         return;
811     }
812     if (token.name() == xmpTag) {
813         processFakePEndTagIfPInButtonScope();
814         m_tree.reconstructTheActiveFormattingElements();
815         m_framesetOk = false;
816         processGenericRawTextStartTag(token);
817         return;
818     }
819     if (token.name() == iframeTag) {
820         m_framesetOk = false;
821         processGenericRawTextStartTag(token);
822         return;
823     }
824     if (token.name() == noembedTag && m_options.pluginsEnabled) {
825         processGenericRawTextStartTag(token);
826         return;
827     }
828     if (token.name() == noscriptTag && m_options.scriptEnabled) {
829         processGenericRawTextStartTag(token);
830         return;
831     }
832     if (token.name() == selectTag) {
833         m_tree.reconstructTheActiveFormattingElements();
834         m_tree.insertHTMLElement(&token);
835         m_framesetOk = false;
836         if (m_insertionMode == InsertionMode::InTable
837             || m_insertionMode == InsertionMode::InCaption
838             || m_insertionMode == InsertionMode::InColumnGroup
839             || m_insertionMode == InsertionMode::InTableBody
840             || m_insertionMode == InsertionMode::InRow
841             || m_insertionMode == InsertionMode::InCell)
842             m_insertionMode = InsertionMode::InSelectInTable;
843         else
844             m_insertionMode = InsertionMode::InSelect;
845         return;
846     }
847     if (token.name() == optgroupTag || token.name() == optionTag) {
848         if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
849             AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
850             processEndTag(endOption);
851         }
852         m_tree.reconstructTheActiveFormattingElements();
853         m_tree.insertHTMLElement(&token);
854         return;
855     }
856     if (token.name() == rbTag || token.name() == rtcTag) {
857         if (m_tree.openElements()->inScope(rubyTag.localName())) {
858             m_tree.generateImpliedEndTags();
859             if (!m_tree.currentStackItem()->hasTagName(rubyTag))
860                 parseError(token);
861         }
862         m_tree.insertHTMLElement(&token);
863         return;
864     }
865     if (token.name() == rtTag || token.name() == rpTag) {
866         if (m_tree.openElements()->inScope(rubyTag.localName())) {
867             m_tree.generateImpliedEndTagsWithExclusion(rtcTag.localName());
868             if (!m_tree.currentStackItem()->hasTagName(rubyTag) && !m_tree.currentStackItem()->hasTagName(rtcTag))
869                 parseError(token);
870         }
871         m_tree.insertHTMLElement(&token);
872         return;
873     }
874     if (token.name() == MathMLNames::mathTag.localName()) {
875         m_tree.reconstructTheActiveFormattingElements();
876         adjustMathMLAttributes(token);
877         adjustForeignAttributes(token);
878         m_tree.insertForeignElement(&token, MathMLNames::mathmlNamespaceURI);
879         return;
880     }
881     if (token.name() == SVGNames::svgTag.localName()) {
882         m_tree.reconstructTheActiveFormattingElements();
883         adjustSVGAttributes(token);
884         adjustForeignAttributes(token);
885         m_tree.insertForeignElement(&token, SVGNames::svgNamespaceURI);
886         return;
887     }
888     if (isCaptionColOrColgroupTag(token.name())
889         || token.name() == frameTag
890         || token.name() == headTag
891         || isTableBodyContextTag(token.name())
892         || isTableCellContextTag(token.name())
893         || token.name() == trTag) {
894         parseError(token);
895         return;
896     }
897 #if ENABLE(TEMPLATE_ELEMENT)
898     if (token.name() == templateTag) {
899         processTemplateStartTag(token);
900         return;
901     }
902 #endif
903     m_tree.reconstructTheActiveFormattingElements();
904     m_tree.insertHTMLElement(&token);
905 }
906
907 #if ENABLE(TEMPLATE_ELEMENT)
908
909 void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken& token)
910 {
911     m_tree.activeFormattingElements()->appendMarker();
912     m_tree.insertHTMLElement(&token);
913     m_templateInsertionModes.append(InsertionMode::TemplateContents);
914     m_insertionMode = InsertionMode::TemplateContents;
915 }
916
917 bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken& token)
918 {
919     ASSERT(token.name() == templateTag.localName());
920     if (!m_tree.openElements()->hasTemplateInHTMLScope()) {
921         ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement().hasTagName(templateTag)));
922         parseError(token);
923         return false;
924     }
925     m_tree.generateImpliedEndTags();
926     if (!m_tree.currentStackItem()->hasTagName(templateTag))
927         parseError(token);
928     m_tree.openElements()->popUntilPopped(templateTag);
929     m_tree.activeFormattingElements()->clearToLastMarker();
930     m_templateInsertionModes.removeLast();
931     resetInsertionModeAppropriately();
932     return true;
933 }
934
935 bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken& token)
936 {
937     AtomicHTMLToken endTemplate(HTMLToken::EndTag, templateTag.localName());
938     if (!processTemplateEndTag(endTemplate))
939         return false;
940
941     processEndOfFile(token);
942     return true;
943 }
944
945 #endif
946
947 bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
948 {
949     bool ignoreFakeEndTag = m_tree.currentIsRootNode();
950 #if ENABLE(TEMPLATE_ELEMENT)
951     ignoreFakeEndTag = ignoreFakeEndTag || m_tree.currentNode()->hasTagName(templateTag);
952 #endif
953
954     if (ignoreFakeEndTag) {
955         ASSERT(isParsingFragmentOrTemplateContents());
956         // FIXME: parse error
957         return false;
958     }
959     m_tree.openElements()->pop();
960     m_insertionMode = InsertionMode::InTable;
961     return true;
962 }
963
964 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
965 void HTMLTreeBuilder::closeTheCell()
966 {
967     ASSERT(m_insertionMode == InsertionMode::InCell);
968     if (m_tree.openElements()->inTableScope(tdTag)) {
969         ASSERT(!m_tree.openElements()->inTableScope(thTag));
970         processFakeEndTag(tdTag);
971         return;
972     }
973     ASSERT(m_tree.openElements()->inTableScope(thTag));
974     processFakeEndTag(thTag);
975     ASSERT(m_insertionMode == InsertionMode::InRow);
976 }
977
978 void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken& token)
979 {
980     ASSERT(token.type() == HTMLToken::StartTag);
981     if (token.name() == captionTag) {
982         m_tree.openElements()->popUntilTableScopeMarker();
983         m_tree.activeFormattingElements()->appendMarker();
984         m_tree.insertHTMLElement(&token);
985         m_insertionMode = InsertionMode::InCaption;
986         return;
987     }
988     if (token.name() == colgroupTag) {
989         m_tree.openElements()->popUntilTableScopeMarker();
990         m_tree.insertHTMLElement(&token);
991         m_insertionMode = InsertionMode::InColumnGroup;
992         return;
993     }
994     if (token.name() == colTag) {
995         processFakeStartTag(colgroupTag);
996         ASSERT(m_insertionMode == InsertionMode::InColumnGroup);
997         processStartTag(token);
998         return;
999     }
1000     if (isTableBodyContextTag(token.name())) {
1001         m_tree.openElements()->popUntilTableScopeMarker();
1002         m_tree.insertHTMLElement(&token);
1003         m_insertionMode = InsertionMode::InTableBody;
1004         return;
1005     }
1006     if (isTableCellContextTag(token.name()) || token.name() == trTag) {
1007         processFakeStartTag(tbodyTag);
1008         ASSERT(m_insertionMode == InsertionMode::InTableBody);
1009         processStartTag(token);
1010         return;
1011     }
1012     if (token.name() == tableTag) {
1013         parseError(token);
1014         if (!processTableEndTagForInTable()) {
1015             ASSERT(isParsingFragmentOrTemplateContents());
1016             return;
1017         }
1018         processStartTag(token);
1019         return;
1020     }
1021     if (token.name() == styleTag || token.name() == scriptTag) {
1022         processStartTagForInHead(token);
1023         return;
1024     }
1025     if (token.name() == inputTag) {
1026         Attribute* typeAttribute = token.getAttributeItem(typeAttr);
1027         if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
1028             parseError(token);
1029             m_tree.insertSelfClosingHTMLElement(&token);
1030             return;
1031         }
1032         // Fall through to "anything else" case.
1033     }
1034     if (token.name() == formTag) {
1035         parseError(token);
1036         if (m_tree.form() && !isParsingTemplateContents())
1037             return;
1038         m_tree.insertHTMLFormElement(&token, true);
1039         m_tree.openElements()->pop();
1040         return;
1041     }
1042 #if ENABLE(TEMPLATE_ELEMENT)
1043     if (token.name() == templateTag) {
1044         processTemplateStartTag(token);
1045         return;
1046     }
1047 #endif
1048     parseError(token);
1049     HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
1050     processStartTagForInBody(token);
1051 }
1052
1053 void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
1054 {
1055     ASSERT(token.type() == HTMLToken::StartTag);
1056     switch (m_insertionMode) {
1057     case InsertionMode::Initial:
1058         defaultForInitial();
1059         ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
1060         FALLTHROUGH;
1061     case InsertionMode::BeforeHTML:
1062         if (token.name() == htmlTag) {
1063             m_tree.insertHTMLHtmlStartTagBeforeHTML(&token);
1064             m_insertionMode = InsertionMode::BeforeHead;
1065             return;
1066         }
1067         defaultForBeforeHTML();
1068         ASSERT(m_insertionMode == InsertionMode::BeforeHead);
1069         FALLTHROUGH;
1070     case InsertionMode::BeforeHead:
1071         if (token.name() == htmlTag) {
1072             processHtmlStartTagForInBody(token);
1073             return;
1074         }
1075         if (token.name() == headTag) {
1076             m_tree.insertHTMLHeadElement(&token);
1077             m_insertionMode = InsertionMode::InHead;
1078             return;
1079         }
1080         defaultForBeforeHead();
1081         ASSERT(m_insertionMode == InsertionMode::InHead);
1082         FALLTHROUGH;
1083     case InsertionMode::InHead:
1084         if (processStartTagForInHead(token))
1085             return;
1086         defaultForInHead();
1087         ASSERT(m_insertionMode == InsertionMode::AfterHead);
1088         FALLTHROUGH;
1089     case InsertionMode::AfterHead:
1090         if (token.name() == htmlTag) {
1091             processHtmlStartTagForInBody(token);
1092             return;
1093         }
1094         if (token.name() == bodyTag) {
1095             m_framesetOk = false;
1096             m_tree.insertHTMLBodyElement(&token);
1097             m_insertionMode = InsertionMode::InBody;
1098             return;
1099         }
1100         if (token.name() == framesetTag) {
1101             m_tree.insertHTMLElement(&token);
1102             m_insertionMode = InsertionMode::InFrameset;
1103             return;
1104         }
1105         if (token.name() == baseTag
1106             || token.name() == basefontTag
1107             || token.name() == bgsoundTag
1108             || token.name() == linkTag
1109             || token.name() == metaTag
1110             || token.name() == noframesTag
1111             || token.name() == scriptTag
1112             || token.name() == styleTag
1113 #if ENABLE(TEMPLATE_ELEMENT)
1114             || token.name() == templateTag
1115 #endif
1116             || token.name() == titleTag) {
1117             parseError(token);
1118             ASSERT(m_tree.head());
1119             m_tree.openElements()->pushHTMLHeadElement(m_tree.headStackItem());
1120             processStartTagForInHead(token);
1121             m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
1122             return;
1123         }
1124         if (token.name() == headTag) {
1125             parseError(token);
1126             return;
1127         }
1128         defaultForAfterHead();
1129         ASSERT(m_insertionMode == InsertionMode::InBody);
1130         FALLTHROUGH;
1131     case InsertionMode::InBody:
1132         processStartTagForInBody(token);
1133         break;
1134     case InsertionMode::InTable:
1135         processStartTagForInTable(token);
1136         break;
1137     case InsertionMode::InCaption:
1138         if (isCaptionColOrColgroupTag(token.name())
1139             || isTableBodyContextTag(token.name())
1140             || isTableCellContextTag(token.name())
1141             || token.name() == trTag) {
1142             parseError(token);
1143             if (!processCaptionEndTagForInCaption()) {
1144                 ASSERT(isParsingFragment());
1145                 return;
1146             }
1147             processStartTag(token);
1148             return;
1149         }
1150         processStartTagForInBody(token);
1151         break;
1152     case InsertionMode::InColumnGroup:
1153         if (token.name() == htmlTag) {
1154             processHtmlStartTagForInBody(token);
1155             return;
1156         }
1157         if (token.name() == colTag) {
1158             m_tree.insertSelfClosingHTMLElement(&token);
1159             return;
1160         }
1161 #if ENABLE(TEMPLATE_ELEMENT)
1162         if (token.name() == templateTag) {
1163             processTemplateStartTag(token);
1164             return;
1165         }
1166 #endif
1167         if (!processColgroupEndTagForInColumnGroup()) {
1168             ASSERT(isParsingFragmentOrTemplateContents());
1169             return;
1170         }
1171         processStartTag(token);
1172         break;
1173     case InsertionMode::InTableBody:
1174         if (token.name() == trTag) {
1175             m_tree.openElements()->popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
1176             m_tree.insertHTMLElement(&token);
1177             m_insertionMode = InsertionMode::InRow;
1178             return;
1179         }
1180         if (isTableCellContextTag(token.name())) {
1181             parseError(token);
1182             processFakeStartTag(trTag);
1183             ASSERT(m_insertionMode == InsertionMode::InRow);
1184             processStartTag(token);
1185             return;
1186         }
1187         if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name())) {
1188             // FIXME: This is slow.
1189             if (!m_tree.openElements()->inTableScope(tbodyTag) && !m_tree.openElements()->inTableScope(theadTag) && !m_tree.openElements()->inTableScope(tfootTag)) {
1190                 ASSERT(isParsingFragmentOrTemplateContents());
1191                 parseError(token);
1192                 return;
1193             }
1194             m_tree.openElements()->popUntilTableBodyScopeMarker();
1195             ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
1196             processFakeEndTag(m_tree.currentStackItem()->localName());
1197             processStartTag(token);
1198             return;
1199         }
1200         processStartTagForInTable(token);
1201         break;
1202     case InsertionMode::InRow:
1203         if (isTableCellContextTag(token.name())) {
1204             m_tree.openElements()->popUntilTableRowScopeMarker();
1205             m_tree.insertHTMLElement(&token);
1206             m_insertionMode = InsertionMode::InCell;
1207             m_tree.activeFormattingElements()->appendMarker();
1208             return;
1209         }
1210         if (token.name() == trTag
1211             || isCaptionColOrColgroupTag(token.name())
1212             || isTableBodyContextTag(token.name())) {
1213             if (!processTrEndTagForInRow()) {
1214                 ASSERT(isParsingFragmentOrTemplateContents());
1215                 return;
1216             }
1217             ASSERT(m_insertionMode == InsertionMode::InTableBody);
1218             processStartTag(token);
1219             return;
1220         }
1221         processStartTagForInTable(token);
1222         break;
1223     case InsertionMode::InCell:
1224         if (isCaptionColOrColgroupTag(token.name())
1225             || isTableCellContextTag(token.name())
1226             || token.name() == trTag
1227             || isTableBodyContextTag(token.name())) {
1228             // FIXME: This could be more efficient.
1229             if (!m_tree.openElements()->inTableScope(tdTag) && !m_tree.openElements()->inTableScope(thTag)) {
1230                 ASSERT(isParsingFragment());
1231                 parseError(token);
1232                 return;
1233             }
1234             closeTheCell();
1235             processStartTag(token);
1236             return;
1237         }
1238         processStartTagForInBody(token);
1239         break;
1240     case InsertionMode::AfterBody:
1241     case InsertionMode::AfterAfterBody:
1242         if (token.name() == htmlTag) {
1243             processHtmlStartTagForInBody(token);
1244             return;
1245         }
1246         m_insertionMode = InsertionMode::InBody;
1247         processStartTag(token);
1248         break;
1249     case InsertionMode::InHeadNoscript:
1250         if (token.name() == htmlTag) {
1251             processHtmlStartTagForInBody(token);
1252             return;
1253         }
1254         if (token.name() == basefontTag
1255             || token.name() == bgsoundTag
1256             || token.name() == linkTag
1257             || token.name() == metaTag
1258             || token.name() == noframesTag
1259             || token.name() == styleTag) {
1260             bool didProcess = processStartTagForInHead(token);
1261             ASSERT_UNUSED(didProcess, didProcess);
1262             return;
1263         }
1264         if (token.name() == htmlTag || token.name() == noscriptTag) {
1265             parseError(token);
1266             return;
1267         }
1268         defaultForInHeadNoscript();
1269         processToken(token);
1270         break;
1271     case InsertionMode::InFrameset:
1272         if (token.name() == htmlTag) {
1273             processHtmlStartTagForInBody(token);
1274             return;
1275         }
1276         if (token.name() == framesetTag) {
1277             m_tree.insertHTMLElement(&token);
1278             return;
1279         }
1280         if (token.name() == frameTag) {
1281             m_tree.insertSelfClosingHTMLElement(&token);
1282             return;
1283         }
1284         if (token.name() == noframesTag) {
1285             processStartTagForInHead(token);
1286             return;
1287         }
1288 #if ENABLE(TEMPLATE_ELEMENT)
1289         if (token.name() == templateTag) {
1290             processTemplateStartTag(token);
1291             return;
1292         }
1293 #endif
1294         parseError(token);
1295         break;
1296     case InsertionMode::AfterFrameset:
1297     case InsertionMode::AfterAfterFrameset:
1298         if (token.name() == htmlTag) {
1299             processHtmlStartTagForInBody(token);
1300             return;
1301         }
1302         if (token.name() == noframesTag) {
1303             processStartTagForInHead(token);
1304             return;
1305         }
1306         parseError(token);
1307         break;
1308     case InsertionMode::InSelectInTable:
1309         if (token.name() == captionTag
1310             || token.name() == tableTag
1311             || isTableBodyContextTag(token.name())
1312             || token.name() == trTag
1313             || isTableCellContextTag(token.name())) {
1314             parseError(token);
1315             AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
1316             processEndTag(endSelect);
1317             processStartTag(token);
1318             return;
1319         }
1320         FALLTHROUGH;
1321     case InsertionMode::InSelect:
1322         if (token.name() == htmlTag) {
1323             processHtmlStartTagForInBody(token);
1324             return;
1325         }
1326         if (token.name() == optionTag) {
1327             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
1328                 AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
1329                 processEndTag(endOption);
1330             }
1331             m_tree.insertHTMLElement(&token);
1332             return;
1333         }
1334         if (token.name() == optgroupTag) {
1335             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
1336                 AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
1337                 processEndTag(endOption);
1338             }
1339             if (is<HTMLOptGroupElement>(*m_tree.currentStackItem()->node())) {
1340                 AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName());
1341                 processEndTag(endOptgroup);
1342             }
1343             m_tree.insertHTMLElement(&token);
1344             return;
1345         }
1346         if (token.name() == selectTag) {
1347             parseError(token);
1348             AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
1349             processEndTag(endSelect);
1350             return;
1351         }
1352         if (token.name() == inputTag || token.name() == keygenTag || token.name() == textareaTag) {
1353             parseError(token);
1354             if (!m_tree.openElements()->inSelectScope(selectTag)) {
1355                 ASSERT(isParsingFragment());
1356                 return;
1357             }
1358             AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
1359             processEndTag(endSelect);
1360             processStartTag(token);
1361             return;
1362         }
1363         if (token.name() == scriptTag) {
1364             bool didProcess = processStartTagForInHead(token);
1365             ASSERT_UNUSED(didProcess, didProcess);
1366             return;
1367         }
1368 #if ENABLE(TEMPLATE_ELEMENT)
1369         if (token.name() == templateTag) {
1370             processTemplateStartTag(token);
1371             return;
1372         }
1373 #endif
1374         break;
1375     case InsertionMode::InTableText:
1376         defaultForInTableText();
1377         processStartTag(token);
1378         break;
1379     case InsertionMode::Text:
1380         ASSERT_NOT_REACHED();
1381         break;
1382 #if ENABLE(TEMPLATE_ELEMENT)
1383     case InsertionMode::TemplateContents:
1384         if (token.name() == templateTag) {
1385             processTemplateStartTag(token);
1386             return;
1387         }
1388
1389         if (token.name() == linkTag
1390             || token.name() == scriptTag
1391             || token.name() == styleTag
1392             || token.name() == metaTag) {
1393             processStartTagForInHead(token);
1394             return;
1395         }
1396
1397         InsertionMode insertionMode = InsertionMode::TemplateContents;
1398         if (token.name() == frameTag)
1399             insertionMode = InsertionMode::InFrameset;
1400         else if (token.name() == colTag)
1401             insertionMode = InsertionMode::InColumnGroup;
1402         else if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name()))
1403             insertionMode = InsertionMode::InTable;
1404         else if (token.name() == trTag)
1405             insertionMode = InsertionMode::InTableBody;
1406         else if (isTableCellContextTag(token.name()))
1407             insertionMode = InsertionMode::InRow;
1408         else
1409             insertionMode = InsertionMode::InBody;
1410
1411         ASSERT(insertionMode != InsertionMode::TemplateContents);
1412         ASSERT(m_templateInsertionModes.last() == InsertionMode::TemplateContents);
1413         m_templateInsertionModes.last() = insertionMode;
1414         m_insertionMode = insertionMode;
1415
1416         processStartTag(token);
1417         break;
1418 #endif
1419     }
1420 }
1421
1422 void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken& token)
1423 {
1424     parseError(token);
1425 #if ENABLE(TEMPLATE_ELEMENT)
1426     if (m_tree.openElements()->hasTemplateInHTMLScope()) {
1427         ASSERT(isParsingTemplateContents());
1428         return;
1429     }
1430 #endif
1431     m_tree.insertHTMLHtmlStartTagInBody(&token);
1432 }
1433
1434 bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken& token)
1435 {
1436     ASSERT(token.type() == HTMLToken::EndTag);
1437     ASSERT(token.name() == bodyTag);
1438     if (!m_tree.openElements()->inScope(bodyTag.localName())) {
1439         parseError(token);
1440         return false;
1441     }
1442     notImplemented(); // Emit a more specific parse error based on stack contents.
1443     m_insertionMode = InsertionMode::AfterBody;
1444     return true;
1445 }
1446
1447 void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken& token)
1448 {
1449     ASSERT(token.type() == HTMLToken::EndTag);
1450     for (auto* record = m_tree.openElements()->topRecord(); ; record = record->next()) {
1451         HTMLStackItem& item = *record->stackItem();
1452         if (item.matchesHTMLTag(token.name())) {
1453             m_tree.generateImpliedEndTagsWithExclusion(token.name());
1454             if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1455                 parseError(token);
1456             m_tree.openElements()->popUntilPopped(item.element());
1457             return;
1458         }
1459         if (item.isSpecialNode()) {
1460             parseError(token);
1461             return;
1462         }
1463     }
1464 }
1465
1466 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
1467 void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
1468 {
1469     // The adoption agency algorithm is N^2. We limit the number of iterations
1470     // to stop from hanging the whole browser. This limit is specified in the
1471     // adoption agency algorithm: 
1472     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inbody
1473     static const int outerIterationLimit = 8;
1474     static const int innerIterationLimit = 3;
1475
1476     // 1, 2, 3 and 16 are covered by the for() loop.
1477     for (int i = 0; i < outerIterationLimit; ++i) {
1478         // 4.
1479         Element* formattingElement = m_tree.activeFormattingElements()->closestElementInScopeWithName(token.name());
1480         // 4.a
1481         if (!formattingElement)
1482             return processAnyOtherEndTagForInBody(token);
1483         // 4.c
1484         if ((m_tree.openElements()->contains(formattingElement)) && !m_tree.openElements()->inScope(formattingElement)) {
1485             parseError(token);
1486             notImplemented(); // Check the stack of open elements for a more specific parse error.
1487             return;
1488         }
1489         // 4.b
1490         auto* formattingElementRecord = m_tree.openElements()->find(formattingElement);
1491         if (!formattingElementRecord) {
1492             parseError(token);
1493             m_tree.activeFormattingElements()->remove(formattingElement);
1494             return;
1495         }
1496         // 4.d
1497         if (formattingElement != m_tree.currentElement())
1498             parseError(token);
1499         // 5.
1500         auto* furthestBlock = m_tree.openElements()->furthestBlockForFormattingElement(formattingElement);
1501         // 6.
1502         if (!furthestBlock) {
1503             m_tree.openElements()->popUntilPopped(formattingElement);
1504             m_tree.activeFormattingElements()->remove(formattingElement);
1505             return;
1506         }
1507         // 7.
1508         ASSERT(furthestBlock->isAbove(formattingElementRecord));
1509         RefPtr<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
1510         // 8.
1511         HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
1512         // 9.
1513         auto* node = furthestBlock;
1514         auto* nextNode = node->next();
1515         auto* lastNode = furthestBlock;
1516         // 9.1, 9.2, 9.3 and 9.11 are covered by the for() loop.
1517         for (int i = 0; i < innerIterationLimit; ++i) {
1518             // 9.4
1519             node = nextNode;
1520             ASSERT(node);
1521             nextNode = node->next(); // Save node->next() for the next iteration in case node is deleted in 9.5.
1522             // 9.5
1523             if (!m_tree.activeFormattingElements()->contains(node->element())) {
1524                 m_tree.openElements()->remove(node->element());
1525                 node = 0;
1526                 continue;
1527             }
1528             // 9.6
1529             if (node == formattingElementRecord)
1530                 break;
1531             // 9.7
1532             RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(node->stackItem().get());
1533
1534             HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements()->find(node->element());
1535             nodeEntry->replaceElement(newItem);
1536             node->replaceElement(newItem.release());
1537
1538             // 9.8
1539             if (lastNode == furthestBlock)
1540                 bookmark.moveToAfter(nodeEntry);
1541             // 9.9
1542             m_tree.reparent(*node, *lastNode);
1543             // 9.10
1544             lastNode = node;
1545         }
1546         // 10.
1547         m_tree.insertAlreadyParsedChild(*commonAncestor, *lastNode);
1548         // 11.
1549         RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem().get());
1550         // 12.
1551         m_tree.takeAllChildren(*newItem, *furthestBlock);
1552         // 13.
1553         m_tree.reparent(*furthestBlock, *newItem);
1554         // 14.
1555         m_tree.activeFormattingElements()->swapTo(formattingElement, newItem, bookmark);
1556         // 15.
1557         m_tree.openElements()->remove(formattingElement);
1558         m_tree.openElements()->insertAbove(newItem, furthestBlock);
1559     }
1560 }
1561
1562 void HTMLTreeBuilder::resetInsertionModeAppropriately()
1563 {
1564     // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#reset-the-insertion-mode-appropriately
1565     bool last = false;
1566     for (auto* record = m_tree.openElements()->topRecord(); ; record = record->next()) {
1567         HTMLStackItem* item = record->stackItem().get();
1568         if (item->node() == m_tree.openElements()->rootNode()) {
1569             last = true;
1570 #if ENABLE(TEMPLATE_ELEMENT)
1571             bool shouldCreateItem = isParsingFragment();
1572 #else
1573             ASSERT(isParsingFragment());
1574             bool shouldCreateItem = true;
1575 #endif
1576             if (shouldCreateItem)
1577                 item = &m_fragmentContext.contextElementStackItem();
1578         }
1579
1580 #if ENABLE(TEMPLATE_ELEMENT)
1581         if (item->hasTagName(templateTag)) {
1582             m_insertionMode = m_templateInsertionModes.last();
1583             return;
1584         }
1585 #endif
1586         if (item->hasTagName(selectTag)) {
1587 #if ENABLE(TEMPLATE_ELEMENT)
1588             if (!last) {
1589                 while (item->node() != m_tree.openElements()->rootNode() && !item->hasTagName(templateTag)) {
1590                     record = record->next();
1591                     item = record->stackItem().get();
1592                     if (is<HTMLTableElement>(*item->node())) {
1593                         m_insertionMode = InsertionMode::InSelectInTable;
1594                         return;
1595                     }
1596                 }
1597             }
1598 #endif
1599             m_insertionMode = InsertionMode::InSelect;
1600             return;
1601         }
1602         if (item->hasTagName(tdTag) || item->hasTagName(thTag)) {
1603             m_insertionMode = InsertionMode::InCell;
1604             return;
1605         }
1606         if (item->hasTagName(trTag)) {
1607             m_insertionMode = InsertionMode::InRow;
1608             return;
1609         }
1610         if (item->hasTagName(tbodyTag) || item->hasTagName(theadTag) || item->hasTagName(tfootTag)) {
1611             m_insertionMode = InsertionMode::InTableBody;
1612             return;
1613         }
1614         if (item->hasTagName(captionTag)) {
1615             m_insertionMode = InsertionMode::InCaption;
1616             return;
1617         }
1618         if (item->hasTagName(colgroupTag)) {
1619             m_insertionMode = InsertionMode::InColumnGroup;
1620             return;
1621         }
1622         if (is<HTMLTableElement>(*item->node())) {
1623             m_insertionMode = InsertionMode::InTable;
1624             return;
1625         }
1626         if (item->hasTagName(headTag)) {
1627 #if ENABLE(TEMPLATE_ELEMENT)
1628             if (!m_fragmentContext.fragment() || &m_fragmentContext.contextElement() != item->node()) {
1629                 m_insertionMode = InsertionMode::InHead;
1630                 return;
1631             }
1632 #endif
1633             m_insertionMode = InsertionMode::InBody;
1634             return;
1635         }
1636         if (item->hasTagName(bodyTag)) {
1637             m_insertionMode = InsertionMode::InBody;
1638             return;
1639         }
1640         if (item->hasTagName(framesetTag)) {
1641             m_insertionMode = InsertionMode::InFrameset;
1642             return;
1643         }
1644         if (item->hasTagName(htmlTag)) {
1645             if (m_tree.headStackItem()) {
1646                 m_insertionMode = InsertionMode::AfterHead;
1647                 return;
1648             }
1649             ASSERT(isParsingFragment());
1650             m_insertionMode = InsertionMode::BeforeHead;
1651             return;
1652         }
1653         if (last) {
1654             ASSERT(isParsingFragment());
1655             m_insertionMode = InsertionMode::InBody;
1656             return;
1657         }
1658     }
1659 }
1660
1661 void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken& token)
1662 {
1663     ASSERT(token.type() == HTMLToken::EndTag);
1664     if (isTableBodyContextTag(token.name())) {
1665         if (!m_tree.openElements()->inTableScope(token.name())) {
1666             parseError(token);
1667             return;
1668         }
1669         m_tree.openElements()->popUntilTableBodyScopeMarker();
1670         m_tree.openElements()->pop();
1671         m_insertionMode = InsertionMode::InTable;
1672         return;
1673     }
1674     if (token.name() == tableTag) {
1675         // FIXME: This is slow.
1676         if (!m_tree.openElements()->inTableScope(tbodyTag) && !m_tree.openElements()->inTableScope(theadTag) && !m_tree.openElements()->inTableScope(tfootTag)) {
1677             ASSERT(isParsingFragmentOrTemplateContents());
1678             parseError(token);
1679             return;
1680         }
1681         m_tree.openElements()->popUntilTableBodyScopeMarker();
1682         ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
1683         processFakeEndTag(m_tree.currentStackItem()->localName());
1684         processEndTag(token);
1685         return;
1686     }
1687     if (token.name() == bodyTag
1688         || isCaptionColOrColgroupTag(token.name())
1689         || token.name() == htmlTag
1690         || isTableCellContextTag(token.name())
1691         || token.name() == trTag) {
1692         parseError(token);
1693         return;
1694     }
1695     processEndTagForInTable(token);
1696 }
1697
1698 void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken& token)
1699 {
1700     ASSERT(token.type() == HTMLToken::EndTag);
1701     if (token.name() == trTag) {
1702         processTrEndTagForInRow();
1703         return;
1704     }
1705     if (token.name() == tableTag) {
1706         if (!processTrEndTagForInRow()) {
1707             ASSERT(isParsingFragmentOrTemplateContents());
1708             return;
1709         }
1710         ASSERT(m_insertionMode == InsertionMode::InTableBody);
1711         processEndTag(token);
1712         return;
1713     }
1714     if (isTableBodyContextTag(token.name())) {
1715         if (!m_tree.openElements()->inTableScope(token.name())) {
1716             parseError(token);
1717             return;
1718         }
1719         processFakeEndTag(trTag);
1720         ASSERT(m_insertionMode == InsertionMode::InTableBody);
1721         processEndTag(token);
1722         return;
1723     }
1724     if (token.name() == bodyTag
1725         || isCaptionColOrColgroupTag(token.name())
1726         || token.name() == htmlTag
1727         || isTableCellContextTag(token.name())) {
1728         parseError(token);
1729         return;
1730     }
1731     processEndTagForInTable(token);
1732 }
1733
1734 void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
1735 {
1736     ASSERT(token.type() == HTMLToken::EndTag);
1737     if (isTableCellContextTag(token.name())) {
1738         if (!m_tree.openElements()->inTableScope(token.name())) {
1739             parseError(token);
1740             return;
1741         }
1742         m_tree.generateImpliedEndTags();
1743         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1744             parseError(token);
1745         m_tree.openElements()->popUntilPopped(token.name());
1746         m_tree.activeFormattingElements()->clearToLastMarker();
1747         m_insertionMode = InsertionMode::InRow;
1748         return;
1749     }
1750     if (token.name() == bodyTag
1751         || isCaptionColOrColgroupTag(token.name())
1752         || token.name() == htmlTag) {
1753         parseError(token);
1754         return;
1755     }
1756     if (token.name() == tableTag
1757         || token.name() == trTag
1758         || isTableBodyContextTag(token.name())) {
1759         if (!m_tree.openElements()->inTableScope(token.name())) {
1760 #if ENABLE(TEMPLATE_ELEMENT)
1761             ASSERT(isTableBodyContextTag(token.name()) || m_tree.openElements()->inTableScope(templateTag) || isParsingFragment());
1762 #else
1763             ASSERT(isTableBodyContextTag(token.name()) || isParsingFragment());
1764 #endif
1765             parseError(token);
1766             return;
1767         }
1768         closeTheCell();
1769         processEndTag(token);
1770         return;
1771     }
1772     processEndTagForInBody(token);
1773 }
1774
1775 void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken& token)
1776 {
1777     ASSERT(token.type() == HTMLToken::EndTag);
1778     if (token.name() == bodyTag) {
1779         processBodyEndTagForInBody(token);
1780         return;
1781     }
1782     if (token.name() == htmlTag) {
1783         AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag.localName());
1784         if (processBodyEndTagForInBody(endBody))
1785             processEndTag(token);
1786         return;
1787     }
1788     if (token.name() == addressTag
1789         || token.name() == articleTag
1790         || token.name() == asideTag
1791         || token.name() == blockquoteTag
1792         || token.name() == buttonTag
1793         || token.name() == centerTag
1794         || token.name() == detailsTag
1795         || token.name() == dirTag
1796         || token.name() == divTag
1797         || token.name() == dlTag
1798         || token.name() == fieldsetTag
1799         || token.name() == figcaptionTag
1800         || token.name() == figureTag
1801         || token.name() == footerTag
1802         || token.name() == headerTag
1803         || token.name() == hgroupTag
1804         || token.name() == listingTag
1805         || token.name() == mainTag
1806         || token.name() == menuTag
1807         || token.name() == navTag
1808         || token.name() == olTag
1809         || token.name() == preTag
1810         || token.name() == sectionTag
1811         || token.name() == summaryTag
1812         || token.name() == ulTag) {
1813         if (!m_tree.openElements()->inScope(token.name())) {
1814             parseError(token);
1815             return;
1816         }
1817         m_tree.generateImpliedEndTags();
1818         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1819             parseError(token);
1820         m_tree.openElements()->popUntilPopped(token.name());
1821         return;
1822     }
1823     if (token.name() == formTag) {
1824         if (!isParsingTemplateContents()) {
1825             RefPtr<Element> node = m_tree.takeForm();
1826             if (!node || !m_tree.openElements()->inScope(node.get())) {
1827                 parseError(token);
1828                 return;
1829             }
1830             m_tree.generateImpliedEndTags();
1831             if (m_tree.currentNode() != node.get())
1832                 parseError(token);
1833             m_tree.openElements()->remove(node.get());
1834         } else {
1835             if (!m_tree.openElements()->inScope(token.name())) {
1836                 parseError(token);
1837                 return;
1838             }
1839             m_tree.generateImpliedEndTags();
1840             if (!m_tree.currentNode()->hasTagName(formTag))
1841                 parseError(token);
1842             m_tree.openElements()->popUntilPopped(token.name());
1843         }
1844     }
1845     if (token.name() == pTag) {
1846         if (!m_tree.openElements()->inButtonScope(token.name())) {
1847             parseError(token);
1848             processFakeStartTag(pTag);
1849             ASSERT(m_tree.openElements()->inScope(token.name()));
1850             processEndTag(token);
1851             return;
1852         }
1853         m_tree.generateImpliedEndTagsWithExclusion(token.name());
1854         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1855             parseError(token);
1856         m_tree.openElements()->popUntilPopped(token.name());
1857         return;
1858     }
1859     if (token.name() == liTag) {
1860         if (!m_tree.openElements()->inListItemScope(token.name())) {
1861             parseError(token);
1862             return;
1863         }
1864         m_tree.generateImpliedEndTagsWithExclusion(token.name());
1865         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1866             parseError(token);
1867         m_tree.openElements()->popUntilPopped(token.name());
1868         return;
1869     }
1870     if (token.name() == ddTag || token.name() == dtTag) {
1871         if (!m_tree.openElements()->inScope(token.name())) {
1872             parseError(token);
1873             return;
1874         }
1875         m_tree.generateImpliedEndTagsWithExclusion(token.name());
1876         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1877             parseError(token);
1878         m_tree.openElements()->popUntilPopped(token.name());
1879         return;
1880     }
1881     if (isNumberedHeaderTag(token.name())) {
1882         if (!m_tree.openElements()->hasNumberedHeaderElementInScope()) {
1883             parseError(token);
1884             return;
1885         }
1886         m_tree.generateImpliedEndTags();
1887         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1888             parseError(token);
1889         m_tree.openElements()->popUntilNumberedHeaderElementPopped();
1890         return;
1891     }
1892     if (isFormattingTag(token.name())) {
1893         callTheAdoptionAgency(token);
1894         return;
1895     }
1896     if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
1897         if (!m_tree.openElements()->inScope(token.name())) {
1898             parseError(token);
1899             return;
1900         }
1901         m_tree.generateImpliedEndTags();
1902         if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
1903             parseError(token);
1904         m_tree.openElements()->popUntilPopped(token.name());
1905         m_tree.activeFormattingElements()->clearToLastMarker();
1906         return;
1907     }
1908     if (token.name() == brTag) {
1909         parseError(token);
1910         processFakeStartTag(brTag);
1911         return;
1912     }
1913 #if ENABLE(TEMPLATE_ELEMENT)
1914     if (token.name() == templateTag) {
1915         processTemplateEndTag(token);
1916         return;
1917     }
1918 #endif
1919     processAnyOtherEndTagForInBody(token);
1920 }
1921
1922 bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
1923 {
1924     if (!m_tree.openElements()->inTableScope(captionTag.localName())) {
1925         ASSERT(isParsingFragment());
1926         // FIXME: parse error
1927         return false;
1928     }
1929     m_tree.generateImpliedEndTags();
1930     // FIXME: parse error if (!m_tree.currentStackItem()->hasTagName(captionTag))
1931     m_tree.openElements()->popUntilPopped(captionTag.localName());
1932     m_tree.activeFormattingElements()->clearToLastMarker();
1933     m_insertionMode = InsertionMode::InTable;
1934     return true;
1935 }
1936
1937 bool HTMLTreeBuilder::processTrEndTagForInRow()
1938 {
1939     if (!m_tree.openElements()->inTableScope(trTag)) {
1940         ASSERT(isParsingFragmentOrTemplateContents());
1941         // FIXME: parse error
1942         return false;
1943     }
1944     m_tree.openElements()->popUntilTableRowScopeMarker();
1945     ASSERT(m_tree.currentStackItem()->hasTagName(trTag));
1946     m_tree.openElements()->pop();
1947     m_insertionMode = InsertionMode::InTableBody;
1948     return true;
1949 }
1950
1951 bool HTMLTreeBuilder::processTableEndTagForInTable()
1952 {
1953     if (!m_tree.openElements()->inTableScope(tableTag)) {
1954         ASSERT(isParsingFragmentOrTemplateContents());
1955         // FIXME: parse error.
1956         return false;
1957     }
1958     m_tree.openElements()->popUntilPopped(tableTag.localName());
1959     resetInsertionModeAppropriately();
1960     return true;
1961 }
1962
1963 void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken& token)
1964 {
1965     ASSERT(token.type() == HTMLToken::EndTag);
1966     if (token.name() == tableTag) {
1967         processTableEndTagForInTable();
1968         return;
1969     }
1970     if (token.name() == bodyTag
1971         || isCaptionColOrColgroupTag(token.name())
1972         || token.name() == htmlTag
1973         || isTableBodyContextTag(token.name())
1974         || isTableCellContextTag(token.name())
1975         || token.name() == trTag) {
1976         parseError(token);
1977         return;
1978     }
1979     parseError(token);
1980     // Is this redirection necessary here?
1981     HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
1982     processEndTagForInBody(token);
1983 }
1984
1985 void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
1986 {
1987     ASSERT(token.type() == HTMLToken::EndTag);
1988     switch (m_insertionMode) {
1989     case InsertionMode::Initial:
1990         defaultForInitial();
1991         ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
1992         FALLTHROUGH;
1993     case InsertionMode::BeforeHTML:
1994         if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
1995             parseError(token);
1996             return;
1997         }
1998         defaultForBeforeHTML();
1999         ASSERT(m_insertionMode == InsertionMode::BeforeHead);
2000         FALLTHROUGH;
2001     case InsertionMode::BeforeHead:
2002         if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
2003             parseError(token);
2004             return;
2005         }
2006         defaultForBeforeHead();
2007         ASSERT(m_insertionMode == InsertionMode::InHead);
2008         FALLTHROUGH;
2009     case InsertionMode::InHead:
2010         // FIXME: This case should be broken out into processEndTagForInHead,
2011         // because other end tag cases now refer to it ("process the token for using the rules of the "in head" insertion mode").
2012         // but because the logic falls through to InsertionMode::AfterHead, that gets a little messy.
2013 #if ENABLE(TEMPLATE_ELEMENT)
2014         if (token.name() == templateTag) {
2015             processTemplateEndTag(token);
2016             return;
2017         }
2018 #endif
2019         if (token.name() == headTag) {
2020             m_tree.openElements()->popHTMLHeadElement();
2021             m_insertionMode = InsertionMode::AfterHead;
2022             return;
2023         }
2024         if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
2025             parseError(token);
2026             return;
2027         }
2028         defaultForInHead();
2029         ASSERT(m_insertionMode == InsertionMode::AfterHead);
2030         FALLTHROUGH;
2031     case InsertionMode::AfterHead:
2032         if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
2033             parseError(token);
2034             return;
2035         }
2036         defaultForAfterHead();
2037         ASSERT(m_insertionMode == InsertionMode::InBody);
2038         FALLTHROUGH;
2039     case InsertionMode::InBody:
2040         processEndTagForInBody(token);
2041         break;
2042     case InsertionMode::InTable:
2043         processEndTagForInTable(token);
2044         break;
2045     case InsertionMode::InCaption:
2046         if (token.name() == captionTag) {
2047             processCaptionEndTagForInCaption();
2048             return;
2049         }
2050         if (token.name() == tableTag) {
2051             parseError(token);
2052             if (!processCaptionEndTagForInCaption()) {
2053                 ASSERT(isParsingFragment());
2054                 return;
2055             }
2056             processEndTag(token);
2057             return;
2058         }
2059         if (token.name() == bodyTag
2060             || token.name() == colTag
2061             || token.name() == colgroupTag
2062             || token.name() == htmlTag
2063             || isTableBodyContextTag(token.name())
2064             || isTableCellContextTag(token.name())
2065             || token.name() == trTag) {
2066             parseError(token);
2067             return;
2068         }
2069         processEndTagForInBody(token);
2070         break;
2071     case InsertionMode::InColumnGroup:
2072         if (token.name() == colgroupTag) {
2073             processColgroupEndTagForInColumnGroup();
2074             return;
2075         }
2076         if (token.name() == colTag) {
2077             parseError(token);
2078             return;
2079         }
2080 #if ENABLE(TEMPLATE_ELEMENT)
2081         if (token.name() == templateTag) {
2082             processTemplateEndTag(token);
2083             return;
2084         }
2085 #endif
2086         if (!processColgroupEndTagForInColumnGroup()) {
2087             ASSERT(isParsingFragmentOrTemplateContents());
2088             return;
2089         }
2090         processEndTag(token);
2091         break;
2092     case InsertionMode::InRow:
2093         processEndTagForInRow(token);
2094         break;
2095     case InsertionMode::InCell:
2096         processEndTagForInCell(token);
2097         break;
2098     case InsertionMode::InTableBody:
2099         processEndTagForInTableBody(token);
2100         break;
2101     case InsertionMode::AfterBody:
2102         if (token.name() == htmlTag) {
2103             if (isParsingFragment()) {
2104                 parseError(token);
2105                 return;
2106             }
2107             m_insertionMode = InsertionMode::AfterAfterBody;
2108             return;
2109         }
2110         FALLTHROUGH;
2111     case InsertionMode::AfterAfterBody:
2112         ASSERT(m_insertionMode == InsertionMode::AfterBody || m_insertionMode == InsertionMode::AfterAfterBody);
2113         parseError(token);
2114         m_insertionMode = InsertionMode::InBody;
2115         processEndTag(token);
2116         break;
2117     case InsertionMode::InHeadNoscript:
2118         if (token.name() == noscriptTag) {
2119             ASSERT(m_tree.currentStackItem()->hasTagName(noscriptTag));
2120             m_tree.openElements()->pop();
2121             ASSERT(m_tree.currentStackItem()->hasTagName(headTag));
2122             m_insertionMode = InsertionMode::InHead;
2123             return;
2124         }
2125         if (token.name() != brTag) {
2126             parseError(token);
2127             return;
2128         }
2129         defaultForInHeadNoscript();
2130         processToken(token);
2131         break;
2132     case InsertionMode::Text:
2133         if (token.name() == scriptTag) {
2134             // Pause ourselves so that parsing stops until the script can be processed by the caller.
2135             ASSERT(m_tree.currentStackItem()->hasTagName(scriptTag));
2136             if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
2137                 m_scriptToProcess = m_tree.currentElement();
2138             m_tree.openElements()->pop();
2139             m_insertionMode = m_originalInsertionMode;
2140
2141             // This token will not have been created by the tokenizer if a
2142             // self-closing script tag was encountered and pre-HTML5 parser
2143             // quirks are enabled. We must set the tokenizer's state to
2144             // DataState explicitly if the tokenizer didn't have a chance to.
2145             ASSERT(m_parser.tokenizer().state() == HTMLTokenizer::DataState || m_options.usePreHTML5ParserQuirks);
2146             m_parser.tokenizer().setState(HTMLTokenizer::DataState);
2147             return;
2148         }
2149         m_tree.openElements()->pop();
2150         m_insertionMode = m_originalInsertionMode;
2151         break;
2152     case InsertionMode::InFrameset:
2153         if (token.name() == framesetTag) {
2154             bool ignoreFramesetForFragmentParsing  = m_tree.currentIsRootNode();
2155 #if ENABLE(TEMPLATE_ELEMENT)
2156             ignoreFramesetForFragmentParsing = ignoreFramesetForFragmentParsing || m_tree.openElements()->hasTemplateInHTMLScope();
2157 #endif
2158             if (ignoreFramesetForFragmentParsing) {
2159                 ASSERT(isParsingFragmentOrTemplateContents());
2160                 parseError(token);
2161                 return;
2162             }
2163             m_tree.openElements()->pop();
2164             if (!isParsingFragment() && !m_tree.currentStackItem()->hasTagName(framesetTag))
2165                 m_insertionMode = InsertionMode::AfterFrameset;
2166             return;
2167         }
2168 #if ENABLE(TEMPLATE_ELEMENT)
2169         if (token.name() == templateTag) {
2170             processTemplateEndTag(token);
2171             return;
2172         }
2173 #endif
2174         break;
2175     case InsertionMode::AfterFrameset:
2176         if (token.name() == htmlTag) {
2177             m_insertionMode = InsertionMode::AfterAfterFrameset;
2178             return;
2179         }
2180         FALLTHROUGH;
2181     case InsertionMode::AfterAfterFrameset:
2182         ASSERT(m_insertionMode == InsertionMode::AfterFrameset || m_insertionMode == InsertionMode::AfterAfterFrameset);
2183         parseError(token);
2184         break;
2185     case InsertionMode::InSelectInTable:
2186         if (token.name() == captionTag
2187             || token.name() == tableTag
2188             || isTableBodyContextTag(token.name())
2189             || token.name() == trTag
2190             || isTableCellContextTag(token.name())) {
2191             parseError(token);
2192             if (m_tree.openElements()->inTableScope(token.name())) {
2193                 AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
2194                 processEndTag(endSelect);
2195                 processEndTag(token);
2196             }
2197             return;
2198         }
2199         FALLTHROUGH;
2200     case InsertionMode::InSelect:
2201         ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable);
2202         if (token.name() == optgroupTag) {
2203             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node()) && m_tree.oneBelowTop() && is<HTMLOptGroupElement>(*m_tree.oneBelowTop()->node()))
2204                 processFakeEndTag(optionTag);
2205             if (is<HTMLOptGroupElement>(*m_tree.currentStackItem()->node())) {
2206                 m_tree.openElements()->pop();
2207                 return;
2208             }
2209             parseError(token);
2210             return;
2211         }
2212         if (token.name() == optionTag) {
2213             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
2214                 m_tree.openElements()->pop();
2215                 return;
2216             }
2217             parseError(token);
2218             return;
2219         }
2220         if (token.name() == selectTag) {
2221             if (!m_tree.openElements()->inSelectScope(token.name())) {
2222                 ASSERT(isParsingFragment());
2223                 parseError(token);
2224                 return;
2225             }
2226             m_tree.openElements()->popUntilPopped(selectTag.localName());
2227             resetInsertionModeAppropriately();
2228             return;
2229         }
2230 #if ENABLE(TEMPLATE_ELEMENT)
2231         if (token.name() == templateTag) {
2232             processTemplateEndTag(token);
2233             return;
2234         }
2235 #endif
2236         break;
2237     case InsertionMode::InTableText:
2238         defaultForInTableText();
2239         processEndTag(token);
2240         break;
2241 #if ENABLE(TEMPLATE_ELEMENT)
2242     case InsertionMode::TemplateContents:
2243         if (token.name() == templateTag) {
2244             processTemplateEndTag(token);
2245             return;
2246         }
2247         break;
2248 #endif
2249     }
2250 }
2251
2252 void HTMLTreeBuilder::processComment(AtomicHTMLToken& token)
2253 {
2254     ASSERT(token.type() == HTMLToken::Comment);
2255     if (m_insertionMode == InsertionMode::Initial
2256         || m_insertionMode == InsertionMode::BeforeHTML
2257         || m_insertionMode == InsertionMode::AfterAfterBody
2258         || m_insertionMode == InsertionMode::AfterAfterFrameset) {
2259         m_tree.insertCommentOnDocument(&token);
2260         return;
2261     }
2262     if (m_insertionMode == InsertionMode::AfterBody) {
2263         m_tree.insertCommentOnHTMLHtmlElement(&token);
2264         return;
2265     }
2266     if (m_insertionMode == InsertionMode::InTableText) {
2267         defaultForInTableText();
2268         processComment(token);
2269         return;
2270     }
2271     m_tree.insertComment(&token);
2272 }
2273
2274 void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
2275 {
2276     ASSERT(token.type() == HTMLToken::Character);
2277     ExternalCharacterTokenBuffer buffer(token);
2278     processCharacterBuffer(buffer);
2279 }
2280
2281 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
2282
2283 // FIXME: Extract the following iOS-specific code into a separate file.
2284 // From the string 4089961010, creates a link of the form <a href="tel:4089961010">4089961010</a> and inserts it.
2285 void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
2286 {
2287     Vector<Attribute> attributes;
2288     attributes.append(Attribute(HTMLNames::hrefAttr, ASCIILiteral("tel:") + string));
2289
2290     const AtomicString& aTagLocalName = aTag.localName();
2291     AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, attributes);
2292     AtomicHTMLToken aEndToken(HTMLToken::EndTag, aTagLocalName);
2293
2294     processStartTag(aStartToken);
2295     m_tree.executeQueuedTasks();
2296     m_tree.insertTextNode(string);
2297     processEndTag(aEndToken);
2298 }
2299
2300 // Locates the phone numbers in the string and deals with it
2301 // 1. Appends the text before the phone number as a text node.
2302 // 2. Wraps the phone number in a tel: link.
2303 // 3. Goes back to step 1 if a phone number is found in the rest of the string.
2304 // 4. Appends the rest of the string as a text node.
2305 void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
2306 {
2307     ASSERT(TelephoneNumberDetector::isSupported());
2308
2309     // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
2310     // relative to the scannerPosition
2311     unsigned length = string.length();
2312     unsigned scannerPosition = 0;
2313     int relativeStartPosition = 0;
2314     int relativeEndPosition = 0;
2315
2316     auto characters = StringView(string).upconvertedCharacters();
2317
2318     // While there's a phone number in the rest of the string...
2319     while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
2320         // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
2321         // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So substract 1 to get the same
2322         // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
2323         // to the old parser).
2324         --relativeEndPosition;
2325
2326         ASSERT(scannerPosition + relativeEndPosition < length);
2327
2328         m_tree.insertTextNode(string.substring(scannerPosition, relativeStartPosition));
2329         insertPhoneNumberLink(string.substring(scannerPosition + relativeStartPosition, relativeEndPosition - relativeStartPosition + 1));
2330
2331         scannerPosition += relativeEndPosition + 1;
2332     }
2333
2334     // Append the rest as a text node.
2335     if (scannerPosition > 0) {
2336         if (scannerPosition < length) {
2337             String after = string.substring(scannerPosition, length - scannerPosition);
2338             m_tree.insertTextNode(after);
2339         }
2340     } else
2341         m_tree.insertTextNode(string);
2342 }
2343
2344 // Looks at the ancestors of the element to determine whether we're inside an element which disallows parsing phone numbers.
2345 static inline bool disallowTelephoneNumberParsing(const Node& node)
2346 {
2347     return node.isLink()
2348         || node.nodeType() == Node::COMMENT_NODE
2349         || node.hasTagName(scriptTag)
2350         || is<HTMLFormControlElement>(node)
2351         || node.hasTagName(styleTag)
2352         || node.hasTagName(ttTag)
2353         || node.hasTagName(preTag)
2354         || node.hasTagName(codeTag);
2355 }
2356
2357 static inline bool shouldParseTelephoneNumbersInNode(const ContainerNode& node)
2358 {
2359     const ContainerNode* currentNode = &node;
2360     do {
2361         if (currentNode->isElementNode() && disallowTelephoneNumberParsing(*currentNode))
2362             return false;
2363         currentNode = currentNode->parentNode();
2364     } while (currentNode);
2365     return true;
2366 }
2367
2368 #endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
2369
2370 void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
2371 {
2372 ReprocessBuffer:
2373     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
2374     // Note that this logic is different than the generic \r\n collapsing
2375     // handled in the input stream preprocessor. This logic is here as an
2376     // "authoring convenience" so folks can write:
2377     //
2378     // <pre>
2379     // lorem ipsum
2380     // lorem ipsum
2381     // </pre>
2382     //
2383     // without getting an extra newline at the start of their <pre> element.
2384     if (m_shouldSkipLeadingNewline) {
2385         m_shouldSkipLeadingNewline = false;
2386         buffer.skipAtMostOneLeadingNewline();
2387         if (buffer.isEmpty())
2388             return;
2389     }
2390
2391     switch (m_insertionMode) {
2392     case InsertionMode::Initial:
2393         buffer.skipLeadingWhitespace();
2394         if (buffer.isEmpty())
2395             return;
2396         defaultForInitial();
2397         ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
2398         FALLTHROUGH;
2399     case InsertionMode::BeforeHTML:
2400         buffer.skipLeadingWhitespace();
2401         if (buffer.isEmpty())
2402             return;
2403         defaultForBeforeHTML();
2404         ASSERT(m_insertionMode == InsertionMode::BeforeHead);
2405         FALLTHROUGH;
2406     case InsertionMode::BeforeHead:
2407         buffer.skipLeadingWhitespace();
2408         if (buffer.isEmpty())
2409             return;
2410         defaultForBeforeHead();
2411         ASSERT(m_insertionMode == InsertionMode::InHead);
2412         FALLTHROUGH;
2413     case InsertionMode::InHead: {
2414         String leadingWhitespace = buffer.takeLeadingWhitespace();
2415         if (!leadingWhitespace.isEmpty())
2416             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2417         if (buffer.isEmpty())
2418             return;
2419         defaultForInHead();
2420         ASSERT(m_insertionMode == InsertionMode::AfterHead);
2421         FALLTHROUGH;
2422     }
2423     case InsertionMode::AfterHead: {
2424         String leadingWhitespace = buffer.takeLeadingWhitespace();
2425         if (!leadingWhitespace.isEmpty())
2426             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2427         if (buffer.isEmpty())
2428             return;
2429         defaultForAfterHead();
2430         ASSERT(m_insertionMode == InsertionMode::InBody);
2431         FALLTHROUGH;
2432     }
2433     case InsertionMode::InBody:
2434     case InsertionMode::InCaption:
2435     case InsertionMode::InCell:
2436 #if ENABLE(TEMPLATE_ELEMENT)
2437     case InsertionMode::TemplateContents:
2438 #endif
2439         processCharacterBufferForInBody(buffer);
2440         break;
2441     case InsertionMode::InTable:
2442     case InsertionMode::InTableBody:
2443     case InsertionMode::InRow:
2444         ASSERT(m_pendingTableCharacters.isEmpty());
2445         if (m_tree.currentStackItem()->isElementNode()
2446             && (is<HTMLTableElement>(*m_tree.currentStackItem()->element())
2447                 || m_tree.currentStackItem()->hasTagName(HTMLNames::tbodyTag)
2448                 || m_tree.currentStackItem()->hasTagName(HTMLNames::tfootTag)
2449                 || m_tree.currentStackItem()->hasTagName(HTMLNames::theadTag)
2450                 || m_tree.currentStackItem()->hasTagName(HTMLNames::trTag))) {
2451             m_originalInsertionMode = m_insertionMode;
2452             m_insertionMode = InsertionMode::InTableText;
2453             // Note that we fall through to the InsertionMode::InTableText case below.
2454         } else {
2455             HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
2456             processCharacterBufferForInBody(buffer);
2457             break;
2458         }
2459         FALLTHROUGH;
2460     case InsertionMode::InTableText:
2461         buffer.giveRemainingTo(m_pendingTableCharacters);
2462         break;
2463     case InsertionMode::InColumnGroup: {
2464         String leadingWhitespace = buffer.takeLeadingWhitespace();
2465         if (!leadingWhitespace.isEmpty())
2466             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2467         if (buffer.isEmpty())
2468             return;
2469         if (!processColgroupEndTagForInColumnGroup()) {
2470             ASSERT(isParsingFragmentOrTemplateContents());
2471             // The spec tells us to drop these characters on the floor.
2472             buffer.skipLeadingNonWhitespace();
2473             if (buffer.isEmpty())
2474                 return;
2475         }
2476         goto ReprocessBuffer;
2477     }
2478     case InsertionMode::AfterBody:
2479     case InsertionMode::AfterAfterBody:
2480         // FIXME: parse error
2481         m_insertionMode = InsertionMode::InBody;
2482         goto ReprocessBuffer;
2483     case InsertionMode::Text:
2484         m_tree.insertTextNode(buffer.takeRemaining());
2485         break;
2486     case InsertionMode::InHeadNoscript: {
2487         String leadingWhitespace = buffer.takeLeadingWhitespace();
2488         if (!leadingWhitespace.isEmpty())
2489             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2490         if (buffer.isEmpty())
2491             return;
2492         defaultForInHeadNoscript();
2493         goto ReprocessBuffer;
2494     }
2495     case InsertionMode::InFrameset:
2496     case InsertionMode::AfterFrameset: {
2497         String leadingWhitespace = buffer.takeRemainingWhitespace();
2498         if (!leadingWhitespace.isEmpty())
2499             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2500         // FIXME: We should generate a parse error if we skipped over any
2501         // non-whitespace characters.
2502         break;
2503     }
2504     case InsertionMode::InSelectInTable:
2505     case InsertionMode::InSelect:
2506         m_tree.insertTextNode(buffer.takeRemaining());
2507         break;
2508     case InsertionMode::AfterAfterFrameset: {
2509         String leadingWhitespace = buffer.takeRemainingWhitespace();
2510         if (!leadingWhitespace.isEmpty()) {
2511             m_tree.reconstructTheActiveFormattingElements();
2512             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
2513         }
2514         // FIXME: We should generate a parse error if we skipped over any
2515         // non-whitespace characters.
2516         break;
2517     }
2518     }
2519 }
2520
2521 void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuffer& buffer)
2522 {
2523     m_tree.reconstructTheActiveFormattingElements();
2524     String characters = buffer.takeRemaining();
2525 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
2526     if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(*m_tree.currentNode()) && TelephoneNumberDetector::isSupported())
2527         linkifyPhoneNumbers(characters);
2528     else
2529         m_tree.insertTextNode(characters);
2530 #else
2531     m_tree.insertTextNode(characters);
2532 #endif
2533     if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
2534         m_framesetOk = false;
2535 }
2536
2537 void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
2538 {
2539     ASSERT(token.type() == HTMLToken::EndOfFile);
2540     switch (m_insertionMode) {
2541     case InsertionMode::Initial:
2542         defaultForInitial();
2543         ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
2544         FALLTHROUGH;
2545     case InsertionMode::BeforeHTML:
2546         defaultForBeforeHTML();
2547         ASSERT(m_insertionMode == InsertionMode::BeforeHead);
2548         FALLTHROUGH;
2549     case InsertionMode::BeforeHead:
2550         defaultForBeforeHead();
2551         ASSERT(m_insertionMode == InsertionMode::InHead);
2552         FALLTHROUGH;
2553     case InsertionMode::InHead:
2554         defaultForInHead();
2555         ASSERT(m_insertionMode == InsertionMode::AfterHead);
2556         FALLTHROUGH;
2557     case InsertionMode::AfterHead:
2558         defaultForAfterHead();
2559         ASSERT(m_insertionMode == InsertionMode::InBody);
2560         FALLTHROUGH;
2561     case InsertionMode::InBody:
2562     case InsertionMode::InCell:
2563     case InsertionMode::InCaption:
2564     case InsertionMode::InRow:
2565         notImplemented(); // Emit parse error based on what elements are still open.
2566 #if ENABLE(TEMPLATE_ELEMENT)
2567         if (!m_templateInsertionModes.isEmpty()) {
2568             if (processEndOfFileForInTemplateContents(token))
2569                 return;
2570         }
2571 #endif
2572         break;
2573     case InsertionMode::AfterBody:
2574     case InsertionMode::AfterAfterBody:
2575         break;
2576     case InsertionMode::InHeadNoscript:
2577         defaultForInHeadNoscript();
2578         processEndOfFile(token);
2579         return;
2580     case InsertionMode::AfterFrameset:
2581     case InsertionMode::AfterAfterFrameset:
2582         break;
2583     case InsertionMode::InColumnGroup:
2584         if (m_tree.currentIsRootNode()) {
2585             ASSERT(isParsingFragment());
2586             return; // FIXME: Should we break here instead of returning?
2587         }
2588 #if ENABLE(TEMPLATE_ELEMENT)
2589         ASSERT(m_tree.currentNode()->hasTagName(colgroupTag) || m_tree.currentNode()->hasTagName(templateTag));
2590 #else
2591         ASSERT(m_tree.currentNode()->hasTagName(colgroupTag));
2592 #endif
2593         processColgroupEndTagForInColumnGroup();
2594         FALLTHROUGH;
2595     case InsertionMode::InFrameset:
2596     case InsertionMode::InTable:
2597     case InsertionMode::InTableBody:
2598     case InsertionMode::InSelectInTable:
2599     case InsertionMode::InSelect:
2600         ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable || m_insertionMode == InsertionMode::InTable || m_insertionMode == InsertionMode::InFrameset || m_insertionMode == InsertionMode::InTableBody || m_insertionMode == InsertionMode::InColumnGroup);
2601         if (m_tree.currentNode() != m_tree.openElements()->rootNode())
2602             parseError(token);
2603 #if ENABLE(TEMPLATE_ELEMENT)
2604         if (!m_templateInsertionModes.isEmpty()) {
2605             if (processEndOfFileForInTemplateContents(token))
2606                 return;
2607         }
2608 #endif
2609         break;
2610     case InsertionMode::InTableText:
2611         defaultForInTableText();
2612         processEndOfFile(token);
2613         return;
2614     case InsertionMode::Text:
2615         parseError(token);
2616         if (m_tree.currentStackItem()->hasTagName(scriptTag))
2617             notImplemented(); // mark the script element as "already started".
2618         m_tree.openElements()->pop();
2619         ASSERT(m_originalInsertionMode != InsertionMode::Text);
2620         m_insertionMode = m_originalInsertionMode;
2621         processEndOfFile(token);
2622         return;
2623 #if ENABLE(TEMPLATE_ELEMENT)
2624     case InsertionMode::TemplateContents:
2625         if (processEndOfFileForInTemplateContents(token))
2626             return;
2627         break;
2628 #endif
2629     }
2630     ASSERT(m_tree.currentNode());
2631     m_tree.openElements()->popAll();
2632 }
2633
2634 void HTMLTreeBuilder::defaultForInitial()
2635 {
2636     notImplemented();
2637     m_tree.setDefaultCompatibilityMode();
2638     // FIXME: parse error
2639     m_insertionMode = InsertionMode::BeforeHTML;
2640 }
2641
2642 void HTMLTreeBuilder::defaultForBeforeHTML()
2643 {
2644     AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag.localName());
2645     m_tree.insertHTMLHtmlStartTagBeforeHTML(&startHTML);
2646     m_insertionMode = InsertionMode::BeforeHead;
2647 }
2648
2649 void HTMLTreeBuilder::defaultForBeforeHead()
2650 {
2651     AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
2652     processStartTag(startHead);
2653 }
2654
2655 void HTMLTreeBuilder::defaultForInHead()
2656 {
2657     AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
2658     processEndTag(endHead);
2659 }
2660
2661 void HTMLTreeBuilder::defaultForInHeadNoscript()
2662 {
2663     AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
2664     processEndTag(endNoscript);
2665 }
2666
2667 void HTMLTreeBuilder::defaultForAfterHead()
2668 {
2669     AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
2670     processStartTag(startBody);
2671     m_framesetOk = true;
2672 }
2673
2674 void HTMLTreeBuilder::defaultForInTableText()
2675 {
2676     String characters = m_pendingTableCharacters.toString();
2677     m_pendingTableCharacters.clear();
2678     if (!isAllWhitespace(characters)) {
2679         // FIXME: parse error
2680         HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
2681         m_tree.reconstructTheActiveFormattingElements();
2682         m_tree.insertTextNode(characters, NotAllWhitespace);
2683         m_framesetOk = false;
2684         m_insertionMode = m_originalInsertionMode;
2685         return;
2686     }
2687     m_tree.insertTextNode(characters);
2688     m_insertionMode = m_originalInsertionMode;
2689 }
2690
2691 bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken& token)
2692 {
2693     ASSERT(token.type() == HTMLToken::StartTag);
2694     if (token.name() == htmlTag) {
2695         processHtmlStartTagForInBody(token);
2696         return true;
2697     }
2698     if (token.name() == baseTag
2699         || token.name() == basefontTag
2700         || token.name() == bgsoundTag
2701         || token.name() == commandTag
2702         || token.name() == linkTag
2703         || token.name() == metaTag) {
2704         m_tree.insertSelfClosingHTMLElement(&token);
2705         // Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
2706         return true;
2707     }
2708     if (token.name() == titleTag) {
2709         processGenericRCDATAStartTag(token);
2710         return true;
2711     }
2712     if (token.name() == noscriptTag) {
2713         if (m_options.scriptEnabled) {
2714             processGenericRawTextStartTag(token);
2715             return true;
2716         }
2717         m_tree.insertHTMLElement(&token);
2718         m_insertionMode = InsertionMode::InHeadNoscript;
2719         return true;
2720     }
2721     if (token.name() == noframesTag || token.name() == styleTag) {
2722         processGenericRawTextStartTag(token);
2723         return true;
2724     }
2725     if (token.name() == scriptTag) {
2726         processScriptStartTag(token);
2727         if (m_options.usePreHTML5ParserQuirks && token.selfClosing())
2728             processFakeEndTag(scriptTag);
2729         return true;
2730     }
2731 #if ENABLE(TEMPLATE_ELEMENT)
2732     if (token.name() == templateTag) {
2733         processTemplateStartTag(token);
2734         return true;
2735     }
2736 #endif
2737     if (token.name() == headTag) {
2738         parseError(token);
2739         return true;
2740     }
2741     return false;
2742 }
2743
2744 void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken& token)
2745 {
2746     ASSERT(token.type() == HTMLToken::StartTag);
2747     m_tree.insertHTMLElement(&token);
2748     m_parser.tokenizer().setState(HTMLTokenizer::RCDATAState);
2749     m_originalInsertionMode = m_insertionMode;
2750     m_insertionMode = InsertionMode::Text;
2751 }
2752
2753 void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken& token)
2754 {
2755     ASSERT(token.type() == HTMLToken::StartTag);
2756     m_tree.insertHTMLElement(&token);
2757     m_parser.tokenizer().setState(HTMLTokenizer::RAWTEXTState);
2758     m_originalInsertionMode = m_insertionMode;
2759     m_insertionMode = InsertionMode::Text;
2760 }
2761
2762 void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken& token)
2763 {
2764     ASSERT(token.type() == HTMLToken::StartTag);
2765     m_tree.insertScriptElement(&token);
2766     m_parser.tokenizer().setState(HTMLTokenizer::ScriptDataState);
2767     m_originalInsertionMode = m_insertionMode;
2768
2769     TextPosition position = m_parser.textPosition();
2770
2771     m_scriptToProcessStartPosition = position;
2772
2773     m_insertionMode = InsertionMode::Text;
2774 }
2775
2776 // http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node
2777 HTMLStackItem& HTMLTreeBuilder::adjustedCurrentStackItem() const
2778 {
2779     ASSERT(!m_tree.isEmpty());
2780     if (isParsingFragment() && m_tree.openElements()->hasOnlyOneElement())
2781         return m_fragmentContext.contextElementStackItem();
2782
2783     return *m_tree.currentStackItem();
2784 }
2785
2786 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
2787 bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken& token)
2788 {
2789     if (m_tree.isEmpty())
2790         return false;
2791     HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
2792     if (adjustedCurrentNode.isInHTMLNamespace())
2793         return false;
2794     if (HTMLElementStack::isMathMLTextIntegrationPoint(&adjustedCurrentNode)) {
2795         if (token.type() == HTMLToken::StartTag
2796             && token.name() != MathMLNames::mglyphTag
2797             && token.name() != MathMLNames::malignmarkTag)
2798             return false;
2799         if (token.type() == HTMLToken::Character)
2800             return false;
2801     }
2802     if (adjustedCurrentNode.hasTagName(MathMLNames::annotation_xmlTag)
2803         && token.type() == HTMLToken::StartTag
2804         && token.name() == SVGNames::svgTag)
2805         return false;
2806     if (HTMLElementStack::isHTMLIntegrationPoint(&adjustedCurrentNode)) {
2807         if (token.type() == HTMLToken::StartTag)
2808             return false;
2809         if (token.type() == HTMLToken::Character)
2810             return false;
2811     }
2812     if (token.type() == HTMLToken::EndOfFile)
2813         return false;
2814     return true;
2815 }
2816
2817 void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
2818 {
2819     HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
2820     
2821     switch (token.type()) {
2822     case HTMLToken::Uninitialized:
2823         ASSERT_NOT_REACHED();
2824         break;
2825     case HTMLToken::DOCTYPE:
2826         parseError(token);
2827         break;
2828     case HTMLToken::StartTag: {
2829         if (token.name() == bTag
2830             || token.name() == bigTag
2831             || token.name() == blockquoteTag
2832             || token.name() == bodyTag
2833             || token.name() == brTag
2834             || token.name() == centerTag
2835             || token.name() == codeTag
2836             || token.name() == ddTag
2837             || token.name() == divTag
2838             || token.name() == dlTag
2839             || token.name() == dtTag
2840             || token.name() == emTag
2841             || token.name() == embedTag
2842             || isNumberedHeaderTag(token.name())
2843             || token.name() == headTag
2844             || token.name() == hrTag
2845             || token.name() == iTag
2846             || token.name() == imgTag
2847             || token.name() == liTag
2848             || token.name() == listingTag
2849             || token.name() == menuTag
2850             || token.name() == metaTag
2851             || token.name() == nobrTag
2852             || token.name() == olTag
2853             || token.name() == pTag
2854             || token.name() == preTag
2855             || token.name() == rubyTag
2856             || token.name() == sTag
2857             || token.name() == smallTag
2858             || token.name() == spanTag
2859             || token.name() == strongTag
2860             || token.name() == strikeTag
2861             || token.name() == subTag
2862             || token.name() == supTag
2863             || token.name() == tableTag
2864             || token.name() == ttTag
2865             || token.name() == uTag
2866             || token.name() == ulTag
2867             || token.name() == varTag
2868             || (token.name() == fontTag && (token.getAttributeItem(colorAttr) || token.getAttributeItem(faceAttr) || token.getAttributeItem(sizeAttr)))) {
2869             parseError(token);
2870             m_tree.openElements()->popUntilForeignContentScopeMarker();
2871             processStartTag(token);
2872             return;
2873         }
2874         const AtomicString& currentNamespace = adjustedCurrentNode.namespaceURI();
2875         if (currentNamespace == MathMLNames::mathmlNamespaceURI)
2876             adjustMathMLAttributes(token);
2877         if (currentNamespace == SVGNames::svgNamespaceURI) {
2878             adjustSVGTagNameCase(token);
2879             adjustSVGAttributes(token);
2880         }
2881         adjustForeignAttributes(token);
2882         m_tree.insertForeignElement(&token, currentNamespace);
2883         break;
2884     }
2885     case HTMLToken::EndTag: {
2886         if (adjustedCurrentNode.namespaceURI() == SVGNames::svgNamespaceURI)
2887             adjustSVGTagNameCase(token);
2888
2889         if (token.name() == SVGNames::scriptTag && m_tree.currentStackItem()->hasTagName(SVGNames::scriptTag)) {
2890             if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
2891                 m_scriptToProcess = m_tree.currentElement();
2892             m_tree.openElements()->pop();
2893             return;
2894         }
2895         if (!m_tree.currentStackItem()->isInHTMLNamespace()) {
2896             // FIXME: This code just wants an Element* iterator, instead of an ElementRecord*
2897             auto* nodeRecord = m_tree.openElements()->topRecord();
2898             if (!nodeRecord->stackItem()->hasLocalName(token.name()))
2899                 parseError(token);
2900             while (1) {
2901                 if (nodeRecord->stackItem()->hasLocalName(token.name())) {
2902                     m_tree.openElements()->popUntilPopped(nodeRecord->element());
2903                     return;
2904                 }
2905                 nodeRecord = nodeRecord->next();
2906
2907                 if (nodeRecord->stackItem()->isInHTMLNamespace())
2908                     break;
2909             }
2910         }
2911         // Otherwise, process the token according to the rules given in the section corresponding to the current insertion mode in HTML content.
2912         processEndTag(token);
2913         break;
2914     }
2915     case HTMLToken::Comment:
2916         m_tree.insertComment(&token);
2917         return;
2918     case HTMLToken::Character: {
2919         String characters = String(token.characters(), token.charactersLength());
2920         m_tree.insertTextNode(characters);
2921         if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
2922             m_framesetOk = false;
2923         break;
2924     }
2925     case HTMLToken::EndOfFile:
2926         ASSERT_NOT_REACHED();
2927         break;
2928     }
2929 }
2930
2931 void HTMLTreeBuilder::finished()
2932 {
2933     ASSERT(!m_destroyed);
2934
2935     if (isParsingFragment())
2936         return;
2937
2938 #if ENABLE(TEMPLATE_ELEMENT)
2939     ASSERT(m_templateInsertionModes.isEmpty());
2940 #endif
2941
2942     m_tree.finishedParsing();
2943     // The tree builder might have been destroyed as an indirect result of finishing the parsing.
2944 }
2945
2946 inline void HTMLTreeBuilder::parseError(AtomicHTMLToken&)
2947 {
2948 }
2949
2950 }