diff options
Diffstat (limited to 'Source/WebCore/html/parser')
| -rw-r--r-- | Source/WebCore/html/parser/CSSPreloadScanner.cpp | 39 | ||||
| -rw-r--r-- | Source/WebCore/html/parser/CSSPreloadScanner.h | 3 | ||||
| -rw-r--r-- | Source/WebCore/html/parser/HTMLDocumentParser.cpp | 31 | ||||
| -rw-r--r-- | Source/WebCore/html/parser/HTMLDocumentParser.h | 2 | ||||
| -rw-r--r-- | Source/WebCore/html/parser/HTMLParserScheduler.h | 14 | ||||
| -rw-r--r-- | Source/WebCore/html/parser/HTMLScriptRunner.cpp | 5 | ||||
| -rw-r--r-- | Source/WebCore/html/parser/HTMLScriptRunnerHost.h | 4 |
7 files changed, 78 insertions, 20 deletions
diff --git a/Source/WebCore/html/parser/CSSPreloadScanner.cpp b/Source/WebCore/html/parser/CSSPreloadScanner.cpp index 23364f9..3c23b9f 100644 --- a/Source/WebCore/html/parser/CSSPreloadScanner.cpp +++ b/Source/WebCore/html/parser/CSSPreloadScanner.cpp @@ -54,7 +54,7 @@ void CSSPreloadScanner::scan(const HTMLToken& token, bool scanningBody) m_scanningBody = scanningBody; const HTMLToken::DataVector& characters = token.characters(); - for (HTMLToken::DataVector::const_iterator iter = characters.begin(); iter != characters.end(); ++iter) + for (HTMLToken::DataVector::const_iterator iter = characters.begin(); iter != characters.end() && m_state != DoneParsingImportRules; ++iter) tokenize(*iter); } @@ -64,10 +64,14 @@ inline void CSSPreloadScanner::tokenize(UChar c) // Searching for other types of resources is probably low payoff. switch (m_state) { case Initial: + if (isHTMLSpace(c)) + break; if (c == '@') m_state = RuleStart; else if (c == '/') m_state = MaybeComment; + else + m_state = DoneParsingImportRules; break; case MaybeComment: if (c == '*') @@ -80,10 +84,10 @@ inline void CSSPreloadScanner::tokenize(UChar c) m_state = MaybeCommentEnd; break; case MaybeCommentEnd: + if (c == '*') + break; if (c == '/') m_state = Initial; - else if (c == '*') - ; else m_state = Comment; break; @@ -106,9 +110,11 @@ inline void CSSPreloadScanner::tokenize(UChar c) break; case AfterRule: if (isHTMLSpace(c)) - ; - else if (c == ';') + break; + if (c == ';') m_state = Initial; + else if (c == '{') + m_state = DoneParsingImportRules; else { m_state = RuleValue; m_ruleValue.append(c); @@ -117,23 +123,26 @@ inline void CSSPreloadScanner::tokenize(UChar c) case RuleValue: if (isHTMLSpace(c)) m_state = AfterRuleValue; - else if (c == ';') { + else if (c == ';') emitRule(); - m_state = Initial; - } else + else m_ruleValue.append(c); break; case AfterRuleValue: if (isHTMLSpace(c)) - ; - else if (c == ';') { + break; + if (c == ';') emitRule(); - m_state = Initial; - } else { + else if (c == '{') + m_state = DoneParsingImportRules; + else { // FIXME: media rules m_state = Initial; } break; + case DoneParsingImportRules: + ASSERT_NOT_REACHED(); + break; } } @@ -187,7 +196,11 @@ void CSSPreloadScanner::emitRule() String value = parseCSSStringOrURL(m_ruleValue.data(), m_ruleValue.size()); if (!value.isEmpty()) m_document->cachedResourceLoader()->preload(CachedResource::CSSStyleSheet, value, String(), m_scanningBody); - } + m_state = Initial; + } else if (equalIgnoringCase("charset", m_rule.data(), m_rule.size())) + m_state = Initial; + else + m_state = DoneParsingImportRules; m_rule.clear(); m_ruleValue.clear(); } diff --git a/Source/WebCore/html/parser/CSSPreloadScanner.h b/Source/WebCore/html/parser/CSSPreloadScanner.h index fae95a1..e45fa2d 100644 --- a/Source/WebCore/html/parser/CSSPreloadScanner.h +++ b/Source/WebCore/html/parser/CSSPreloadScanner.h @@ -53,7 +53,8 @@ private: Rule, AfterRule, RuleValue, - AfterRuleValue + AfterRuleValue, + DoneParsingImportRules, }; inline void tokenize(UChar c); diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.cpp b/Source/WebCore/html/parser/HTMLDocumentParser.cpp index 88db3c2..7519699 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.cpp +++ b/Source/WebCore/html/parser/HTMLDocumentParser.cpp @@ -40,7 +40,6 @@ #include "InspectorInstrumentation.h" #include "NestingLevelIncrementer.h" #include "Settings.h" -#include <wtf/CurrentTime.h> #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" @@ -331,6 +330,14 @@ void HTMLDocumentParser::insert(const SegmentedString& source) excludedLineNumberSource.setExcludeLineNumbers(); m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); pumpTokenizerIfPossible(ForceSynchronous); + + if (isWaitingForScripts()) { + // Check the document.write() output with a separate preload scanner as + // the main scanner can't deal with insertions. + HTMLPreloadScanner preloadScanner(document()); + preloadScanner.appendToEnd(source); + preloadScanner.scan(); + } endIfDelayed(); } @@ -344,9 +351,19 @@ void HTMLDocumentParser::append(const SegmentedString& source) // but we need to ensure it isn't deleted yet. RefPtr<HTMLDocumentParser> protect(this); + if (m_preloadScanner) { + if (m_input.current().isEmpty() && !isWaitingForScripts()) { + // 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()) + m_preloadScanner->scan(); + } + } + m_input.appendToEnd(source); - if (m_preloadScanner) - m_preloadScanner->appendToEnd(source); if (inPumpSession()) { // We've gotten data off the network in a nested write. @@ -473,7 +490,6 @@ void HTMLDocumentParser::resumeParsingAfterScriptExecution() ASSERT(!inScriptExecution()); ASSERT(!m_treeBuilder->isPaused()); - m_preloadScanner.clear(); pumpTokenizerIfPossible(AllowYield); endIfDelayed(); } @@ -491,6 +507,13 @@ void HTMLDocumentParser::stopWatchingForLoad(CachedResource* cachedScript) { cachedScript->removeClient(this); } + +void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() +{ + ASSERT(m_preloadScanner); + m_preloadScanner->appendToEnd(m_input.current()); + m_preloadScanner->scan(); +} void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource) { diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.h b/Source/WebCore/html/parser/HTMLDocumentParser.h index a016cf3..d482a3d 100644 --- a/Source/WebCore/html/parser/HTMLDocumentParser.h +++ b/Source/WebCore/html/parser/HTMLDocumentParser.h @@ -109,6 +109,8 @@ private: virtual void watchForLoad(CachedResource*); virtual void stopWatchingForLoad(CachedResource*); virtual HTMLInputStream& inputStream() { return m_input; } + virtual bool hasPreloadScanner() const { return m_preloadScanner.get(); } + virtual void appendCurrentInputStreamToPreloadScannerAndScan(); // CachedResourceClient virtual void notifyFinished(CachedResource*); diff --git a/Source/WebCore/html/parser/HTMLParserScheduler.h b/Source/WebCore/html/parser/HTMLParserScheduler.h index 730b52b..b0e2e85 100644 --- a/Source/WebCore/html/parser/HTMLParserScheduler.h +++ b/Source/WebCore/html/parser/HTMLParserScheduler.h @@ -26,6 +26,8 @@ #ifndef HTMLParserScheduler_h #define HTMLParserScheduler_h +#include <limits.h> + #include "NestingLevelIncrementer.h" #include "Timer.h" #include <wtf/CurrentTime.h> @@ -39,8 +41,11 @@ class PumpSession : public NestingLevelIncrementer { public: PumpSession(unsigned& nestingLevel) : NestingLevelIncrementer(nestingLevel) - , processedTokens(0) - , startTime(currentTime()) + // Setting processedTokens to INT_MAX causes us to check for yields + // after any token during any parse where yielding is allowed. + // At that time we'll initialize startTime. + , processedTokens(INT_MAX) + , startTime(0) , needsYield(false) { } @@ -63,6 +68,11 @@ public: void checkForYieldBeforeToken(PumpSession& session) { if (session.processedTokens > m_parserChunkSize) { + // currentTime() can be expensive. By delaying, we avoided calling + // currentTime() when constructing non-yielding PumpSessions. + if (!session.startTime) + session.startTime = currentTime(); + session.processedTokens = 0; double elapsedTime = currentTime() - session.startTime; if (elapsedTime > m_parserTimeLimit) diff --git a/Source/WebCore/html/parser/HTMLScriptRunner.cpp b/Source/WebCore/html/parser/HTMLScriptRunner.cpp index 99fff5e..7312334 100644 --- a/Source/WebCore/html/parser/HTMLScriptRunner.cpp +++ b/Source/WebCore/html/parser/HTMLScriptRunner.cpp @@ -169,12 +169,17 @@ bool HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosi ASSERT(scriptElement); // FIXME: If scripting is disabled, always just return true; + bool hadPreloadScanner = m_host->hasPreloadScanner(); + // Try to execute the script given to us. runScript(scriptElement.get(), scriptStartPosition); if (haveParsingBlockingScript()) { if (m_scriptNestingLevel) return false; // Block the parser. 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. } diff --git a/Source/WebCore/html/parser/HTMLScriptRunnerHost.h b/Source/WebCore/html/parser/HTMLScriptRunnerHost.h index 454bc6f..1f22896 100644 --- a/Source/WebCore/html/parser/HTMLScriptRunnerHost.h +++ b/Source/WebCore/html/parser/HTMLScriptRunnerHost.h @@ -45,6 +45,10 @@ public: virtual void stopWatchingForLoad(CachedResource*) = 0; virtual HTMLInputStream& inputStream() = 0; + + virtual bool hasPreloadScanner() const = 0; + virtual void appendCurrentInputStreamToPreloadScannerAndScan() = 0; + }; } |
