Changeset 63998 in webkit


Ignore:
Timestamp:
Jul 23, 2010 3:14:02 PM (14 years ago)
Author:
abarth@webkit.org
Message:

2010-07-23 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

HTML5 Parser: document.write in a asynchronous script which is specified to load before page finish blows away document
https://bugs.webkit.org/show_bug.cgi?id=42365

  • http/tests/misc/write-from-dom-script-expected.txt: Added.
  • http/tests/misc/write-from-dom-script.html: Added.
    • Test the scenario where a script added to the DOM asynchronously while the nesting level is >0. It's supposed to have its calls to document.write blocked.
  • http/tests/misc/write-while-waiting.html:
    • Writes are only prevented from scripts that are added to the DOM. Scripts that run via setTimeout do not have their writes blocked.

2010-07-23 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

HTML5 Parser: document.write in a asynchronous script which is specified to load before page finish blows away document
https://bugs.webkit.org/show_bug.cgi?id=42365

This patch implements the changes Ian made to HTML5 to address these
issues. Let's try it and see how well it works.

Test: http/tests/misc/write-from-dom-script.html

  • dom/Document.cpp: (WebCore::Document::Document): (WebCore::Document::write):
  • dom/Document.h: (WebCore::Document::writeDisabled): (WebCore::Document::setWriteDisabled):
  • dom/DocumentParser.h: (WebCore::DocumentParser::hasInsertionPoint):
  • dom/ScriptElement.cpp: (WebCore::ScriptElement::insertedIntoDocument): (WebCore::ScriptElementData::ScriptElementData): (WebCore::ScriptElementData::evaluateScript):
  • dom/ScriptElement.h: (WebCore::ScriptElementData::writeDisabled): (WebCore::ScriptElementData::setWriteDisabled):
  • html/HTMLDocumentParser.cpp: (WebCore::HTMLDocumentParser::hasInsertionPoint): (WebCore::HTMLDocumentParser::insert):
  • html/HTMLDocumentParser.h:
