summaryrefslogtreecommitdiffstats
path: root/WebCore/html/parser/HTMLTreeBuilder.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/html/parser/HTMLTreeBuilder.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/html/parser/HTMLTreeBuilder.cpp')
-rw-r--r--WebCore/html/parser/HTMLTreeBuilder.cpp2811
1 files changed, 0 insertions, 2811 deletions
diff --git a/WebCore/html/parser/HTMLTreeBuilder.cpp b/WebCore/html/parser/HTMLTreeBuilder.cpp
deleted file mode 100644
index 3d39131..0000000
--- a/WebCore/html/parser/HTMLTreeBuilder.cpp
+++ /dev/null
@@ -1,2811 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "HTMLTreeBuilder.h"
-
-#include "CharacterNames.h"
-#include "Comment.h"
-#include "DocumentFragment.h"
-#include "DocumentType.h"
-#include "Frame.h"
-#include "HTMLDocument.h"
-#include "HTMLElementFactory.h"
-#include "HTMLFormElement.h"
-#include "HTMLHtmlElement.h"
-#include "HTMLNames.h"
-#include "HTMLParserIdioms.h"
-#include "HTMLScriptElement.h"
-#include "HTMLToken.h"
-#include "HTMLTokenizer.h"
-#include "LocalizedStrings.h"
-#include "MathMLNames.h"
-#include "NotImplemented.h"
-#include "SVGNames.h"
-#include "ScriptController.h"
-#include "Text.h"
-#include "XLinkNames.h"
-#include "XMLNSNames.h"
-#include "XMLNames.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-static const int uninitializedLineNumberValue = -1;
-
-static TextPosition1 uninitializedPositionValue1()
-{
- return TextPosition1(WTF::OneBasedNumber::fromOneBasedInt(-1), WTF::OneBasedNumber::base());
-}
-
-namespace {
-
-inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
-{
- return isHTMLSpace(character) || character == replacementCharacter;
-}
-
-inline bool isAllWhitespace(const String& string)
-{
- return string.isAllSpecialCharacters<isHTMLSpace>();
-}
-
-inline bool isAllWhitespaceOrReplacementCharacters(const String& string)
-{
- return string.isAllSpecialCharacters<isHTMLSpaceOrReplacementCharacter>();
-}
-
-bool isNumberedHeaderTag(const AtomicString& tagName)
-{
- return tagName == h1Tag
- || tagName == h2Tag
- || tagName == h3Tag
- || tagName == h4Tag
- || tagName == h5Tag
- || tagName == h6Tag;
-}
-
-bool isCaptionColOrColgroupTag(const AtomicString& tagName)
-{
- return tagName == captionTag
- || tagName == colTag
- || tagName == colgroupTag;
-}
-
-bool isTableCellContextTag(const AtomicString& tagName)
-{
- return tagName == thTag || tagName == tdTag;
-}
-
-bool isTableBodyContextTag(const AtomicString& tagName)
-{
- return tagName == tbodyTag
- || tagName == tfootTag
- || tagName == theadTag;
-}
-
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special
-bool isSpecialNode(Node* node)
-{
- if (node->hasTagName(MathMLNames::miTag)
- || node->hasTagName(MathMLNames::moTag)
- || node->hasTagName(MathMLNames::mnTag)
- || node->hasTagName(MathMLNames::msTag)
- || node->hasTagName(MathMLNames::mtextTag)
- || node->hasTagName(MathMLNames::annotation_xmlTag)
- || node->hasTagName(SVGNames::foreignObjectTag)
- || node->hasTagName(SVGNames::descTag)
- || node->hasTagName(SVGNames::titleTag))
- return true;
- if (node->namespaceURI() != xhtmlNamespaceURI)
- return false;
- const AtomicString& tagName = node->localName();
- return tagName == addressTag
- || tagName == appletTag
- || tagName == areaTag
- || tagName == articleTag
- || tagName == asideTag
- || tagName == baseTag
- || tagName == basefontTag
- || tagName == bgsoundTag
- || tagName == blockquoteTag
- || tagName == bodyTag
- || tagName == brTag
- || tagName == buttonTag
- || tagName == captionTag
- || tagName == centerTag
- || tagName == colTag
- || tagName == colgroupTag
- || tagName == commandTag
- || tagName == ddTag
- || tagName == detailsTag
- || tagName == dirTag
- || tagName == divTag
- || tagName == dlTag
- || tagName == dtTag
- || tagName == embedTag
- || tagName == fieldsetTag
- || tagName == figcaptionTag
- || tagName == figureTag
- || tagName == footerTag
- || tagName == formTag
- || tagName == frameTag
- || tagName == framesetTag
- || isNumberedHeaderTag(tagName)
- || tagName == headTag
- || tagName == headerTag
- || tagName == hgroupTag
- || tagName == hrTag
- || tagName == htmlTag
- || tagName == iframeTag
- || tagName == imgTag
- || tagName == inputTag
- || tagName == isindexTag
- || tagName == liTag
- || tagName == linkTag
- || tagName == listingTag
- || tagName == marqueeTag
- || tagName == menuTag
- || tagName == metaTag
- || tagName == navTag
- || tagName == noembedTag
- || tagName == noframesTag
- || tagName == noscriptTag
- || tagName == objectTag
- || tagName == olTag
- || tagName == pTag
- || tagName == paramTag
- || tagName == plaintextTag
- || tagName == preTag
- || tagName == scriptTag
- || tagName == sectionTag
- || tagName == selectTag
- || tagName == styleTag
- || tagName == summaryTag
- || tagName == tableTag
- || isTableBodyContextTag(tagName)
- || tagName == tdTag
- || tagName == textareaTag
- || tagName == thTag
- || tagName == titleTag
- || tagName == trTag
- || tagName == ulTag
- || tagName == wbrTag
- || tagName == xmpTag;
-}
-
-bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
-{
- return tagName == bTag
- || tagName == bigTag
- || tagName == codeTag
- || tagName == emTag
- || tagName == fontTag
- || tagName == iTag
- || tagName == sTag
- || tagName == smallTag
- || tagName == strikeTag
- || tagName == strongTag
- || tagName == ttTag
- || tagName == uTag;
-}
-
-bool isNonAnchorFormattingTag(const AtomicString& tagName)
-{
- return tagName == nobrTag
- || isNonAnchorNonNobrFormattingTag(tagName);
-}
-
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#formatting
-bool isFormattingTag(const AtomicString& tagName)
-{
- return tagName == aTag || isNonAnchorFormattingTag(tagName);
-}
-
-HTMLFormElement* closestFormAncestor(Element* element)
-{
- while (element) {
- if (element->hasTagName(formTag))
- return static_cast<HTMLFormElement*>(element);
- ContainerNode* parent = element->parentNode();
- if (!parent || !parent->isElementNode())
- return 0;
- element = static_cast<Element*>(parent);
- }
- return 0;
-}
-
-} // namespace
-
-class HTMLTreeBuilder::ExternalCharacterTokenBuffer : public Noncopyable {
-public:
- explicit ExternalCharacterTokenBuffer(AtomicHTMLToken& token)
- : m_current(token.characters().data())
- , m_end(m_current + token.characters().size())
- {
- ASSERT(!isEmpty());
- }
-
- explicit ExternalCharacterTokenBuffer(const String& string)
- : m_current(string.characters())
- , m_end(m_current + string.length())
- {
- ASSERT(!isEmpty());
- }
-
- ~ExternalCharacterTokenBuffer()
- {
- ASSERT(isEmpty());
- }
-
- bool isEmpty() const { return m_current == m_end; }
-
- void skipLeadingWhitespace()
- {
- skipLeading<isHTMLSpace>();
- }
-
- String takeLeadingWhitespace()
- {
- return takeLeading<isHTMLSpace>();
- }
-
- String takeLeadingNonWhitespace()
- {
- return takeLeading<isNotHTMLSpace>();
- }
-
- String takeRemaining()
- {
- ASSERT(!isEmpty());
- const UChar* start = m_current;
- m_current = m_end;
- return String(start, m_current - start);
- }
-
- void giveRemainingTo(Vector<UChar>& recipient)
- {
- recipient.append(m_current, m_end - m_current);
- m_current = m_end;
- }
-
- String takeRemainingWhitespace()
- {
- ASSERT(!isEmpty());
- Vector<UChar> whitespace;
- do {
- UChar cc = *m_current++;
- if (isHTMLSpace(cc))
- whitespace.append(cc);
- } while (m_current < m_end);
- // Returning the null string when there aren't any whitespace
- // characters is slightly cleaner semantically because we don't want
- // to insert a text node (as opposed to inserting an empty text node).
- if (whitespace.isEmpty())
- return String();
- return String::adopt(whitespace);
- }
-
-private:
- template<bool characterPredicate(UChar)>
- void skipLeading()
- {
- ASSERT(!isEmpty());
- while (characterPredicate(*m_current)) {
- if (++m_current == m_end)
- return;
- }
- }
-
- template<bool characterPredicate(UChar)>
- String takeLeading()
- {
- ASSERT(!isEmpty());
- const UChar* start = m_current;
- skipLeading<characterPredicate>();
- if (start == m_current)
- return String();
- return String(start, m_current - start);
- }
-
- const UChar* m_current;
- const UChar* m_end;
-};
-
-
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
- : m_framesetOk(true)
- , m_document(document)
- , m_tree(document, FragmentScriptingAllowed, false)
- , m_reportErrors(reportErrors)
- , m_isPaused(false)
- , m_insertionMode(InitialMode)
- , m_originalInsertionMode(InitialMode)
- , m_tokenizer(tokenizer)
- , m_scriptToProcessStartPosition(uninitializedPositionValue1())
- , m_lastScriptElementStartPosition(TextPosition0::belowRangePosition())
- , m_usePreHTML5ParserQuirks(usePreHTML5ParserQuirks)
- , m_hasPendingForeignInsertionModeSteps(false)
-{
-}
-
-// FIXME: Member variables should be grouped into self-initializing structs to
-// minimize code duplication between these constructors.
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
- : m_framesetOk(true)
- , m_fragmentContext(fragment, contextElement, scriptingPermission)
- , m_document(m_fragmentContext.document())
- , m_tree(m_document, scriptingPermission, true)
- , m_reportErrors(false) // FIXME: Why not report errors in fragments?
- , m_isPaused(false)
- , m_insertionMode(InitialMode)
- , m_originalInsertionMode(InitialMode)
- , m_tokenizer(tokenizer)
- , m_scriptToProcessStartPosition(uninitializedPositionValue1())
- , m_lastScriptElementStartPosition(TextPosition0::belowRangePosition())
- , m_usePreHTML5ParserQuirks(usePreHTML5ParserQuirks)
- , m_hasPendingForeignInsertionModeSteps(false)
-{
- if (contextElement) {
- // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm:
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
- m_document->setCompatibilityMode(contextElement->document()->compatibilityMode());
- processFakeStartTag(htmlTag);
- resetInsertionModeAppropriately();
- m_tree.setForm(closestFormAncestor(contextElement));
- }
-}
-
-HTMLTreeBuilder::~HTMLTreeBuilder()
-{
-}
-
-void HTMLTreeBuilder::detach()
-{
- // This call makes little sense in fragment mode, but for consistency
- // DocumentParser expects detach() to always be called before it's destroyed.
- m_document = 0;
- // HTMLConstructionSite might be on the callstack when detach() is called
- // otherwise we'd just call m_tree.clear() here instead.
- m_tree.detach();
-}
-
-HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
- : m_fragment(0)
- , m_contextElement(0)
- , m_scriptingPermission(FragmentScriptingAllowed)
-{
-}
-
-HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
- : m_dummyDocumentForFragmentParsing(HTMLDocument::create(0, KURL(), fragment->document()->baseURI()))
- , m_fragment(fragment)
- , m_contextElement(contextElement)
- , m_scriptingPermission(scriptingPermission)
-{
- m_dummyDocumentForFragmentParsing->setCompatibilityMode(fragment->document()->compatibilityMode());
-}
-
-Document* HTMLTreeBuilder::FragmentParsingContext::document() const
-{
- ASSERT(m_fragment);
- return m_dummyDocumentForFragmentParsing.get();
-}
-
-void HTMLTreeBuilder::FragmentParsingContext::finished()
-{
- // Populate the DocumentFragment with the parsed content now that we're done.
- ContainerNode* root = m_dummyDocumentForFragmentParsing.get();
- if (m_contextElement)
- root = m_dummyDocumentForFragmentParsing->documentElement();
- m_fragment->takeAllChildrenFrom(root);
-}
-
-HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
-{
-}
-
-PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition1& scriptStartPosition)
-{
- // Unpause ourselves, callers may pause us again when processing the script.
- // The HTML5 spec is written as though scripts are executed inside the tree
- // builder. We pause the parser to exit the tree builder, and then resume
- // before running scripts.
- m_isPaused = false;
- scriptStartPosition = m_scriptToProcessStartPosition;
- m_scriptToProcessStartPosition = uninitializedPositionValue1();
- return m_scriptToProcess.release();
-}
-
-void HTMLTreeBuilder::constructTreeFromToken(HTMLToken& rawToken)
-{
- AtomicHTMLToken token(rawToken);
- constructTreeFromAtomicToken(token);
-}
-
-void HTMLTreeBuilder::constructTreeFromAtomicToken(AtomicHTMLToken& token)
-{
- processToken(token);
-
- // Swallowing U+0000 characters isn't in the HTML5 spec, but turning all
- // the U+0000 characters into replacement characters has compatibility
- // problems.
- m_tokenizer->setForceNullCharacterReplacement(m_insertionMode == TextMode || m_insertionMode == InForeignContentMode);
- m_tokenizer->setShouldAllowCDATA(m_insertionMode == InForeignContentMode && m_tree.currentElement()->namespaceURI() != xhtmlNamespaceURI);
-}
-
-void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
-{
- switch (token.type()) {
- case HTMLToken::Uninitialized:
- ASSERT_NOT_REACHED();
- break;
- case HTMLToken::DOCTYPE:
- processDoctypeToken(token);
- break;
- case HTMLToken::StartTag:
- processStartTag(token);
- break;
- case HTMLToken::EndTag:
- processEndTag(token);
- break;
- case HTMLToken::Comment:
- processComment(token);
- return;
- case HTMLToken::Character:
- processCharacter(token);
- break;
- case HTMLToken::EndOfFile:
- processEndOfFile(token);
- break;
- }
-}
-
-void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::DOCTYPE);
- if (m_insertionMode == InitialMode) {
- m_tree.insertDoctype(token);
- setInsertionMode(BeforeHTMLMode);
- return;
- }
- if (m_insertionMode == InTableTextMode) {
- defaultForInTableText();
- processDoctypeToken(token);
- return;
- }
- parseError(token);
-}
-
-void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, PassRefPtr<NamedNodeMap> attributes)
-{
- // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
- AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), attributes);
- processStartTag(fakeToken);
-}
-
-void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
-{
- // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
- AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName.localName());
- processEndTag(fakeToken);
-}
-
-void HTMLTreeBuilder::processFakeCharacters(const String& characters)
-{
- ASSERT(!characters.isEmpty());
- ExternalCharacterTokenBuffer buffer(characters);
- processCharacterBuffer(buffer);
-}
-
-void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
-{
- if (!m_tree.openElements()->inButtonScope(pTag.localName()))
- return;
- AtomicHTMLToken endP(HTMLToken::EndTag, pTag.localName());
- processEndTag(endP);
-}
-
-PassRefPtr<NamedNodeMap> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token)
-{
- RefPtr<NamedNodeMap> attributes = token.takeAtributes();
- if (!attributes)
- attributes = NamedNodeMap::create();
- else {
- attributes->removeAttribute(nameAttr);
- attributes->removeAttribute(actionAttr);
- attributes->removeAttribute(promptAttr);
- }
-
- RefPtr<Attribute> mappedAttribute = Attribute::createMapped(nameAttr, isindexTag.localName());
- attributes->insertAttribute(mappedAttribute.release(), false);
- return attributes.release();
-}
-
-void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- ASSERT(token.name() == isindexTag);
- parseError(token);
- if (m_tree.form())
- return;
- notImplemented(); // Acknowledge self-closing flag
- processFakeStartTag(formTag);
- RefPtr<Attribute> actionAttribute = token.getAttributeItem(actionAttr);
- if (actionAttribute) {
- ASSERT(m_tree.currentElement()->hasTagName(formTag));
- m_tree.currentElement()->setAttribute(actionAttr, actionAttribute->value());
- }
- processFakeStartTag(hrTag);
- processFakeStartTag(labelTag);
- RefPtr<Attribute> promptAttribute = token.getAttributeItem(promptAttr);
- if (promptAttribute)
- processFakeCharacters(promptAttribute->value());
- else
- processFakeCharacters(searchableIndexIntroduction());
- processFakeStartTag(inputTag, attributesForIsindexInput(token));
- notImplemented(); // This second set of characters may be needed by non-english locales.
- processFakeEndTag(labelTag);
- processFakeStartTag(hrTag);
- processFakeEndTag(formTag);
-}
-
-namespace {
-
-bool isLi(const Element* element)
-{
- return element->hasTagName(liTag);
-}
-
-bool isDdOrDt(const Element* element)
-{
- return element->hasTagName(ddTag)
- || element->hasTagName(dtTag);
-}
-
-}
-
-template <bool shouldClose(const Element*)>
-void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken& token)
-{
- m_framesetOk = false;
- HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
- while (1) {
- Element* node = nodeRecord->element();
- if (shouldClose(node)) {
- processFakeEndTag(node->tagQName());
- break;
- }
- if (isSpecialNode(node) && !node->hasTagName(addressTag) && !node->hasTagName(divTag) && !node->hasTagName(pTag))
- break;
- nodeRecord = nodeRecord->next();
- }
- processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
-}
-
-namespace {
-
-typedef HashMap<AtomicString, QualifiedName> PrefixedNameToQualifiedNameMap;
-
-void mapLoweredLocalNameToName(PrefixedNameToQualifiedNameMap* map, QualifiedName** names, size_t length)
-{
- for (size_t i = 0; i < length; ++i) {
- const QualifiedName& name = *names[i];
- const AtomicString& localName = name.localName();
- AtomicString loweredLocalName = localName.lower();
- if (loweredLocalName != localName)
- map->add(loweredLocalName, name);
- }
-}
-
-void adjustSVGTagNameCase(AtomicHTMLToken& token)
-{
- static PrefixedNameToQualifiedNameMap* caseMap = 0;
- if (!caseMap) {
- caseMap = new PrefixedNameToQualifiedNameMap;
- size_t length = 0;
- QualifiedName** svgTags = SVGNames::getSVGTags(&length);
- mapLoweredLocalNameToName(caseMap, svgTags, length);
- }
-
- const QualifiedName& casedName = caseMap->get(token.name());
- if (casedName.localName().isNull())
- return;
- token.setName(casedName.localName());
-}
-
-template<QualifiedName** getAttrs(size_t* length)>
-void adjustAttributes(AtomicHTMLToken& token)
-{
- static PrefixedNameToQualifiedNameMap* caseMap = 0;
- if (!caseMap) {
- caseMap = new PrefixedNameToQualifiedNameMap;
- size_t length = 0;
- QualifiedName** attrs = getAttrs(&length);
- mapLoweredLocalNameToName(caseMap, attrs, length);
- }
-
- NamedNodeMap* attributes = token.attributes();
- if (!attributes)
- return;
-
- for (unsigned x = 0; x < attributes->length(); ++x) {
- Attribute* attribute = attributes->attributeItem(x);
- const QualifiedName& casedName = caseMap->get(attribute->localName());
- if (!casedName.localName().isNull())
- attribute->parserSetName(casedName);
- }
-}
-
-void adjustSVGAttributes(AtomicHTMLToken& token)
-{
- adjustAttributes<SVGNames::getSVGAttrs>(token);
-}
-
-void adjustMathMLAttributes(AtomicHTMLToken& token)
-{
- adjustAttributes<MathMLNames::getMathMLAttrs>(token);
-}
-
-void addNamesWithPrefix(PrefixedNameToQualifiedNameMap* map, const AtomicString& prefix, QualifiedName** names, size_t length)
-{
- for (size_t i = 0; i < length; ++i) {
- QualifiedName* name = names[i];
- const AtomicString& localName = name->localName();
- AtomicString prefixColonLocalName(prefix + ":" + localName);
- QualifiedName nameWithPrefix(prefix, localName, name->namespaceURI());
- map->add(prefixColonLocalName, nameWithPrefix);
- }
-}
-
-void adjustForeignAttributes(AtomicHTMLToken& token)
-{
- static PrefixedNameToQualifiedNameMap* map = 0;
- if (!map) {
- map = new PrefixedNameToQualifiedNameMap;
- size_t length = 0;
- QualifiedName** attrs = XLinkNames::getXLinkAttrs(&length);
- addNamesWithPrefix(map, "xlink", attrs, length);
-
- attrs = XMLNames::getXMLAttrs(&length);
- addNamesWithPrefix(map, "xml", attrs, length);
-
- map->add("xmlns", XMLNSNames::xmlnsAttr);
- map->add("xmlns:xlink", QualifiedName("xmlns", "xlink", XMLNSNames::xmlnsNamespaceURI));
- }
-
- NamedNodeMap* attributes = token.attributes();
- if (!attributes)
- return;
-
- for (unsigned x = 0; x < attributes->length(); ++x) {
- Attribute* attribute = attributes->attributeItem(x);
- const QualifiedName& name = map->get(attribute->localName());
- if (!name.localName().isNull())
- attribute->parserSetName(name);
- }
-}
-
-}
-
-void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == baseTag
- || token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == commandTag
- || token.name() == linkTag
- || token.name() == metaTag
- || token.name() == noframesTag
- || token.name() == scriptTag
- || token.name() == styleTag
- || token.name() == titleTag) {
- bool didProcess = processStartTagForInHead(token);
- ASSERT_UNUSED(didProcess, didProcess);
- return;
- }
- if (token.name() == bodyTag) {
- if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
- ASSERT(isParsingFragment());
- return;
- }
- m_tree.insertHTMLBodyStartTagInBody(token);
- return;
- }
- if (token.name() == framesetTag) {
- parseError(token);
- if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
- ASSERT(isParsingFragment());
- return;
- }
- if (!m_framesetOk)
- return;
- ExceptionCode ec = 0;
- m_tree.openElements()->bodyElement()->remove(ec);
- ASSERT(!ec);
- m_tree.openElements()->popUntil(m_tree.openElements()->bodyElement());
- m_tree.openElements()->popHTMLBodyElement();
- ASSERT(m_tree.openElements()->top() == m_tree.openElements()->htmlElement());
- m_tree.insertHTMLElement(token);
- setInsertionMode(InFramesetMode);
- return;
- }
- if (token.name() == addressTag
- || token.name() == articleTag
- || token.name() == asideTag
- || token.name() == blockquoteTag
- || token.name() == centerTag
- || token.name() == detailsTag
- || token.name() == dirTag
- || token.name() == divTag
- || token.name() == dlTag
- || token.name() == fieldsetTag
- || token.name() == figcaptionTag
- || token.name() == figureTag
- || token.name() == footerTag
- || token.name() == headerTag
- || token.name() == hgroupTag
- || token.name() == menuTag
- || token.name() == navTag
- || token.name() == olTag
- || token.name() == pTag
- || token.name() == sectionTag
- || token.name() == summaryTag
- || token.name() == ulTag) {
- processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
- return;
- }
- if (isNumberedHeaderTag(token.name())) {
- processFakePEndTagIfPInButtonScope();
- if (isNumberedHeaderTag(m_tree.currentElement()->localName())) {
- parseError(token);
- m_tree.openElements()->pop();
- }
- m_tree.insertHTMLElement(token);
- return;
- }
- if (token.name() == preTag || token.name() == listingTag) {
- processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
- m_tokenizer->setSkipLeadingNewLineForListing(true);
- m_framesetOk = false;
- return;
- }
- if (token.name() == formTag) {
- if (m_tree.form()) {
- parseError(token);
- return;
- }
- processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLFormElement(token);
- return;
- }
- if (token.name() == liTag) {
- processCloseWhenNestedTag<isLi>(token);
- return;
- }
- if (token.name() == ddTag || token.name() == dtTag) {
- processCloseWhenNestedTag<isDdOrDt>(token);
- return;
- }
- if (token.name() == plaintextTag) {
- processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
- m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
- return;
- }
- if (token.name() == buttonTag) {
- if (m_tree.openElements()->inScope(buttonTag)) {
- parseError(token);
- processFakeEndTag(buttonTag);
- reprocessStartTag(token); // FIXME: Could we just fall through here?
- return;
- }
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
- m_framesetOk = false;
- return;
- }
- if (token.name() == aTag) {
- Element* activeATag = m_tree.activeFormattingElements()->closestElementInScopeWithName(aTag.localName());
- if (activeATag) {
- parseError(token);
- processFakeEndTag(aTag);
- m_tree.activeFormattingElements()->remove(activeATag);
- if (m_tree.openElements()->contains(activeATag))
- m_tree.openElements()->remove(activeATag);
- }
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertFormattingElement(token);
- return;
- }
- if (isNonAnchorNonNobrFormattingTag(token.name())) {
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertFormattingElement(token);
- return;
- }
- if (token.name() == nobrTag) {
- m_tree.reconstructTheActiveFormattingElements();
- if (m_tree.openElements()->inScope(nobrTag)) {
- parseError(token);
- processFakeEndTag(nobrTag);
- m_tree.reconstructTheActiveFormattingElements();
- }
- m_tree.insertFormattingElement(token);
- return;
- }
- if (token.name() == appletTag
- || token.name() == marqueeTag
- || token.name() == objectTag) {
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
- m_tree.activeFormattingElements()->appendMarker();
- m_framesetOk = false;
- return;
- }
- if (token.name() == tableTag) {
- if (!m_document->inQuirksMode() && m_tree.openElements()->inButtonScope(pTag))
- processFakeEndTag(pTag);
- m_tree.insertHTMLElement(token);
- m_framesetOk = false;
- setInsertionMode(InTableMode);
- return;
- }
- if (token.name() == imageTag) {
- parseError(token);
- // Apparently we're not supposed to ask.
- token.setName(imgTag.localName());
- prepareToReprocessToken();
- // Note the fall through to the imgTag handling below!
- }
- if (token.name() == areaTag
- || token.name() == brTag
- || token.name() == embedTag
- || token.name() == imgTag
- || token.name() == inputTag
- || token.name() == keygenTag
- || token.name() == wbrTag) {
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertSelfClosingHTMLElement(token);
- m_framesetOk = false;
- return;
- }
- if (token.name() == paramTag
- || token.name() == sourceTag
- || token.name() == trackTag) {
- m_tree.insertSelfClosingHTMLElement(token);
- return;
- }
- if (token.name() == hrTag) {
- processFakePEndTagIfPInButtonScope();
- m_tree.insertSelfClosingHTMLElement(token);
- m_framesetOk = false;
- return;
- }
- if (token.name() == isindexTag) {
- processIsindexStartTagForInBody(token);
- return;
- }
- if (token.name() == textareaTag) {
- m_tree.insertHTMLElement(token);
- m_tokenizer->setSkipLeadingNewLineForListing(true);
- m_tokenizer->setState(HTMLTokenizer::RCDATAState);
- m_originalInsertionMode = m_insertionMode;
- m_framesetOk = false;
- setInsertionMode(TextMode);
- return;
- }
- if (token.name() == xmpTag) {
- processFakePEndTagIfPInButtonScope();
- m_tree.reconstructTheActiveFormattingElements();
- m_framesetOk = false;
- processGenericRawTextStartTag(token);
- return;
- }
- if (token.name() == iframeTag) {
- m_framesetOk = false;
- processGenericRawTextStartTag(token);
- return;
- }
- if (token.name() == noembedTag && pluginsEnabled(m_document->frame())) {
- processGenericRawTextStartTag(token);
- return;
- }
- if (token.name() == noscriptTag && scriptEnabled(m_document->frame())) {
- processGenericRawTextStartTag(token);
- return;
- }
- if (token.name() == selectTag) {
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
- m_framesetOk = false;
- if (m_insertionMode == InTableMode
- || m_insertionMode == InCaptionMode
- || m_insertionMode == InColumnGroupMode
- || m_insertionMode == InTableBodyMode
- || m_insertionMode == InRowMode
- || m_insertionMode == InCellMode)
- setInsertionMode(InSelectInTableMode);
- else
- setInsertionMode(InSelectMode);
- return;
- }
- if (token.name() == optgroupTag || token.name() == optionTag) {
- if (m_tree.openElements()->inScope(optionTag.localName())) {
- AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(endOption);
- }
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
- return;
- }
- if (token.name() == rpTag || token.name() == rtTag) {
- if (m_tree.openElements()->inScope(rubyTag.localName())) {
- m_tree.generateImpliedEndTags();
- if (!m_tree.currentElement()->hasTagName(rubyTag)) {
- parseError(token);
- m_tree.openElements()->popUntil(rubyTag.localName());
- }
- }
- m_tree.insertHTMLElement(token);
- return;
- }
- if (token.name() == MathMLNames::mathTag.localName()) {
- m_tree.reconstructTheActiveFormattingElements();
- adjustMathMLAttributes(token);
- adjustForeignAttributes(token);
- m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI);
- if (m_insertionMode != InForeignContentMode)
- setInsertionMode(InForeignContentMode);
- return;
- }
- if (token.name() == SVGNames::svgTag.localName()) {
- m_tree.reconstructTheActiveFormattingElements();
- adjustSVGAttributes(token);
- adjustForeignAttributes(token);
- m_tree.insertForeignElement(token, SVGNames::svgNamespaceURI);
- if (m_insertionMode != InForeignContentMode)
- setInsertionMode(InForeignContentMode);
- return;
- }
- if (isCaptionColOrColgroupTag(token.name())
- || token.name() == frameTag
- || token.name() == headTag
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
- parseError(token);
- return;
- }
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
-}
-
-bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
-{
- if (m_tree.currentElement() == m_tree.openElements()->htmlElement()) {
- ASSERT(isParsingFragment());
- // FIXME: parse error
- return false;
- }
- m_tree.openElements()->pop();
- setInsertionMode(InTableMode);
- return true;
-}
-
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
-void HTMLTreeBuilder::closeTheCell()
-{
- ASSERT(insertionMode() == InCellMode);
- if (m_tree.openElements()->inTableScope(tdTag)) {
- ASSERT(!m_tree.openElements()->inTableScope(thTag));
- processFakeEndTag(tdTag);
- return;
- }
- ASSERT(m_tree.openElements()->inTableScope(thTag));
- processFakeEndTag(thTag);
- ASSERT(insertionMode() == InRowMode);
-}
-
-void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- if (token.name() == captionTag) {
- m_tree.openElements()->popUntilTableScopeMarker();
- m_tree.activeFormattingElements()->appendMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InCaptionMode);
- return;
- }
- if (token.name() == colgroupTag) {
- m_tree.openElements()->popUntilTableScopeMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InColumnGroupMode);
- return;
- }
- if (token.name() == colTag) {
- processFakeStartTag(colgroupTag);
- ASSERT(InColumnGroupMode);
- reprocessStartTag(token);
- return;
- }
- if (isTableBodyContextTag(token.name())) {
- m_tree.openElements()->popUntilTableScopeMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InTableBodyMode);
- return;
- }
- if (isTableCellContextTag(token.name())
- || token.name() == trTag) {
- processFakeStartTag(tbodyTag);
- ASSERT(insertionMode() == InTableBodyMode);
- reprocessStartTag(token);
- return;
- }
- if (token.name() == tableTag) {
- parseError(token);
- if (!processTableEndTagForInTable()) {
- ASSERT(isParsingFragment());
- return;
- }
- reprocessStartTag(token);
- return;
- }
- if (token.name() == styleTag || token.name() == scriptTag) {
- processStartTagForInHead(token);
- return;
- }
- if (token.name() == inputTag) {
- Attribute* typeAttribute = token.getAttributeItem(typeAttr);
- if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
- parseError(token);
- m_tree.insertSelfClosingHTMLElement(token);
- return;
- }
- // Fall through to "anything else" case.
- }
- if (token.name() == formTag) {
- parseError(token);
- if (m_tree.form())
- return;
- m_tree.insertHTMLFormElement(token, true);
- m_tree.openElements()->pop();
- return;
- }
- parseError(token);
- HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
- processStartTagForInBody(token);
-}
-
-namespace {
-
-bool shouldProcessForeignContentUsingInBodyInsertionMode(AtomicHTMLToken& token, Element* currentElement)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- if (currentElement->hasTagName(MathMLNames::miTag)
- || currentElement->hasTagName(MathMLNames::moTag)
- || currentElement->hasTagName(MathMLNames::mnTag)
- || currentElement->hasTagName(MathMLNames::msTag)
- || currentElement->hasTagName(MathMLNames::mtextTag)) {
- return token.name() != MathMLNames::mglyphTag
- && token.name() != MathMLNames::malignmarkTag;
- }
- if (currentElement->hasTagName(MathMLNames::annotation_xmlTag))
- return token.name() == SVGNames::svgTag;
- if (currentElement->hasTagName(SVGNames::foreignObjectTag)
- || currentElement->hasTagName(SVGNames::descTag)
- || currentElement->hasTagName(SVGNames::titleTag))
- return true;
- return currentElement->namespaceURI() == HTMLNames::xhtmlNamespaceURI;
-}
-
-}
-
-void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- switch (insertionMode()) {
- case InitialMode:
- ASSERT(insertionMode() == InitialMode);
- defaultForInitial();
- // Fall through.
- case BeforeHTMLMode:
- ASSERT(insertionMode() == BeforeHTMLMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagBeforeHTML(token);
- setInsertionMode(BeforeHeadMode);
- return;
- }
- defaultForBeforeHTML();
- // Fall through.
- case BeforeHeadMode:
- ASSERT(insertionMode() == BeforeHeadMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == headTag) {
- m_tree.insertHTMLHeadElement(token);
- setInsertionMode(InHeadMode);
- return;
- }
- defaultForBeforeHead();
- // Fall through.
- case InHeadMode:
- ASSERT(insertionMode() == InHeadMode);
- if (processStartTagForInHead(token))
- return;
- defaultForInHead();
- // Fall through.
- case AfterHeadMode:
- ASSERT(insertionMode() == AfterHeadMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == bodyTag) {
- m_framesetOk = false;
- m_tree.insertHTMLBodyElement(token);
- setInsertionMode(InBodyMode);
- return;
- }
- if (token.name() == framesetTag) {
- m_tree.insertHTMLElement(token);
- setInsertionMode(InFramesetMode);
- return;
- }
- if (token.name() == baseTag
- || token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == linkTag
- || token.name() == metaTag
- || token.name() == noframesTag
- || token.name() == scriptTag
- || token.name() == styleTag
- || token.name() == titleTag) {
- parseError(token);
- ASSERT(m_tree.head());
- m_tree.openElements()->pushHTMLHeadElement(m_tree.head());
- processStartTagForInHead(token);
- m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
- return;
- }
- if (token.name() == headTag) {
- parseError(token);
- return;
- }
- defaultForAfterHead();
- // Fall through
- case InBodyMode:
- ASSERT(insertionMode() == InBodyMode);
- processStartTagForInBody(token);
- break;
- case InTableMode:
- ASSERT(insertionMode() == InTableMode);
- processStartTagForInTable(token);
- break;
- case InCaptionMode:
- ASSERT(insertionMode() == InCaptionMode);
- if (isCaptionColOrColgroupTag(token.name())
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
- parseError(token);
- if (!processCaptionEndTagForInCaption()) {
- ASSERT(isParsingFragment());
- return;
- }
- reprocessStartTag(token);
- return;
- }
- processStartTagForInBody(token);
- break;
- case InColumnGroupMode:
- ASSERT(insertionMode() == InColumnGroupMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == colTag) {
- m_tree.insertSelfClosingHTMLElement(token);
- return;
- }
- if (!processColgroupEndTagForInColumnGroup()) {
- ASSERT(isParsingFragment());
- return;
- }
- reprocessStartTag(token);
- break;
- case InTableBodyMode:
- ASSERT(insertionMode() == InTableBodyMode);
- if (token.name() == trTag) {
- m_tree.openElements()->popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
- m_tree.insertHTMLElement(token);
- setInsertionMode(InRowMode);
- return;
- }
- if (isTableCellContextTag(token.name())) {
- parseError(token);
- processFakeStartTag(trTag);
- ASSERT(insertionMode() == InRowMode);
- reprocessStartTag(token);
- return;
- }
- if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name())) {
- // FIXME: This is slow.
- if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
- ASSERT(isParsingFragment());
- parseError(token);
- return;
- }
- m_tree.openElements()->popUntilTableBodyScopeMarker();
- ASSERT(isTableBodyContextTag(m_tree.currentElement()->localName()));
- processFakeEndTag(m_tree.currentElement()->tagQName());
- reprocessStartTag(token);
- return;
- }
- processStartTagForInTable(token);
- break;
- case InRowMode:
- ASSERT(insertionMode() == InRowMode);
- if (isTableCellContextTag(token.name())) {
- m_tree.openElements()->popUntilTableRowScopeMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InCellMode);
- m_tree.activeFormattingElements()->appendMarker();
- return;
- }
- if (token.name() == trTag
- || isCaptionColOrColgroupTag(token.name())
- || isTableBodyContextTag(token.name())) {
- if (!processTrEndTagForInRow()) {
- ASSERT(isParsingFragment());
- return;
- }
- ASSERT(insertionMode() == InTableBodyMode);
- reprocessStartTag(token);
- return;
- }
- processStartTagForInTable(token);
- break;
- case InCellMode:
- ASSERT(insertionMode() == InCellMode);
- if (isCaptionColOrColgroupTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag
- || isTableBodyContextTag(token.name())) {
- // FIXME: This could be more efficient.
- if (!m_tree.openElements()->inTableScope(tdTag) && !m_tree.openElements()->inTableScope(thTag)) {
- ASSERT(isParsingFragment());
- parseError(token);
- return;
- }
- closeTheCell();
- reprocessStartTag(token);
- return;
- }
- processStartTagForInBody(token);
- break;
- case AfterBodyMode:
- case AfterAfterBodyMode:
- ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- setInsertionMode(InBodyMode);
- reprocessStartTag(token);
- break;
- case InHeadNoscriptMode:
- ASSERT(insertionMode() == InHeadNoscriptMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == linkTag
- || token.name() == metaTag
- || token.name() == noframesTag
- || token.name() == styleTag) {
- bool didProcess = processStartTagForInHead(token);
- ASSERT_UNUSED(didProcess, didProcess);
- return;
- }
- if (token.name() == htmlTag || token.name() == noscriptTag) {
- parseError(token);
- return;
- }
- defaultForInHeadNoscript();
- processToken(token);
- break;
- case InFramesetMode:
- ASSERT(insertionMode() == InFramesetMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == framesetTag) {
- m_tree.insertHTMLElement(token);
- return;
- }
- if (token.name() == frameTag) {
- m_tree.insertSelfClosingHTMLElement(token);
- return;
- }
- if (token.name() == noframesTag) {
- processStartTagForInHead(token);
- return;
- }
- parseError(token);
- break;
- case AfterFramesetMode:
- case AfterAfterFramesetMode:
- ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == noframesTag) {
- processStartTagForInHead(token);
- return;
- }
- parseError(token);
- break;
- case InSelectInTableMode:
- ASSERT(insertionMode() == InSelectInTableMode);
- if (token.name() == captionTag
- || token.name() == tableTag
- || isTableBodyContextTag(token.name())
- || token.name() == trTag
- || isTableCellContextTag(token.name())) {
- parseError(token);
- AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
- reprocessStartTag(token);
- return;
- }
- // Fall through
- case InSelectMode:
- ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return;
- }
- if (token.name() == optionTag) {
- if (m_tree.currentElement()->hasTagName(optionTag)) {
- AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(endOption);
- }
- m_tree.insertHTMLElement(token);
- return;
- }
- if (token.name() == optgroupTag) {
- if (m_tree.currentElement()->hasTagName(optionTag)) {
- AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(endOption);
- }
- if (m_tree.currentElement()->hasTagName(optgroupTag)) {
- AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName());
- processEndTag(endOptgroup);
- }
- m_tree.insertHTMLElement(token);
- return;
- }
- if (token.name() == selectTag) {
- parseError(token);
- AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
- return;
- }
- if (token.name() == inputTag
- || token.name() == keygenTag
- || token.name() == textareaTag) {
- parseError(token);
- if (!m_tree.openElements()->inSelectScope(selectTag)) {
- ASSERT(isParsingFragment());
- return;
- }
- AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
- reprocessStartTag(token);
- return;
- }
- if (token.name() == scriptTag) {
- bool didProcess = processStartTagForInHead(token);
- ASSERT_UNUSED(didProcess, didProcess);
- return;
- }
- break;
- case InTableTextMode:
- defaultForInTableText();
- processStartTag(token);
- break;
- case InForeignContentMode: {
- if (shouldProcessForeignContentUsingInBodyInsertionMode(token, m_tree.currentElement())) {
- processForeignContentUsingInBodyModeAndResetMode(token);
- return;
- }
- if (token.name() == bTag
- || token.name() == bigTag
- || token.name() == blockquoteTag
- || token.name() == bodyTag
- || token.name() == brTag
- || token.name() == centerTag
- || token.name() == codeTag
- || token.name() == ddTag
- || token.name() == divTag
- || token.name() == dlTag
- || token.name() == dtTag
- || token.name() == emTag
- || token.name() == embedTag
- || isNumberedHeaderTag(token.name())
- || token.name() == headTag
- || token.name() == hrTag
- || token.name() == iTag
- || token.name() == imgTag
- || token.name() == liTag
- || token.name() == listingTag
- || token.name() == menuTag
- || token.name() == metaTag
- || token.name() == nobrTag
- || token.name() == olTag
- || token.name() == pTag
- || token.name() == preTag
- || token.name() == rubyTag
- || token.name() == sTag
- || token.name() == smallTag
- || token.name() == spanTag
- || token.name() == strongTag
- || token.name() == strikeTag
- || token.name() == subTag
- || token.name() == supTag
- || token.name() == tableTag
- || token.name() == ttTag
- || token.name() == uTag
- || token.name() == ulTag
- || token.name() == varTag
- || (token.name() == fontTag && (token.getAttributeItem(colorAttr) || token.getAttributeItem(faceAttr) || token.getAttributeItem(sizeAttr)))) {
- parseError(token);
- m_tree.openElements()->popUntilForeignContentScopeMarker();
- resetInsertionModeAppropriately();
- reprocessStartTag(token);
- return;
- }
- const AtomicString& currentNamespace = m_tree.currentElement()->namespaceURI();
- if (currentNamespace == MathMLNames::mathmlNamespaceURI)
- adjustMathMLAttributes(token);
- if (currentNamespace == SVGNames::svgNamespaceURI) {
- adjustSVGTagNameCase(token);
- adjustSVGAttributes(token);
- }
- adjustForeignAttributes(token);
- m_tree.insertForeignElement(token, currentNamespace);
- break;
- }
- case TextMode:
- ASSERT_NOT_REACHED();
- break;
- }
-}
-
-bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- ASSERT(token.name() == bodyTag);
- if (!m_tree.openElements()->inScope(bodyTag.localName())) {
- parseError(token);
- return false;
- }
- notImplemented(); // Emit a more specific parse error based on stack contents.
- setInsertionMode(AfterBodyMode);
- return true;
-}
-
-void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
- while (1) {
- Element* node = record->element();
- if (node->hasLocalName(token.name())) {
- m_tree.generateImpliedEndTags();
- if (!m_tree.currentElement()->hasLocalName(token.name())) {
- parseError(token);
- // FIXME: This is either a bug in the spec, or a bug in our
- // implementation. Filed a bug with HTML5:
- // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10080
- // We might have already popped the node for the token in
- // generateImpliedEndTags, just abort.
- if (!m_tree.openElements()->contains(node))
- return;
- }
- m_tree.openElements()->popUntilPopped(node);
- return;
- }
- if (isSpecialNode(node)) {
- parseError(token);
- return;
- }
- record = record->next();
- }
-}
-
-// FIXME: This probably belongs on HTMLElementStack.
-HTMLElementStack::ElementRecord* HTMLTreeBuilder::furthestBlockForFormattingElement(Element* formattingElement)
-{
- HTMLElementStack::ElementRecord* furthestBlock = 0;
- HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
- for (; record; record = record->next()) {
- if (record->element() == formattingElement)
- return furthestBlock;
- if (isSpecialNode(record->element()))
- furthestBlock = record;
- }
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
-void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
-{
- // The adoption agency algorithm is N^2. We limit the number of iterations
- // to stop from hanging the whole browser. This limit is copied from the
- // legacy tree builder and might need to be tweaked in the future.
- static const int adoptionAgencyIterationLimit = 10;
-
- for (int i = 0; i < adoptionAgencyIterationLimit; ++i) {
- // 1.
- Element* formattingElement = m_tree.activeFormattingElements()->closestElementInScopeWithName(token.name());
- if (!formattingElement || ((m_tree.openElements()->contains(formattingElement)) && !m_tree.openElements()->inScope(formattingElement))) {
- parseError(token);
- notImplemented(); // Check the stack of open elements for a more specific parse error.
- return;
- }
- HTMLElementStack::ElementRecord* formattingElementRecord = m_tree.openElements()->find(formattingElement);
- if (!formattingElementRecord) {
- parseError(token);
- m_tree.activeFormattingElements()->remove(formattingElement);
- return;
- }
- if (formattingElement != m_tree.currentElement())
- parseError(token);
- // 2.
- HTMLElementStack::ElementRecord* furthestBlock = furthestBlockForFormattingElement(formattingElement);
- // 3.
- if (!furthestBlock) {
- m_tree.openElements()->popUntilPopped(formattingElement);
- m_tree.activeFormattingElements()->remove(formattingElement);
- return;
- }
- // 4.
- ASSERT(furthestBlock->isAbove(formattingElementRecord));
- Element* commonAncestor = formattingElementRecord->next()->element();
- // 5.
- HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
- // 6.
- HTMLElementStack::ElementRecord* node = furthestBlock;
- HTMLElementStack::ElementRecord* nextNode = node->next();
- HTMLElementStack::ElementRecord* lastNode = furthestBlock;
- for (int i = 0; i < adoptionAgencyIterationLimit; ++i) {
- // 6.1
- node = nextNode;
- ASSERT(node);
- nextNode = node->next(); // Save node->next() for the next iteration in case node is deleted in 6.2.
- // 6.2
- if (!m_tree.activeFormattingElements()->contains(node->element())) {
- m_tree.openElements()->remove(node->element());
- node = 0;
- continue;
- }
- // 6.3
- if (node == formattingElementRecord)
- break;
- // 6.5
- RefPtr<Element> newElement = m_tree.createHTMLElementFromElementRecord(node);
- HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements()->find(node->element());
- nodeEntry->replaceElement(newElement.get());
- node->replaceElement(newElement.release());
- // 6.4 -- Intentionally out of order to handle the case where node
- // was replaced in 6.5.
- // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10096
- if (lastNode == furthestBlock)
- bookmark.moveToAfter(nodeEntry);
- // 6.6
- if (Element* parent = lastNode->element()->parentElement())
- parent->parserRemoveChild(lastNode->element());
- node->element()->parserAddChild(lastNode->element());
- if (lastNode->element()->parentElement()->attached() && !lastNode->element()->attached())
- lastNode->element()->lazyAttach();
- // 6.7
- lastNode = node;
- }
- // 7
- const AtomicString& commonAncestorTag = commonAncestor->localName();
- if (Element* parent = lastNode->element()->parentElement())
- parent->parserRemoveChild(lastNode->element());
- // FIXME: If this moves to HTMLConstructionSite, this check should use
- // causesFosterParenting(tagName) instead.
- if (commonAncestorTag == tableTag
- || commonAncestorTag == trTag
- || isTableBodyContextTag(commonAncestorTag))
- m_tree.fosterParent(lastNode->element());
- else {
- commonAncestor->parserAddChild(lastNode->element());
- if (lastNode->element()->parentElement()->attached() && !lastNode->element()->attached())
- lastNode->element()->lazyAttach();
- }
- // 8
- RefPtr<Element> newElement = m_tree.createHTMLElementFromElementRecord(formattingElementRecord);
- // 9
- newElement->takeAllChildrenFrom(furthestBlock->element());
- // 10
- Element* furthestBlockElement = furthestBlock->element();
- // FIXME: All this creation / parserAddChild / attach business should
- // be in HTMLConstructionSite. My guess is that steps 8--12
- // should all be in some HTMLConstructionSite function.
- furthestBlockElement->parserAddChild(newElement);
- if (furthestBlockElement->attached() && !newElement->attached()) {
- // Notice that newElement might already be attached if, for example, one of the reparented
- // children is a style element, which attaches itself automatically.
- newElement->attach();
- }
- // 11
- m_tree.activeFormattingElements()->swapTo(formattingElement, newElement.get(), bookmark);
- // 12
- m_tree.openElements()->remove(formattingElement);
- m_tree.openElements()->insertAbove(newElement, furthestBlock);
- }
-}
-
-void HTMLTreeBuilder::resetInsertionModeAppropriately()
-{
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#reset-the-insertion-mode-appropriately
- bool last = false;
- HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
- while (1) {
- Element* node = nodeRecord->element();
- if (node == m_tree.openElements()->bottom()) {
- ASSERT(isParsingFragment());
- last = true;
- node = m_fragmentContext.contextElement();
- }
- if (node->hasTagName(selectTag)) {
- ASSERT(isParsingFragment());
- return setInsertionMode(InSelectMode);
- }
- if (node->hasTagName(tdTag) || node->hasTagName(thTag))
- return setInsertionMode(InCellMode);
- if (node->hasTagName(trTag))
- return setInsertionMode(InRowMode);
- if (node->hasTagName(tbodyTag) || node->hasTagName(theadTag) || node->hasTagName(tfootTag))
- return setInsertionMode(InTableBodyMode);
- if (node->hasTagName(captionTag))
- return setInsertionMode(InCaptionMode);
- if (node->hasTagName(colgroupTag)) {
- ASSERT(isParsingFragment());
- return setInsertionMode(InColumnGroupMode);
- }
- if (node->hasTagName(tableTag))
- return setInsertionMode(InTableMode);
- if (node->hasTagName(headTag)) {
- ASSERT(isParsingFragment());
- return setInsertionMode(InBodyMode);
- }
- if (node->hasTagName(bodyTag))
- return setInsertionMode(InBodyMode);
- if (node->hasTagName(framesetTag)) {
- ASSERT(isParsingFragment());
- return setInsertionMode(InFramesetMode);
- }
- if (node->hasTagName(htmlTag)) {
- ASSERT(isParsingFragment());
- return setInsertionMode(BeforeHeadMode);
- }
- if (node->namespaceURI() == SVGNames::svgNamespaceURI
- || node->namespaceURI() == MathMLNames::mathmlNamespaceURI)
- return setInsertionMode(InForeignContentMode);
- if (last) {
- ASSERT(isParsingFragment());
- return setInsertionMode(InBodyMode);
- }
- nodeRecord = nodeRecord->next();
- }
-}
-
-void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (isTableBodyContextTag(token.name())) {
- if (!m_tree.openElements()->inTableScope(token.name())) {
- parseError(token);
- return;
- }
- m_tree.openElements()->popUntilTableBodyScopeMarker();
- m_tree.openElements()->pop();
- setInsertionMode(InTableMode);
- return;
- }
- if (token.name() == tableTag) {
- // FIXME: This is slow.
- if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
- ASSERT(isParsingFragment());
- parseError(token);
- return;
- }
- m_tree.openElements()->popUntilTableBodyScopeMarker();
- ASSERT(isTableBodyContextTag(m_tree.currentElement()->localName()));
- processFakeEndTag(m_tree.currentElement()->tagQName());
- reprocessEndTag(token);
- return;
- }
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
- parseError(token);
- return;
- }
- processEndTagForInTable(token);
-}
-
-void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (token.name() == trTag) {
- processTrEndTagForInRow();
- return;
- }
- if (token.name() == tableTag) {
- if (!processTrEndTagForInRow()) {
- ASSERT(isParsingFragment());
- return;
- }
- ASSERT(insertionMode() == InTableBodyMode);
- reprocessEndTag(token);
- return;
- }
- if (isTableBodyContextTag(token.name())) {
- if (!m_tree.openElements()->inTableScope(token.name())) {
- parseError(token);
- return;
- }
- processFakeEndTag(trTag);
- ASSERT(insertionMode() == InTableBodyMode);
- reprocessEndTag(token);
- return;
- }
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag
- || isTableCellContextTag(token.name())) {
- parseError(token);
- return;
- }
- processEndTagForInTable(token);
-}
-
-void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (isTableCellContextTag(token.name())) {
- if (!m_tree.openElements()->inTableScope(token.name())) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTags();
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilPopped(token.name());
- m_tree.activeFormattingElements()->clearToLastMarker();
- setInsertionMode(InRowMode);
- return;
- }
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag) {
- parseError(token);
- return;
- }
- if (token.name() == tableTag
- || token.name() == trTag
- || isTableBodyContextTag(token.name())) {
- if (!m_tree.openElements()->inTableScope(token.name())) {
- ASSERT(isTableBodyContextTag(token.name()) || isParsingFragment());
- parseError(token);
- return;
- }
- closeTheCell();
- reprocessEndTag(token);
- return;
- }
- processEndTagForInBody(token);
-}
-
-void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (token.name() == bodyTag) {
- processBodyEndTagForInBody(token);
- return;
- }
- if (token.name() == htmlTag) {
- AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag.localName());
- if (processBodyEndTagForInBody(endBody))
- reprocessEndTag(token);
- return;
- }
- if (token.name() == addressTag
- || token.name() == articleTag
- || token.name() == asideTag
- || token.name() == blockquoteTag
- || token.name() == buttonTag
- || token.name() == centerTag
- || token.name() == detailsTag
- || token.name() == dirTag
- || token.name() == divTag
- || token.name() == dlTag
- || token.name() == fieldsetTag
- || token.name() == figcaptionTag
- || token.name() == figureTag
- || token.name() == footerTag
- || token.name() == headerTag
- || token.name() == hgroupTag
- || token.name() == listingTag
- || token.name() == menuTag
- || token.name() == navTag
- || token.name() == olTag
- || token.name() == preTag
- || token.name() == sectionTag
- || token.name() == summaryTag
- || token.name() == ulTag) {
- if (!m_tree.openElements()->inScope(token.name())) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTags();
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilPopped(token.name());
- return;
- }
- if (token.name() == formTag) {
- RefPtr<Element> node = m_tree.takeForm();
- if (!node || !m_tree.openElements()->inScope(node.get())) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTags();
- if (m_tree.currentElement() != node.get())
- parseError(token);
- m_tree.openElements()->remove(node.get());
- }
- if (token.name() == pTag) {
- if (!m_tree.openElements()->inButtonScope(token.name())) {
- parseError(token);
- processFakeStartTag(pTag);
- ASSERT(m_tree.openElements()->inScope(token.name()));
- reprocessEndTag(token);
- return;
- }
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilPopped(token.name());
- return;
- }
- if (token.name() == liTag) {
- if (!m_tree.openElements()->inListItemScope(token.name())) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilPopped(token.name());
- return;
- }
- if (token.name() == ddTag
- || token.name() == dtTag) {
- if (!m_tree.openElements()->inScope(token.name())) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilPopped(token.name());
- return;
- }
- if (isNumberedHeaderTag(token.name())) {
- if (!m_tree.openElements()->hasNumberedHeaderElementInScope()) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTags();
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilNumberedHeaderElementPopped();
- return;
- }
- if (isFormattingTag(token.name())) {
- callTheAdoptionAgency(token);
- return;
- }
- if (token.name() == appletTag
- || token.name() == marqueeTag
- || token.name() == objectTag) {
- if (!m_tree.openElements()->inScope(token.name())) {
- parseError(token);
- return;
- }
- m_tree.generateImpliedEndTags();
- if (!m_tree.currentElement()->hasLocalName(token.name()))
- parseError(token);
- m_tree.openElements()->popUntilPopped(token.name());
- m_tree.activeFormattingElements()->clearToLastMarker();
- return;
- }
- if (token.name() == brTag) {
- parseError(token);
- processFakeStartTag(brTag);
- return;
- }
- processAnyOtherEndTagForInBody(token);
-}
-
-bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
-{
- if (!m_tree.openElements()->inTableScope(captionTag.localName())) {
- ASSERT(isParsingFragment());
- // FIXME: parse error
- return false;
- }
- m_tree.generateImpliedEndTags();
- // FIXME: parse error if (!m_tree.currentElement()->hasTagName(captionTag))
- m_tree.openElements()->popUntilPopped(captionTag.localName());
- m_tree.activeFormattingElements()->clearToLastMarker();
- setInsertionMode(InTableMode);
- return true;
-}
-
-bool HTMLTreeBuilder::processTrEndTagForInRow()
-{
- if (!m_tree.openElements()->inTableScope(trTag.localName())) {
- ASSERT(isParsingFragment());
- // FIXME: parse error
- return false;
- }
- m_tree.openElements()->popUntilTableRowScopeMarker();
- ASSERT(m_tree.currentElement()->hasTagName(trTag));
- m_tree.openElements()->pop();
- setInsertionMode(InTableBodyMode);
- return true;
-}
-
-bool HTMLTreeBuilder::processTableEndTagForInTable()
-{
- if (!m_tree.openElements()->inTableScope(tableTag)) {
- ASSERT(isParsingFragment());
- // FIXME: parse error.
- return false;
- }
- m_tree.openElements()->popUntilPopped(tableTag.localName());
- resetInsertionModeAppropriately();
- return true;
-}
-
-void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (token.name() == tableTag) {
- processTableEndTagForInTable();
- return;
- }
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
- parseError(token);
- return;
- }
- // Is this redirection necessary here?
- HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
- processEndTagForInBody(token);
-}
-
-void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndTag);
- switch (insertionMode()) {
- case InitialMode:
- ASSERT(insertionMode() == InitialMode);
- defaultForInitial();
- // Fall through.
- case BeforeHTMLMode:
- ASSERT(insertionMode() == BeforeHTMLMode);
- if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
- parseError(token);
- return;
- }
- defaultForBeforeHTML();
- // Fall through.
- case BeforeHeadMode:
- ASSERT(insertionMode() == BeforeHeadMode);
- if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
- parseError(token);
- return;
- }
- defaultForBeforeHead();
- // Fall through.
- case InHeadMode:
- ASSERT(insertionMode() == InHeadMode);
- if (token.name() == headTag) {
- m_tree.openElements()->popHTMLHeadElement();
- setInsertionMode(AfterHeadMode);
- return;
- }
- if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
- parseError(token);
- return;
- }
- defaultForInHead();
- // Fall through.
- case AfterHeadMode:
- ASSERT(insertionMode() == AfterHeadMode);
- if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
- parseError(token);
- return;
- }
- defaultForAfterHead();
- // Fall through
- case InBodyMode:
- ASSERT(insertionMode() == InBodyMode);
- processEndTagForInBody(token);
- break;
- case InTableMode:
- ASSERT(insertionMode() == InTableMode);
- processEndTagForInTable(token);
- break;
- case InCaptionMode:
- ASSERT(insertionMode() == InCaptionMode);
- if (token.name() == captionTag) {
- processCaptionEndTagForInCaption();
- return;
- }
- if (token.name() == tableTag) {
- parseError(token);
- if (!processCaptionEndTagForInCaption()) {
- ASSERT(isParsingFragment());
- return;
- }
- reprocessEndTag(token);
- return;
- }
- if (token.name() == bodyTag
- || token.name() == colTag
- || token.name() == colgroupTag
- || token.name() == htmlTag
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
- parseError(token);
- return;
- }
- processEndTagForInBody(token);
- break;
- case InColumnGroupMode:
- ASSERT(insertionMode() == InColumnGroupMode);
- if (token.name() == colgroupTag) {
- processColgroupEndTagForInColumnGroup();
- return;
- }
- if (token.name() == colTag) {
- parseError(token);
- return;
- }
- if (!processColgroupEndTagForInColumnGroup()) {
- ASSERT(isParsingFragment());
- return;
- }
- reprocessEndTag(token);
- break;
- case InRowMode:
- ASSERT(insertionMode() == InRowMode);
- processEndTagForInRow(token);
- break;
- case InCellMode:
- ASSERT(insertionMode() == InCellMode);
- processEndTagForInCell(token);
- break;
- case InTableBodyMode:
- ASSERT(insertionMode() == InTableBodyMode);
- processEndTagForInTableBody(token);
- break;
- case AfterBodyMode:
- ASSERT(insertionMode() == AfterBodyMode);
- if (token.name() == htmlTag) {
- if (isParsingFragment()) {
- parseError(token);
- return;
- }
- setInsertionMode(AfterAfterBodyMode);
- return;
- }
- prepareToReprocessToken();
- // Fall through.
- case AfterAfterBodyMode:
- ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
- parseError(token);
- setInsertionMode(InBodyMode);
- reprocessEndTag(token);
- break;
- case InHeadNoscriptMode:
- ASSERT(insertionMode() == InHeadNoscriptMode);
- if (token.name() == noscriptTag) {
- ASSERT(m_tree.currentElement()->hasTagName(noscriptTag));
- m_tree.openElements()->pop();
- ASSERT(m_tree.currentElement()->hasTagName(headTag));
- setInsertionMode(InHeadMode);
- return;
- }
- if (token.name() != brTag) {
- parseError(token);
- return;
- }
- defaultForInHeadNoscript();
- processToken(token);
- break;
- case TextMode:
- if (token.name() == scriptTag) {
- // Pause ourselves so that parsing stops until the script can be processed by the caller.
- m_isPaused = true;
- ASSERT(m_tree.currentElement()->hasTagName(scriptTag));
- m_scriptToProcess = m_tree.currentElement();
- m_scriptToProcessStartPosition = WTF::toOneBasedTextPosition(m_lastScriptElementStartPosition);
- m_tree.openElements()->pop();
- if (isParsingFragment() && m_fragmentContext.scriptingPermission() == FragmentScriptingNotAllowed)
- m_scriptToProcess->removeAllChildren();
- setInsertionMode(m_originalInsertionMode);
-
- // This token will not have been created by the tokenizer if a
- // self-closing script tag was encountered and pre-HTML5 parser
- // quirks are enabled. We must set the tokenizer's state to
- // DataState explicitly if the tokenizer didn't have a chance to.
- ASSERT(m_tokenizer->state() == HTMLTokenizer::DataState || m_usePreHTML5ParserQuirks);
- m_tokenizer->setState(HTMLTokenizer::DataState);
- return;
- }
- m_tree.openElements()->pop();
- setInsertionMode(m_originalInsertionMode);
- break;
- case InFramesetMode:
- ASSERT(insertionMode() == InFramesetMode);
- if (token.name() == framesetTag) {
- if (m_tree.currentElement() == m_tree.openElements()->htmlElement()) {
- parseError(token);
- return;
- }
- m_tree.openElements()->pop();
- if (!isParsingFragment() && !m_tree.currentElement()->hasTagName(framesetTag))
- setInsertionMode(AfterFramesetMode);
- return;
- }
- break;
- case AfterFramesetMode:
- ASSERT(insertionMode() == AfterFramesetMode);
- if (token.name() == htmlTag) {
- setInsertionMode(AfterAfterFramesetMode);
- return;
- }
- // Fall through.
- case AfterAfterFramesetMode:
- ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
- parseError(token);
- break;
- case InSelectInTableMode:
- ASSERT(insertionMode() == InSelectInTableMode);
- if (token.name() == captionTag
- || token.name() == tableTag
- || isTableBodyContextTag(token.name())
- || token.name() == trTag
- || isTableCellContextTag(token.name())) {
- parseError(token);
- if (m_tree.openElements()->inTableScope(token.name())) {
- AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
- reprocessEndTag(token);
- }
- return;
- }
- // Fall through.
- case InSelectMode:
- ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
- if (token.name() == optgroupTag) {
- if (m_tree.currentElement()->hasTagName(optionTag) && m_tree.oneBelowTop()->hasTagName(optgroupTag))
- processFakeEndTag(optionTag);
- if (m_tree.currentElement()->hasTagName(optgroupTag)) {
- m_tree.openElements()->pop();
- return;
- }
- parseError(token);
- return;
- }
- if (token.name() == optionTag) {
- if (m_tree.currentElement()->hasTagName(optionTag)) {
- m_tree.openElements()->pop();
- return;
- }
- parseError(token);
- return;
- }
- if (token.name() == selectTag) {
- if (!m_tree.openElements()->inSelectScope(token.name())) {
- ASSERT(isParsingFragment());
- parseError(token);
- return;
- }
- m_tree.openElements()->popUntilPopped(selectTag.localName());
- resetInsertionModeAppropriately();
- return;
- }
- break;
- case InTableTextMode:
- defaultForInTableText();
- processEndTag(token);
- break;
- case InForeignContentMode:
- if (token.name() == SVGNames::scriptTag && m_tree.currentElement()->hasTagName(SVGNames::scriptTag)) {
- notImplemented();
- return;
- }
- if (m_tree.currentElement()->namespaceURI() != xhtmlNamespaceURI) {
- // FIXME: This code just wants an Element* iterator, instead of an ElementRecord*
- HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
- if (!nodeRecord->element()->hasLocalName(token.name()))
- parseError(token);
- while (1) {
- if (nodeRecord->element()->hasLocalName(token.name())) {
- m_tree.openElements()->popUntilPopped(nodeRecord->element());
- resetForeignInsertionMode();
- return;
- }
- nodeRecord = nodeRecord->next();
- if (nodeRecord->element()->namespaceURI() == xhtmlNamespaceURI)
- break;
- }
- }
- // Any other end tag (also the last two steps of "An end tag, if the current node is not an element in the HTML namespace."
- processForeignContentUsingInBodyModeAndResetMode(token);
- break;
- }
-}
-
-void HTMLTreeBuilder::prepareToReprocessToken()
-{
- if (m_hasPendingForeignInsertionModeSteps) {
- resetForeignInsertionMode();
- m_hasPendingForeignInsertionModeSteps = false;
- }
-}
-
-void HTMLTreeBuilder::reprocessStartTag(AtomicHTMLToken& token)
-{
- prepareToReprocessToken();
- processStartTag(token);
-}
-
-void HTMLTreeBuilder::reprocessEndTag(AtomicHTMLToken& token)
-{
- prepareToReprocessToken();
- processEndTag(token);
-}
-
-class HTMLTreeBuilder::FakeInsertionMode : public Noncopyable {
-public:
- FakeInsertionMode(HTMLTreeBuilder* treeBuilder, InsertionMode mode)
- : m_treeBuilder(treeBuilder)
- , m_originalMode(treeBuilder->insertionMode())
- {
- m_treeBuilder->setFakeInsertionMode(mode);
- }
-
- ~FakeInsertionMode()
- {
- if (m_treeBuilder->isFakeInsertionMode())
- m_treeBuilder->setInsertionMode(m_originalMode);
- }
-
-private:
- HTMLTreeBuilder* m_treeBuilder;
- InsertionMode m_originalMode;
-};
-
-void HTMLTreeBuilder::processForeignContentUsingInBodyModeAndResetMode(AtomicHTMLToken& token)
-{
- m_hasPendingForeignInsertionModeSteps = true;
- {
- FakeInsertionMode fakeMode(this, InBodyMode);
- processToken(token);
- }
- if (m_hasPendingForeignInsertionModeSteps)
- resetForeignInsertionMode();
-}
-
-void HTMLTreeBuilder::resetForeignInsertionMode()
-{
- if (insertionMode() == InForeignContentMode)
- resetInsertionModeAppropriately();
-}
-
-void HTMLTreeBuilder::processComment(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::Comment);
- if (m_insertionMode == InitialMode
- || m_insertionMode == BeforeHTMLMode
- || m_insertionMode == AfterAfterBodyMode
- || m_insertionMode == AfterAfterFramesetMode) {
- m_tree.insertCommentOnDocument(token);
- return;
- }
- if (m_insertionMode == AfterBodyMode) {
- m_tree.insertCommentOnHTMLHtmlElement(token);
- return;
- }
- if (m_insertionMode == InTableTextMode) {
- defaultForInTableText();
- processComment(token);
- return;
- }
- m_tree.insertComment(token);
-}
-
-void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::Character);
- ExternalCharacterTokenBuffer buffer(token);
- processCharacterBuffer(buffer);
-}
-
-void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
-{
-ReprocessBuffer:
- switch (insertionMode()) {
- case InitialMode: {
- ASSERT(insertionMode() == InitialMode);
- buffer.skipLeadingWhitespace();
- if (buffer.isEmpty())
- return;
- defaultForInitial();
- // Fall through.
- }
- case BeforeHTMLMode: {
- ASSERT(insertionMode() == BeforeHTMLMode);
- buffer.skipLeadingWhitespace();
- if (buffer.isEmpty())
- return;
- defaultForBeforeHTML();
- // Fall through.
- }
- case BeforeHeadMode: {
- ASSERT(insertionMode() == BeforeHeadMode);
- buffer.skipLeadingWhitespace();
- if (buffer.isEmpty())
- return;
- defaultForBeforeHead();
- // Fall through.
- }
- case InHeadMode: {
- ASSERT(insertionMode() == InHeadMode);
- String leadingWhitespace = buffer.takeLeadingWhitespace();
- if (!leadingWhitespace.isEmpty())
- m_tree.insertTextNode(leadingWhitespace);
- if (buffer.isEmpty())
- return;
- defaultForInHead();
- // Fall through.
- }
- case AfterHeadMode: {
- ASSERT(insertionMode() == AfterHeadMode);
- String leadingWhitespace = buffer.takeLeadingWhitespace();
- if (!leadingWhitespace.isEmpty())
- m_tree.insertTextNode(leadingWhitespace);
- if (buffer.isEmpty())
- return;
- defaultForAfterHead();
- // Fall through.
- }
- case InBodyMode:
- case InCaptionMode:
- case InCellMode: {
- ASSERT(insertionMode() == InBodyMode || insertionMode() == InCaptionMode || insertionMode() == InCellMode);
- m_tree.reconstructTheActiveFormattingElements();
- String characters = buffer.takeRemaining();
- m_tree.insertTextNode(characters);
- if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
- m_framesetOk = false;
- break;
- }
- case InTableMode:
- case InTableBodyMode:
- case InRowMode: {
- ASSERT(insertionMode() == InTableMode || insertionMode() == InTableBodyMode || insertionMode() == InRowMode);
- ASSERT(m_pendingTableCharacters.isEmpty());
- m_originalInsertionMode = m_insertionMode;
- setInsertionMode(InTableTextMode);
- prepareToReprocessToken();
- // Fall through.
- }
- case InTableTextMode: {
- buffer.giveRemainingTo(m_pendingTableCharacters);
- break;
- }
- case InColumnGroupMode: {
- ASSERT(insertionMode() == InColumnGroupMode);
- String leadingWhitespace = buffer.takeLeadingWhitespace();
- if (!leadingWhitespace.isEmpty())
- m_tree.insertTextNode(leadingWhitespace);
- if (buffer.isEmpty())
- return;
- if (!processColgroupEndTagForInColumnGroup()) {
- ASSERT(isParsingFragment());
- // The spec tells us to drop these characters on the floor.
- buffer.takeLeadingNonWhitespace();
- if (buffer.isEmpty())
- return;
- }
- prepareToReprocessToken();
- goto ReprocessBuffer;
- }
- case AfterBodyMode:
- case AfterAfterBodyMode: {
- ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
- // FIXME: parse error
- setInsertionMode(InBodyMode);
- prepareToReprocessToken();
- goto ReprocessBuffer;
- break;
- }
- case TextMode: {
- ASSERT(insertionMode() == TextMode);
- m_tree.insertTextNode(buffer.takeRemaining());
- break;
- }
- case InHeadNoscriptMode: {
- ASSERT(insertionMode() == InHeadNoscriptMode);
- String leadingWhitespace = buffer.takeLeadingWhitespace();
- if (!leadingWhitespace.isEmpty())
- m_tree.insertTextNode(leadingWhitespace);
- if (buffer.isEmpty())
- return;
- defaultForInHeadNoscript();
- goto ReprocessBuffer;
- break;
- }
- case InFramesetMode:
- case AfterFramesetMode: {
- ASSERT(insertionMode() == InFramesetMode || insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
- String leadingWhitespace = buffer.takeRemainingWhitespace();
- if (!leadingWhitespace.isEmpty())
- m_tree.insertTextNode(leadingWhitespace);
- // FIXME: We should generate a parse error if we skipped over any
- // non-whitespace characters.
- break;
- }
- case InSelectInTableMode:
- case InSelectMode: {
- ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
- m_tree.insertTextNode(buffer.takeRemaining());
- break;
- }
- case InForeignContentMode: {
- ASSERT(insertionMode() == InForeignContentMode);
- String characters = buffer.takeRemaining();
- m_tree.insertTextNode(characters);
- if (m_framesetOk && !isAllWhitespace(characters))
- m_framesetOk = false;
- break;
- }
- case AfterAfterFramesetMode: {
- String leadingWhitespace = buffer.takeRemainingWhitespace();
- if (!leadingWhitespace.isEmpty()) {
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertTextNode(leadingWhitespace);
- }
- // FIXME: We should generate a parse error if we skipped over any
- // non-whitespace characters.
- break;
- }
- }
-}
-
-void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::EndOfFile);
- switch (insertionMode()) {
- case InitialMode:
- ASSERT(insertionMode() == InitialMode);
- defaultForInitial();
- // Fall through.
- case BeforeHTMLMode:
- ASSERT(insertionMode() == BeforeHTMLMode);
- defaultForBeforeHTML();
- // Fall through.
- case BeforeHeadMode:
- ASSERT(insertionMode() == BeforeHeadMode);
- defaultForBeforeHead();
- // Fall through.
- case InHeadMode:
- ASSERT(insertionMode() == InHeadMode);
- defaultForInHead();
- // Fall through.
- case AfterHeadMode:
- ASSERT(insertionMode() == AfterHeadMode);
- defaultForAfterHead();
- // Fall through
- case InBodyMode:
- case InCellMode:
- case InCaptionMode:
- case InRowMode:
- ASSERT(insertionMode() == InBodyMode || insertionMode() == InCellMode || insertionMode() == InCaptionMode || insertionMode() == InRowMode);
- notImplemented(); // Emit parse error based on what elements are still open.
- break;
- case AfterBodyMode:
- case AfterAfterBodyMode:
- ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
- break;
- case InHeadNoscriptMode:
- ASSERT(insertionMode() == InHeadNoscriptMode);
- defaultForInHeadNoscript();
- processEndOfFile(token);
- return;
- case AfterFramesetMode:
- case AfterAfterFramesetMode:
- ASSERT(insertionMode() == AfterFramesetMode || insertionMode() == AfterAfterFramesetMode);
- break;
- case InFramesetMode:
- case InTableMode:
- case InTableBodyMode:
- case InSelectInTableMode:
- case InSelectMode:
- ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode || insertionMode() == InTableMode || insertionMode() == InFramesetMode || insertionMode() == InTableBodyMode);
- if (m_tree.currentElement() != m_tree.openElements()->htmlElement())
- parseError(token);
- break;
- case InColumnGroupMode:
- if (m_tree.currentElement() == m_tree.openElements()->htmlElement()) {
- ASSERT(isParsingFragment());
- return; // FIXME: Should we break here instead of returning?
- }
- if (!processColgroupEndTagForInColumnGroup()) {
- ASSERT(isParsingFragment());
- return; // FIXME: Should we break here instead of returning?
- }
- prepareToReprocessToken();
- processEndOfFile(token);
- return;
- case InForeignContentMode:
- setInsertionMode(InBodyMode);
- processEndOfFile(token);
- return;
- case InTableTextMode:
- defaultForInTableText();
- processEndOfFile(token);
- return;
- case TextMode:
- parseError(token);
- if (m_tree.currentElement()->hasTagName(scriptTag))
- notImplemented(); // mark the script element as "already started".
- m_tree.openElements()->pop();
- setInsertionMode(m_originalInsertionMode);
- prepareToReprocessToken();
- processEndOfFile(token);
- return;
- }
- ASSERT(m_tree.openElements()->top());
- m_tree.openElements()->popAll();
-}
-
-void HTMLTreeBuilder::defaultForInitial()
-{
- notImplemented();
- if (!m_fragmentContext.fragment())
- m_document->setCompatibilityMode(Document::QuirksMode);
- // FIXME: parse error
- setInsertionMode(BeforeHTMLMode);
- prepareToReprocessToken();
-}
-
-void HTMLTreeBuilder::defaultForBeforeHTML()
-{
- AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag.localName());
- m_tree.insertHTMLHtmlStartTagBeforeHTML(startHTML);
- setInsertionMode(BeforeHeadMode);
- prepareToReprocessToken();
-}
-
-void HTMLTreeBuilder::defaultForBeforeHead()
-{
- AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
- processStartTag(startHead);
- prepareToReprocessToken();
-}
-
-void HTMLTreeBuilder::defaultForInHead()
-{
- AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
- processEndTag(endHead);
- prepareToReprocessToken();
-}
-
-void HTMLTreeBuilder::defaultForInHeadNoscript()
-{
- AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
- processEndTag(endNoscript);
- prepareToReprocessToken();
-}
-
-void HTMLTreeBuilder::defaultForAfterHead()
-{
- AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
- processStartTag(startBody);
- m_framesetOk = true;
- prepareToReprocessToken();
-}
-
-void HTMLTreeBuilder::defaultForInTableText()
-{
- String characters = String::adopt(m_pendingTableCharacters);
- if (!isAllWhitespace(characters)) {
- // FIXME: parse error
- HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
- m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertTextNode(characters);
- m_framesetOk = false;
- setInsertionMode(m_originalInsertionMode);
- prepareToReprocessToken();
- return;
- }
- m_tree.insertTextNode(characters);
- setInsertionMode(m_originalInsertionMode);
- prepareToReprocessToken();
-}
-
-bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagInBody(token);
- return true;
- }
- if (token.name() == baseTag
- || token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == commandTag
- || token.name() == linkTag
- || token.name() == metaTag) {
- m_tree.insertSelfClosingHTMLElement(token);
- // Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
- return true;
- }
- if (token.name() == titleTag) {
- processGenericRCDATAStartTag(token);
- return true;
- }
- if (token.name() == noscriptTag) {
- if (scriptEnabled(m_document->frame())) {
- processGenericRawTextStartTag(token);
- return true;
- }
- m_tree.insertHTMLElement(token);
- setInsertionMode(InHeadNoscriptMode);
- return true;
- }
- if (token.name() == noframesTag || token.name() == styleTag) {
- processGenericRawTextStartTag(token);
- return true;
- }
- if (token.name() == scriptTag) {
- processScriptStartTag(token);
- if (m_usePreHTML5ParserQuirks && token.selfClosing())
- processFakeEndTag(scriptTag);
- return true;
- }
- if (token.name() == headTag) {
- parseError(token);
- return true;
- }
- return false;
-}
-
-void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- m_tree.insertHTMLElement(token);
- m_tokenizer->setState(HTMLTokenizer::RCDATAState);
- m_originalInsertionMode = m_insertionMode;
- setInsertionMode(TextMode);
-}
-
-void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- m_tree.insertHTMLElement(token);
- m_tokenizer->setState(HTMLTokenizer::RAWTEXTState);
- m_originalInsertionMode = m_insertionMode;
- setInsertionMode(TextMode);
-}
-
-void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken& token)
-{
- ASSERT(token.type() == HTMLToken::StartTag);
- m_tree.insertScriptElement(token);
- m_tokenizer->setState(HTMLTokenizer::ScriptDataState);
- m_originalInsertionMode = m_insertionMode;
-
- TextPosition0 position = TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(m_tokenizer->lineNumber()), WTF::ZeroBasedNumber::base());
- m_lastScriptElementStartPosition = position;
-
- setInsertionMode(TextMode);
-}
-
-void HTMLTreeBuilder::finished()
-{
- ASSERT(m_document);
- if (isParsingFragment()) {
- m_fragmentContext.finished();
- return;
- }
-
- // Warning, this may detach the parser. Do not do anything else after this.
- m_document->finishedParsing();
-}
-
-bool HTMLTreeBuilder::scriptEnabled(Frame* frame)
-{
- if (!frame)
- return false;
- return frame->script()->canExecuteScripts(NotAboutToExecuteScript);
-}
-
-bool HTMLTreeBuilder::pluginsEnabled(Frame* frame)
-{
- if (!frame)
- return false;
- return frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin);
-}
-
-}