Changeset 66670 in webkit


Ignore:
Timestamp:
Sep 2, 2010 8:45:43 AM (14 years ago)
Author:
tonyg@chromium.org
Message:

2010-09-01 Tony Gentilcore <tonyg@chromium.org>

Reviewed by Adam Barth.

Support <script defer> as specified by HTML5
https://bugs.webkit.org/show_bug.cgi?id=40934

  • fast/dom/HTMLScriptElement/defer-double-defer-write-expected.txt: Added.
  • 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.
  • fast/dom/HTMLScriptElement/defer-double-write-expected.txt: Added.
  • fast/dom/HTMLScriptElement/defer-double-write.html: Added. Tests that a script block written from a deferred script will write into the new document.
  • fast/dom/HTMLScriptElement/defer-inline-script-expected.txt: Added.
  • fast/dom/HTMLScriptElement/defer-inline-script.html: Added. Tests that inline scripts are not deferred. This is consistent with HTML5 and inconsistent with IE.
  • fast/dom/HTMLScriptElement/defer-onbeforeload-expected.txt: Added.
  • fast/dom/HTMLScriptElement/defer-onbeforeload.html: Added. Tests that the beforeload event is fired immediately and is cancellable.
  • fast/dom/HTMLScriptElement/defer-script-invalid-url-expected.txt: Added.
  • 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.
  • fast/dom/HTMLScriptElement/defer-write-expected.txt: Added.
  • fast/dom/HTMLScriptElement/defer-write.html: Added. Tests that a basic write from a deferred script blows away the document.
  • fast/dom/HTMLScriptElement/resources/defer.js: Added.
  • fast/dom/HTMLScriptElement/resources/external.js: Added.
  • fast/dom/HTMLScriptElement/resources/shouldnotexecute.js: Added.
  • fast/dom/HTMLScriptElement/shouldnotexecute.js: Added.
  • fast/dom/HTMLScriptElement/two-defer-writes-expected.txt: Added.
  • 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.
  • http/tests/misc/resources/defer-script.js: Added.
  • http/tests/misc/resources/external-script.js: Added.
  • http/tests/misc/resources/script-debug-body-background.js: Added.
  • http/tests/misc/resources/script-write-slow-stylesheet.js: Added.
  • http/tests/misc/resources/slow-defer-script.cgi: Added.
  • http/tests/misc/resources/slow-stylesheet.cgi: Added.
  • http/tests/misc/script-defer-after-slow-stylesheet-expected.txt: Added.
  • http/tests/misc/script-defer-after-slow-stylesheet.html: Added. Tests that deferred scripts respect blocking stylesheets.
  • http/tests/misc/script-defer-expected.txt: Added.
  • http/tests/misc/script-defer.html: Added. Tests basic ordering of deferred scripts.

2010-09-01 Tony Gentilcore <tonyg@chromium.org>

Reviewed by Adam Barth.

Support <script defer> as specified by HTML5
https://bugs.webkit.org/show_bug.cgi?id=40934

Tests: fast/dom/HTMLScriptElement/defer-double-defer-write.html

