2010-08-09 Eric Seidel <eric@webkit.org>
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Aug 2010 21:52:01 +0000 (21:52 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Aug 2010 21:52:01 +0000 (21:52 +0000)
        Reviewed by Adam Barth.

        Use the HTML5 TreeBuilder for Fragment Parsing
        https://bugs.webkit.org/show_bug.cgi?id=43586

        * html5lib/runner-expected.txt:
         - We pass 2 more tests now that the tokenizer is set to
           the right state before fragment parsing.
        * html5lib/runner-expected-html5.txt:
         - We pass 4 more tests now that HTML5 fragment parsing is
           (partially) implemented behind the --html5-treebuilder flag.
2010-08-09  Eric Seidel  <eric@webkit.org>

        Reviewed by Adam Barth.

        Use the HTML5 TreeBuilder for Fragment Parsing
        https://bugs.webkit.org/show_bug.cgi?id=43586

        The bulk of this change is just a transcription of the HTML5 spec:
        http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case

        DocumentParser() now sets the right tokenizer state before handling
        fragments.  Since default code path uses the HTML5 tokenizer with the
        legacy tree builder, this fixes 2 tokenizer-state tests for the html5lib.
        This fixes 2 more tree-builder tests when the html5 treebuilder is enabled too.

        * dom/DocumentFragment.cpp:
        (WebCore::DocumentFragment::parseHTML):
         - HTML5 implementation of fragment parsing requires the context element (parent)
           pointer.  The legacy implementation handles all parsing branches which require
           the context element outside of the parser itself, which likely produces "wrong"
           results.  We'll remove those branches when we turn on the HMTL5 fragment parser.
        (WebCore::DocumentFragment::parseXML):
         - Rename "parent" to "contextElement" to match the HTML path (and the HTML5 spec).
        * dom/DocumentFragment.h:
        * dom/Element.cpp:
        (WebCore::Element::createContextualFragment):
         - Pass the contextElement (this).
        * html/HTMLConstructionSite.cpp:
        (WebCore::HTMLConstructionSite::setForm):
         - Needed by for the fragment case.
        (WebCore::HTMLConstructionSite::insertHTMLBodyStartTagInBody):
         - I'm not sure this method should exist, it only has one caller.
           but for now, I've moved the fragment case FIXME out to the
           one caller and implemented it.
        * html/HTMLConstructionSite.h:
        * html/HTMLDocumentParser.cpp:
        (WebCore::HTMLNames::tokenizerStateForContextElement):
         - Part of the fragment case handling for the HTML5 parser.
        (WebCore::HTMLDocumentParser::HTMLDocumentParser):
         - Set the Tokenizer state based on the contextElement.
        (WebCore::HTMLDocumentParser::parseDocumentFragment):
         - Take a contextElement argument.
        * html/HTMLDocumentParser.h:
        * html/HTMLElement.cpp:
        (WebCore::HTMLElement::setInnerHTML):
         - Added a FIXME before the branches the old parser used to avoid ever needing
           to pass a context element when parsing HTML fragments.
        (WebCore::HTMLElement::insertAdjacentHTML):
         - Pass the context element.
        * html/HTMLTokenizer.h:
        * html/HTMLTreeBuilder.cpp:
         - I added a new helper class FragmentParsingContext to simplify the two
           HTMLTreeBuilder constructors and hide the existence of m_dummyDocumentForFragmentParse.
         - I also removed m_isParsingFragment and replaced it with an isParsingFragment() function.
        (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
        (WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext):
        (WebCore::HTMLTreeBuilder::FragmentParsingContext::document):
        (WebCore::HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext):
        (WebCore::HTMLTreeBuilder::passTokenToLegacyParser):
        (WebCore::HTMLTreeBuilder::processStartTagForInBody):
         - I had to implement two notImplemented() states in order to get most of the
           layout tests to pass when using the HTML5 parser fragment case.
        (WebCore::HTMLTreeBuilder::processColgroupEndTagForInColumnGroup):
        (WebCore::HTMLTreeBuilder::processStartTagForInTable):
        (WebCore::HTMLTreeBuilder::processStartTag):
        (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately):
        (WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
        (WebCore::HTMLTreeBuilder::processEndTagForInRow):
        (WebCore::HTMLTreeBuilder::processEndTagForInCell):
        (WebCore::HTMLTreeBuilder::processCaptionEndTagForInCaption):
        (WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
        (WebCore::HTMLTreeBuilder::processTableEndTagForInTable):
        (WebCore::HTMLTreeBuilder::processEndTag):
        (WebCore::HTMLTreeBuilder::processCharacterBuffer):
        (WebCore::HTMLTreeBuilder::processEndOfFile):
        (WebCore::HTMLTreeBuilder::finished):
         - The HTML5 parsing algorithm fragment case uses a dummy document to handle all the parsing
           and then moves all the children from the dummy document over into a DocumentFragment
           when the parse is done.  We could avoid this adopt step by making the TreeBuilder a bit
           more complicated, but I'm not sure that's necessary (yet).
        * html/HTMLTreeBuilder.h:
        (WebCore::HTMLTreeBuilder::isParsingFragment):
        (WebCore::HTMLTreeBuilder::FragmentParsingContext::fragment):
        (WebCore::HTMLTreeBuilder::FragmentParsingContext::contextElement):
        (WebCore::HTMLTreeBuilder::FragmentParsingContext::scriptingPermission):
        * xml/XSLTProcessor.cpp:
        (WebCore::createFragmentFromSource):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@65006 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/html5lib/runner-expected-html5.txt
LayoutTests/html5lib/runner-expected.txt
WebCore/ChangeLog
WebCore/dom/DocumentFragment.cpp
WebCore/dom/DocumentFragment.h
WebCore/dom/Element.cpp
WebCore/html/HTMLConstructionSite.cpp
WebCore/html/HTMLConstructionSite.h
WebCore/html/HTMLDocumentParser.cpp
WebCore/html/HTMLDocumentParser.h
WebCore/html/HTMLElement.cpp
WebCore/html/HTMLElementStack.cpp
WebCore/html/HTMLElementStack.h
WebCore/html/HTMLTokenizer.h
WebCore/html/HTMLTreeBuilder.cpp
WebCore/html/HTMLTreeBuilder.h
WebCore/xml/XSLTProcessor.cpp

index d8b8fd7..dd633e6 100644 (file)
@@ -1,3 +1,17 @@
+2010-08-09  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Adam Barth.
+
+        Use the HTML5 TreeBuilder for Fragment Parsing
+        https://bugs.webkit.org/show_bug.cgi?id=43586
+
+        * html5lib/runner-expected.txt:
+         - We pass 2 more tests now that the tokenizer is set to
+           the right state before fragment parsing.
+        * html5lib/runner-expected-html5.txt:
+         - We pass 4 more tests now that HTML5 fragment parsing is
+           (partially) implemented behind the --html5-treebuilder flag.
+
 2010-08-09  Dumitru Daniliuc  <dumi@chromium.org>
 
         Reviewed by Adam Barth.
index ac019ff..5ca2329 100644 (file)
@@ -17,30 +17,9 @@ resources/tests2.dat: PASS
 resources/tests3.dat: PASS
 
 resources/tests4.dat:
-3
-5
 6
 7
 
-Test 3 of 7 in resources/tests4.dat failed. Input:
-textarea content with <em>pseudo</em> <foo>markup
-Got:
-| "textarea content with "
-| <em>
-|   "pseudo"
-| " "
-| <foo>
-|   "markup"
-Expected:
-| "textarea content with <em>pseudo</em> <foo>markup"
-
-Test 5 of 7 in resources/tests4.dat failed. Input:
-</plaintext>
-Got:
-| 
-Expected:
-| "</plaintext>"
-
 Test 6 of 7 in resources/tests4.dat failed. Input:
 setting html's innerHTML
 Got:
@@ -62,8 +41,6 @@ resources/tests5.dat: PASS
 resources/tests6.dat:
 27
 30
-37
-44
 45
 
 Test 27 of 51 in resources/tests6.dat failed. Input:
@@ -80,26 +57,6 @@ Got:
 Expected:
 | <frame>
 
-Test 37 of 51 in resources/tests6.dat failed. Input:
-<caption><col><colgroup><tbody><tfoot><thead><tr>
-Got:
-| <caption>
-| <colgroup>
-| <tbody>
-| <tfoot>
-| <thead>
-|   <tr>
-Expected:
-| <tr>
-
-Test 44 of 51 in resources/tests6.dat failed. Input:
-</table><tr>
-Got:
-| <tr>
-Expected:
-| <tbody>
-|   <tr>
-
 Test 45 of 51 in resources/tests6.dat failed. Input:
 <body></body></html>
 Got:
index 14d3ea5..8a8f7be 100644 (file)
@@ -16,30 +16,9 @@ resources/tests2.dat: PASS
 resources/tests3.dat: PASS
 
 resources/tests4.dat:
-3
-5
 6
 7
 
-Test 3 of 7 in resources/tests4.dat failed. Input:
-textarea content with <em>pseudo</em> <foo>markup
-Got:
-| "textarea content with "
-| <em>
-|   "pseudo"
-| " "
-| <foo>
-|   "markup"
-Expected:
-| "textarea content with <em>pseudo</em> <foo>markup"
-
-Test 5 of 7 in resources/tests4.dat failed. Input:
-</plaintext>
-Got:
-| 
-Expected:
-| "</plaintext>"
-
 Test 6 of 7 in resources/tests4.dat failed. Input:
 setting html's innerHTML
 Got:
index 843ca49..72ac12b 100644 (file)
@@ -1,3 +1,91 @@
+2010-08-09  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Adam Barth.
+
+        Use the HTML5 TreeBuilder for Fragment Parsing
+        https://bugs.webkit.org/show_bug.cgi?id=43586
+
+        The bulk of this change is just a transcription of the HTML5 spec:
+        http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
+
+        DocumentParser() now sets the right tokenizer state before handling
+        fragments.  Since default code path uses the HTML5 tokenizer with the
+        legacy tree builder, this fixes 2 tokenizer-state tests for the html5lib.
+        This fixes 2 more tree-builder tests when the html5 treebuilder is enabled too.
+
+        * dom/DocumentFragment.cpp:
+        (WebCore::DocumentFragment::parseHTML):
+         - HTML5 implementation of fragment parsing requires the context element (parent)
+           pointer.  The legacy implementation handles all parsing branches which require
+           the context element outside of the parser itself, which likely produces "wrong"
+           results.  We'll remove those branches when we turn on the HMTL5 fragment parser.
+        (WebCore::DocumentFragment::parseXML):
+         - Rename "parent" to "contextElement" to match the HTML path (and the HTML5 spec).
+        * dom/DocumentFragment.h:
+        * dom/Element.cpp:
+        (WebCore::Element::createContextualFragment):
+         - Pass the contextElement (this).
+        * html/HTMLConstructionSite.cpp:
+        (WebCore::HTMLConstructionSite::setForm):
+         - Needed by for the fragment case.
+        (WebCore::HTMLConstructionSite::insertHTMLBodyStartTagInBody):
+         - I'm not sure this method should exist, it only has one caller.
+           but for now, I've moved the fragment case FIXME out to the
+           one caller and implemented it.
+        * html/HTMLConstructionSite.h:
+        * html/HTMLDocumentParser.cpp:
+        (WebCore::HTMLNames::tokenizerStateForContextElement):
+         - Part of the fragment case handling for the HTML5 parser.
+        (WebCore::HTMLDocumentParser::HTMLDocumentParser):
+         - Set the Tokenizer state based on the contextElement.
+        (WebCore::HTMLDocumentParser::parseDocumentFragment):
+         - Take a contextElement argument.
+        * html/HTMLDocumentParser.h:
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::setInnerHTML):
+         - Added a FIXME before the branches the old parser used to avoid ever needing
+           to pass a context element when parsing HTML fragments.
+        (WebCore::HTMLElement::insertAdjacentHTML):
+         - Pass the context element.
+        * html/HTMLTokenizer.h:
+        * html/HTMLTreeBuilder.cpp:
+         - I added a new helper class FragmentParsingContext to simplify the two
+           HTMLTreeBuilder constructors and hide the existence of m_dummyDocumentForFragmentParse.
+         - I also removed m_isParsingFragment and replaced it with an isParsingFragment() function.
+        (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
+        (WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext):
+        (WebCore::HTMLTreeBuilder::FragmentParsingContext::document):
+        (WebCore::HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext):
+        (WebCore::HTMLTreeBuilder::passTokenToLegacyParser):
+        (WebCore::HTMLTreeBuilder::processStartTagForInBody):
+         - I had to implement two notImplemented() states in order to get most of the
+           layout tests to pass when using the HTML5 parser fragment case.
+        (WebCore::HTMLTreeBuilder::processColgroupEndTagForInColumnGroup):
+        (WebCore::HTMLTreeBuilder::processStartTagForInTable):
+        (WebCore::HTMLTreeBuilder::processStartTag):
+        (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately):
+        (WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
+        (WebCore::HTMLTreeBuilder::processEndTagForInRow):
+        (WebCore::HTMLTreeBuilder::processEndTagForInCell):
+        (WebCore::HTMLTreeBuilder::processCaptionEndTagForInCaption):
+        (WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
+        (WebCore::HTMLTreeBuilder::processTableEndTagForInTable):
+        (WebCore::HTMLTreeBuilder::processEndTag):
+        (WebCore::HTMLTreeBuilder::processCharacterBuffer):
+        (WebCore::HTMLTreeBuilder::processEndOfFile):
+        (WebCore::HTMLTreeBuilder::finished):
+         - The HTML5 parsing algorithm fragment case uses a dummy document to handle all the parsing
+           and then moves all the children from the dummy document over into a DocumentFragment
+           when the parse is done.  We could avoid this adopt step by making the TreeBuilder a bit
+           more complicated, but I'm not sure that's necessary (yet).
+        * html/HTMLTreeBuilder.h:
+        (WebCore::HTMLTreeBuilder::isParsingFragment):
+        (WebCore::HTMLTreeBuilder::FragmentParsingContext::fragment):
+        (WebCore::HTMLTreeBuilder::FragmentParsingContext::contextElement):
+        (WebCore::HTMLTreeBuilder::FragmentParsingContext::scriptingPermission):
+        * xml/XSLTProcessor.cpp:
+        (WebCore::createFragmentFromSource):
+
 2010-08-09  Dumitru Daniliuc  <dumi@chromium.org>
 
         Reviewed by Adam Barth.
index ecc5725..47485b7 100644 (file)
@@ -82,16 +82,16 @@ bool DocumentFragment::shouldUseLegacyHTMLParser() const
         && !document()->page()->settings()->html5ParserEnabled();
 }
 
-void DocumentFragment::parseHTML(const String& source, FragmentScriptingPermission scriptingPermission)
+void DocumentFragment::parseHTML(const String& source, Element* contextElement, FragmentScriptingPermission scriptingPermission)
 {
     if (shouldUseLegacyHTMLParser())
         return LegacyHTMLDocumentParser::parseDocumentFragment(source, this, scriptingPermission);
-    HTMLDocumentParser::parseDocumentFragment(source, this, scriptingPermission);
+    HTMLDocumentParser::parseDocumentFragment(source, this, contextElement, scriptingPermission);
 }
 
-bool DocumentFragment::parseXML(const String& source, Element* parent, FragmentScriptingPermission scriptingPermission)
+bool DocumentFragment::parseXML(const String& source, Element* contextElement, FragmentScriptingPermission scriptingPermission)
 {
-    return XMLDocumentParser::parseDocumentFragment(source, this, parent, scriptingPermission);
+    return XMLDocumentParser::parseDocumentFragment(source, this, contextElement, scriptingPermission);
 }
 
 }
index 5eff17f..d3dadb8 100644 (file)
@@ -33,8 +33,8 @@ class DocumentFragment : public ContainerNode {
 public:
     static PassRefPtr<DocumentFragment> create(Document*);
 
-    void parseHTML(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
-    bool parseXML(const String&, Element* parent, FragmentScriptingPermission = FragmentScriptingAllowed);
+    void parseHTML(const String&, Element* contextElement, FragmentScriptingPermission = FragmentScriptingAllowed);
+    bool parseXML(const String&, Element* contextElement, FragmentScriptingPermission = FragmentScriptingAllowed);
 
 private:
     DocumentFragment(Document*);
index 2fa75ce..0e89e93 100644 (file)
@@ -95,7 +95,7 @@ PassRefPtr<DocumentFragment> Element::createContextualFragment(const String& mar
     RefPtr<DocumentFragment> fragment = document()->createDocumentFragment();
 
     if (document()->isHTMLDocument())
-        fragment->parseHTML(markup, scriptingPermission);
+        fragment->parseHTML(markup, this, scriptingPermission);
     else {
         if (!fragment->parseXML(markup, this, scriptingPermission))
             // FIXME: We should propagate a syntax error exception out here.
index 0b17086..1a9a373 100644 (file)
@@ -141,6 +141,13 @@ HTMLConstructionSite::~HTMLConstructionSite()
 {
 }
 
+void HTMLConstructionSite::setForm(HTMLFormElement* form)
+{
+    // This method should only be needed for HTMLTreeBuilder in the fragment case.
+    ASSERT(!m_form);
+    m_form = form;
+}
+
 PassRefPtr<HTMLFormElement> HTMLConstructionSite::takeForm()
 {
     return m_form.release();
@@ -182,7 +189,6 @@ void HTMLConstructionSite::insertHTMLHtmlStartTagInBody(AtomicHTMLToken& token)
 void HTMLConstructionSite::insertHTMLBodyStartTagInBody(AtomicHTMLToken& token)
 {
     // FIXME: parse error
-    notImplemented(); // fragment case
     mergeAttributesFromTokenIntoElement(token, m_openElements.bodyElement());
 }
 
index d9c8ac5..16ba56b 100644 (file)
@@ -84,6 +84,7 @@ public:
 
     Element* head() const { return m_head.get(); }
 
+    void setForm(HTMLFormElement*);
     HTMLFormElement* form() const { return m_form.get(); }
     PassRefPtr<HTMLFormElement> takeForm();
 
index 354e7ed..28b3198 100644 (file)
@@ -29,6 +29,7 @@
 #include "DocumentFragment.h"
 #include "Element.h"
 #include "Frame.h"
+#include "HTMLNames.h"
 #include "HTMLParserScheduler.h"
 #include "HTMLTokenizer.h"
 #include "HTMLPreloadScanner.h"
@@ -44,6 +45,8 @@
 
 namespace WebCore {
 
+using namespace HTMLNames;
+
 namespace {
 
 class NestingLevelIncrementer : public Noncopyable {
@@ -63,6 +66,31 @@ private:
     int* m_counter;
 };
 
+// This is a direct transcription of step 4 from:
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
+HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElement, bool reportErrors)
+{
+    if (!contextElement)
+        return HTMLTokenizer::DataState;
+
+    const QualifiedName& contextTag = contextElement->tagQName();
+
+    if (contextTag.matches(titleTag) || contextTag.matches(textareaTag))
+        return HTMLTokenizer::RCDATAState;
+    if (contextTag.matches(styleTag)
+        || contextTag.matches(xmpTag)
+        || contextTag.matches(iframeTag)
+        || (contextTag.matches(noembedTag) && HTMLTreeBuilder::pluginsEnabled(contextElement->document()->frame()))
+        || (contextTag.matches(noscriptTag) && HTMLTreeBuilder::scriptEnabled(contextElement->document()->frame()))
+        || contextTag.matches(noframesTag))
+        return reportErrors ? HTMLTokenizer::RAWTEXTState : HTMLTokenizer::PLAINTEXTState;
+    if (contextTag.matches(scriptTag))
+        return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PLAINTEXTState;
+    if (contextTag.matches(plaintextTag))
+        return HTMLTokenizer::PLAINTEXTState;
+    return HTMLTokenizer::DataState;
+}
+
 } // namespace
 
 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors)
@@ -74,19 +102,19 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
     , m_endWasDelayed(false)
     , m_writeNestingLevel(0)
 {
-    begin();
 }
 
 // FIXME: Member variables should be grouped into self-initializing structs to
 // minimize code duplication between these constructors.
-HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
+HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
     : ScriptableDocumentParser(fragment->document())
     , m_tokenizer(new HTMLTokenizer)
-    , m_treeBuilder(new HTMLTreeBuilder(m_tokenizer.get(), fragment, scriptingPermission))
+    , m_treeBuilder(new HTMLTreeBuilder(m_tokenizer.get(), fragment, contextElement, scriptingPermission))
     , m_endWasDelayed(false)
     , m_writeNestingLevel(0)
 {
-    begin();
+    bool reportErrors = false; // For now document fragment parsing never reports errors.
+    m_tokenizer->setState(tokenizerStateForContextElement(contextElement, reportErrors));
 }
 
 HTMLDocumentParser::~HTMLDocumentParser()
@@ -97,11 +125,6 @@ HTMLDocumentParser::~HTMLDocumentParser()
     // then we could ASSERT some invariants here.
 }
 
-void HTMLDocumentParser::begin()
-{
-    // FIXME: Should we reset the tokenizer?
-}
-
 void HTMLDocumentParser::stopParsing()
 {
     DocumentParser::stopParsing();
@@ -413,9 +436,9 @@ ScriptController* HTMLDocumentParser::script() const
     return m_document->frame() ? m_document->frame()->script() : 0;
 }
 
-void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
+void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
 {
-    HTMLDocumentParser parser(fragment, scriptingPermission);
+    HTMLDocumentParser parser(fragment, contextElement, scriptingPermission);
     parser.insert(source); // Use insert() so that the parser will not yield.
     parser.finish();
     ASSERT(!parser.processingData()); // Make sure we're done. <rdar://problem/3963151>
index cc46d31..d055861 100644 (file)
@@ -54,13 +54,13 @@ class HTMLDocumentParser :  public ScriptableDocumentParser, HTMLScriptRunnerHos
 public:
     // FIXME: These constructors should be made private and replaced by create() methods.
     HTMLDocumentParser(HTMLDocument*, bool reportErrors);
-    HTMLDocumentParser(DocumentFragment*, FragmentScriptingPermission);
+    HTMLDocumentParser(DocumentFragment*, Element* contextElement, FragmentScriptingPermission);
     virtual ~HTMLDocumentParser();
 
     // Exposed for HTMLParserScheduler
     void resumeParsingAfterYield();
 
-    static void parseDocumentFragment(const String&, DocumentFragment*, FragmentScriptingPermission = FragmentScriptingAllowed);
+    static void parseDocumentFragment(const String&, DocumentFragment*, Element* contextElement, FragmentScriptingPermission = FragmentScriptingAllowed);
 
 private:
     // DocumentParser
index 0198901..6fc53a2 100644 (file)
@@ -275,6 +275,7 @@ String HTMLElement::outerHTML() const
     return createMarkup(this);
 }
 
+// FIXME: This method is unecessary with the new HTMLDocumentParser.
 PassRefPtr<DocumentFragment> HTMLElement::createContextualFragment(const String& markup, FragmentScriptingPermission scriptingPermission)
 {
     // The following is in accordance with the definition as used by IE.
@@ -340,6 +341,7 @@ static void replaceChildrenWithText(HTMLElement* element, const String& text, Ex
 
 void HTMLElement::setInnerHTML(const String& html, ExceptionCode& ec)
 {
+    // FIXME: This code can be removed, it's handled by the HTMLDocumentParser correctly.
     if (hasLocalName(scriptTag) || hasLocalName(styleTag)) {
         // Script and CSS source shouldn't be parsed as HTML.
         removeChildren();
@@ -551,7 +553,7 @@ void HTMLElement::insertAdjacentHTML(const String& where, const String& markup,
 {
     RefPtr<DocumentFragment> fragment = document()->createDocumentFragment();
     if (document()->isHTMLDocument())
-         fragment->parseHTML(markup);
+         fragment->parseHTML(markup, this);
     else {
         if (!fragment->parseXML(markup, this))
             // FIXME: We should propagate a syntax error exception out here.
index 531a3b4..194753b 100644 (file)
@@ -138,6 +138,23 @@ HTMLElementStack::~HTMLElementStack()
 {
 }
 
+bool HTMLElementStack::hasOnlyOneElement() const
+{
+    return !topRecord()->next();
+}
+
+bool HTMLElementStack::secondElementIsHTMLBodyElement() const
+{
+    // This is used the fragment case of <body> and <frameset> in the "in body"
+    // insertion mode.
+    // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
+    ASSERT(m_htmlElement);
+    // If we have a body element, it must always be the second element on the
+    // stack, as we always start with an html element, and any other element
+    // would cause the implicit creation of a body element.
+    return !!m_bodyElement;
+}
+
 void HTMLElementStack::popHTMLHeadElement()
 {
     ASSERT(top() == m_headElement);
index 62d031f..fd9f3b5 100644 (file)
@@ -121,6 +121,9 @@ public:
     bool hasOnlyHTMLElementsInScope() const;
     bool hasNumberedHeaderElementInScope() const;
 
+    bool hasOnlyOneElement() const;
+    bool secondElementIsHTMLBodyElement() const;
+
     Element* htmlElement() const;
     Element* headElement() const;
     Element* bodyElement() const;
index e4ca16a..0e9ba3a 100644 (file)
@@ -34,6 +34,7 @@
 
 namespace WebCore {
 
+class Element;
 class HTMLToken;
 
 class HTMLTokenizer : public Noncopyable {
index 016074e..2c7d40d 100644 (file)
@@ -253,6 +253,29 @@ bool isNotFormattingAndNotPhrasing(const Element* element)
     return isScopingTag(tagName) || isSpecialTag(tagName);
 }
 
+HTMLFormElement* closestFormAncestor(Element* element)
+{
+    while (element) {
+        if (element->hasTagName(formTag))
+            return static_cast<HTMLFormElement*>(element);
+        Node* parent = element->parent();
+        if (!parent || !parent->isElementNode())
+            return 0;
+        element = static_cast<Element*>(parent);
+    }
+    return 0;
+}
+
+// FIXME: This belongs on ContainerNode, where it could avoid the double ref
+// by directly releasing into the Vector.  Such an implementation would need to
+// be careful not to send mutation events.
+void takeChildrenFromNode(ContainerNode* container, Vector<RefPtr<Node> >& children)
+{
+    for (Node* child = container->firstChild(); child; child = child->nextSibling())
+        children.append(child);
+    container->removeAllChildren();
+}
+
 } // namespace
 
 class HTMLTreeBuilder::ExternalCharacterTokenBuffer : public Noncopyable {
@@ -346,35 +369,87 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* documen
     , m_tokenizer(tokenizer)
     , m_lastScriptElementStartLine(uninitializedLineNumberValue)
     , m_scriptToProcessStartLine(uninitializedLineNumberValue)
-    , m_fragmentScriptingPermission(FragmentScriptingAllowed)
-    , m_isParsingFragment(false)
 {
 }
 
 // FIXME: Member variables should be grouped into self-initializing structs to
 // minimize code duplication between these constructors.
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, DocumentFragment* fragment, FragmentScriptingPermission scriptingPermission)
+HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
     : m_framesetOk(true)
-    , m_document(fragment->document())
-    , m_tree(fragment->document(), scriptingPermission, true)
+    , m_fragmentContext(fragment, contextElement, scriptingPermission, shouldUseLegacyTreeBuilder(fragment->document()))
+    , m_document(m_fragmentContext.document())
+    , m_tree(m_document, scriptingPermission, true)
     , m_reportErrors(false) // FIXME: Why not report errors in fragments?
     , m_isPaused(false)
     , m_insertionMode(InitialMode)
     , m_originalInsertionMode(InitialMode)
     , m_secondaryInsertionMode(InitialMode)
     , m_tokenizer(tokenizer)
-    , m_legacyTreeBuilder(new LegacyHTMLTreeBuilder(fragment, scriptingPermission))
+    , m_legacyTreeBuilder(shouldUseLegacyTreeBuilder(fragment->document()) ? new LegacyHTMLTreeBuilder(fragment, scriptingPermission) : 0)
     , m_lastScriptElementStartLine(uninitializedLineNumberValue)
     , m_scriptToProcessStartLine(uninitializedLineNumberValue)
-    , m_fragmentScriptingPermission(scriptingPermission)
-    , m_isParsingFragment(true)
 {
+    if (shouldUseLegacyTreeBuilder(fragment->document()))
+        return;
+    // This is steps 2-6 of the HTML5 Fragment Case parsing algorithm:
+    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
+    if (contextElement)
+        m_document->setParseMode(contextElement->document()->parseMode());
+    processFakeStartTag(htmlTag);
+    resetInsertionModeAppropriately();
+    m_tree.setForm(closestFormAncestor(contextElement));
 }
 
 HTMLTreeBuilder::~HTMLTreeBuilder()
 {
 }
 
+HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
+    : m_fragment(0)
+    , m_contextElement(0)
+    , m_usingLegacyTreeBuilder(false)
+    , m_scriptingPermission(FragmentScriptingAllowed)
+{
+}
+
+HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool legacyMode)
+    : m_dummyDocumentForFragmentParsing(legacyMode ? 0 : HTMLDocument::create(0, KURL()))
+    , m_fragment(fragment)
+    , m_contextElement(contextElement)
+    , m_usingLegacyTreeBuilder(legacyMode)
+    , m_scriptingPermission(scriptingPermission)
+{
+}
+
+Document* HTMLTreeBuilder::FragmentParsingContext::document() const
+{
+    ASSERT(m_fragment);
+    if (m_usingLegacyTreeBuilder)
+        return m_fragment->document();
+    return m_dummyDocumentForFragmentParsing.get();
+}
+
+void HTMLTreeBuilder::FragmentParsingContext::finished()
+{
+    // Populate the DocumentFragment with the parsed content now that we're done.
+    ContainerNode* root = m_dummyDocumentForFragmentParsing.get();
+    if (m_contextElement)
+        root = m_dummyDocumentForFragmentParsing->documentElement();
+    Vector<RefPtr<Node> > children;
+    takeChildrenFromNode(root, children);
+    for (unsigned i = 0; i < children.size(); ++i) {
+        ExceptionCode ec = 0;
+        // FIXME: We need a parser-safe (no events) version of adoptNode.
+        RefPtr<Node> child = m_fragment->document()->adoptNode(children[i].release(), ec);
+        ASSERT(!ec);
+        m_fragment->parserAddChild(child.release());
+    }
+}
+
+HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
+{
+}
+
 static void convertToOldStyle(AtomicHTMLToken& token, Token& oldStyleToken)
 {
     switch (token.type()) {
@@ -476,7 +551,7 @@ void HTMLTreeBuilder::passTokenToLegacyParser(HTMLToken& token)
         if (oldStyleToken.tagName == scriptTag) {
             if (m_lastScriptElement) {
                 ASSERT(m_lastScriptElementStartLine != uninitializedLineNumberValue);
-                if (m_fragmentScriptingPermission == FragmentScriptingNotAllowed) {
+                if (m_fragmentContext.scriptingPermission() == FragmentScriptingNotAllowed) {
                     // FIXME: This is a horrible hack for platform/Pasteboard.
                     // Clear the <script> tag when using the Parser to create
                     // a DocumentFragment for pasting so that javascript content
@@ -797,12 +872,19 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
         return;
     }
     if (token.name() == bodyTag) {
+        if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
+            ASSERT(isParsingFragment());
+            return;
+        }
         m_tree.insertHTMLBodyStartTagInBody(token);
         return;
     }
     if (token.name() == framesetTag) {
         parseError(token);
-        notImplemented(); // fragment case
+        if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
+            ASSERT(isParsingFragment());
+            return;
+        }
         if (!m_framesetOk)
             return;
         ExceptionCode ec = 0;
@@ -1073,7 +1155,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
 bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
 {
     if (m_tree.currentElement() == m_tree.openElements()->htmlElement()) {
-        ASSERT(m_isParsingFragment);
+        ASSERT(isParsingFragment());
         // FIXME: parse error
         return false;
     }
@@ -1134,7 +1216,7 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken& token)
     if (token.name() == tableTag) {
         parseError(token);
         if (!processTableEndTagForInTable()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         processStartTag(token);
@@ -1283,7 +1365,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             || token.name() == trTag) {
             parseError(token);
             if (!processCaptionEndTagForInCaption()) {
-                ASSERT(m_isParsingFragment);
+                ASSERT(isParsingFragment());
                 return;
             }
             processStartTag(token);
@@ -1302,7 +1384,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             return;
         }
         if (!processColgroupEndTagForInColumnGroup()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         processStartTag(token);
@@ -1325,7 +1407,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
         if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name())) {
             // FIXME: This is slow.
             if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
-                ASSERT(m_isParsingFragment);
+                ASSERT(isParsingFragment());
                 parseError(token);
                 return;
             }
@@ -1350,7 +1432,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             || isCaptionColOrColgroupTag(token.name())
             || isTableBodyContextTag(token.name())) {
             if (!processTrEndTagForInRow()) {
-                ASSERT(m_isParsingFragment);
+                ASSERT(isParsingFragment());
                 return;
             }
             ASSERT(insertionMode() == InTableBodyMode);
@@ -1367,7 +1449,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             || isTableBodyContextTag(token.name())) {
             // FIXME: This could be more efficient.
             if (!m_tree.openElements()->inTableScope(tdTag) && !m_tree.openElements()->inTableScope(thTag)) {
-                ASSERT(m_isParsingFragment);
+                ASSERT(isParsingFragment());
                 parseError(token);
                 return;
             }
@@ -1781,12 +1863,12 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
     while (1) {
         Element* node = nodeRecord->element();
         if (node == m_tree.openElements()->bottom()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             last = true;
-            notImplemented(); // node = m_contextElement;
+            node = m_fragmentContext.contextElement();
         }
         if (node->hasTagName(selectTag)) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return setInsertionModeAndEnd(InSelectMode, foreign);
         }
         if (node->hasTagName(tdTag) || node->hasTagName(thTag))
@@ -1798,30 +1880,30 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
         if (node->hasTagName(captionTag))
             return setInsertionModeAndEnd(InCaptionMode, foreign);
         if (node->hasTagName(colgroupTag)) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return setInsertionModeAndEnd(InColumnGroupMode, foreign);
         }
         if (node->hasTagName(tableTag))
             return setInsertionModeAndEnd(InTableMode, foreign);
         if (node->hasTagName(headTag)) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return setInsertionModeAndEnd(InBodyMode, foreign);
         }
         if (node->hasTagName(bodyTag))
             return setInsertionModeAndEnd(InBodyMode, foreign);
         if (node->hasTagName(framesetTag)) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return setInsertionModeAndEnd(InFramesetMode, foreign);
         }
         if (node->hasTagName(htmlTag)) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return setInsertionModeAndEnd(BeforeHeadMode, foreign);
         }
         if (node->namespaceURI() == SVGNames::svgNamespaceURI
             || node->namespaceURI() == MathMLNames::mathmlNamespaceURI)
             foreign = true;
         if (last) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return setInsertionModeAndEnd(InBodyMode, foreign);
         }
         nodeRecord = nodeRecord->next();
@@ -1844,7 +1926,7 @@ void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken& token)
     if (token.name() == tableTag) {
         // FIXME: This is slow.
         if (!m_tree.openElements()->inTableScope(tbodyTag.localName()) && !m_tree.openElements()->inTableScope(theadTag.localName()) && !m_tree.openElements()->inTableScope(tfootTag.localName())) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             parseError(token);
             return;
         }
@@ -1874,7 +1956,7 @@ void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken& token)
     }
     if (token.name() == tableTag) {
         if (!processTrEndTagForInRow()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         ASSERT(insertionMode() == InTableBodyMode);
@@ -1928,7 +2010,7 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
         || token.name() == trTag
         || isTableBodyContextTag(token.name())) {
         if (!m_tree.openElements()->inTableScope(token.name())) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             // FIXME: It is unclear what the exact ASSERT should be.
             // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10098
             parseError(token);
@@ -2080,7 +2162,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken& token)
 bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
 {
     if (!m_tree.openElements()->inTableScope(captionTag.localName())) {
-        ASSERT(m_isParsingFragment);
+        ASSERT(isParsingFragment());
         // FIXME: parse error
         return false;
     }
@@ -2095,7 +2177,7 @@ bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
 bool HTMLTreeBuilder::processTrEndTagForInRow()
 {
     if (!m_tree.openElements()->inTableScope(trTag.localName())) {
-        ASSERT(m_isParsingFragment);
+        ASSERT(isParsingFragment());
         // FIXME: parse error
         return false;
     }
@@ -2109,7 +2191,7 @@ bool HTMLTreeBuilder::processTrEndTagForInRow()
 bool HTMLTreeBuilder::processTableEndTagForInTable()
 {
     if (!m_tree.openElements()->inTableScope(tableTag)) {
-        ASSERT(m_isParsingFragment);
+        ASSERT(isParsingFragment());
         // FIXME: parse error.
         return false;
     }
@@ -2201,7 +2283,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
         if (token.name() == tableTag) {
             parseError(token);
             if (!processCaptionEndTagForInCaption()) {
-                ASSERT(m_isParsingFragment);
+                ASSERT(isParsingFragment());
                 return;
             }
             processEndTag(token);
@@ -2230,7 +2312,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
             return;
         }
         if (!processColgroupEndTagForInColumnGroup()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         processEndTag(token);
@@ -2250,7 +2332,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
     case AfterBodyMode:
         ASSERT(insertionMode() == AfterBodyMode);
         if (token.name() == htmlTag) {
-            if (m_isParsingFragment) {
+            if (isParsingFragment()) {
                 parseError(token);
                 return;
             }
@@ -2302,7 +2384,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
                 return;
             }
             m_tree.openElements()->pop();
-            if (!m_isParsingFragment && !m_tree.currentElement()->hasTagName(framesetTag))
+            if (!isParsingFragment() && !m_tree.currentElement()->hasTagName(framesetTag))
                 setInsertionMode(AfterFramesetMode);
             return;
         }
@@ -2545,7 +2627,7 @@ ReprocessBuffer:
         if (buffer.isEmpty())
             return;
         if (!processColgroupEndTagForInColumnGroup()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         goto ReprocessBuffer;
@@ -2665,11 +2747,11 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
         break;
     case InColumnGroupMode:
         if (m_tree.currentElement() == m_tree.openElements()->htmlElement()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         if (!processColgroupEndTagForInColumnGroup()) {
-            ASSERT(m_isParsingFragment);
+            ASSERT(isParsingFragment());
             return;
         }
         processEndOfFile(token);
@@ -2833,9 +2915,13 @@ void HTMLTreeBuilder::finished()
         return;
     }
 
+    if (isParsingFragment()) {
+        m_fragmentContext.finished();
+        return;
+    }
+
     // Warning, this may delete the parser, so don't try to do anything else after this.
-    if (!m_isParsingFragment)
-        m_document->finishedParsing();
+    m_document->finishedParsing();
 }
 
 bool HTMLTreeBuilder::scriptEnabled(Frame* frame)
index e31d09b..24cb542 100644 (file)
@@ -54,7 +54,7 @@ class HTMLTreeBuilder : public Noncopyable {
 public:
     // FIXME: Replace constructors with create() functions returning PassOwnPtrs
     HTMLTreeBuilder(HTMLTokenizer*, HTMLDocument*, bool reportErrors);
-    HTMLTreeBuilder(HTMLTokenizer*, DocumentFragment*, FragmentScriptingPermission);
+    HTMLTreeBuilder(HTMLTokenizer*, DocumentFragment*, Element* contextElement, FragmentScriptingPermission);
     ~HTMLTreeBuilder();
 
     void setPaused(bool paused) { m_isPaused = paused; }
@@ -74,6 +74,9 @@ public:
     // until we stop using the legacy parser. DO NOT CALL THIS METHOD.
     LegacyHTMLTreeBuilder* legacyTreeBuilder() const { return m_legacyTreeBuilder.get(); }
 
+    static bool scriptEnabled(Frame*);
+    static bool pluginsEnabled(Frame*);
+
 private:
     class FakeInsertionMode;
     class ExternalCharacterTokenBuffer;
@@ -105,6 +108,8 @@ private:
         AfterAfterFramesetMode,
     };
 
+    bool isParsingFragment() const { return !!m_fragmentContext.fragment(); }
+
     void passTokenToLegacyParser(HTMLToken&);
 
     void processToken(AtomicHTMLToken&);
@@ -192,8 +197,31 @@ private:
     void setInsertionModeAndEnd(InsertionMode, bool foreign); // Helper for resetInsertionModeAppropriately
     void resetInsertionModeAppropriately();
 
-    static bool scriptEnabled(Frame* frame);
-    static bool pluginsEnabled(Frame* frame);
+    class FragmentParsingContext : public Noncopyable {
+    public:
+        FragmentParsingContext();
+        FragmentParsingContext(DocumentFragment*, Element* contextElement, FragmentScriptingPermission, bool usingLegacyTreeBuilder);
+        ~FragmentParsingContext();
+
+        Document* document() const;
+        DocumentFragment* fragment() const { return m_fragment; }
+        Element* contextElement() const { ASSERT(m_fragment); ASSERT(!m_usingLegacyTreeBuilder); return m_contextElement; }
+        FragmentScriptingPermission scriptingPermission() const { ASSERT(m_fragment); return m_scriptingPermission; }
+
+        void finished();
+
+    private:
+        RefPtr<Document> m_dummyDocumentForFragmentParsing;
+        DocumentFragment* m_fragment;
+        Element* m_contextElement;
+        bool m_usingLegacyTreeBuilder;
+
+        // FragmentScriptingNotAllowed causes the Parser to remove children
+        // from <script> tags (so javascript doesn't show up in pastes).
+        FragmentScriptingPermission m_scriptingPermission;
+    };
+
+    FragmentParsingContext m_fragmentContext;
 
     Document* m_document;
     HTMLConstructionSite m_tree;
@@ -226,12 +254,6 @@ private:
 
     RefPtr<Element> m_scriptToProcess; // <script> tag which needs processing before resuming the parser.
     int m_scriptToProcessStartLine; // Starting line number of the script tag needing processing.
-
-    // FIXME: FragmentScriptingPermission is a HACK for platform/Pasteboard.
-    // FragmentScriptingNotAllowed causes the Parser to remove children
-    // from <script> tags (so javascript doesn't show up in pastes).
-    FragmentScriptingPermission m_fragmentScriptingPermission;
-    bool m_isParsingFragment;
 };
 
 }
index f949163..7e07ee3 100644 (file)
@@ -100,7 +100,7 @@ static inline RefPtr<DocumentFragment> createFragmentFromSource(const String& so
     RefPtr<DocumentFragment> fragment = outputDoc->createDocumentFragment();
 
     if (sourceMIMEType == "text/html")
-        fragment->parseHTML(sourceString);
+        fragment->parseHTML(sourceString, outputDoc->documentElement());
     else if (sourceMIMEType == "text/plain")
         fragment->legacyParserAddChild(Text::create(outputDoc, sourceString));
     else {