summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/parser
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/parser')
-rw-r--r--Source/WebCore/html/parser/HTMLDocumentParser.cpp14
-rw-r--r--Source/WebCore/html/parser/HTMLDocumentParser.h1
-rw-r--r--Source/WebCore/html/parser/HTMLElementStack.cpp44
-rw-r--r--Source/WebCore/html/parser/HTMLElementStack.h10
-rw-r--r--Source/WebCore/html/parser/HTMLParserScheduler.cpp10
-rw-r--r--Source/WebCore/html/parser/HTMLParserScheduler.h1
-rw-r--r--Source/WebCore/html/parser/HTMLPreloadScanner.cpp17
-rw-r--r--Source/WebCore/html/parser/HTMLScriptRunnerHost.h2
-rw-r--r--Source/WebCore/html/parser/HTMLToken.h48
-rw-r--r--Source/WebCore/html/parser/HTMLTreeBuilder.cpp21
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;
}
}