Chromium Code Reviews| Index: sky/engine/core/html/parser/HTMLDocumentParser.cpp |
| diff --git a/sky/engine/core/html/parser/HTMLDocumentParser.cpp b/sky/engine/core/html/parser/HTMLDocumentParser.cpp |
| index 82db5d2e63cd55d8b52730f237230b7e6107648e..12df25567bc39571f06f756b28c613df4fedd917 100644 |
| --- a/sky/engine/core/html/parser/HTMLDocumentParser.cpp |
| +++ b/sky/engine/core/html/parser/HTMLDocumentParser.cpp |
| @@ -159,7 +159,13 @@ void HTMLDocumentParser::runScriptsForPausedTreeBuilder() |
| return; |
| TextPosition scriptStartPosition = TextPosition::belowRangePosition(); |
| RefPtr<Element> scriptToProcess = m_treeBuilder->takeScriptToProcess(scriptStartPosition); |
| - m_scriptRunner.runScript(toHTMLScriptElement(scriptToProcess.get()), scriptStartPosition); |
| + |
| + // Sending the script to dart may find additional 'import' declarations |
| + // which need to load before the script can execute. HTMLScriptRunner |
| + // always calls scriptExecutionCompleted regardless of success/failure. |
| + m_scriptRunner = HTMLScriptRunner::createForScript( |
| + toHTMLScriptElement(scriptToProcess.get()), scriptStartPosition, this); |
| + m_scriptRunner->start(); |
| } |
| void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk> chunk) |
| @@ -168,7 +174,8 @@ void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa |
| // Sky should not need nested parsers. |
| ASSERT(document()->activeParserCount() == 0); |
| - if (isWaitingForScripts() || !m_pendingChunks.isEmpty() || document()->activeParserCount() > 0 || !document()->haveImportsLoaded()) { |
| + if (isWaitingForScripts() || !m_pendingChunks.isEmpty() || |
| + document()->activeParserCount() > 0) { |
| m_pendingChunks.append(chunk); |
| return; |
| } |
| @@ -200,8 +207,12 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse |
| OwnPtr<ParsedChunk> chunk(popChunk); |
| OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); |
| - for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != tokens->end(); ++it) { |
| - ASSERT(!isWaitingForScripts()); |
| + Vector<CompactHTMLToken>::const_iterator it; |
| + for (it = tokens->begin(); it != tokens->end(); ++it) { |
| + // A chunk can issue import loads causing us to be isWaitingForScripts |
| + // but we don't stop processing in that case. |
| + ASSERT(!m_treeBuilder->hasParserBlockingScript()); |
| + ASSERT(!m_scriptRunner); |
| m_textPosition = it->textPosition(); |
| @@ -210,20 +221,25 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse |
| if (isStopped()) |
| break; |
| - if (isWaitingForScripts()) { |
| - ASSERT(it + 1 == tokens->end()); // The </script> is assumed to be the last token of this bunch. |
| + if (m_treeBuilder->hasParserBlockingScript()) { |
| + ASSERT(++it == tokens->end()); // The </script> is assumed to be the |
|
abarth-chromium
2015/02/19 02:51:40
s/++it/it + 1/ ?
It seems very dangerous to mutat
|
| + // last token of this bunch. |
| runScriptsForPausedTreeBuilder(); |
| break; |
| } |
| if (it->type() == HTMLToken::EndOfFile) { |
| - ASSERT(it + 1 == tokens->end()); // The EOF is assumed to be the last token of this bunch. |
| + ASSERT(++it == tokens->end()); // The EOF is assumed to be the last |
|
abarth-chromium
2015/02/19 02:51:40
Ditto
|
| + // token of this bunch. |
| ASSERT(m_pendingChunks.isEmpty()); // There should never be any chunks after the EOF. |
| prepareToStopParsing(); |
| break; |
| } |
| } |
| + // Either we aborted due to stopping or we processed all tokens. |
| + ASSERT(isStopped() || it == tokens->end()); |
|
abarth-chromium
2015/02/19 02:51:40
I see... Maybe move the ++it outside of the ASSER
|
| + |
| // Make sure any pending text nodes are emitted before returning. |
| if (!isStopped()) |
| m_treeBuilder->flush(); |
| @@ -238,7 +254,6 @@ void HTMLDocumentParser::pumpPendingChunks() |
| ASSERT(refCount() >= 2); |
| ASSERT(!isWaitingForScripts()); |
| ASSERT(!isStopped()); |
| - ASSERT(document()->haveImportsLoaded()); |
| double startTime = currentTime(); |
| @@ -246,7 +261,7 @@ void HTMLDocumentParser::pumpPendingChunks() |
| processParsedChunkFromBackgroundParser(m_pendingChunks.takeFirst()); |
| // Always check isStopped first as m_document may be null. |
| - if (isStopped() || isWaitingForScripts() || !document()->haveImportsLoaded()) |
| + if (isStopped() || isWaitingForScripts()) |
| break; |
| if (currentTime() - startTime > parserTimeLimit && !m_pendingChunks.isEmpty()) { |
| @@ -353,7 +368,8 @@ void HTMLDocumentParser::endIfDelayed() |
| bool HTMLDocumentParser::isExecutingScript() const |
| { |
| - return m_scriptRunner.isExecutingScript(); |
| + // TODO(eseidel): Callers may need updates now that scripts can be async. |
| + return m_scriptRunner && m_scriptRunner->isExecutingScript(); |
|
abarth-chromium
2015/02/19 02:51:40
four-space indent
|
| } |
| OrdinalNumber HTMLDocumentParser::lineNumber() const |
| @@ -370,13 +386,13 @@ TextPosition HTMLDocumentParser::textPosition() const |
| bool HTMLDocumentParser::isWaitingForScripts() const |
| { |
| - return m_treeBuilder->hasParserBlockingScript(); |
| + return m_treeBuilder->hasParserBlockingScript() || m_scriptRunner || |
| + !document()->haveImportsLoaded(); |
| } |
| void HTMLDocumentParser::resumeAfterWaitingForImports() |
| { |
| RefPtr<HTMLDocumentParser> protect(this); |
| - ASSERT(!isExecutingScript()); |
| ASSERT(!isWaitingForScripts()); |
| if (m_pendingChunks.isEmpty()) |
| return; |
| @@ -384,4 +400,14 @@ void HTMLDocumentParser::resumeAfterWaitingForImports() |
| pumpPendingChunks(); |
| } |
| +// HTMLScriptRunner has finished executing a script. |
| +// Just call resumeAfterWaitingForImports since it happens to do what we need. |
| +void HTMLDocumentParser::scriptExecutionCompleted() { |
| + ASSERT(m_scriptRunner); |
| + m_scriptRunner.clear(); |
| + // To avoid re-entering the parser for synchronous scripts, we use a postTask. |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, base::Bind(&HTMLDocumentParser::resumeAfterWaitingForImports, |
| + m_weakFactory.GetWeakPtr())); |
| +} |
| } |