Location:
trunk
Files:
2 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r63995 r63998  
     12010-07-23  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        HTML5 Parser: document.write in a asynchronous script which is specified to load before page finish blows away document
     6        https://bugs.webkit.org/show_bug.cgi?id=42365
     7
     8        * http/tests/misc/write-from-dom-script-expected.txt: Added.
     9        * http/tests/misc/write-from-dom-script.html: Added.
     10          - Test the scenario where a script added to the DOM asynchronously
     11            while the nesting level is >0.  It's supposed to have its calls to
     12            document.write blocked.
     13        * http/tests/misc/write-while-waiting.html:
     14          - Writes are only prevented from scripts that are added to the DOM.
     15            Scripts that run via setTimeout do not have their writes blocked.
     16
    1172010-07-23  Shinichiro Hamaji  <hamaji@chromium.org>
    218
  • trunk/LayoutTests/http/tests/misc/write-while-waiting.html

    r63165 r63998  
    11<html>
    22<body>
    3 PASS
     3FAIL
    44<script>
    55if (window.layoutTestController)
    66    layoutTestController.dumpAsText();
    77
    8 setTimeout("document.write('FAIL');document.close();", 100);
     8setTimeout("document.write('PASS');document.close();", 100);
    99</script>
    1010<script src="resources/script-slow1.pl"></script>
  • trunk/WebCore/ChangeLog

    r63996 r63998  
     12010-07-23  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        HTML5 Parser: document.write in a asynchronous script which is specified to load before page finish blows away document
     6        https://bugs.webkit.org/show_bug.cgi?id=42365
     7
     8        This patch implements the changes Ian made to HTML5 to address these
     9        issues.  Let's try it and see how well it works.
     10
     11        Test: http/tests/misc/write-from-dom-script.html
     12
     13        * dom/Document.cpp:
     14        (WebCore::Document::Document):
     15        (WebCore::Document::write):
     16        * dom/Document.h:
     17        (WebCore::Document::writeDisabled):
     18        (WebCore::Document::setWriteDisabled):
     19        * dom/DocumentParser.h:
     20        (WebCore::DocumentParser::hasInsertionPoint):
     21        * dom/ScriptElement.cpp:
     22        (WebCore::ScriptElement::insertedIntoDocument):
     23        (WebCore::ScriptElementData::ScriptElementData):
     24        (WebCore::ScriptElementData::evaluateScript):
     25        * dom/ScriptElement.h:
     26        (WebCore::ScriptElementData::writeDisabled):
     27        (WebCore::ScriptElementData::setWriteDisabled):
     28        * html/HTMLDocumentParser.cpp:
     29        (WebCore::HTMLDocumentParser::hasInsertionPoint):
     30        (WebCore::HTMLDocumentParser::insert):
     31        * html/HTMLDocumentParser.h:
     32
    1332010-07-23  Patrick Gansterer  <paroga@paroga.com>
    234
  • trunk/WebCore/dom/Document.cpp

    r63165 r63998  
    364364    , m_containsValidityStyleRules(false)
    365365    , m_updateFocusAppearanceRestoresSelection(false)
     366    , m_writeDisabled(false)
    366367    , m_title("")
    367368    , m_rawTitle("")
     
    20172018#endif
    20182019
    2019     if (!m_parser)
     2020    // If the insertion point is undefined and the Document has the
     2021    // "write-neutralised" flag set, then abort these steps.
     2022    bool hasInsertionPoint = m_parser && m_parser->hasInsertionPoint();
     2023    if (!hasInsertionPoint && writeDisabled())
     2024        return;
     2025
     2026    if (!hasInsertionPoint)
    20202027        open(ownerDocument);
    20212028
  • trunk/WebCore/dom/Document.h

    r62693 r63998  
    10031003    const QualifiedName& idAttributeName() const { return m_idAttributeName; }
    10041004
     1005    bool writeDisabled() const { return m_writeDisabled; }
     1006    void setWriteDisabled(bool flag) { m_writeDisabled = flag; }
     1007
    10051008protected:
    10061009    Document(Frame*, const KURL&, bool isXHTML, bool isHTML);
     
    11561159    bool m_updateFocusAppearanceRestoresSelection;
    11571160
     1161    // http://www.whatwg.org/specs/web-apps/current-work/#write-neutralised
     1162    bool m_writeDisabled;
     1163
    11581164    String m_title;
    11591165    String m_rawTitle;
  • trunk/WebCore/dom/DocumentParser.h

    r61985 r63998  
    4141    virtual ScriptableDocumentParser* asScriptableDocumentParser() { return 0; }
    4242
     43    // http://www.whatwg.org/specs/web-apps/current-work/#insertion-point
     44    virtual bool hasInsertionPoint() { return true; }
     45
    4346    // insert is used by document.write
    4447    virtual void insert(const SegmentedString&) = 0;
  • trunk/WebCore/dom/ScriptElement.cpp

    r61518 r63998  
    2828#include "DocLoader.h"
    2929#include "Document.h"
     30#include "DocumentParser.h"
    3031#include "Frame.h"
    3132#include "FrameLoader.h"
     
    5455        return;
    5556
     57    // http://www.whatwg.org/specs/web-apps/current-work/#script
     58
     59    // If the element's Document has an active parser, and the parser's script
     60    // nesting level is non-zero, but this script element does not have the
     61    // "parser-inserted" flag set, the user agent must set the element's
     62    // "write-neutralised" flag.
     63    DocumentParser* parser = data.element()->document()->parser();
     64    if (parser && parser->hasInsertionPoint())
     65        data.setWriteDisabled(true);
     66
    5667    if (!sourceUrl.isEmpty()) {
    5768        data.requestScript(sourceUrl);
     
    8394    if (element->inDocument() && element->firstChild())
    8495        data.evaluateScript(ScriptSourceCode(data.scriptContent(), element->document()->url())); // FIXME: Provide a real starting line number here
    85 }
    86 
    87 static inline bool useHTML5Parser(Document* document)
    88 {
    89     ASSERT(document);
    90     Settings* settings = document->page() ? document->page()->settings() : 0;
    91     return settings && settings->html5ParserEnabled();
    9296}
    9397
     
    138142    , m_cachedScript(0)
    139143    , m_createdByParser(false)
     144    , m_writeDisabled(false)
    140145    , m_requested(false)
    141146    , m_evaluated(false)
     
    192197        m_evaluated = true;
    193198
     199        // http://www.whatwg.org/specs/web-apps/current-work/#script
     200
     201        // If the script element's "write-neutralised" flag is set, then flag
     202        // the Document the script element was in when the "write-neutralised"
     203        // flag was set as being itself "write-neutralised". Let neutralised doc
     204        // be that Document.
     205        if (m_writeDisabled) {
     206            ASSERT(!m_element->document()->writeDisabled());
     207            m_element->document()->setWriteDisabled(true);
     208        }
     209
     210        // Create a script from the script element node, using the script
     211        // block's source and the script block's type.
     212        // Note: This is where the script is compiled and actually executed.
    194213        frame->script()->evaluate(sourceCode);
     214
     215        // Remove the "write-neutralised" flag from neutralised doc, if it was
     216        // set in the earlier step.
     217        if (m_writeDisabled) {
     218            ASSERT(m_element->document()->writeDisabled());
     219            m_element->document()->setWriteDisabled(false);
     220        }
     221
    195222        Document::updateStyleForAllDocuments();
    196223    }
  • trunk/WebCore/dom/ScriptElement.h

    r61518 r63998  
    8383    bool createdByParser() const { return m_createdByParser; }
    8484    void setCreatedByParser(bool value) { m_createdByParser = value; }
     85    bool writeDisabled() const { return m_writeDisabled; }
     86    void setWriteDisabled(bool value) { m_writeDisabled = value; }
    8587    bool haveFiredLoadEvent() const { return m_firedLoad; }
    8688    void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; }
     
    100102    CachedResourceHandle<CachedScript> m_cachedScript;
    101103    bool m_createdByParser; // HTML5: "parser-inserted"
     104    bool m_writeDisabled; // http://www.whatwg.org/specs/web-apps/current-work/#write-neutralised
    102105    bool m_requested;
    103106    bool m_evaluated; // HTML5: "already started"
  • trunk/WebCore/html/HTMLDocumentParser.cpp

    r63165 r63998  
    214214}
    215215
     216bool HTMLDocumentParser::hasInsertionPoint()
     217{
     218    return m_input.hasInsertionPoint();
     219}
     220
    216221void HTMLDocumentParser::insert(const SegmentedString& source)
    217222{
    218223    if (m_parserStopped)
    219224        return;
    220 
    221     if (m_scriptRunner && !m_scriptRunner->inScriptExecution() && m_input.haveSeenEndOfFile()) {
    222         // document.write was called without a current insertion point.
    223         // According to the spec, we're supposed to implicitly open the
    224         // document.  Unfortunately, that behavior isn't sufficiently compatible
    225         // with the web.  The working group is mulling over what exactly to
    226         // do.  In the meantime, we're going to try one of the potential
    227         // solutions, which is to ignore the write.
    228         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=9767
    229         return;
    230     }
    231225
    232226    {
     
    325319    if (!m_scriptRunner)
    326320        return false;
    327     return m_scriptRunner->inScriptExecution();
     321    return m_scriptRunner->isExecutingScript();
    328322}
    329323
     
    403397    if (!m_scriptRunner->hasScriptsWaitingForStylesheets())
    404398        return;
    405     ASSERT(!m_scriptRunner->inScriptExecution());
     399    ASSERT(!m_scriptRunner->isExecutingScript());
    406400    ASSERT(m_treeBuilder->isPaused());
    407401    // Note: We only ever wait on one script at a time, so we always know this
  • trunk/WebCore/html/HTMLDocumentParser.h

    r62033 r63998  
    6565private:
    6666    // DocumentParser
     67    virtual bool hasInsertionPoint();
    6768    virtual void insert(const SegmentedString&);
    6869    virtual void append(const SegmentedString&);
  • trunk/WebCore/html/HTMLInputStream.h

    r62168 r63998  
    6565    }
    6666
     67    bool hasInsertionPoint() const
     68    {
     69        if (&m_first != m_last)
     70            return true;
     71        if (!haveSeenEndOfFile()) {
     72            // FIXME: Somehow we need to understand the difference between
     73            // input streams that are coming off the network and streams that
     74            // were created with document.open(). In the later case, we always
     75            // have an isertion point at the end of the stream until someone
     76            // calls document.close().
     77            return true;
     78        }
     79        return false;
     80    }
     81
    6782    void markEndOfFile()
    6883    {
     
    7489    }
    7590
    76     bool haveSeenEndOfFile()
     91    bool haveSeenEndOfFile() const
    7792    {
    7893        return m_last->isClosed();
  • trunk/WebCore/html/HTMLScriptRunner.cpp

    r61940 r63998  
    155155    if (!scriptElement->shouldExecuteAsJavaScript())
    156156        return;
    157     ASSERT(inScriptExecution());
     157    ASSERT(isExecutingScript());
    158158    if (!m_document->frame())
    159159        return;
  • trunk/WebCore/html/HTMLScriptRunner.h

    r61940 r63998  
    5454    bool executeScriptsWaitingForStylesheets();
    5555
    56     bool inScriptExecution() { return !!m_scriptNestingLevel; }
     56    bool isExecutingScript() { return !!m_scriptNestingLevel; }
    5757
    5858private:
Note: See TracChangeset for help on using the changeset viewer.