Commit f32fcdcc authored by eric@webkit.org's avatar eric@webkit.org

document.write of scripts that also document.write sometimes writes async

https://bugs.webkit.org/show_bug.cgi?id=89102

Reviewed by Adam Barth.

Source/WebCore:

When a script tag is first encountered, the TreeBuilder holds the element and returns
out to the outer HTMLDocumentParser parse loop.  The HTMLDocumentParser then takes
the script element and passes it to the HTMLScriptRunner for execution. However, if the
script is an "external script" the HTMLScriptRunner may have to wait for that parser
blocking script to load, and may store the script in its own m_parserBlockingScript member.

While the HTMLScriptRunner has this not-yet-loaded-script the parser is also blocked.
Because the "paused" state of the parser was held as a separate bool on the TreeBuilder
we'd have to be careful to update it to reflect the current state of this pending script
on the HTMLScriptRunner.

This patch removes this separate "paused" bool and makes the HTMLDocumentParser responsible
for the "paused" state of the parser through the isWaitingForScripts() function which
knows how to check both the TreeBuilder and the ScriptRunner for possible parser-blocking scripts.

I suspect this change may actually fix a bunch of edge cases where we were not
checking for the HTMLScriptRunner's parser blocking script and thus incorrectly ending
the parser, or not starting the pre-load scanner, etc.

As part of this change I also renamed m_haveParsingBlockingScript in HTMLScriptRunner to match
the naming style used elsewhere in the parser, as well as removed all the "bool" return values
for these parse/execute functions as they are no longer useful (or correct). The correct way
is always to check HTMLDocumentParser::isWaitingForScripts().

Test: fast/parser/cached-script-document-write.html

* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::pumpTokenizerIfPossible):
(WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):
(WebCore::HTMLDocumentParser::canTakeNextToken):
(WebCore::HTMLDocumentParser::isWaitingForScripts):
(WebCore::HTMLDocumentParser::resumeParsingAfterScriptExecution):
(WebCore::HTMLDocumentParser::notifyFinished):
(WebCore::HTMLDocumentParser::executeScriptsWaitingForStylesheets):
* html/parser/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::~HTMLScriptRunner):
(WebCore::HTMLScriptRunner::executeParsingBlockingScript):
(WebCore::HTMLScriptRunner::execute):
(WebCore::HTMLScriptRunner::hasParserBlockingScript):
(WebCore::HTMLScriptRunner::executeParsingBlockingScripts):
(WebCore::HTMLScriptRunner::executeScriptsWaitingForLoad):
(WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing):
(WebCore::HTMLScriptRunner::requestParsingBlockingScript):
(WebCore::HTMLScriptRunner::runScript):
* html/parser/HTMLScriptRunner.h:
(HTMLScriptRunner):
* html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::takeScriptToProcess):
(WebCore::HTMLTreeBuilder::processEndTag):
(WebCore::HTMLTreeBuilder::processTokenInForeignContent):
* html/parser/HTMLTreeBuilder.h:
(HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::hasParserBlockingScript):

LayoutTests:

* fast/parser/cached-script-document-write-expected.txt: Added.
* fast/parser/cached-script-document-write.html: Added.
* fast/parser/resources/cached-script-document-write.js: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@122168 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent cacd7dc7
2012-07-09 Eric Seidel <eric@webkit.org>
document.write of scripts that also document.write sometimes writes async
https://bugs.webkit.org/show_bug.cgi?id=89102
Reviewed by Adam Barth.
* fast/parser/cached-script-document-write-expected.txt: Added.
* fast/parser/cached-script-document-write.html: Added.
* fast/parser/resources/cached-script-document-write.js: Added.
2012-07-09 Filip Pizlo <fpizlo@apple.com>
DFG may get stuck in an infinite fix point if it constant folds a mispredicted node
<!DOCTYPE html>
<body>
<script src="resources/cached-script-document-write.js"></script>
<script>
if (window.testRunner)
testRunner.dumpAsText();
window.isTestScriptCached = true;
document.write("<script src='resources/cached-script-document-write.js'></" + "script>");
</script>
</body>
if (window.parent.isTestScriptCached) {
document.write('<div></div>');
document.body.appendChild(document.createTextNode(document.querySelector('div') ? 'PASS' : 'FAIL'));
}
2012-07-09 Eric Seidel <eric@webkit.org>
document.write of scripts that also document.write sometimes writes async
https://bugs.webkit.org/show_bug.cgi?id=89102
Reviewed by Adam Barth.
When a script tag is first encountered, the TreeBuilder holds the element and returns
out to the outer HTMLDocumentParser parse loop. The HTMLDocumentParser then takes
the script element and passes it to the HTMLScriptRunner for execution. However, if the
script is an "external script" the HTMLScriptRunner may have to wait for that parser
blocking script to load, and may store the script in its own m_parserBlockingScript member.
While the HTMLScriptRunner has this not-yet-loaded-script the parser is also blocked.
Because the "paused" state of the parser was held as a separate bool on the TreeBuilder
we'd have to be careful to update it to reflect the current state of this pending script
on the HTMLScriptRunner.
This patch removes this separate "paused" bool and makes the HTMLDocumentParser responsible
for the "paused" state of the parser through the isWaitingForScripts() function which
knows how to check both the TreeBuilder and the ScriptRunner for possible parser-blocking scripts.
I suspect this change may actually fix a bunch of edge cases where we were not
checking for the HTMLScriptRunner's parser blocking script and thus incorrectly ending
the parser, or not starting the pre-load scanner, etc.
As part of this change I also renamed m_haveParsingBlockingScript in HTMLScriptRunner to match
the naming style used elsewhere in the parser, as well as removed all the "bool" return values
for these parse/execute functions as they are no longer useful (or correct). The correct way
is always to check HTMLDocumentParser::isWaitingForScripts().
Test: fast/parser/cached-script-document-write.html
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::pumpTokenizerIfPossible):
(WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder):
(WebCore::HTMLDocumentParser::canTakeNextToken):
(WebCore::HTMLDocumentParser::isWaitingForScripts):
(WebCore::HTMLDocumentParser::resumeParsingAfterScriptExecution):
(WebCore::HTMLDocumentParser::notifyFinished):
(WebCore::HTMLDocumentParser::executeScriptsWaitingForStylesheets):
* html/parser/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::~HTMLScriptRunner):
(WebCore::HTMLScriptRunner::executeParsingBlockingScript):
(WebCore::HTMLScriptRunner::execute):
(WebCore::HTMLScriptRunner::hasParserBlockingScript):
(WebCore::HTMLScriptRunner::executeParsingBlockingScripts):
(WebCore::HTMLScriptRunner::executeScriptsWaitingForLoad):
(WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing):
(WebCore::HTMLScriptRunner::requestParsingBlockingScript):
(WebCore::HTMLScriptRunner::runScript):
* html/parser/HTMLScriptRunner.h:
(HTMLScriptRunner):
* html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::takeScriptToProcess):
(WebCore::HTMLTreeBuilder::processEndTag):
(WebCore::HTMLTreeBuilder::processTokenInForeignContent):
* html/parser/HTMLTreeBuilder.h:
(HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::hasParserBlockingScript):
2012-07-09 Ryosuke Niwa <rniwa@webkit.org>
Microdata tests are flaky
......@@ -165,7 +165,7 @@ bool HTMLDocumentParser::processingData() const
void HTMLDocumentParser::pumpTokenizerIfPossible(SynchronousMode mode)
{
if (isStopped() || m_treeBuilder->isPaused())
if (isStopped() || isWaitingForScripts())
return;
// Once a resume is scheduled, HTMLParserScheduler controls when we next pump.
......@@ -195,16 +195,13 @@ void HTMLDocumentParser::resumeParsingAfterYield()
endIfDelayed();
}
bool HTMLDocumentParser::runScriptsForPausedTreeBuilder()
void HTMLDocumentParser::runScriptsForPausedTreeBuilder()
{
ASSERT(m_treeBuilder->isPaused());
TextPosition scriptStartPosition = TextPosition::belowRangePosition();
RefPtr<Element> scriptElement = m_treeBuilder->takeScriptToProcess(scriptStartPosition);
// We will not have a scriptRunner when parsing a DocumentFragment.
if (!m_scriptRunner)
return true;
return m_scriptRunner->execute(scriptElement.release(), scriptStartPosition);
if (m_scriptRunner)
m_scriptRunner->execute(scriptElement.release(), scriptStartPosition);
}
bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& session)
......@@ -212,8 +209,7 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses
if (isStopped())
return false;
// The parser will pause itself when waiting on a script to load or run.
if (m_treeBuilder->isPaused()) {
if (isWaitingForScripts()) {
if (mode == AllowYield)
m_parserScheduler->checkForYieldBeforeScript(session);
......@@ -222,9 +218,8 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses
return false;
// If we're paused waiting for a script, we try to execute scripts before continuing.
bool shouldContinueParsing = runScriptsForPausedTreeBuilder();
m_treeBuilder->setPaused(!shouldContinueParsing);
if (!shouldContinueParsing || isStopped())
runScriptsForPausedTreeBuilder();
if (isWaitingForScripts() || isStopped())
return false;
}
......@@ -385,8 +380,11 @@ void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd()
{
ASSERT(isStopping());
ASSERT(!hasInsertionPoint());
if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing())
return;
if (m_scriptRunner) {
m_scriptRunner->executeScriptsWaitingForParsing();
if (isWaitingForScripts())
return;
}
end();
}
......@@ -462,13 +460,24 @@ TextPosition HTMLDocumentParser::textPosition() const
bool HTMLDocumentParser::isWaitingForScripts() const
{
return m_treeBuilder->isPaused();
// When the TreeBuilder encounters a </script> tag, it returns to the HTMLDocumentParser
// where the script is transfered from the treebuilder to the script runner.
// The script runner will hold the script until its loaded and run. During
// any of this time, we want to count ourselves as "waiting for a script" and thus
// run the preload scanner, as well as delay completion of parsing.
bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript();
bool scriptRunnerHasBlockingScript = m_scriptRunner && m_scriptRunner->hasParserBlockingScript();
// Since the parser is paused while a script runner has a blocking script, it should
// never be possible to end up with both objects holding a blocking script.
ASSERT(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript));
// If either object has a blocking script, the parser should be paused.
return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript;
}
void HTMLDocumentParser::resumeParsingAfterScriptExecution()
{
ASSERT(!isExecutingScript());
ASSERT(!m_treeBuilder->isPaused());
ASSERT(!isWaitingForScripts());
m_insertionPreloadScanner.clear();
pumpTokenizerIfPossible(AllowYield);
......@@ -509,13 +518,8 @@ void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource)
return;
}
ASSERT(m_treeBuilder->isPaused());
// Note: We only ever wait on one script at a time, so we always know this
// is the one we were waiting on and can un-pause the tree builder.
m_treeBuilder->setPaused(false);
bool shouldContinueParsing = m_scriptRunner->executeScriptsWaitingForLoad(cachedResource);
m_treeBuilder->setPaused(!shouldContinueParsing);
if (shouldContinueParsing)
m_scriptRunner->executeScriptsWaitingForLoad(cachedResource);
if (!isWaitingForScripts())
resumeParsingAfterScriptExecution();
}
......@@ -533,15 +537,8 @@ void HTMLDocumentParser::executeScriptsWaitingForStylesheets()
// pumpTokenizer can cause this parser to be detached from the Document,
// but we need to ensure it isn't deleted yet.
RefPtr<HTMLDocumentParser> protect(this);
ASSERT(!m_scriptRunner->isExecutingScript());
ASSERT(m_treeBuilder->isPaused());
// Note: We only ever wait on one script at a time, so we always know this
// is the one we were waiting on and can un-pause the tree builder.
m_treeBuilder->setPaused(false);
bool shouldContinueParsing = m_scriptRunner->executeScriptsWaitingForStylesheets();
m_treeBuilder->setPaused(!shouldContinueParsing);
if (shouldContinueParsing)
m_scriptRunner->executeScriptsWaitingForStylesheets();
if (!isWaitingForScripts())
resumeParsingAfterScriptExecution();
}
......
......@@ -124,7 +124,7 @@ private:
void pumpTokenizer(SynchronousMode);
void pumpTokenizerIfPossible(SynchronousMode);
bool runScriptsForPausedTreeBuilder();
void runScriptsForPausedTreeBuilder();
void resumeParsingAfterScriptExecution();
void attemptToEnd();
......
......@@ -57,8 +57,8 @@ HTMLScriptRunner::HTMLScriptRunner(Document* document, HTMLScriptRunnerHost* hos
HTMLScriptRunner::~HTMLScriptRunner()
{
// FIXME: Should we be passed a "done loading/parsing" callback sooner than destruction?
if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
stopWatchingForLoad(m_parsingBlockingScript);
if (m_parserBlockingScript.cachedScript() && m_parserBlockingScript.watchingForLoad())
stopWatchingForLoad(m_parserBlockingScript);
while (!m_scriptsToExecuteAfterParsing.isEmpty()) {
PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst();
......@@ -112,10 +112,10 @@ void HTMLScriptRunner::executeParsingBlockingScript()
ASSERT(m_document);
ASSERT(!m_scriptNestingLevel);
ASSERT(m_document->haveStylesheetsLoaded());
ASSERT(isPendingScriptReady(m_parsingBlockingScript));
ASSERT(isPendingScriptReady(m_parserBlockingScript));
InsertionPointRecord insertionPointRecord(m_host->inputStream());
executePendingScriptAndDispatchEvent(m_parsingBlockingScript);
executePendingScriptAndDispatchEvent(m_parserBlockingScript);
}
void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendingScript)
......@@ -159,54 +159,47 @@ void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript)
// This function should match 10.2.5.11 "An end tag whose tag name is 'script'"
// Script handling lives outside the tree builder to keep the each class simple.
bool HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosition& scriptStartPosition)
void HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosition& scriptStartPosition)
{
ASSERT(scriptElement);
// FIXME: If scripting is disabled, always just return true;
// FIXME: If scripting is disabled, always just return.
bool hadPreloadScanner = m_host->hasPreloadScanner();
// Try to execute the script given to us.
runScript(scriptElement.get(), scriptStartPosition);
if (haveParsingBlockingScript()) {
if (hasParserBlockingScript()) {
if (m_scriptNestingLevel)
return false; // Block the parser. Unwind to the outermost HTMLScriptRunner::execute before continuing parsing.
return; // Unwind to the outermost HTMLScriptRunner::execute before continuing parsing.
// If preload scanner got created, it is missing the source after the current insertion point. Append it and scan.
if (!hadPreloadScanner && m_host->hasPreloadScanner())
m_host->appendCurrentInputStreamToPreloadScannerAndScan();
if (!executeParsingBlockingScripts())
return false; // We still have a parsing blocking script, block the parser.
executeParsingBlockingScripts();
}
return true; // Scripts executed as expected, continue parsing.
}
bool HTMLScriptRunner::haveParsingBlockingScript() const
bool HTMLScriptRunner::hasParserBlockingScript() const
{
return !!m_parsingBlockingScript.element();
return !!m_parserBlockingScript.element();
}
bool HTMLScriptRunner::executeParsingBlockingScripts()
void HTMLScriptRunner::executeParsingBlockingScripts()
{
while (haveParsingBlockingScript()) {
// We only really need to check once.
if (!isPendingScriptReady(m_parsingBlockingScript))
return false;
while (hasParserBlockingScript() && isPendingScriptReady(m_parserBlockingScript))
executeParsingBlockingScript();
}
return true;
}
bool HTMLScriptRunner::executeScriptsWaitingForLoad(CachedResource* cachedScript)
void HTMLScriptRunner::executeScriptsWaitingForLoad(CachedResource* cachedScript)
{
ASSERT(!m_scriptNestingLevel);
ASSERT(haveParsingBlockingScript());
ASSERT_UNUSED(cachedScript, m_parsingBlockingScript.cachedScript() == cachedScript);
ASSERT(m_parsingBlockingScript.cachedScript()->isLoaded());
return executeParsingBlockingScripts();
ASSERT(hasParserBlockingScript());
ASSERT_UNUSED(cachedScript, m_parserBlockingScript.cachedScript() == cachedScript);
ASSERT(m_parserBlockingScript.cachedScript()->isLoaded());
executeParsingBlockingScripts();
}
bool HTMLScriptRunner::executeScriptsWaitingForStylesheets()
void HTMLScriptRunner::executeScriptsWaitingForStylesheets()
{
ASSERT(m_document);
// Callers should check hasScriptsWaitingForStylesheets() before calling
......@@ -214,39 +207,39 @@ bool HTMLScriptRunner::executeScriptsWaitingForStylesheets()
ASSERT(hasScriptsWaitingForStylesheets());
ASSERT(!m_scriptNestingLevel);
ASSERT(m_document->haveStylesheetsLoaded());
return executeParsingBlockingScripts();
executeParsingBlockingScripts();
}
bool HTMLScriptRunner::executeScriptsWaitingForParsing()
void HTMLScriptRunner::executeScriptsWaitingForParsing()
{
while (!m_scriptsToExecuteAfterParsing.isEmpty()) {
ASSERT(!m_scriptNestingLevel);
ASSERT(!haveParsingBlockingScript());
ASSERT(!hasParserBlockingScript());
ASSERT(m_scriptsToExecuteAfterParsing.first().cachedScript());
if (!m_scriptsToExecuteAfterParsing.first().cachedScript()->isLoaded()) {
watchForLoad(m_scriptsToExecuteAfterParsing.first());
return false;
return;
}
PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst();
executePendingScriptAndDispatchEvent(first);
// FIXME: What is this m_document check for?
if (!m_document)
return false;
return;
}
return true;
}
void HTMLScriptRunner::requestParsingBlockingScript(Element* element)
{
if (!requestPendingScript(m_parsingBlockingScript, element))
if (!requestPendingScript(m_parserBlockingScript, element))
return;
ASSERT(m_parsingBlockingScript.cachedScript());
ASSERT(m_parserBlockingScript.cachedScript());
// We only care about a load callback if cachedScript is not already
// in the cache. Callers will attempt to run the m_parsingBlockingScript
// in the cache. Callers will attempt to run the m_parserBlockingScript
// if possible before returning control to the parser.
if (!m_parsingBlockingScript.cachedScript()->isLoaded())
watchForLoad(m_parsingBlockingScript);
if (!m_parserBlockingScript.cachedScript()->isLoaded())
watchForLoad(m_parserBlockingScript);
}
void HTMLScriptRunner::requestDeferredScript(Element* element)
......@@ -278,7 +271,7 @@ bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Elemen
void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStartPosition)
{
ASSERT(m_document);
ASSERT(!haveParsingBlockingScript());
ASSERT(!hasParserBlockingScript());
{
InsertionPointRecord insertionPointRecord(m_host->inputStream());
NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
......@@ -302,8 +295,8 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStar
requestDeferredScript(script);
else if (scriptElement->readyToBeParserExecuted()) {
if (m_scriptNestingLevel == 1) {
m_parsingBlockingScript.setElement(script);
m_parsingBlockingScript.setStartingPosition(scriptStartPosition);
m_parserBlockingScript.setElement(script);
m_parserBlockingScript.setStartingPosition(scriptStartPosition);
} else {
ScriptSourceCode sourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition);
scriptElement->executeScript(sourceCode);
......
......@@ -53,13 +53,14 @@ public:
void detach();
// Processes the passed in script and any pending scripts if possible.
bool execute(PassRefPtr<Element> scriptToProcess, const TextPosition& scriptStartPosition);
void execute(PassRefPtr<Element> scriptToProcess, const TextPosition& scriptStartPosition);
bool executeScriptsWaitingForLoad(CachedResource*);
void executeScriptsWaitingForLoad(CachedResource*);
bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; }
bool executeScriptsWaitingForStylesheets();
bool executeScriptsWaitingForParsing();
void executeScriptsWaitingForStylesheets();
void executeScriptsWaitingForParsing();
bool hasParserBlockingScript() const;
bool isExecutingScript() const { return !!m_scriptNestingLevel; }
private:
......@@ -69,8 +70,7 @@ private:
void executeParsingBlockingScript();
void executePendingScriptAndDispatchEvent(PendingScript&);
bool haveParsingBlockingScript() const;
bool executeParsingBlockingScripts();
void executeParsingBlockingScripts();
void requestParsingBlockingScript(Element*);
void requestDeferredScript(Element*);
......@@ -86,7 +86,7 @@ private:
Document* m_document;
HTMLScriptRunnerHost* m_host;
PendingScript m_parsingBlockingScript;
PendingScript m_parserBlockingScript;
Deque<PendingScript> m_scriptsToExecuteAfterParsing; // http://www.whatwg.org/specs/web-apps/current-work/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing
unsigned m_scriptNestingLevel;
......
......@@ -351,7 +351,6 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument* docum
, m_document(document)
, m_tree(document, maximumDOMTreeDepth)
, m_reportErrors(reportErrors)
, m_isPaused(false)
, m_insertionMode(InitialMode)
, m_originalInsertionMode(InitialMode)
, m_shouldSkipLeadingNewline(false)
......@@ -369,7 +368,6 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* f
, m_document(fragment->document())
, m_tree(fragment, scriptingPermission, maximumDOMTreeDepth)
, m_reportErrors(false) // FIXME: Why not report errors in fragments?
, m_isPaused(false)
, m_insertionMode(InitialMode)
, m_originalInsertionMode(InitialMode)
, m_shouldSkipLeadingNewline(false)
......@@ -425,11 +423,11 @@ HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
{
ASSERT(m_scriptToProcess);
// Unpause ourselves, callers may pause us again when processing the script.
// The HTML5 spec is written as though scripts are executed inside the tree
// builder. We pause the parser to exit the tree builder, and then resume
// before running scripts.
m_isPaused = false;
scriptStartPosition = m_scriptToProcessStartPosition;
m_scriptToProcessStartPosition = uninitializedPositionValue1();
return m_scriptToProcess.release();
......@@ -2127,7 +2125,6 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
case TextMode:
if (token.name() == scriptTag) {
// Pause ourselves so that parsing stops until the script can be processed by the caller.
m_isPaused = true;
ASSERT(m_tree.currentElement()->hasTagName(scriptTag));
m_scriptToProcess = m_tree.currentElement();
m_tree.openElements()->pop();
......@@ -2750,7 +2747,6 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
adjustSVGTagNameCase(token);
if (token.name() == SVGNames::scriptTag && m_tree.currentNode()->hasTagName(SVGNames::scriptTag)) {
m_isPaused = true;
m_scriptToProcess = m_tree.currentElement();
m_tree.openElements()->pop();
return;
......
......@@ -70,14 +70,12 @@ public:
void detach();
void setPaused(bool paused) { m_isPaused = paused; }
bool isPaused() const { return m_isPaused; }
// The token really should be passed as a const& since it's never modified.
void constructTreeFromToken(HTMLToken&);
void constructTreeFromAtomicToken(AtomicHTMLToken&);
// Must be called when parser is paused before calling the parser again.
bool hasParserBlockingScript() const { return !!m_scriptToProcess; }
// Must be called to take the parser-blocking script before calling the parser again.
PassRefPtr<Element> takeScriptToProcess(TextPosition& scriptStartPosition);
// Done, close any open tags, etc.
......@@ -216,7 +214,6 @@ private:
HTMLConstructionSite m_tree;
bool m_reportErrors;
bool m_isPaused;
// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#insertion-mode
InsertionMode m_insertionMode;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment