Chromium Code Reviews| 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) |