fast/dom/HTMLScriptElement/defer-double-write.html
fast/dom/HTMLScriptElement/defer-inline-script.html
fast/dom/HTMLScriptElement/defer-onbeforeload.html
fast/dom/HTMLScriptElement/defer-script-invalid-url.html
fast/dom/HTMLScriptElement/defer-write.html
fast/dom/HTMLScriptElement/two-defer-writes.html
http/tests/misc/script-defer-after-slow-stylesheet.html
http/tests/misc/script-defer.html

  • dom/Document.cpp: (WebCore::Document::open): Allow implicit open for writes() while executing deferred scripts.
  • dom/DocumentParser.cpp: (WebCore::DocumentParser::DocumentParser): (WebCore::DocumentParser::startParsing): (WebCore::DocumentParser::prepareToStopParsing): If called when stopped or detached, it shouldn't reset to stopping. (WebCore::DocumentParser::stopParsing): (WebCore::DocumentParser::detach):
  • dom/DocumentParser.h: (WebCore::DocumentParser::isParsing): (WebCore::DocumentParser::isActive): (WebCore::DocumentParser::isStopping): (WebCore::DocumentParser::isDetached):
  • dom/RawDataDocumentParser.h: (WebCore::RawDataDocumentParser::finish):
  • dom/XMLDocumentParser.cpp: (WebCore::XMLDocumentParser::append): (WebCore::XMLDocumentParser::exitText):
  • dom/XMLDocumentParserLibxml2.cpp: (WebCore::XMLDocumentParser::doWrite): (WebCore::XMLDocumentParser::startElementNs): (WebCore::XMLDocumentParser::endElementNs): (WebCore::XMLDocumentParser::characters): (WebCore::XMLDocumentParser::error): (WebCore::XMLDocumentParser::processingInstruction): (WebCore::XMLDocumentParser::cdataBlock): (WebCore::XMLDocumentParser::comment): (WebCore::XMLDocumentParser::internalSubset): (WebCore::XMLDocumentParser::initializeParserContext): (WebCore::XMLDocumentParser::doEnd):
  • html/parser/HTMLDocumentParser.cpp: (WebCore::HTMLDocumentParser::prepareToStopParsing): (WebCore::HTMLDocumentParser::pumpTokenizerIfPossible): (WebCore::HTMLDocumentParser::pumpTokenizer): (WebCore::HTMLDocumentParser::insert): (WebCore::HTMLDocumentParser::append): (WebCore::HTMLDocumentParser::end): (WebCore::HTMLDocumentParser::attemptToEnd): (WebCore::HTMLDocumentParser::endIfDelayed): (WebCore::HTMLDocumentParser::notifyFinished):
  • html/parser/HTMLDocumentParser.h:
  • html/parser/HTMLScriptRunner.cpp: (WebCore::HTMLScriptRunner::~HTMLScriptRunner): (WebCore::HTMLScriptRunner::executeParsingBlockingScript): (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent): (WebCore::HTMLScriptRunner::executeScriptsWaitingForParsing): (WebCore::HTMLScriptRunner::requestDeferredScript): (WebCore::HTMLScriptRunner::runScript):
  • html/parser/HTMLScriptRunner.h:
  • loader/ImageDocument.cpp: (WebCore::ImageDocumentParser::finish):
