Index: third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp |
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp |
index 0ed9b645e97913e65ae42861cfb2848a1a67024c..099c3fa1235415c7a63e185ede234b6ff0629141 100644 |
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp |
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp |
@@ -31,6 +31,7 @@ |
#include "core/dom/DocumentFragment.h" |
#include "core/dom/DocumentLifecycleObserver.h" |
#include "core/dom/Element.h" |
+#include "core/dom/StyleEngine.h" |
#include "core/frame/LocalFrame.h" |
#include "core/frame/Settings.h" |
#include "core/html/HTMLDocument.h" |
@@ -44,6 +45,7 @@ |
#include "core/inspector/InspectorTraceEvents.h" |
#include "core/loader/DocumentLoader.h" |
#include "core/loader/NavigationScheduler.h" |
+#include "platform/RuntimeEnabledFeatures.h" |
#include "platform/SharedBuffer.h" |
#include "platform/ThreadSafeFunctional.h" |
#include "platform/TraceEvent.h" |
@@ -266,7 +268,7 @@ bool HTMLDocumentParser::processingData() const |
void HTMLDocumentParser::pumpTokenizerIfPossible() |
{ |
- if (isStopped() || isWaitingForScripts()) |
+ if (isStopped() || isWaitingForScripts() || isWaitingForStyles()) |
return; |
pumpTokenizer(); |
@@ -314,6 +316,9 @@ bool HTMLDocumentParser::canTakeNextToken() |
return false; |
} |
+ if (isWaitingForStyles()) |
+ return false; |
+ |
// FIXME: It's wrong for the HTMLDocumentParser to reach back to the |
// LocalFrame, but this approach is how the old parser handled |
// stopping when the page assigns window.location. What really |
@@ -358,7 +363,7 @@ void HTMLDocumentParser::notifyPendingParsedChunks() |
for (auto& chunk : pendingChunks) |
m_speculations.append(chunk.release()); |
- if (!isWaitingForScripts() && !isScheduledForResume()) { |
+ if (!isWaitingForScripts() && !isWaitingForStyles() && !isScheduledForResume()) { |
if (m_tasksWereSuspended) |
m_parserScheduler->forceResumeAfterYield(); |
else |
@@ -437,6 +442,7 @@ size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Par |
ASSERT_WITH_SECURITY_IMPLICATION(document()->activeParserCount() == 1); |
ASSERT(!isParsingFragment()); |
ASSERT(!isWaitingForScripts()); |
+ ASSERT(!isWaitingForStyles()); |
ASSERT(!isStopped()); |
#if !ENABLE(OILPAN) |
// ASSERT that this object is both attached to the Document and protected. |
@@ -530,6 +536,7 @@ void HTMLDocumentParser::pumpPendingSpeculations() |
ASSERT(!m_token); |
ASSERT(!m_lastChunkBeforeScript); |
ASSERT(!isWaitingForScripts()); |
+ ASSERT(!isWaitingForStyles()); |
ASSERT(!isStopped()); |
ASSERT(!isScheduledForResume()); |
ASSERT(!inPumpSession()); |
@@ -560,7 +567,7 @@ void HTMLDocumentParser::pumpPendingSpeculations() |
// Surprisingly, isScheduledForResume() may be set here as a result of |
// processParsedChunkFromBackgroundParser running arbitrary javascript |
// which invokes nested event loops. (e.g. inspector breakpoints) |
- if (!isParsing() || isWaitingForScripts() || isScheduledForResume()) |
+ if (!isParsing() || isWaitingForScripts() || isWaitingForStyles() || isScheduledForResume()) |
break; |
if (m_speculations.isEmpty() || m_parserScheduler->yieldIfNeeded(session, m_speculations.first()->startingScript)) |
@@ -649,7 +656,7 @@ void HTMLDocumentParser::pumpTokenizer() |
m_treeBuilder->flush(FlushAlways); |
RELEASE_ASSERT(!isStopped()); |
- if (isWaitingForScripts()) { |
+ if (isWaitingForScripts() || isWaitingForStyles()) { |
ASSERT(m_tokenizer->getState() == HTMLTokenizer::DataState); |
ASSERT(m_preloader); |
@@ -739,7 +746,7 @@ void HTMLDocumentParser::insert(const SegmentedString& source) |
m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); |
pumpTokenizerIfPossible(); |
- if (isWaitingForScripts()) { |
+ if (isWaitingForScripts() || isWaitingForStyles()) { |
// Check the document.write() output with a separate preload scanner as |
// the main scanner can't deal with insertions. |
if (!m_insertionPreloadScanner) { |
@@ -824,13 +831,13 @@ void HTMLDocumentParser::append(const String& inputSource) |
const SegmentedString source(inputSource); |
if (m_preloadScanner) { |
- if (m_input.current().isEmpty() && !isWaitingForScripts()) { |
+ if (m_input.current().isEmpty() && !isWaitingForScripts() && !isWaitingForStyles()) { |
// We have parsed until the end of the current input and so are now moving ahead of the preload scanner. |
// Clear the scanner so we know to scan starting from the current input point if we block again. |
m_preloadScanner.clear(); |
} else { |
m_preloadScanner->appendToEnd(source); |
- if (isWaitingForScripts()) |
+ if (isWaitingForScripts() || isWaitingForStyles()) |
m_preloadScanner->scan(m_preloader.get(), document()->baseElementURL()); |
} |
} |
@@ -987,6 +994,11 @@ bool HTMLDocumentParser::isWaitingForScripts() const |
return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript; |
} |
+bool HTMLDocumentParser::isWaitingForStyles() const |
+{ |
+ return RuntimeEnabledFeatures::htmlParserBlocksOnCSSEnabled() && document()->styleEngine().hasPendingSheets(); |
esprehn
2016/03/07 21:35:50
you need to block on imports too, does this do tha
Pat Meenan
2016/03/07 21:49:53
No, thanks. The chunks are set up so imports will
|
+} |
+ |
void HTMLDocumentParser::resumeParsingAfterScriptExecution() |
{ |
ASSERT(!isExecutingScript()); |
@@ -1042,18 +1054,17 @@ void HTMLDocumentParser::executeScriptsWaitingForResources() |
// Document only calls this when the Document owns the DocumentParser |
// so this will not be called in the DocumentFragment case. |
ASSERT(m_scriptRunner); |
- // Ignore calls unless we have a script blocking the parser waiting on a |
- // stylesheet load. Otherwise we are currently parsing and this |
- // is a re-entrant call from encountering a </ style> tag. |
- if (!m_scriptRunner->hasScriptsWaitingForResources()) |
- return; |
- // pumpTokenizer can cause this parser to be detached from the Document, |
- // but we need to ensure it isn't deleted yet. |
- RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); |
- m_scriptRunner->executeScriptsWaitingForResources(); |
- if (!isWaitingForScripts()) |
- resumeParsingAfterScriptExecution(); |
+ if (m_scriptRunner->hasScriptsWaitingForResources()) { |
+ // pumpTokenizer can cause this parser to be detached from the Document, |
+ // but we need to ensure it isn't deleted yet. |
+ RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); |
+ m_scriptRunner->executeScriptsWaitingForResources(); |
+ if (!isWaitingForScripts()) |
+ resumeParsingAfterScriptExecution(); |
+ } else if (RuntimeEnabledFeatures::htmlParserBlocksOnCSSEnabled() && !inPumpSession() && !isScheduledForResume()) { |
+ m_parserScheduler->scheduleForResume(); |
+ } |
} |
void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFragment* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) |