Changeset 66649 in webkit
- Timestamp:
- Sep 2, 2010 2:05:59 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 28 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r66648 r66649 1 2010-09-02 Tony Gentilcore <tonyg@chromium.org> 2 3 Reviewed by Adam Barth. 4 5 Support <script defer> as specified by HTML5 6 https://bugs.webkit.org/show_bug.cgi?id=40934 7 8 * fast/dom/HTMLScriptElement/defer-double-defer-write-expected.txt: Added. 9 * fast/dom/HTMLScriptElement/defer-double-defer-write.html: Added. Tests that a write of a deferred script from a deferred script will execute when the document is closed. The explicit close is necessary because this is a script created parser. 10 * fast/dom/HTMLScriptElement/defer-double-write-expected.txt: Added. 11 * fast/dom/HTMLScriptElement/defer-double-write.html: Added. Tests that a script block written from a deferred script will write into the new document. 12 * fast/dom/HTMLScriptElement/defer-inline-script-expected.txt: Added. 13 * fast/dom/HTMLScriptElement/defer-inline-script.html: Added. Tests that inline scripts are not deferred. This is consistent with HTML5 and inconsistent with IE. 14 * fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt: Added. 15 * fast/dom/HTMLScriptElement/defer-onbeforeload.html: Added. Tests that the beforeload event is fired immediately and is cancellable. 16 * fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt: Added. 17 * fast/dom/HTMLScriptElement/defer-script-invalid-url.html: Added. Tests that deferred scripts with invalid URLs are ignored and that subsequent deferred scripts will be run. 18 * fast/dom/HTMLScriptElement/defer-write-expected.txt: Added. 19 * fast/dom/HTMLScriptElement/defer-write.html: Added. Tests that a basic write from a deferred script blows away the document. 20 * fast/dom/HTMLScriptElement/resources/defer.js: Added. 21 * fast/dom/HTMLScriptElement/resources/external.js: Added. 22 * fast/dom/HTMLScriptElement/resources/shouldnotexecute.js: Added. 23 * fast/dom/HTMLScriptElement/shouldnotexecute.js: Added. 24 * fast/dom/HTMLScriptElement/two-defer-writes-expected.txt: Added. 25 * fast/dom/HTMLScriptElement/two-defer-writes.html: Added. Tests that when a document.write from the first deferred script blows away the document, subsequent deferred scripts are not executed. 26 * http/tests/misc/resources/defer-script.js: Added. 27 * http/tests/misc/resources/external-script.js: Added. 28 * http/tests/misc/resources/script-debug-body-background.js: Added. 29 * http/tests/misc/resources/script-write-slow-stylesheet.js: Added. 30 * http/tests/misc/resources/slow-defer-script.cgi: Added. 31 * http/tests/misc/resources/slow-stylesheet.cgi: Added. 32 * http/tests/misc/script-defer-after-slow-stylesheet-expected.txt: Added. 33 * http/tests/misc/script-defer-after-slow-stylesheet.html: Added. Tests that deferred scripts respect blocking stylesheets. 34 * http/tests/misc/script-defer-expected.txt: Added. 35 * http/tests/misc/script-defer.html: Added. Tests basic ordering of deferred scripts. 36 1 37 2010-09-02 Philippe Normand <pnormand@igalia.com> 2 38 -
trunk/WebCore/ChangeLog
r66647 r66649 1 2010-09-02 Tony Gentilcore <tonyg@chromium.org> 2 3 Reviewed by Adam Barth. 4 5 Support <script defer> as specified by HTML5 6 https://bugs.webkit.org/show_bug.cgi?id=40934 7 8 Tests: fast/dom/HTMLScriptElement/defer-double-defer-write.html 9 fast/dom/HTMLScriptElement/defer-double-write.html 10 fast/dom/HTMLScriptElement/defer-inline-script.html 11 fast/dom/HTMLScriptElement/defer-onbeforeload.html 12 fast/dom/HTMLScriptElement/defer-script-invalid-url.html 13 fast/dom/HTMLScriptElement/defer-write.html 14 fast/dom/HTMLScriptElement/two-defer-writes.html 15 http/tests/misc/script-defer-after-slow-stylesheet.html 16 http/tests/misc/script-defer.html 17 18 * dom/Document.cpp: 19 (WebCore::Document::open): Allow implicit open for writes() while executing deferred scripts. 20 * dom/DocumentParser.cpp: 21 (WebCore::DocumentParser::DocumentParser): 22 (WebCore::DocumentParser::startParsing): 23 (WebCore::DocumentParser::prepareToStopParsing): If called when stopped or detached, it shouldn't reset to stopping. 24 (WebCore::DocumentParser::stopParsing): 25 (WebCore::DocumentParser::detach): 26 * dom/DocumentParser.h: 27 (WebCore::DocumentParser::isParsing): 28 (WebCore::DocumentParser::isActive): 29 (WebCore::DocumentParser::isStopping): 30 (WebCore::DocumentParser::isDetached): 31 * dom/RawDataDocumentParser.h: 32 (WebCore::RawDataDocumentParser::finish): 33 * dom/XMLDocumentParser.cpp: 34 (WebCore::XMLDocumentParser::append): 35 (WebCore::XMLDocumentParser::exitText): 36 * dom/XMLDocumentParserLibxml2.cpp: 37 (WebCore::XMLDocumentParser::doWrite): 38 (WebCore::XMLDocumentParser::startElementNs): 39 (WebCore::XMLDocumentParser::endElementNs): 40 (WebCore::XMLDocumentParser::characters): 41 (WebCore::XMLDocumentParser::error): 42 (WebCore::XMLDocumentParser::processingInstruction): 43 (WebCore::XMLDocumentParser::cdataBlock): 44 (WebCore::XMLDocumentParser::comment): 45 (WebCore::XMLDocumentParser::internalSubset): 46 (WebCore::XMLDocumentParser::initializeParserContext): 47 (WebCore::XMLDocumentParser::doEnd): 48 * html/parser/HTMLDocumentParser.cpp: 49 (WebCore::HTMLDocumentParser::prepareToStopParsing): 50 (WebCore::HTMLDocumentParser::pumpTokenizerIfPossible): 51 (WebCore::HTMLDocumentParser::pumpTokenizer): 52 (WebCore::HTMLDocumentParser::insert): 53 (WebCore::HTMLDocumentParser::append): 54 (WebCore::HTMLDocumentParser::end): 55 (WebCore::HTMLDocumentParser::attemptToEnd): 56 (WebCore::HTMLDocumentParser::endIfDelayed): 57 (WebCore::HTMLDocumentParser::notifyFinished): 58 * html/parser/HTMLDocumentParser.h: 59 * html/parser/HTMLScriptRunner.cpp: 60 (WebCore::HTMLScriptRunner::~HTMLScriptRunner): 61 (WebCore::HTMLScriptRunner::executeParsingBlockingScript): 62 (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent): 63 (WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing): 64 (WebCore::HTMLScriptRunner::requestDeferredScript): 65 (WebCore::HTMLScriptRunner::runScript): 66 * html/parser/HTMLScriptRunner.h: 67 * loader/ImageDocument.cpp: 68 (WebCore::ImageDocumentParser::finish): 69 1 70 2010-09-02 Ilya Sherman <isherman@google.com> 2 71 -
trunk/WebCore/dom/Document.cpp
r66628 r66649 1824 1824 if (m_frame) { 1825 1825 ScriptableDocumentParser* parser = scriptableDocumentParser(); 1826 if (m_frame->loader()->isLoadingMainResource() || (parser && parser->is ExecutingScript()))1826 if (m_frame->loader()->isLoadingMainResource() || (parser && parser->isParsing() && parser->isExecutingScript())) 1827 1827 return; 1828 1828 -
trunk/WebCore/dom/DocumentParser.cpp
r65692 r66649 32 32 33 33 DocumentParser::DocumentParser(Document* document) 34 : m_ parserStopped(false)34 : m_state(ParsingState) 35 35 , m_document(document) 36 36 { … … 46 46 } 47 47 48 void DocumentParser::startParsing() 49 { 50 m_state = ParsingState; 51 } 52 53 void DocumentParser::prepareToStopParsing() 54 { 55 if (m_state == ParsingState) 56 m_state = StoppingState; 57 } 58 59 void DocumentParser::stopParsing() 60 { 61 m_state = StoppedState; 62 } 63 48 64 void DocumentParser::detach() 49 65 { 66 m_state = DetachedState; 50 67 m_document = 0; 51 68 } -
trunk/WebCore/dom/DocumentParser.h
r65958 r66649 58 58 // FIXME: processingData() is only used by DocumentLoader::isLoadingInAPISense 59 59 // and is very unclear as to what it actually means. The LegacyHTMLDocumentParser 60 // used to implement sit.60 // used to implement it. 61 61 virtual bool processingData() const { return false; } 62 62 63 63 // document() will return 0 after detach() is called. 64 64 Document* document() const { ASSERT(m_document); return m_document; } 65 bool isDetached() const { return !m_document; } 65 66 bool isParsing() const { return m_state == ParsingState; } 67 bool isStopping() const { return m_state == StoppingState; } 68 bool isStopped() const { return m_state >= StoppedState; } 69 bool isDetached() const { return m_state == DetachedState; } 70 71 // FIXME: Is this necessary? Does XMLDocumentParserLibxml2 really need to set this? 72 virtual void startParsing(); 73 74 // prepareToStop() is used when the EOF token is encountered and parsing is to be 75 // stopped normally. 76 virtual void prepareToStopParsing(); 77 78 // stopParsing() is used when a load is canceled/stopped. 79 // stopParsing() is currently different from detach(), but shouldn't be. 80 // It should NOT be ok to call any methods on DocumentParser after either 81 // detach() or stopParsing() but right now only detach() will ASSERT. 82 virtual void stopParsing(); 66 83 67 84 // Document is expected to detach the parser before releasing its ref. … … 72 89 virtual void detach(); 73 90 74 // stopParsing() is used when a load is canceled/stopped.75 // stopParsing() is currently different from detach(), but shouldn't be.76 // It should NOT be ok to call any methods on DocumentParser after either77 // detach() or stopParsing() but right now only detach() will ASSERT.78 virtual void stopParsing() { m_parserStopped = true; }79 80 91 protected: 81 92 DocumentParser(Document*); 82 93 83 // The parser has buffers, so parsing may continue even after 84 // it stops receiving data. We use m_parserStopped to stop the parser 85 // even when it has buffered data. 86 // FIXME: m_document = 0 could be changed to mean "parser stopped". 87 bool m_parserStopped; 94 private: 95 enum ParserState { 96 ParsingState, 97 StoppingState, 98 StoppedState, 99 DetachedState 100 }; 101 ParserState m_state; 88 102 89 private:90 103 // Every DocumentParser needs a pointer back to the document. 91 104 // m_document will be 0 after the parser is stopped. -
trunk/WebCore/dom/RawDataDocumentParser.h
r65958 r66649 40 40 virtual void finish() 41 41 { 42 if (! m_parserStopped && !isDetached())42 if (!isStopped()) 43 43 document()->finishedParsing(); 44 44 } -
trunk/WebCore/dom/XMLDocumentParser.cpp
r66115 r66649 133 133 m_originalSourceForTransform += parseString; 134 134 135 if (is Detached() || m_parserStopped|| m_sawXSLTransform)135 if (isStopped() || m_sawXSLTransform) 136 136 return; 137 137 … … 191 191 void XMLDocumentParser::exitText() 192 192 { 193 if ( m_parserStopped)193 if (isStopped()) 194 194 return; 195 195 -
trunk/WebCore/dom/XMLDocumentParserLibxml2.cpp
r66336 r66649 661 661 // JavaScript (which may be run under the xmlParseChunk callstack) may 662 662 // cause the parser to be stopped or detached. 663 if (is Detached() || m_parserStopped)663 if (isStopped()) 664 664 return; 665 665 } … … 734 734 const xmlChar** libxmlNamespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes) 735 735 { 736 if ( m_parserStopped)736 if (isStopped()) 737 737 return; 738 738 … … 823 823 void XMLDocumentParser::endElementNs() 824 824 { 825 if ( m_parserStopped)825 if (isStopped()) 826 826 return; 827 827 … … 907 907 void XMLDocumentParser::characters(const xmlChar* s, int len) 908 908 { 909 if ( m_parserStopped)909 if (isStopped()) 910 910 return; 911 911 … … 922 922 void XMLDocumentParser::error(ErrorType type, const char* message, va_list args) 923 923 { 924 if ( m_parserStopped)924 if (isStopped()) 925 925 return; 926 926 … … 946 946 void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlChar* data) 947 947 { 948 if ( m_parserStopped)948 if (isStopped()) 949 949 return; 950 950 … … 980 980 void XMLDocumentParser::cdataBlock(const xmlChar* s, int len) 981 981 { 982 if ( m_parserStopped)982 if (isStopped()) 983 983 return; 984 984 … … 998 998 void XMLDocumentParser::comment(const xmlChar* s) 999 999 { 1000 if ( m_parserStopped)1000 if (isStopped()) 1001 1001 return; 1002 1002 … … 1035 1035 void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID) 1036 1036 { 1037 if ( m_parserStopped)1037 if (isStopped()) 1038 1038 return; 1039 1039 … … 1295 1295 sax.entityDecl = xmlSAX2EntityDecl; 1296 1296 sax.initialized = XML_SAX2_MAGIC; 1297 m_parserStopped = false;1297 DocumentParser::startParsing(); 1298 1298 m_sawError = false; 1299 1299 m_sawXSLTransform = false; … … 1319 1319 document()->styleSelectorChanged(RecalcStyleImmediately); 1320 1320 document()->setParsing(true); 1321 m_parserStopped = true;1322 } 1323 #endif 1324 1325 if ( m_parserStopped)1321 DocumentParser::stopParsing(); 1322 } 1323 #endif 1324 1325 if (isStopped()) 1326 1326 return; 1327 1327 -
trunk/WebCore/dom/XMLDocumentParserQt.cpp
r66115 r66649 200 200 void XMLDocumentParser::initializeParserContext(const char*) 201 201 { 202 m_parserStopped = false;202 DocumentParser::stopParsing(); 203 203 m_sawError = false; 204 204 m_sawXSLTransform = false; … … 214 214 document()->styleSelectorChanged(RecalcStyleImmediately); 215 215 document()->setParsing(true); 216 m_parserStopped = true;216 DocumentParser::startParsing(); 217 217 } 218 218 #endif … … 351 351 void XMLDocumentParser::parse() 352 352 { 353 while (! m_parserStopped&& !m_parserPaused && !m_stream.atEnd()) {353 while (!isStopped() && !m_parserPaused && !m_stream.atEnd()) { 354 354 m_stream.readNext(); 355 355 switch (m_stream.tokenType()) { -
trunk/WebCore/html/parser/HTMLDocumentParser.cpp
r66277 r66649 143 143 } 144 144 145 // This kicks off "Once the user agent stops parsing" as described by: 146 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end 147 void HTMLDocumentParser::prepareToStopParsing() 148 { 149 ASSERT(!hasInsertionPoint()); 150 151 // pumpTokenizer can cause this parser to be detached from the Document, 152 // but we need to ensure it isn't deleted yet. 153 RefPtr<HTMLDocumentParser> protect(this); 154 155 // FIXME: Set the current document readiness to "interactive". 156 157 // NOTE: This pump should only ever emit buffered character tokens, 158 // so ForceSynchronous vs. AllowYield should be meaningless. 159 pumpTokenizerIfPossible(ForceSynchronous); 160 161 DocumentParser::prepareToStopParsing(); 162 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) 163 return; 164 end(); 165 } 166 145 167 bool HTMLDocumentParser::processingData() const 146 168 { … … 150 172 void HTMLDocumentParser::pumpTokenizerIfPossible(SynchronousMode mode) 151 173 { 152 if ( m_parserStopped|| m_treeBuilder->isPaused())174 if (isStopped() || m_treeBuilder->isPaused()) 153 175 return; 154 176 … … 194 216 void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) 195 217 { 196 ASSERT(!isDetached()); 197 ASSERT(!m_parserStopped); 218 ASSERT(!isStopped()); 198 219 ASSERT(!m_treeBuilder->isPaused()); 199 220 ASSERT(!isScheduledForResume()); … … 215 236 216 237 // JavaScript may have stopped or detached the parser. 217 if (is Detached() || m_parserStopped)238 if (isStopped()) 218 239 return; 219 240 … … 227 248 228 249 // JavaScript may have stopped or detached the parser. 229 if (is Detached() || m_parserStopped)250 if (isStopped()) 230 251 return; 231 252 … … 276 297 void HTMLDocumentParser::insert(const SegmentedString& source) 277 298 { 278 if ( m_parserStopped)299 if (isStopped()) 279 300 return; 280 301 … … 297 318 void HTMLDocumentParser::append(const SegmentedString& source) 298 319 { 299 if ( m_parserStopped)320 if (isStopped()) 300 321 return; 301 322 … … 329 350 ASSERT(!isScheduledForResume()); 330 351 331 // pumpTokenizer can cause this parser to be detached from the Document,332 // but we need to ensure it isn't deleted yet.333 RefPtr<HTMLDocumentParser> protect(this);334 335 // NOTE: This pump should only ever emit buffered character tokens,336 // so ForceSynchronous vs. AllowYield should be meaningless.337 pumpTokenizerIfPossible(ForceSynchronous);338 339 352 // Informs the the rest of WebCore that parsing is really finished (and deletes this). 340 353 m_treeBuilder->finished(); … … 350 363 return; 351 364 } 352 end();365 prepareToStopParsing(); 353 366 } 354 367 … … 363 376 364 377 m_endWasDelayed = false; 365 end();378 prepareToStopParsing(); 366 379 } 367 380 … … 448 461 void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource) 449 462 { 463 if (isStopping()) { 464 prepareToStopParsing(); 465 return; 466 } 467 450 468 // pumpTokenizer can cause this parser to be detached from the Document, 451 469 // but we need to ensure it isn't deleted yet. -
trunk/WebCore/html/parser/HTMLDocumentParser.h
r66277 r66649 82 82 virtual bool finishWasCalled(); 83 83 virtual bool processingData() const; 84 virtual void prepareToStopParsing(); 84 85 virtual void stopParsing(); 85 86 virtual bool isWaitingForScripts() const; -
trunk/WebCore/html/parser/HTMLScriptRunner.cpp
r66277 r66649 76 76 if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad()) 77 77 stopWatchingForLoad(m_parsingBlockingScript); 78 79 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { 80 PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst(); 81 if (pendingScript.cachedScript() && pendingScript.watchingForLoad()) 82 stopWatchingForLoad(pendingScript); 83 } 78 84 } 79 85 … … 130 136 ASSERT(isPendingScriptReady(m_parsingBlockingScript)); 131 137 132 // Stop watching loads before executeScript to prevent recursion if the script reloads itself.133 if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())134 stopWatchingForLoad(m_parsingBlockingScript);135 136 138 InsertionPointRecord insertionPointRecord(m_host->inputStream()); 137 139 executePendingScriptAndDispatchEvent(m_parsingBlockingScript); … … 142 144 bool errorOccurred = false; 143 145 ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOccurred); 146 147 // Stop watching loads before executeScript to prevent recursion if the script reloads itself. 148 if (pendingScript.cachedScript() && pendingScript.watchingForLoad()) 149 stopWatchingForLoad(pendingScript); 144 150 145 151 // Clear the pending script before possible rentrancy from executeScript() … … 239 245 } 240 246 247 bool HTMLScriptRunner::executeScriptsWaitingForParsing() 248 { 249 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { 250 ASSERT(!m_scriptNestingLevel); 251 ASSERT(!haveParsingBlockingScript()); 252 ASSERT(m_scriptsToExecuteAfterParsing.first().cachedScript()); 253 if (!m_scriptsToExecuteAfterParsing.first().cachedScript()->isLoaded()) { 254 watchForLoad(m_scriptsToExecuteAfterParsing.first()); 255 return false; 256 } 257 PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); 258 executePendingScriptAndDispatchEvent(first); 259 if (!m_document) 260 return false; 261 } 262 return true; 263 } 264 241 265 void HTMLScriptRunner::requestParsingBlockingScript(Element* element) 242 266 { … … 253 277 } 254 278 279 void HTMLScriptRunner::requestDeferredScript(Element* element) 280 { 281 PendingScript pendingScript; 282 if (!requestPendingScript(pendingScript, element)) 283 return; 284 285 ASSERT(pendingScript.cachedScript()); 286 m_scriptsToExecuteAfterParsing.append(pendingScript); 287 } 288 255 289 bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const 256 290 { … … 288 322 289 323 if (script->hasAttribute(srcAttr)) { 290 // FIXME: Handle defer and async 291 requestParsingBlockingScript(script); 324 // FIXME: Handle async. 325 if (script->hasAttribute(deferAttr)) 326 requestDeferredScript(script); 327 else 328 requestParsingBlockingScript(script); 292 329 } else { 293 330 // FIXME: We do not block inline <script> tags on stylesheets to match the -
trunk/WebCore/html/parser/HTMLScriptRunner.h
r66277 r66649 28 28 29 29 #include "PendingScript.h" 30 #include <wtf/Deque.h> 30 31 #include <wtf/Noncopyable.h> 31 32 #include <wtf/PassRefPtr.h> … … 57 58 bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; } 58 59 bool executeScriptsWaitingForStylesheets(); 60 bool executeScriptsWaitingForParsing(); 59 61 60 62 bool isExecutingScript() const { return !!m_scriptNestingLevel; } … … 72 74 73 75 void requestParsingBlockingScript(Element*); 76 void requestDeferredScript(Element*); 74 77 bool requestPendingScript(PendingScript&, Element*) const; 75 78 … … 85 88 HTMLScriptRunnerHost* m_host; 86 89 PendingScript m_parsingBlockingScript; 90 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 87 91 unsigned m_scriptNestingLevel; 88 92 -
trunk/WebCore/loader/ImageDocument.cpp
r66247 r66649 139 139 void ImageDocumentParser::finish() 140 140 { 141 if (! m_parserStopped&& document()->imageElement()) {141 if (!isStopped() && document()->imageElement()) { 142 142 CachedImage* cachedImage = document()->cachedImage(); 143 143 RefPtr<SharedBuffer> data = document()->frame()->loader()->documentLoader()->mainResourceData();
Note: See TracChangeset
for help on using the changeset viewer.