Location:
trunk
Files:
28 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r66669 r66670  
     12010-09-01  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
    1372010-09-02  Andrey Kosyakov  <caseq@chromium.org>
    238
  • trunk/WebCore/ChangeLog

    r66669 r66670  
     12010-09-01  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
    1702010-09-02  Andrey Kosyakov  <caseq@chromium.org>
    271
  • trunk/WebCore/dom/Document.cpp

    r66660 r66670  
    18241824    if (m_frame) {
    18251825        ScriptableDocumentParser* parser = scriptableDocumentParser();
    1826         if (m_frame->loader()->isLoadingMainResource() || (parser && parser->isExecutingScript()))
     1826        if (m_frame->loader()->isLoadingMainResource() || (parser && parser->isParsing() && parser->isExecutingScript()))
    18271827            return;
    18281828
  • trunk/WebCore/dom/DocumentParser.cpp

    r66660 r66670  
    3232
    3333DocumentParser::DocumentParser(Document* document)
    34     : m_parserStopped(false)
     34    : m_state(ParsingState)
    3535    , m_document(document)
    3636{
     
    4646}
    4747
     48void DocumentParser::startParsing()
     49{
     50    m_state = ParsingState;
     51}
     52
     53void DocumentParser::prepareToStopParsing()
     54{
     55    if (m_state == ParsingState)
     56        m_state = StoppingState;
     57}
     58
     59void DocumentParser::stopParsing()
     60{
     61    m_state = StoppedState;
     62}
     63
    4864void DocumentParser::detach()
    4965{
     66    m_state = DetachedState;
    5067    m_document = 0;
    5168}
  • trunk/WebCore/dom/DocumentParser.h

    r66660 r66670  
    5858    // FIXME: processingData() is only used by DocumentLoader::isLoadingInAPISense
    5959    // and is very unclear as to what it actually means.  The LegacyHTMLDocumentParser
    60     // used to implements it.
     60    // used to implement it.
    6161    virtual bool processingData() const { return false; }
    6262
    6363    // document() will return 0 after detach() is called.
    6464    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();
    6683
    6784    // Document is expected to detach the parser before releasing its ref.
     
    7289    virtual void detach();
    7390
    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 either
    77     // detach() or stopParsing() but right now only detach() will ASSERT.
    78     virtual void stopParsing() { m_parserStopped = true; }
    79 
    8091protected:
    8192    DocumentParser(Document*);
    8293
    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;
     94private:
     95    enum ParserState {
     96        ParsingState,
     97        StoppingState,
     98        StoppedState,
     99        DetachedState
     100    };
     101    ParserState m_state;
    88102
    89 private:
    90103    // Every DocumentParser needs a pointer back to the document.
    91104    // m_document will be 0 after the parser is stopped.
  • trunk/WebCore/dom/RawDataDocumentParser.h

    r66660 r66670  
    4040    virtual void finish()
    4141    {
    42         if (!m_parserStopped && !isDetached())
     42        if (!isStopped())
    4343            document()->finishedParsing();
    4444    }
  • trunk/WebCore/dom/XMLDocumentParser.cpp

    r66660 r66670  
    133133        m_originalSourceForTransform += parseString;
    134134
    135     if (isDetached() || m_parserStopped || m_sawXSLTransform)
     135    if (isStopped() || m_sawXSLTransform)
    136136        return;
    137137
     
    191191void XMLDocumentParser::exitText()
    192192{
    193     if (m_parserStopped)
     193    if (isStopped())
    194194        return;
    195195
  • trunk/WebCore/dom/XMLDocumentParserLibxml2.cpp

    r66660 r66670  
    661661        // JavaScript (which may be run under the xmlParseChunk callstack) may
    662662        // cause the parser to be stopped or detached.
    663         if (isDetached() || m_parserStopped)
     663        if (isStopped())
    664664            return;
    665665    }
     
    734734                                  const xmlChar** libxmlNamespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes)
    735735{
    736     if (m_parserStopped)
     736    if (isStopped())
    737737        return;
    738738
     
    823823void XMLDocumentParser::endElementNs()
    824824{
    825     if (m_parserStopped)
     825    if (isStopped())
    826826        return;
    827827
     
    907907void XMLDocumentParser::characters(const xmlChar* s, int len)
    908908{
    909     if (m_parserStopped)
     909    if (isStopped())
    910910        return;
    911911
     
    922922void XMLDocumentParser::error(ErrorType type, const char* message, va_list args)
    923923{
    924     if (m_parserStopped)
     924    if (isStopped())
    925925        return;
    926926
     
    946946void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlChar* data)
    947947{
    948     if (m_parserStopped)
     948    if (isStopped())
    949949        return;
    950950
     
    980980void XMLDocumentParser::cdataBlock(const xmlChar* s, int len)
    981981{
    982     if (m_parserStopped)
     982    if (isStopped())
    983983        return;
    984984
     
    998998void XMLDocumentParser::comment(const xmlChar* s)
    999999{
    1000     if (m_parserStopped)
     1000    if (isStopped())
    10011001        return;
    10021002
     
    10351035void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
    10361036{
    1037     if (m_parserStopped)
     1037    if (isStopped())
    10381038        return;
    10391039
     
    12951295    sax.entityDecl = xmlSAX2EntityDecl;
    12961296    sax.initialized = XML_SAX2_MAGIC;
    1297     m_parserStopped = false;
     1297    DocumentParser::startParsing();
    12981298    m_sawError = false;
    12991299    m_sawXSLTransform = false;
     
    13191319        document()->styleSelectorChanged(RecalcStyleImmediately);
    13201320        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())
    13261326        return;
    13271327
  • trunk/WebCore/dom/XMLDocumentParserQt.cpp

    r66660 r66670  
    200200void XMLDocumentParser::initializeParserContext(const char*)
    201201{
    202     m_parserStopped = false;
     202    DocumentParser::startParsing();
    203203    m_sawError = false;
    204204    m_sawXSLTransform = false;
     
    214214        document()->styleSelectorChanged(RecalcStyleImmediately);
    215215        document()->setParsing(true);
    216         m_parserStopped = true;
     216        DocumentParser::stopParsing();
    217217    }
    218218#endif
     
    351351void XMLDocumentParser::parse()
    352352{
    353     while (!m_parserStopped && !m_parserPaused && !m_stream.atEnd()) {
     353    while (!isStopped() && !m_parserPaused && !m_stream.atEnd()) {
    354354        m_stream.readNext();
    355355        switch (m_stream.tokenType()) {
  • trunk/WebCore/html/parser/HTMLDocumentParser.cpp

    r66660 r66670  
    143143}
    144144
     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
     147void 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
    145167bool HTMLDocumentParser::processingData() const
    146168{
     
    150172void HTMLDocumentParser::pumpTokenizerIfPossible(SynchronousMode mode)
    151173{
    152     if (m_parserStopped || m_treeBuilder->isPaused())
     174    if (isStopped() || m_treeBuilder->isPaused())
    153175        return;
    154176
     
    194216void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
    195217{
    196     ASSERT(!isDetached());
    197     ASSERT(!m_parserStopped);
     218    ASSERT(!isStopped());
    198219    ASSERT(!m_treeBuilder->isPaused());
    199220    ASSERT(!isScheduledForResume());
     
    215236
    216237        // JavaScript may have stopped or detached the parser.
    217         if (isDetached() || m_parserStopped)
     238        if (isStopped())
    218239            return;
    219240
     
    227248
    228249        // JavaScript may have stopped or detached the parser.
    229         if (isDetached() || m_parserStopped)
     250        if (isStopped())
    230251            return;
    231252
     
    276297void HTMLDocumentParser::insert(const SegmentedString& source)
    277298{
    278     if (m_parserStopped)
     299    if (isStopped())
    279300        return;
    280301
     
    297318void HTMLDocumentParser::append(const SegmentedString& source)
    298319{
    299     if (m_parserStopped)
     320    if (isStopped())
    300321        return;
    301322
     
    329350    ASSERT(!isScheduledForResume());
    330351
    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 
    339352    // Informs the the rest of WebCore that parsing is really finished (and deletes this).
    340353    m_treeBuilder->finished();
     
    350363        return;
    351364    }
    352     end();
     365    prepareToStopParsing();
    353366}
    354367
     
    363376
    364377    m_endWasDelayed = false;
    365     end();
     378    prepareToStopParsing();
    366379}
    367380
     
    448461void HTMLDocumentParser::notifyFinished(CachedResource* cachedResource)
    449462{
     463    if (isStopping()) {
     464        prepareToStopParsing();
     465        return;
     466    }
     467
    450468    // pumpTokenizer can cause this parser to be detached from the Document,
    451469    // but we need to ensure it isn't deleted yet.
  • trunk/WebCore/html/parser/HTMLDocumentParser.h

    r66660 r66670  
    8282    virtual bool finishWasCalled();
    8383    virtual bool processingData() const;
     84    virtual void prepareToStopParsing();
    8485    virtual void stopParsing();
    8586    virtual bool isWaitingForScripts() const;
  • trunk/WebCore/html/parser/HTMLScriptRunner.cpp

    r66660 r66670  
    7676    if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchingForLoad())
    7777        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    }
    7884}
    7985
     
    130136    ASSERT(isPendingScriptReady(m_parsingBlockingScript));
    131137
    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 
    136138    InsertionPointRecord insertionPointRecord(m_host->inputStream());
    137139    executePendingScriptAndDispatchEvent(m_parsingBlockingScript);
     
    142144    bool errorOccurred = false;
    143145    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);
    144150
    145151    // Clear the pending script before possible rentrancy from executeScript()
     
    239245}
    240246
     247bool 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
    241265void HTMLScriptRunner::requestParsingBlockingScript(Element* element)
    242266{
     
    253277}
    254278
     279void 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
    255289bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Element* script) const
    256290{
     
    288322
    289323        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);
    292329        } else {
    293330            // FIXME: We do not block inline <script> tags on stylesheets to match the
  • trunk/WebCore/html/parser/HTMLScriptRunner.h

    r66660 r66670  
    2828
    2929#include "PendingScript.h"
     30#include <wtf/Deque.h>
    3031#include <wtf/Noncopyable.h>
    3132#include <wtf/PassRefPtr.h>
     
    5758    bool hasScriptsWaitingForStylesheets() const { return m_hasScriptsWaitingForStylesheets; }
    5859    bool executeScriptsWaitingForStylesheets();
     60    bool executeScriptsWaitingForParsing();
    5961
    6062    bool isExecutingScript() const { return !!m_scriptNestingLevel; }
     
    7274
    7375    void requestParsingBlockingScript(Element*);
     76    void requestDeferredScript(Element*);
    7477    bool requestPendingScript(PendingScript&, Element*) const;
    7578
     
    8588    HTMLScriptRunnerHost* m_host;
    8689    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
    8791    unsigned m_scriptNestingLevel;
    8892
  • trunk/WebCore/loader/ImageDocument.cpp

    r66660 r66670  
    139139void ImageDocumentParser::finish()
    140140{
    141     if (!m_parserStopped && document()->imageElement()) {
     141    if (!isStopped() && document()->imageElement()) {
    142142        CachedImage* cachedImage = document()->cachedImage();
    143143        RefPtr<SharedBuffer> data = document()->frame()->loader()->documentLoader()->mainResourceData();
Note: See TracChangeset for help on using the changeset viewer.