diff options
Diffstat (limited to 'Source/WebCore/html/parser')
-rw-r--r-- | Source/WebCore/html/parser/HTMLDocumentParser.cpp | 14 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLDocumentParser.h | 1 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLElementStack.cpp | 44 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLElementStack.h | 10 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLParserScheduler.cpp | 10 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLParserScheduler.h | 1 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLPreloadScanner.cpp | 17 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLScriptRunnerHost.h | 2 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLToken.h | 48 | ||||
-rw-r--r-- | Source/WebCore/html/parser/HTMLTreeBuilder.cpp | 21 |
10 files changed, 100 insertions, 68 deletions
diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.cpp b/Source/WebCore/html/parser/HTMLDocumentParser.cpp index e79a97a..88db3c2 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.cpp +++ b/Source/WebCore/html/parser/HTMLDocumentParser.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "HTMLDocumentParser.h" +#include "ContentSecurityPolicy.h" #include "DocumentFragment.h" #include "Element.h" #include "Frame.h" @@ -216,6 +217,13 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses // The parser will pause itself when waiting on a script to load or run. if (m_treeBuilder->isPaused()) { + if (mode == AllowYield) + m_parserScheduler->checkForYieldBeforeScript(session); + + // If we don't run the script, we cannot allow the next token to be taken. + if (session.needsYield) + return false; + // If we're paused waiting for a script, we try to execute scripts before continuing. bool shouldContinueParsing = runScriptsForPausedTreeBuilder(); m_treeBuilder->setPaused(!shouldContinueParsing); @@ -242,7 +250,6 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) { ASSERT(!isStopped()); - ASSERT(!m_treeBuilder->isPaused()); ASSERT(!isScheduledForResume()); // ASSERT that this object is both attached to the Document and protected. ASSERT(refCount() >= 2); @@ -485,11 +492,6 @@ void HTMLDocumentParser::stopWatchingForLoad(CachedResource* cachedScript) cachedScript->removeClient(this); } -bool HTMLDocumentParser::shouldLoadExternalScriptFromSrc(const AtomicString& srcValue) -{ - return document()->contentSecurityPolicy()->canLoadExternalScriptFromSrc(srcValue); -} - void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource) { // pumpTokenizer can cause this parser to be detached from the Document, diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.h b/Source/WebCore/html/parser/HTMLDocumentParser.h index 4bc33e4..a016cf3 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.h +++ b/Source/WebCore/html/parser/HTMLDocumentParser.h @@ -108,7 +108,6 @@ private: // HTMLScriptRunnerHost virtual void watchForLoad(CachedResource*); virtual void stopWatchingForLoad(CachedResource*); - virtual bool shouldLoadExternalScriptFromSrc(const AtomicString&); virtual HTMLInputStream& inputStream() { return m_input; } // CachedResourceClient diff --git a/Source/WebCore/html/parser/HTMLElementStack.cpp b/Source/WebCore/html/parser/HTMLElementStack.cpp index 6f5f9ed..a4a7383 100644 --- a/Source/WebCore/html/parser/HTMLElementStack.cpp +++ b/Source/WebCore/html/parser/HTMLElementStack.cpp @@ -50,7 +50,7 @@ inline bool isNumberedHeaderElement(ContainerNode* node) || node->hasTagName(h6Tag); } -inline bool isRootMarker(ContainerNode* node) +inline bool isRootNode(ContainerNode* node) { return node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE || node->hasTagName(htmlTag); @@ -74,7 +74,7 @@ inline bool isScopeMarker(ContainerNode* node) || node->hasTagName(SVGNames::foreignObjectTag) || node->hasTagName(SVGNames::descTag) || node->hasTagName(SVGNames::titleTag) - || isRootMarker(node); + || isRootNode(node); } inline bool isListItemScopeMarker(ContainerNode* node) @@ -87,7 +87,7 @@ inline bool isListItemScopeMarker(ContainerNode* node) inline bool isTableScopeMarker(ContainerNode* node) { return node->hasTagName(tableTag) - || isRootMarker(node); + || isRootNode(node); } inline bool isTableBodyScopeMarker(ContainerNode* node) @@ -95,26 +95,26 @@ inline bool isTableBodyScopeMarker(ContainerNode* node) return node->hasTagName(tbodyTag) || node->hasTagName(tfootTag) || node->hasTagName(theadTag) - || isRootMarker(node); + || isRootNode(node); } inline bool isTableRowScopeMarker(ContainerNode* node) { return node->hasTagName(trTag) - || isRootMarker(node); + || isRootNode(node); } -inline bool isForeignContentScopeMarker(Element* element) +inline bool isForeignContentScopeMarker(ContainerNode* node) { - return element->hasTagName(MathMLNames::miTag) - || element->hasTagName(MathMLNames::moTag) - || element->hasTagName(MathMLNames::mnTag) - || element->hasTagName(MathMLNames::msTag) - || element->hasTagName(MathMLNames::mtextTag) - || element->hasTagName(SVGNames::foreignObjectTag) - || element->hasTagName(SVGNames::descTag) - || element->hasTagName(SVGNames::titleTag) - || element->namespaceURI() == HTMLNames::xhtmlNamespaceURI; + return node->hasTagName(MathMLNames::miTag) + || node->hasTagName(MathMLNames::moTag) + || node->hasTagName(MathMLNames::mnTag) + || node->hasTagName(MathMLNames::msTag) + || node->hasTagName(MathMLNames::mtextTag) + || node->hasTagName(SVGNames::foreignObjectTag) + || node->hasTagName(SVGNames::descTag) + || node->hasTagName(SVGNames::titleTag) + || isInHTMLNamespace(node); } inline bool isButtonScopeMarker(ContainerNode* node) @@ -275,7 +275,7 @@ void HTMLElementStack::popUntilTableRowScopeMarker() void HTMLElementStack::popUntilForeignContentScopeMarker() { - while (!isForeignContentScopeMarker(top())) + while (!isForeignContentScopeMarker(topNode())) pop(); } @@ -434,10 +434,10 @@ bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& tar bool HTMLElementStack::hasOnlyHTMLElementsInScope() const { for (ElementRecord* record = m_top.get(); record; record = record->next()) { - Element* element = record->element(); - if (element->namespaceURI() != xhtmlNamespaceURI) + ContainerNode* node = record->node(); + if (!isInHTMLNamespace(node)) return false; - if (isScopeMarker(element)) + if (isScopeMarker(node)) return true; } ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker. @@ -460,10 +460,10 @@ bool HTMLElementStack::hasNumberedHeaderElementInScope() const bool HTMLElementStack::inScope(Element* targetElement) const { for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { - Element* element = pos->element(); - if (element == targetElement) + ContainerNode* node = pos->node(); + if (node == targetElement) return true; - if (isScopeMarker(element)) + if (isScopeMarker(node)) return false; } ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker. diff --git a/Source/WebCore/html/parser/HTMLElementStack.h b/Source/WebCore/html/parser/HTMLElementStack.h index a710932..fd0e494 100644 --- a/Source/WebCore/html/parser/HTMLElementStack.h +++ b/Source/WebCore/html/parser/HTMLElementStack.h @@ -28,6 +28,7 @@ #define HTMLElementStack_h #include "Element.h" +#include "HTMLNames.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> @@ -167,6 +168,15 @@ private: Element* m_headElement; Element* m_bodyElement; }; + +inline bool isInHTMLNamespace(Node* node) +{ + // A DocumentFragment takes the place of the document element when parsing + // fragments and should be considered in the HTML namespace. + return node->namespaceURI() == HTMLNames::xhtmlNamespaceURI + || node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE; +} + } // namespace WebCore diff --git a/Source/WebCore/html/parser/HTMLParserScheduler.cpp b/Source/WebCore/html/parser/HTMLParserScheduler.cpp index c4525c8..393c4be 100644 --- a/Source/WebCore/html/parser/HTMLParserScheduler.cpp +++ b/Source/WebCore/html/parser/HTMLParserScheduler.cpp @@ -86,6 +86,16 @@ void HTMLParserScheduler::continueNextChunkTimerFired(Timer<HTMLParserScheduler> m_parser->resumeParsingAfterYield(); } +void HTMLParserScheduler::checkForYieldBeforeScript(PumpSession& session) +{ + // If we've never painted before and a layout is pending, yield prior to running + // scripts to give the page a chance to paint earlier. + Document* document = m_parser->document(); + bool needsFirstPaint = document->view() && !document->view()->hasEverPainted(); + if (needsFirstPaint && document->isLayoutTimerActive()) + session.needsYield = true; +} + void HTMLParserScheduler::scheduleForResume() { m_continueNextChunkTimer.startOneShot(0); diff --git a/Source/WebCore/html/parser/HTMLParserScheduler.h b/Source/WebCore/html/parser/HTMLParserScheduler.h index 9aa12eb..730b52b 100644 --- a/Source/WebCore/html/parser/HTMLParserScheduler.h +++ b/Source/WebCore/html/parser/HTMLParserScheduler.h @@ -70,6 +70,7 @@ public: } ++session.processedTokens; } + void checkForYieldBeforeScript(PumpSession&); void scheduleForResume(); bool isScheduledForResume() const { return m_isSuspendedWithActiveTimer || m_continueNextChunkTimer.isActive(); } diff --git a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp index d23542f..5514597 100644 --- a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp +++ b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp @@ -30,6 +30,7 @@ #include "CachedResourceLoader.h" #include "Document.h" +#include "InputType.h" #include "HTMLDocumentParser.h" #include "HTMLTokenizer.h" #include "HTMLLinkElement.h" @@ -50,13 +51,17 @@ public: : m_tagName(token.name().data(), token.name().size()) , m_linkIsStyleSheet(false) , m_linkMediaAttributeIsScreen(true) + , m_inputIsImage(false) { processAttributes(token.attributes()); } void processAttributes(const HTMLToken::AttributeList& attributes) { - if (m_tagName != scriptTag && m_tagName != imgTag && m_tagName != linkTag) + if (m_tagName != imgTag + && m_tagName != inputTag + && m_tagName != linkTag + && m_tagName != scriptTag) return; for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); @@ -77,6 +82,11 @@ public: m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); else if (attributeName == mediaAttr) m_linkMediaAttributeIsScreen = linkMediaAttributeIsScreen(attributeValue); + } else if (m_tagName == inputTag) { + if (attributeName == srcAttr) + setUrlToLoad(attributeValue); + else if (attributeName == typeAttr) + m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeNames::image()); } } } @@ -87,7 +97,7 @@ public: HTMLLinkElement::tokenizeRelAttribute(attributeValue, rel); return rel.m_isStyleSheet && !rel.m_isAlternate && !rel.m_isIcon && !rel.m_isDNSPrefetch; } - + static bool linkMediaAttributeIsScreen(const String& attributeValue) { if (attributeValue.isEmpty()) @@ -118,7 +128,7 @@ public: CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader(); if (m_tagName == scriptTag) cachedResourceLoader->preload(CachedResource::Script, m_urlToLoad, m_charset, scanningBody); - else if (m_tagName == imgTag) + else if (m_tagName == imgTag || (m_tagName == inputTag && m_inputIsImage)) cachedResourceLoader->preload(CachedResource::ImageResource, m_urlToLoad, String(), scanningBody); else if (m_tagName == linkTag && m_linkIsStyleSheet && m_linkMediaAttributeIsScreen) cachedResourceLoader->preload(CachedResource::CSSStyleSheet, m_urlToLoad, m_charset, scanningBody); @@ -132,6 +142,7 @@ private: String m_charset; bool m_linkIsStyleSheet; bool m_linkMediaAttributeIsScreen; + bool m_inputIsImage; }; } // namespace diff --git a/Source/WebCore/html/parser/HTMLScriptRunnerHost.h b/Source/WebCore/html/parser/HTMLScriptRunnerHost.h index 5b40a931..454bc6f 100644 --- a/Source/WebCore/html/parser/HTMLScriptRunnerHost.h +++ b/Source/WebCore/html/parser/HTMLScriptRunnerHost.h @@ -44,8 +44,6 @@ public: // Implementors must call cachedResource->removeClient() immediately. virtual void stopWatchingForLoad(CachedResource*) = 0; - // Implementors can block certain script loads (for XSSAuditor, etc.) - virtual bool shouldLoadExternalScriptFromSrc(const AtomicString&) = 0; virtual HTMLInputStream& inputStream() = 0; }; diff --git a/Source/WebCore/html/parser/HTMLToken.h b/Source/WebCore/html/parser/HTMLToken.h index aa16ab2..49ec312 100644 --- a/Source/WebCore/html/parser/HTMLToken.h +++ b/Source/WebCore/html/parser/HTMLToken.h @@ -398,27 +398,7 @@ public: case HTMLToken::EndTag: { m_selfClosing = token.selfClosing(); m_name = AtomicString(token.name().data(), token.name().size()); - const HTMLToken::AttributeList& attributes = token.attributes(); - for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); - iter != attributes.end(); ++iter) { - if (!iter->m_name.isEmpty()) { - String name(iter->m_name.data(), iter->m_name.size()); - String value(iter->m_value.data(), iter->m_value.size()); - ASSERT(iter->m_nameRange.m_start); - ASSERT(iter->m_nameRange.m_end); - ASSERT(iter->m_valueRange.m_start); - ASSERT(iter->m_valueRange.m_end); - RefPtr<Attribute> mappedAttribute = Attribute::createMapped(name, value); - if (!m_attributes) { - m_attributes = NamedNodeMap::create(); - // Reserving capacity here improves the parser - // benchmark. It might be worth experimenting with - // the constant to see where the optimal point is. - m_attributes->reserveInitialCapacity(10); - } - m_attributes->insertAttribute(mappedAttribute.release(), false); - } - } + initializeAttributes(token.attributes()); break; } case HTMLToken::Comment: @@ -513,6 +493,8 @@ public: private: HTMLToken::Type m_type; + void initializeAttributes(const HTMLToken::AttributeList& attributes); + bool usesName() const { return m_type == HTMLToken::StartTag || m_type == HTMLToken::EndTag || m_type == HTMLToken::DOCTYPE; @@ -548,6 +530,30 @@ private: RefPtr<NamedNodeMap> m_attributes; }; +inline void AtomicHTMLToken::initializeAttributes(const HTMLToken::AttributeList& attributes) +{ + size_t size = attributes.size(); + if (!size) + return; + + m_attributes = NamedNodeMap::create(); + m_attributes->reserveInitialCapacity(size); + for (size_t i = 0; i < size; ++i) { + const HTMLToken::Attribute& attribute = attributes[i]; + if (attribute.m_name.isEmpty()) + continue; + + ASSERT(attribute.m_nameRange.m_start); + ASSERT(attribute.m_nameRange.m_end); + ASSERT(attribute.m_valueRange.m_start); + ASSERT(attribute.m_valueRange.m_end); + + String name(attribute.m_name.data(), attribute.m_name.size()); + String value(attribute.m_value.data(), attribute.m_value.size()); + m_attributes->insertAttribute(Attribute::createMapped(name, value), false); + } +} + } #endif diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp index 8f9e3e1..6db09de 100644 --- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp +++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp @@ -125,7 +125,7 @@ bool isSpecialNode(Node* node) return true; if (node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) return true; - if (node->namespaceURI() != xhtmlNamespaceURI) + if (!isInHTMLNamespace(node)) return false; const AtomicString& tagName = node->localName(); return tagName == addressTag @@ -445,7 +445,7 @@ void HTMLTreeBuilder::constructTreeFromAtomicToken(AtomicHTMLToken& token) // the U+0000 characters into replacement characters has compatibility // problems. m_parser->tokenizer()->setForceNullCharacterReplacement(m_insertionMode == TextMode || m_insertionMode == InForeignContentMode); - m_parser->tokenizer()->setShouldAllowCDATA(m_insertionMode == InForeignContentMode && m_tree.currentNode()->namespaceURI() != xhtmlNamespaceURI); + m_parser->tokenizer()->setShouldAllowCDATA(m_insertionMode == InForeignContentMode && !isInHTMLNamespace(m_tree.currentNode())); } void HTMLTreeBuilder::processToken(AtomicHTMLToken& token) @@ -984,7 +984,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token) adjustMathMLAttributes(token); adjustForeignAttributes(token); m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI); - if (m_insertionMode != InForeignContentMode) + if (m_insertionMode != InForeignContentMode && !token.selfClosing()) setInsertionMode(InForeignContentMode); return; } @@ -993,7 +993,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token) adjustSVGAttributes(token); adjustForeignAttributes(token); m_tree.insertForeignElement(token, SVGNames::svgNamespaceURI); - if (m_insertionMode != InForeignContentMode) + if (m_insertionMode != InForeignContentMode && !token.selfClosing()) setInsertionMode(InForeignContentMode); return; } @@ -1125,7 +1125,7 @@ bool shouldProcessForeignContentUsingInBodyInsertionMode(AtomicHTMLToken& token, || currentElement->hasTagName(SVGNames::descTag) || currentElement->hasTagName(SVGNames::titleTag)) return true; - return currentElement->namespaceURI() == HTMLNames::xhtmlNamespaceURI; + return isInHTMLNamespace(currentElement); } } @@ -1451,7 +1451,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token) processStartTag(token); break; case InForeignContentMode: { - if (shouldProcessForeignContentUsingInBodyInsertionMode(token, m_tree.currentElement())) { + if (shouldProcessForeignContentUsingInBodyInsertionMode(token, m_tree.currentNode())) { processForeignContentUsingInBodyModeAndResetMode(token); return; } @@ -2297,7 +2297,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token) notImplemented(); return; } - if (m_tree.currentNode()->namespaceURI() != xhtmlNamespaceURI) { + if (!isInHTMLNamespace(m_tree.currentNode())) { // FIXME: This code just wants an Element* iterator, instead of an ElementRecord* HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord(); if (!nodeRecord->node()->hasLocalName(token.name())) @@ -2310,12 +2310,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token) } nodeRecord = nodeRecord->next(); - if (nodeRecord->node()->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) { - ASSERT(isParsingFragment()); - break; - } - - if (nodeRecord->node()->namespaceURI() == xhtmlNamespaceURI) + if (isInHTMLNamespace(nodeRecord->node())) break; } } |