createElementFromSavedToken shouldn't have the code to create a non-HTML element
[WebKit.git] / Source / WebCore / html / parser / HTMLConstructionSite.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 "DocumentFragment.h"
32 #include "DocumentType.h"
33 #include "Frame.h"
34 #include "FrameLoader.h"
35 #include "FrameLoaderClient.h"
36 #include "HTMLElementFactory.h"
37 #include "HTMLFormElement.h"
38 #include "HTMLHtmlElement.h"
39 #include "HTMLImageElement.h"
40 #include "HTMLOptGroupElement.h"
41 #include "HTMLOptionElement.h"
42 #include "HTMLParserIdioms.h"
43 #include "HTMLPictureElement.h"
44 #include "HTMLScriptElement.h"
45 #include "HTMLTemplateElement.h"
46 #include "NotImplemented.h"
47 #include "SVGElement.h"
48 #include "Text.h"
49
50 namespace WebCore {
51
52 using namespace HTMLNames;
53
54 static inline void setAttributes(Element& element, AtomicHTMLToken* token, ParserContentPolicy parserContentPolicy)
55 {
56     if (!scriptingContentIsAllowed(parserContentPolicy))
57         element.stripScriptingAttributes(token->attributes());
58     element.parserSetAttributes(token->attributes());
59 }
60
61 static bool hasImpliedEndTag(const HTMLStackItem& item)
62 {
63     return item.hasTagName(ddTag)
64         || item.hasTagName(dtTag)
65         || item.hasTagName(liTag)
66         || is<HTMLOptionElement>(item.node())
67         || is<HTMLOptGroupElement>(item.node())
68         || item.hasTagName(pTag)
69         || item.hasTagName(rbTag)
70         || item.hasTagName(rpTag)
71         || item.hasTagName(rtTag)
72         || item.hasTagName(rtcTag);
73 }
74
75 static bool shouldUseLengthLimit(const ContainerNode* node)
76 {
77     return !node->hasTagName(scriptTag)
78         && !node->hasTagName(styleTag)
79         && !node->hasTagName(SVGNames::scriptTag);
80 }
81
82 static inline bool causesFosterParenting(const HTMLStackItem& item)
83 {
84     return item.hasTagName(HTMLNames::tableTag)
85         || item.hasTagName(HTMLNames::tbodyTag)
86         || item.hasTagName(HTMLNames::tfootTag)
87         || item.hasTagName(HTMLNames::theadTag)
88         || item.hasTagName(HTMLNames::trTag);
89 }
90
91 static inline bool isAllWhitespace(const String& string)
92 {
93     return string.isAllSpecialCharacters<isHTMLSpace>();
94 }
95
96 static inline void insert(HTMLConstructionSiteTask& task)
97 {
98 #if ENABLE(TEMPLATE_ELEMENT)
99     if (is<HTMLTemplateElement>(*task.parent))
100         task.parent = downcast<HTMLTemplateElement>(*task.parent).content();
101 #endif
102
103     if (ContainerNode* parent = task.child->parentNode())
104         parent->parserRemoveChild(*task.child);
105
106     if (task.nextChild)
107         task.parent->parserInsertBefore(*task.child, *task.nextChild);
108     else
109         task.parent->parserAppendChild(*task.child);
110 }
111
112 static inline void executeInsertTask(HTMLConstructionSiteTask& task)
113 {
114     ASSERT(task.operation == HTMLConstructionSiteTask::Insert);
115
116     insert(task);
117
118     task.child->beginParsingChildren();
119
120     if (task.selfClosing)
121         task.child->finishParsingChildren();
122 }
123
124 static inline void executeReparentTask(HTMLConstructionSiteTask& task)
125 {
126     ASSERT(task.operation == HTMLConstructionSiteTask::Reparent);
127
128     if (ContainerNode* parent = task.child->parentNode())
129         parent->parserRemoveChild(*task.child);
130
131     task.parent->parserAppendChild(*task.child);
132 }
133
134 static inline void executeInsertAlreadyParsedChildTask(HTMLConstructionSiteTask& task)
135 {
136     ASSERT(task.operation == HTMLConstructionSiteTask::InsertAlreadyParsedChild);
137
138     insert(task);
139 }
140
141 static inline void executeTakeAllChildrenTask(HTMLConstructionSiteTask& task)
142 {
143     ASSERT(task.operation == HTMLConstructionSiteTask::TakeAllChildren);
144
145     task.parent->takeAllChildrenFrom(task.oldParent());
146     // Notice that we don't need to manually attach the moved children
147     // because takeAllChildrenFrom does that work for us.
148 }
149
150 static inline void executeTask(HTMLConstructionSiteTask& task)
151 {
152     switch (task.operation) {
153     case HTMLConstructionSiteTask::Insert:
154         executeInsertTask(task);
155         return;
156     // All the cases below this point are only used by the adoption agency.
157     case HTMLConstructionSiteTask::InsertAlreadyParsedChild:
158         executeInsertAlreadyParsedChildTask(task);
159         return;
160     case HTMLConstructionSiteTask::Reparent:
161         executeReparentTask(task);
162         return;
163     case HTMLConstructionSiteTask::TakeAllChildren:
164         executeTakeAllChildrenTask(task);
165         return;
166     }
167     ASSERT_NOT_REACHED();
168 }
169
170 void HTMLConstructionSite::attachLater(ContainerNode* parent, PassRefPtr<Node> prpChild, bool selfClosing)
171 {
172     ASSERT(scriptingContentIsAllowed(m_parserContentPolicy) || !is<Element>(*prpChild) || !toScriptElementIfPossible(downcast<Element>(prpChild.get())));
173     ASSERT(pluginContentIsAllowed(m_parserContentPolicy) || !prpChild->isPluginElement());
174
175     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Insert);
176     task.parent = parent;
177     task.child = prpChild;
178     task.selfClosing = selfClosing;
179
180     if (shouldFosterParent()) {
181         fosterParent(task.child);
182         return;
183     }
184
185     // Add as a sibling of the parent if we have reached the maximum depth allowed.
186     if (m_openElements.stackDepth() > m_maximumDOMTreeDepth && task.parent->parentNode())
187         task.parent = task.parent->parentNode();
188
189     ASSERT(task.parent);
190     m_taskQueue.append(task);
191 }
192
193 void HTMLConstructionSite::executeQueuedTasks()
194 {
195     const size_t size = m_taskQueue.size();
196     if (!size)
197         return;
198
199     // Copy the task queue into a local variable in case executeTask
200     // re-enters the parser.
201     TaskQueue queue = WTFMove(m_taskQueue);
202
203     for (size_t i = 0; i < size; ++i)
204         executeTask(queue[i]);
205
206     // We might be detached now.
207 }
208
209 HTMLConstructionSite::HTMLConstructionSite(Document& document, ParserContentPolicy parserContentPolicy, unsigned maximumDOMTreeDepth)
210     : m_document(&document)
211     , m_attachmentRoot(&document)
212     , m_parserContentPolicy(parserContentPolicy)
213     , m_isParsingFragment(false)
214     , m_redirectAttachToFosterParent(false)
215     , m_maximumDOMTreeDepth(maximumDOMTreeDepth)
216     , m_inQuirksMode(document.inQuirksMode())
217 {
218     ASSERT(m_document->isHTMLDocument() || m_document->isXHTMLDocument());
219 }
220
221 HTMLConstructionSite::HTMLConstructionSite(DocumentFragment& fragment, ParserContentPolicy parserContentPolicy, unsigned maximumDOMTreeDepth)
222     : m_document(&fragment.document())
223     , m_attachmentRoot(&fragment)
224     , m_parserContentPolicy(parserContentPolicy)
225     , m_isParsingFragment(true)
226     , m_redirectAttachToFosterParent(false)
227     , m_maximumDOMTreeDepth(maximumDOMTreeDepth)
228     , m_inQuirksMode(fragment.document().inQuirksMode())
229 {
230     ASSERT(m_document->isHTMLDocument() || m_document->isXHTMLDocument());
231 }
232
233 HTMLConstructionSite::~HTMLConstructionSite()
234 {
235 }
236
237 void HTMLConstructionSite::detach()
238 {
239     m_document = 0;
240     m_attachmentRoot = 0;
241 }
242
243 void HTMLConstructionSite::setForm(HTMLFormElement* form)
244 {
245     // This method should only be needed for HTMLTreeBuilder in the fragment case.
246     ASSERT(!m_form);
247     m_form = form;
248 }
249
250 PassRefPtr<HTMLFormElement> HTMLConstructionSite::takeForm()
251 {
252     return m_form.release();
253 }
254
255 void HTMLConstructionSite::dispatchDocumentElementAvailableIfNeeded()
256 {
257     ASSERT(m_document);
258     if (m_document->frame() && !m_isParsingFragment)
259         m_document->frame()->injectUserScripts(InjectAtDocumentStart);
260 }
261
262 void HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken* token)
263 {
264     Ref<HTMLHtmlElement> element = HTMLHtmlElement::create(*m_document);
265     setAttributes(element.get(), token, m_parserContentPolicy);
266     attachLater(m_attachmentRoot, element.ptr());
267     m_openElements.pushHTMLHtmlElement(HTMLStackItem::create(element.copyRef(), *token));
268
269     executeQueuedTasks();
270     element->insertedByParser();
271     dispatchDocumentElementAvailableIfNeeded();
272 }
273
274 void HTMLConstructionSite::mergeAttributesFromTokenIntoElement(AtomicHTMLToken* token, Element* element)
275 {
276     if (token->attributes().isEmpty())
277         return;
278
279     for (auto& tokenAttribute : token->attributes()) {
280         if (!element->elementData() || !element->findAttributeByName(tokenAttribute.name()))
281             element->setAttribute(tokenAttribute.name(), tokenAttribute.value());
282     }
283 }
284
285 void HTMLConstructionSite::insertHTMLHtmlStartTagInBody(AtomicHTMLToken* token)
286 {
287     // Fragments do not have a root HTML element, so any additional HTML elements
288     // encountered during fragment parsing should be ignored.
289     if (m_isParsingFragment)
290         return;
291
292     mergeAttributesFromTokenIntoElement(token, &m_openElements.htmlElement());
293 }
294
295 void HTMLConstructionSite::insertHTMLBodyStartTagInBody(AtomicHTMLToken* token)
296 {
297     mergeAttributesFromTokenIntoElement(token, &m_openElements.bodyElement());
298 }
299
300 void HTMLConstructionSite::setDefaultCompatibilityMode()
301 {
302     if (m_isParsingFragment)
303         return;
304     if (m_document->isSrcdocDocument())
305         return;
306     setCompatibilityMode(DocumentCompatibilityMode::QuirksMode);
307 }
308
309 void HTMLConstructionSite::setCompatibilityMode(DocumentCompatibilityMode mode)
310 {
311     m_inQuirksMode = (mode == DocumentCompatibilityMode::QuirksMode);
312     m_document->setCompatibilityMode(mode);
313 }
314
315 void HTMLConstructionSite::setCompatibilityModeFromDoctype(const String& name, const String& publicId, const String& systemId)
316 {
317     // There are three possible compatibility modes:
318     // Quirks - quirks mode emulates WinIE and NS4. CSS parsing is also relaxed in this mode, e.g., unit types can
319     // be omitted from numbers.
320     // Limited Quirks - This mode is identical to no-quirks mode except for its treatment of line-height in the inline box model.  
321     // No Quirks - no quirks apply. Web pages will obey the specifications to the letter.
322
323     // Check for Quirks Mode.
324     if (name != "html"
325         || publicId.startsWith("+//Silmaril//dtd html Pro v0r11 19970101//", false)
326         || publicId.startsWith("-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//", false)
327         || publicId.startsWith("-//AS//DTD HTML 3.0 asWedit + extensions//", false)
328         || publicId.startsWith("-//IETF//DTD HTML 2.0 Level 1//", false)
329         || publicId.startsWith("-//IETF//DTD HTML 2.0 Level 2//", false)
330         || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict Level 1//", false)
331         || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict Level 2//", false)
332         || publicId.startsWith("-//IETF//DTD HTML 2.0 Strict//", false)
333         || publicId.startsWith("-//IETF//DTD HTML 2.0//", false)
334         || publicId.startsWith("-//IETF//DTD HTML 2.1E//", false)
335         || publicId.startsWith("-//IETF//DTD HTML 3.0//", false)
336         || publicId.startsWith("-//IETF//DTD HTML 3.2 Final//", false)
337         || publicId.startsWith("-//IETF//DTD HTML 3.2//", false)
338         || publicId.startsWith("-//IETF//DTD HTML 3//", false)
339         || publicId.startsWith("-//IETF//DTD HTML Level 0//", false)
340         || publicId.startsWith("-//IETF//DTD HTML Level 1//", false)
341         || publicId.startsWith("-//IETF//DTD HTML Level 2//", false)
342         || publicId.startsWith("-//IETF//DTD HTML Level 3//", false)
343         || publicId.startsWith("-//IETF//DTD HTML Strict Level 0//", false)
344         || publicId.startsWith("-//IETF//DTD HTML Strict Level 1//", false)
345         || publicId.startsWith("-//IETF//DTD HTML Strict Level 2//", false)
346         || publicId.startsWith("-//IETF//DTD HTML Strict Level 3//", false)
347         || publicId.startsWith("-//IETF//DTD HTML Strict//", false)
348         || publicId.startsWith("-//IETF//DTD HTML//", false)
349         || publicId.startsWith("-//Metrius//DTD Metrius Presentational//", false)
350         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//", false)
351         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 HTML//", false)
352         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 2.0 Tables//", false)
353         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//", false)
354         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 HTML//", false)
355         || publicId.startsWith("-//Microsoft//DTD Internet Explorer 3.0 Tables//", false)
356         || publicId.startsWith("-//Netscape Comm. Corp.//DTD HTML//", false)
357         || publicId.startsWith("-//Netscape Comm. Corp.//DTD Strict HTML//", false)
358         || publicId.startsWith("-//O'Reilly and Associates//DTD HTML 2.0//", false)
359         || publicId.startsWith("-//O'Reilly and Associates//DTD HTML Extended 1.0//", false)
360         || publicId.startsWith("-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//", false)
361         || publicId.startsWith("-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//", false)
362         || publicId.startsWith("-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//", false)
363         || publicId.startsWith("-//Spyglass//DTD HTML 2.0 Extended//", false)
364         || publicId.startsWith("-//SQ//DTD HTML 2.0 HoTMetaL + extensions//", false)
365         || publicId.startsWith("-//Sun Microsystems Corp.//DTD HotJava HTML//", false)
366         || publicId.startsWith("-//Sun Microsystems Corp.//DTD HotJava Strict HTML//", false)
367         || publicId.startsWith("-//W3C//DTD HTML 3 1995-03-24//", false)
368         || publicId.startsWith("-//W3C//DTD HTML 3.2 Draft//", false)
369         || publicId.startsWith("-//W3C//DTD HTML 3.2 Final//", false)
370         || publicId.startsWith("-//W3C//DTD HTML 3.2//", false)
371         || publicId.startsWith("-//W3C//DTD HTML 3.2S Draft//", false)
372         || publicId.startsWith("-//W3C//DTD HTML 4.0 Frameset//", false)
373         || publicId.startsWith("-//W3C//DTD HTML 4.0 Transitional//", false)
374         || publicId.startsWith("-//W3C//DTD HTML Experimental 19960712//", false)
375         || publicId.startsWith("-//W3C//DTD HTML Experimental 970421//", false)
376         || publicId.startsWith("-//W3C//DTD W3 HTML//", false)
377         || publicId.startsWith("-//W3O//DTD W3 HTML 3.0//", false)
378         || equalIgnoringCase(publicId, "-//W3O//DTD W3 HTML Strict 3.0//EN//")
379         || publicId.startsWith("-//WebTechs//DTD Mozilla HTML 2.0//", false)
380         || publicId.startsWith("-//WebTechs//DTD Mozilla HTML//", false)
381         || equalIgnoringCase(publicId, "-/W3C/DTD HTML 4.0 Transitional/EN")
382         || equalIgnoringCase(publicId, "HTML")
383         || equalIgnoringCase(systemId, "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd")
384         || (systemId.isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Frameset//", false))
385         || (systemId.isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Transitional//", false))) {
386         setCompatibilityMode(DocumentCompatibilityMode::QuirksMode);
387         return;
388     }
389
390     // Check for Limited Quirks Mode.
391     if (publicId.startsWith("-//W3C//DTD XHTML 1.0 Frameset//", false)
392         || publicId.startsWith("-//W3C//DTD XHTML 1.0 Transitional//", false)
393         || (!systemId.isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Frameset//", false))
394         || (!systemId.isEmpty() && publicId.startsWith("-//W3C//DTD HTML 4.01 Transitional//", false))) {
395         setCompatibilityMode(DocumentCompatibilityMode::LimitedQuirksMode);
396         return;
397     }
398
399     // Otherwise we are No Quirks Mode.
400     setCompatibilityMode(DocumentCompatibilityMode::NoQuirksMode);
401 }
402
403 void HTMLConstructionSite::finishedParsing()
404 {
405     m_document->finishedParsing();
406 }
407
408 void HTMLConstructionSite::insertDoctype(AtomicHTMLToken* token)
409 {
410     ASSERT(token->type() == HTMLToken::DOCTYPE);
411
412     String publicId = token->publicIdentifier();
413     String systemId = token->systemIdentifier();
414
415     RefPtr<DocumentType> doctype = DocumentType::create(*m_document, token->name(), publicId, systemId);
416     attachLater(m_attachmentRoot, doctype.release());
417
418     // DOCTYPE nodes are only processed when parsing fragments w/o contextElements, which
419     // never occurs.  However, if we ever chose to support such, this code is subtly wrong,
420     // because context-less fragments can determine their own quirks mode, and thus change
421     // parsing rules (like <p> inside <table>).  For now we ASSERT that we never hit this code
422     // in a fragment, as changing the owning document's compatibility mode would be wrong.
423     ASSERT(!m_isParsingFragment);
424     if (m_isParsingFragment)
425         return;
426
427     if (token->forceQuirks())
428         setCompatibilityMode(DocumentCompatibilityMode::QuirksMode);
429     else
430         setCompatibilityModeFromDoctype(token->name(), publicId, systemId);
431 }
432
433 void HTMLConstructionSite::insertComment(AtomicHTMLToken* token)
434 {
435     ASSERT(token->type() == HTMLToken::Comment);
436     attachLater(&currentNode(), Comment::create(ownerDocumentForCurrentNode(), token->comment()));
437 }
438
439 void HTMLConstructionSite::insertCommentOnDocument(AtomicHTMLToken* token)
440 {
441     ASSERT(token->type() == HTMLToken::Comment);
442     attachLater(m_attachmentRoot, Comment::create(*m_document, token->comment()));
443 }
444
445 void HTMLConstructionSite::insertCommentOnHTMLHtmlElement(AtomicHTMLToken* token)
446 {
447     ASSERT(token->type() == HTMLToken::Comment);
448     ContainerNode& parent = m_openElements.rootNode();
449     attachLater(&parent, Comment::create(parent.document(), token->comment()));
450 }
451
452 void HTMLConstructionSite::insertHTMLHeadElement(AtomicHTMLToken* token)
453 {
454     ASSERT(!shouldFosterParent());
455     m_head = HTMLStackItem::create(createHTMLElement(token), *token);
456     attachLater(&currentNode(), &m_head->element());
457     m_openElements.pushHTMLHeadElement(m_head);
458 }
459
460 void HTMLConstructionSite::insertHTMLBodyElement(AtomicHTMLToken* token)
461 {
462     ASSERT(!shouldFosterParent());
463     RefPtr<Element> body = createHTMLElement(token);
464     attachLater(&currentNode(), body.get());
465     m_openElements.pushHTMLBodyElement(HTMLStackItem::create(body.releaseNonNull(), *token));
466 }
467
468 void HTMLConstructionSite::insertHTMLFormElement(AtomicHTMLToken* token, bool isDemoted)
469 {
470     RefPtr<Element> element = createHTMLElement(token);
471     ASSERT(is<HTMLFormElement>(*element));
472     m_form = static_pointer_cast<HTMLFormElement>(element.release());
473     m_form->setDemoted(isDemoted);
474     attachLater(&currentNode(), m_form);
475     m_openElements.push(HTMLStackItem::create(*m_form, *token));
476 }
477
478 void HTMLConstructionSite::insertHTMLElement(AtomicHTMLToken* token)
479 {
480     RefPtr<Element> element = createHTMLElement(token);
481     attachLater(&currentNode(), element);
482     m_openElements.push(HTMLStackItem::create(element.releaseNonNull(), *token));
483 }
484
485 void HTMLConstructionSite::insertSelfClosingHTMLElement(AtomicHTMLToken* token)
486 {
487     ASSERT(token->type() == HTMLToken::StartTag);
488     // Normally HTMLElementStack is responsible for calling finishParsingChildren,
489     // but self-closing elements are never in the element stack so the stack
490     // doesn't get a chance to tell them that we're done parsing their children.
491     attachLater(&currentNode(), createHTMLElement(token), true);
492     // FIXME: Do we want to acknowledge the token's self-closing flag?
493     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#acknowledge-self-closing-flag
494 }
495
496 void HTMLConstructionSite::insertFormattingElement(AtomicHTMLToken* token)
497 {
498     // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements
499     // Possible active formatting elements include:
500     // a, b, big, code, em, font, i, nobr, s, small, strike, strong, tt, and u.
501     ASSERT(isFormattingTag(token->name()));
502     insertHTMLElement(token);
503     m_activeFormattingElements.append(&currentStackItem());
504 }
505
506 void HTMLConstructionSite::insertScriptElement(AtomicHTMLToken* token)
507 {
508     // http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#already-started
509     // http://html5.org/specs/dom-parsing.html#dom-range-createcontextualfragment
510     // For createContextualFragment, the specifications say to mark it parser-inserted and already-started and later unmark them.
511     // However, we short circuit that logic to avoid the subtree traversal to find script elements since scripts can never see
512     // those flags or effects thereof.
513     const bool parserInserted = m_parserContentPolicy != AllowScriptingContentAndDoNotMarkAlreadyStarted;
514     const bool alreadyStarted = m_isParsingFragment && parserInserted;
515     Ref<HTMLScriptElement> element = HTMLScriptElement::create(scriptTag, ownerDocumentForCurrentNode(), parserInserted, alreadyStarted);
516     setAttributes(element.get(), token, m_parserContentPolicy);
517     if (scriptingContentIsAllowed(m_parserContentPolicy))
518         attachLater(&currentNode(), element.ptr());
519     m_openElements.push(HTMLStackItem::create(WTFMove(element), *token));
520 }
521
522 void HTMLConstructionSite::insertForeignElement(AtomicHTMLToken* token, const AtomicString& namespaceURI)
523 {
524     ASSERT(token->type() == HTMLToken::StartTag);
525     notImplemented(); // parseError when xmlns or xmlns:xlink are wrong.
526
527     RefPtr<Element> element = createElement(token, namespaceURI);
528     if (scriptingContentIsAllowed(m_parserContentPolicy) || !toScriptElementIfPossible(element.get()))
529         attachLater(&currentNode(), element, token->selfClosing());
530     if (!token->selfClosing())
531         m_openElements.push(HTMLStackItem::create(element.releaseNonNull(), *token, namespaceURI));
532 }
533
534 void HTMLConstructionSite::insertTextNode(const String& characters, WhitespaceMode whitespaceMode)
535 {
536     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Insert);
537     task.parent = &currentNode();
538
539     if (shouldFosterParent())
540         findFosterSite(task);
541
542 #if ENABLE(TEMPLATE_ELEMENT)
543     if (is<HTMLTemplateElement>(*task.parent))
544         task.parent = downcast<HTMLTemplateElement>(*task.parent).content();
545 #endif
546
547     // Strings composed entirely of whitespace are likely to be repeated.
548     // Turn them into AtomicString so we share a single string for each.
549     bool shouldUseAtomicString = whitespaceMode == AllWhitespace
550         || (whitespaceMode == WhitespaceUnknown && isAllWhitespace(characters));
551
552     unsigned currentPosition = 0;
553     unsigned lengthLimit = shouldUseLengthLimit(task.parent.get()) ? Text::defaultLengthLimit : std::numeric_limits<unsigned>::max();
554
555     // FIXME: Splitting text nodes into smaller chunks contradicts HTML5 spec, but is currently necessary
556     // for performance, see <https://bugs.webkit.org/show_bug.cgi?id=55898>.
557
558     Node* previousChild = task.nextChild ? task.nextChild->previousSibling() : task.parent->lastChild();
559     if (is<Text>(previousChild)) {
560         // FIXME: We're only supposed to append to this text node if it
561         // was the last text node inserted by the parser.
562         Text& textNode = downcast<Text>(*previousChild);
563         currentPosition = textNode.parserAppendData(characters, 0, lengthLimit);
564     }
565
566     while (currentPosition < characters.length()) {
567         Ref<Text> textNode = Text::createWithLengthLimit(task.parent->document(), shouldUseAtomicString ? AtomicString(characters).string() : characters, currentPosition, lengthLimit);
568         // If we have a whole string of unbreakable characters the above could lead to an infinite loop. Exceeding the length limit is the lesser evil.
569         if (!textNode->length()) {
570             String substring = characters.substring(currentPosition);
571             textNode = Text::create(task.parent->document(), shouldUseAtomicString ? AtomicString(substring).string() : substring);
572         }
573
574         currentPosition += textNode->length();
575         ASSERT(currentPosition <= characters.length());
576         task.child = WTFMove(textNode);
577
578         executeTask(task);
579     }
580 }
581
582 void HTMLConstructionSite::reparent(HTMLElementStack::ElementRecord& newParent, HTMLElementStack::ElementRecord& child)
583 {
584     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Reparent);
585     task.parent = &newParent.node();
586     task.child = &child.element();
587     m_taskQueue.append(task);
588 }
589
590 void HTMLConstructionSite::reparent(HTMLElementStack::ElementRecord& newParent, HTMLStackItem& child)
591 {
592     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Reparent);
593     task.parent = &newParent.node();
594     task.child = &child.element();
595     m_taskQueue.append(task);
596 }
597
598 void HTMLConstructionSite::insertAlreadyParsedChild(HTMLStackItem& newParent, HTMLElementStack::ElementRecord& child)
599 {
600     if (causesFosterParenting(newParent)) {
601         fosterParent(&child.element());
602         return;
603     }
604
605     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::InsertAlreadyParsedChild);
606     task.parent = &newParent.node();
607     task.child = &child.element();
608     m_taskQueue.append(task);
609 }
610
611 void HTMLConstructionSite::takeAllChildren(HTMLStackItem& newParent, HTMLElementStack::ElementRecord& oldParent)
612 {
613     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::TakeAllChildren);
614     task.parent = &newParent.node();
615     task.child = &oldParent.node();
616     m_taskQueue.append(task);
617 }
618
619 Ref<Element> HTMLConstructionSite::createElement(AtomicHTMLToken* token, const AtomicString& namespaceURI)
620 {
621     QualifiedName tagName(nullAtom, token->name(), namespaceURI);
622     Ref<Element> element = ownerDocumentForCurrentNode().createElement(tagName, true);
623     setAttributes(element.get(), token, m_parserContentPolicy);
624     return element;
625 }
626
627 inline Document& HTMLConstructionSite::ownerDocumentForCurrentNode()
628 {
629 #if ENABLE(TEMPLATE_ELEMENT)
630     if (is<HTMLTemplateElement>(currentNode()))
631         return downcast<HTMLTemplateElement>(currentNode()).content()->document();
632 #endif
633     return currentNode().document();
634 }
635
636 Ref<Element> HTMLConstructionSite::createHTMLElement(AtomicHTMLToken* token)
637 {
638     QualifiedName tagName(nullAtom, token->name(), xhtmlNamespaceURI);
639     // FIXME: This can't use HTMLConstructionSite::createElement because we
640     // have to pass the current form element.  We should rework form association
641     // to occur after construction to allow better code sharing here.
642     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#create-an-element-for-the-token
643     Document& ownerDocument = ownerDocumentForCurrentNode();
644     bool insideTemplateElement = !ownerDocument.frame();
645     Ref<Element> element = HTMLElementFactory::createElement(tagName, ownerDocument, insideTemplateElement ? nullptr : form(), true);
646     
647     // FIXME: This is a hack to connect images to pictures before the image has
648     // been inserted into the document. It can be removed once asynchronous image
649     // loading is working.
650     if (is<HTMLPictureElement>(currentNode()) && is<HTMLImageElement>(element))
651         downcast<HTMLImageElement>(element.get()).setPictureElement(&downcast<HTMLPictureElement>(currentNode()));
652
653     setAttributes(element.get(), token, m_parserContentPolicy);
654     ASSERT(element->isHTMLElement());
655     return element;
656 }
657
658 Ref<HTMLStackItem> HTMLConstructionSite::createElementFromSavedToken(HTMLStackItem* item)
659 {
660     // NOTE: Moving from item -> token -> item copies the Attribute vector twice!
661     AtomicHTMLToken fakeToken(HTMLToken::StartTag, item->localName(), Vector<Attribute>(item->attributes()));
662     ASSERT(item->namespaceURI() == HTMLNames::xhtmlNamespaceURI);
663     ASSERT(isFormattingTag(item->localName()));
664     return HTMLStackItem::create(createHTMLElement(&fakeToken), fakeToken, item->namespaceURI());
665 }
666
667 bool HTMLConstructionSite::indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const
668 {
669     if (m_activeFormattingElements.isEmpty())
670         return false;
671     unsigned index = m_activeFormattingElements.size();
672     do {
673         --index;
674         const HTMLFormattingElementList::Entry& entry = m_activeFormattingElements.at(index);
675         if (entry.isMarker() || m_openElements.contains(&entry.element())) {
676             firstUnopenElementIndex = index + 1;
677             return firstUnopenElementIndex < m_activeFormattingElements.size();
678         }
679     } while (index);
680     firstUnopenElementIndex = index;
681     return true;
682 }
683
684 void HTMLConstructionSite::reconstructTheActiveFormattingElements()
685 {
686     unsigned firstUnopenElementIndex;
687     if (!indexOfFirstUnopenFormattingElement(firstUnopenElementIndex))
688         return;
689
690     unsigned unopenEntryIndex = firstUnopenElementIndex;
691     ASSERT(unopenEntryIndex < m_activeFormattingElements.size());
692     for (; unopenEntryIndex < m_activeFormattingElements.size(); ++unopenEntryIndex) {
693         HTMLFormattingElementList::Entry& unopenedEntry = m_activeFormattingElements.at(unopenEntryIndex);
694         RefPtr<HTMLStackItem> reconstructed = createElementFromSavedToken(unopenedEntry.stackItem());
695         attachLater(&currentNode(), &reconstructed->node());
696         m_openElements.push(reconstructed);
697         unopenedEntry.replaceElement(reconstructed.release());
698     }
699 }
700
701 void HTMLConstructionSite::generateImpliedEndTagsWithExclusion(const AtomicString& tagName)
702 {
703     while (hasImpliedEndTag(currentStackItem()) && !currentStackItem().matchesHTMLTag(tagName))
704         m_openElements.pop();
705 }
706
707 void HTMLConstructionSite::generateImpliedEndTags()
708 {
709     while (hasImpliedEndTag(currentStackItem()))
710         m_openElements.pop();
711 }
712
713 bool HTMLConstructionSite::inQuirksMode()
714 {
715     return m_inQuirksMode;
716 }
717
718 void HTMLConstructionSite::findFosterSite(HTMLConstructionSiteTask& task)
719 {
720 #if ENABLE(TEMPLATE_ELEMENT)
721     // When a node is to be foster parented, the last template element with no table element is below it in the stack of open elements is the foster parent element (NOT the template's parent!)
722     HTMLElementStack::ElementRecord* lastTemplateElement = m_openElements.topmost(templateTag.localName());
723     if (lastTemplateElement && !m_openElements.inTableScope(tableTag)) {
724         task.parent = &lastTemplateElement->element();
725         return;
726     }
727
728 #endif
729
730     HTMLElementStack::ElementRecord* lastTableElementRecord = m_openElements.topmost(tableTag.localName());
731     if (lastTableElementRecord) {
732         Element& lastTableElement = lastTableElementRecord->element();
733         ContainerNode* parent = lastTableElement.parentNode();
734         // When parsing HTML fragments, we skip step 4.2 ("Let root be a new html element with no attributes") for efficiency,
735         // and instead use the DocumentFragment as a root node. So we must treat the root node (DocumentFragment) as if it is a html element here.
736         bool parentCanBeFosterParent = parent && (parent->isElementNode() || (m_isParsingFragment && parent == &m_openElements.rootNode()));
737 #if ENABLE(TEMPLATE_ELEMENT)
738         parentCanBeFosterParent = parentCanBeFosterParent || (is<DocumentFragment>(parent) && downcast<DocumentFragment>(parent)->isTemplateContent());
739 #endif
740         if (parentCanBeFosterParent) {
741             task.parent = parent;
742             task.nextChild = &lastTableElement;
743             return;
744         }
745         task.parent = &lastTableElementRecord->next()->element();
746         return;
747     }
748     // Fragment case
749     task.parent = &m_openElements.rootNode(); // DocumentFragment
750 }
751
752 bool HTMLConstructionSite::shouldFosterParent() const
753 {
754     return m_redirectAttachToFosterParent
755         && causesFosterParenting(currentStackItem());
756 }
757
758 void HTMLConstructionSite::fosterParent(PassRefPtr<Node> node)
759 {
760     HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Insert);
761     findFosterSite(task);
762     task.child = node;
763     ASSERT(task.parent);
764
765     m_taskQueue.append(task);
766 }
767
768 }