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