⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 176630 in webkit


Ignore:
Timestamp:
Dec 2, 2014, 2:50:11 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Source/WebCore:
Missing support for innerHTML on SVGElement
https://bugs.webkit.org/show_bug.cgi?id=136903

Patch by Sylvain Galineau <galineau@adobe.com> on 2014-12-02
Reviewed by Dean Jackson.

Two parts to this patch:

  1. Move innerHTML/outerHTML to Element so SVG elements can inherit them, per https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#innerhtml
  2. Make sure fragment insertion is processed relative to the proper node, per http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node

The latter part was ported over from Blink.

Test: svg/in-html/svg-inner-html.html

  • bindings/objc/PublicDOMInterfaces.h: Move innerHTML/outerHTML to Element.
  • dom/Element.cpp:

(WebCore::Element::mergeWithNextTextNode): Helper used by Element::innerHTML/outerHTML as well as HTMLElement::innerText/outerText; moved to Element as protected static.
(WebCore::Element::innerHTML): Moved from HTMLElement.
(WebCore::Element::outerHTML): Moved from HTMLElement.
(WebCore::Element::setOuterHTML): Moved from HTMLElement.
(WebCore::Element::setInnerHTML): Moved from HTMLElement.

  • dom/Element.h:
  • dom/Element.idl:
  • html/HTMLElement.cpp:

(WebCore::HTMLElement::innerHTML): Deleted.
(WebCore::HTMLElement::outerHTML): Deleted.
(WebCore::HTMLElement::setInnerHTML): Deleted.
(WebCore::mergeWithNextTextNode): Deleted.
(WebCore::HTMLElement::setOuterHTML): Deleted.

  • html/HTMLElement.h:
  • html/HTMLElement.idl:
  • html/parser/HTMLTreeBuilder.cpp:

(WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext): no more m_contextElement.
(WebCore::HTMLTreeBuilder::constructTree): read namespace from adjusted current node.
(WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately): use contextElementStackItem for insertion.
(WebCore::HTMLTreeBuilder::adjustedCurrentStackItem): compute adjusted current node.
(WebCore::HTMLTreeBuilder::shouldProcessTokenInForeignContent): use adjusted current node for context.
(WebCore::HTMLTreeBuilder::processTokenInForeignContent): use adjusted current node to read namespace.

  • html/parser/HTMLTreeBuilder.h:

(WebCore::HTMLTreeBuilder::FragmentParsingContext::contextElement): Deleted. Read from contextElementStackItem.
(WebCore::HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem): Added.

LayoutTests:

Missing support for innerHTML on SVGElement
https://bugs.webkit.org/show_bug.cgi?id=136903

Patch by Sylvain Galineau <galineau@adobe.com> on 2014-12-02
Reviewed by Dean Jackson.

  • js/dom/dom-static-property-for-in-iteration-expected.txt: The property enumeration order is different now that inner/outerHTML are inherited from Element
  • platform/mac/svg/in-html/svg-inner-html-expected.png: Added.
  • svg/css/svg-attribute-length-parsing-expected.txt:

Now that innerHTML works, the output should start with 'Test'

  • svg/in-html/svg-inner-html-expected.txt: Added.
  • svg/in-html/svg-inner-html.html: Added.
Location:
trunk
Files:
2 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r176628 r176630  
     12014-12-02  Sylvain Galineau  <galineau@adobe.com>
     2
     3    Missing support for innerHTML on SVGElement
     4    https://bugs.webkit.org/show_bug.cgi?id=136903
     5
     6        Reviewed by Dean Jackson.
     7
     8        * js/dom/dom-static-property-for-in-iteration-expected.txt: The property enumeration order is different now that inner/outerHTML are inherited from Element
     9        * platform/mac/svg/in-html/svg-inner-html-expected.png: Added.
     10        * svg/css/svg-attribute-length-parsing-expected.txt:
     11        Now that innerHTML works, the output should start with 'Test'
     12        * svg/in-html/svg-inner-html-expected.txt: Added.
     13        * svg/in-html/svg-inner-html.html: Added.
     14
    1152014-12-02  Andrzej Badowski  <a.badowski@samsung.com>
    216
  • trunk/LayoutTests/js/dom/dom-static-property-for-in-iteration-expected.txt

    r175028 r176630  
    3838PASS a["hidden"] is false
    3939PASS a["accessKey"] is
    40 PASS a["innerHTML"] is nerget
    4140PASS a["innerText"] is nerget
    42 PASS a["outerHTML"] is <a id="foo" href="bar">nerget</a>
    4341PASS a["outerText"] is nerget
    4442PASS a["children"] is [object HTMLCollection]
     
    5149PASS a["id"] is foo
    5250PASS a["offsetLeft"] is 8
    53 PASS a["offsetTop"] is 789
     51PASS a["offsetTop"] is 759
    5452PASS a["offsetWidth"] is 39
    5553PASS a["offsetHeight"] is 18
     
    6361PASS a["scrollHeight"] is 0
    6462PASS a["offsetParent"] is [object HTMLBodyElement]
     63PASS a["innerHTML"] is nerget
     64PASS a["outerHTML"] is <a id="foo" href="bar">nerget</a>
    6565PASS a["className"] is
    6666PASS a["classList"] is
  • trunk/LayoutTests/svg/css/svg-attribute-length-parsing-expected.txt

    r112769 r176630  
     1Test
    12Test CSS parsing on SVG presentation attributes.
    23
  • trunk/Source/WebCore/ChangeLog

    r176626 r176630  
     12014-12-02  Sylvain Galineau  <galineau@adobe.com>
     2
     3        Missing support for innerHTML on SVGElement
     4        https://bugs.webkit.org/show_bug.cgi?id=136903
     5
     6        Reviewed by Dean Jackson.
     7
     8        Two parts to this patch:
     9        1. Move innerHTML/outerHTML to Element so SVG elements can inherit them, per https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#innerhtml
     10        2. Make sure fragment insertion is processed relative to the proper node, per http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node
     11
     12        The latter part was ported over from Blink.
     13
     14        Test: svg/in-html/svg-inner-html.html
     15
     16        * bindings/objc/PublicDOMInterfaces.h: Move innerHTML/outerHTML to Element.
     17        * dom/Element.cpp:
     18        (WebCore::Element::mergeWithNextTextNode): Helper used by Element::innerHTML/outerHTML as well as HTMLElement::innerText/outerText; moved to Element as protected static.
     19        (WebCore::Element::innerHTML): Moved from HTMLElement.
     20        (WebCore::Element::outerHTML): Moved from HTMLElement.
     21        (WebCore::Element::setOuterHTML): Moved from HTMLElement.
     22        (WebCore::Element::setInnerHTML): Moved from HTMLElement.
     23        * dom/Element.h:
     24        * dom/Element.idl:
     25        * html/HTMLElement.cpp:
     26        (WebCore::HTMLElement::innerHTML): Deleted.
     27        (WebCore::HTMLElement::outerHTML): Deleted.
     28        (WebCore::HTMLElement::setInnerHTML): Deleted.
     29        (WebCore::mergeWithNextTextNode): Deleted.
     30        (WebCore::HTMLElement::setOuterHTML): Deleted.
     31        * html/HTMLElement.h:
     32        * html/HTMLElement.idl:
     33        * html/parser/HTMLTreeBuilder.cpp:
     34        (WebCore::HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext): no more m_contextElement.
     35        (WebCore::HTMLTreeBuilder::constructTree): read namespace from adjusted current node.
     36        (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately): use contextElementStackItem for insertion.
     37        (WebCore::HTMLTreeBuilder::adjustedCurrentStackItem): compute adjusted current node.
     38        (WebCore::HTMLTreeBuilder::shouldProcessTokenInForeignContent): use adjusted current node for context.
     39        (WebCore::HTMLTreeBuilder::processTokenInForeignContent): use adjusted current node to read namespace.
     40        * html/parser/HTMLTreeBuilder.h:
     41        (WebCore::HTMLTreeBuilder::FragmentParsingContext::contextElement): Deleted. Read from contextElementStackItem.
     42        (WebCore::HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem): Added.
     43
    1442014-11-20  Jeffrey Pfau  <jpfau@apple.com>
    245
  • trunk/Source/WebCore/bindings/objc/PublicDOMInterfaces.h

    r172884 r176630  
    196196@property (readonly) int clientTop WEBKIT_AVAILABLE_MAC(10_5);
    197197@property (readonly, copy) NSString *innerText WEBKIT_AVAILABLE_MAC(10_5);
     198@property (copy) NSString *innerHTML;
     199@property (copy) NSString *outerHTML;
    198200@property (readonly, strong) DOMElement *firstElementChild WEBKIT_AVAILABLE_MAC(10_6);
    199201@property (readonly, strong) DOMElement *lastElementChild WEBKIT_AVAILABLE_MAC(10_6);
     
    477479@property (copy) NSString *lang;
    478480@property (copy) NSString *dir;
    479 @property (copy) NSString *innerHTML;
    480481@property (copy) NSString *innerText;
    481 @property (copy) NSString *outerHTML;
    482482@property (copy) NSString *outerText;
    483483@property (readonly, strong) DOMHTMLCollection *children;
  • trunk/Source/WebCore/dom/Element.cpp

    r176502 r176630  
    5555#include "HTMLSelectElement.h"
    5656#include "HTMLTableRowsCollection.h"
     57#include "HTMLTemplateElement.h"
    5758#include "InsertionPoint.h"
    5859#include "KeyboardEvent.h"
     
    8283#include "XMLNames.h"
    8384#include "htmlediting.h"
     85#include "markup.h"
    8486#include <wtf/BitVector.h>
    8587#include <wtf/CurrentTime.h>
     
    20232025}
    20242026
     2027void Element::mergeWithNextTextNode(Text& node, ExceptionCode& ec)
     2028{
     2029    Node* next = node.nextSibling();
     2030    if (!is<Text>(next))
     2031        return;
     2032
     2033    Ref<Text> textNode(node);
     2034    Ref<Text> textNext(downcast<Text>(*next));
     2035    textNode->appendData(textNext->data(), ec);
     2036    if (ec)
     2037        return;
     2038    textNext->remove(ec);
     2039}
     2040
     2041String Element::innerHTML() const
     2042{
     2043    return createMarkup(*this, ChildrenOnly);
     2044}
     2045
     2046String Element::outerHTML() const
     2047{
     2048    return createMarkup(*this);
     2049}
     2050
     2051void Element::setOuterHTML(const String& html, ExceptionCode& ec)
     2052{
     2053    Element* p = parentElement();
     2054    if (!is<HTMLElement>(p)) {
     2055        ec = NO_MODIFICATION_ALLOWED_ERR;
     2056        return;
     2057    }
     2058    RefPtr<HTMLElement> parent = downcast<HTMLElement>(p);
     2059    RefPtr<Node> prev = previousSibling();
     2060    RefPtr<Node> next = nextSibling();
     2061
     2062    RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, parent.get(), AllowScriptingContent, ec);
     2063    if (ec)
     2064        return;
     2065   
     2066    parent->replaceChild(fragment.release(), this, ec);
     2067    RefPtr<Node> node = next ? next->previousSibling() : nullptr;
     2068    if (!ec && is<Text>(node.get()))
     2069        mergeWithNextTextNode(downcast<Text>(*node), ec);
     2070    if (!ec && is<Text>(prev.get()))
     2071        mergeWithNextTextNode(downcast<Text>(*prev), ec);
     2072}
     2073
     2074
     2075void Element::setInnerHTML(const String& html, ExceptionCode& ec)
     2076{
     2077    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, this, AllowScriptingContent, ec)) {
     2078        ContainerNode* container = this;
     2079
     2080#if ENABLE(TEMPLATE_ELEMENT)
     2081        if (is<HTMLTemplateElement>(*this))
     2082            container = downcast<HTMLTemplateElement>(*this).content();
     2083#endif
     2084
     2085        replaceChildrenWithFragment(*container, fragment.release(), ec);
     2086    }
     2087}
    20252088
    20262089String Element::innerText()
  • trunk/Source/WebCore/dom/Element.h

    r176502 r176630  
    396396    virtual void blur();
    397397
     398    String innerHTML() const;
     399    String outerHTML() const;
     400    void setInnerHTML(const String&, ExceptionCode&);
     401    void setOuterHTML(const String&, ExceptionCode&);
    398402    WEBCORE_EXPORT String innerText();
    399403    String outerText();
     
    573577    // svgAttributeChanged (called when element.className.baseValue is set)
    574578    void classAttributeChanged(const AtomicString& newClassString);
     579   
     580    static void mergeWithNextTextNode(Text& node, ExceptionCode& ec);
    575581
    576582private:
  • trunk/Source/WebCore/dom/Element.idl

    r174363 r176630  
    109109    // HTML 5
    110110    NodeList getElementsByClassName([Default=Undefined] optional DOMString name);
     111    [TreatNullAs=NullString, SetterRaisesException] attribute DOMString innerHTML;
     112    [TreatNullAs=NullString, SetterRaisesException] attribute DOMString outerHTML;
     113             
    111114
    112115    [Reflect=class] attribute DOMString className;
  • trunk/Source/WebCore/html/HTMLElement.cpp

    r176502 r176630  
    4949#include "HTMLNames.h"
    5050#include "HTMLParserIdioms.h"
    51 #include "HTMLTemplateElement.h"
    5251#include "HTMLTextFormControlElement.h"
    5352#include "NodeTraversal.h"
     
    415414}
    416415
    417 String HTMLElement::innerHTML() const
    418 {
    419     return createMarkup(*this, ChildrenOnly);
    420 }
    421 
    422 String HTMLElement::outerHTML() const
    423 {
    424     return createMarkup(*this);
    425 }
    426 
    427 void HTMLElement::setInnerHTML(const String& html, ExceptionCode& ec)
    428 {
    429     if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, this, AllowScriptingContent, ec)) {
    430         ContainerNode* container = this;
    431 #if ENABLE(TEMPLATE_ELEMENT)
    432         if (is<HTMLTemplateElement>(*this))
    433             container = downcast<HTMLTemplateElement>(*this).content();
    434 #endif
    435         replaceChildrenWithFragment(*container, fragment.release(), ec);
    436     }
    437 }
    438 
    439 static void mergeWithNextTextNode(Text& node, ExceptionCode& ec)
    440 {
    441     Node* next = node.nextSibling();
    442     if (!is<Text>(next))
    443         return;
    444 
    445     Ref<Text> textNode(node);
    446     Ref<Text> textNext(downcast<Text>(*next));
    447     textNode->appendData(textNext->data(), ec);
    448     if (ec)
    449         return;
    450     textNext->remove(ec);
    451 }
    452 
    453 void HTMLElement::setOuterHTML(const String& html, ExceptionCode& ec)
    454 {
    455     Element* p = parentElement();
    456     if (!is<HTMLElement>(p)) {
    457         ec = NO_MODIFICATION_ALLOWED_ERR;
    458         return;
    459     }
    460     RefPtr<HTMLElement> parent = downcast<HTMLElement>(p);
    461     RefPtr<Node> prev = previousSibling();
    462     RefPtr<Node> next = nextSibling();
    463 
    464     RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(html, parent.get(), AllowScriptingContent, ec);
    465     if (ec)
    466         return;
    467      
    468     parent->replaceChild(fragment.release(), this, ec);
    469     RefPtr<Node> node = next ? next->previousSibling() : nullptr;
    470     if (!ec && is<Text>(node.get()))
    471         mergeWithNextTextNode(downcast<Text>(*node), ec);
    472     if (!ec && is<Text>(prev.get()))
    473         mergeWithNextTextNode(downcast<Text>(*prev), ec);
    474 }
    475 
    476416RefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, ExceptionCode& ec)
    477417{
  • trunk/Source/WebCore/html/HTMLElement.h

    r176502 r176630  
    4949    virtual short tabIndex() const override;
    5050
    51     String innerHTML() const;
    52     String outerHTML() const;
    53     void setInnerHTML(const String&, ExceptionCode&);
    54     void setOuterHTML(const String&, ExceptionCode&);
    5551    void setInnerText(const String&, ExceptionCode&);
    5652    void setOuterText(const String&, ExceptionCode&);
  • trunk/Source/WebCore/html/HTMLElement.idl

    r160068 r176630  
    3939
    4040    // Extensions
    41              [TreatNullAs=NullString, SetterRaisesException] attribute DOMString innerHTML;
    42              [TreatNullAs=NullString, SetterRaisesException] attribute DOMString innerText;
    43              [TreatNullAs=NullString, SetterRaisesException] attribute DOMString outerHTML;
    44              [TreatNullAs=NullString, SetterRaisesException] attribute DOMString outerText;
    45 
     41    [TreatNullAs=NullString, SetterRaisesException] attribute DOMString innerText;
     42    [TreatNullAs=NullString, SetterRaisesException] attribute DOMString outerText;
     43             
    4644    [RaisesException] Element insertAdjacentElement([Default=Undefined] optional DOMString where,
    4745                                  [Default=Undefined] optional Element element);
  • trunk/Source/WebCore/html/parser/HTMLTreeBuilder.cpp

    r174225 r176630  
    321321HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
    322322    : m_fragment(0)
    323     , m_contextElement(0)
    324323{
    325324}
     
    327326HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element* contextElement)
    328327    : m_fragment(&fragment)
    329     , m_contextElement(contextElement)
    330328{
    331329    ASSERT(!fragment.hasChildNodes());
     330    m_contextElementStackItem = HTMLStackItem::create(contextElement, HTMLStackItem::ItemForContextElement);
    332331}
    333332
     
    357356    if (m_parser.tokenizer()) {
    358357        bool inForeignContent = !m_tree.isEmpty()
    359             && !m_tree.currentStackItem()->isInHTMLNamespace()
     358            && !adjustedCurrentStackItem()->isInHTMLNamespace()
    360359            && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
    361360            && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
     
    16181617#endif
    16191618            if (shouldCreateItem)
    1620                 item = HTMLStackItem::create(m_fragmentContext.contextElement(), HTMLStackItem::ItemForContextElement);
     1619                item = m_fragmentContext.contextElementStackItem();
    16211620        }
    16221621#if ENABLE(TEMPLATE_ELEMENT)
     
    28412840    setInsertionMode(InsertionMode::Text);
    28422841}
     2842   
     2843// http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node
     2844HTMLStackItem* HTMLTreeBuilder::adjustedCurrentStackItem() const
     2845{
     2846    ASSERT(!m_tree.isEmpty());
     2847    if (isParsingFragment() && m_tree.openElements()->hasOnlyOneElement())
     2848        return m_fragmentContext.contextElementStackItem();
     2849       
     2850    return m_tree.currentStackItem();
     2851}
     2852
    28432853
    28442854// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
     
    28472857    if (m_tree.isEmpty())
    28482858        return false;
    2849     HTMLStackItem* item = m_tree.currentStackItem();
    2850     if (item->isInHTMLNamespace())
     2859    HTMLStackItem* adjustedCurrentNode = adjustedCurrentStackItem();
     2860    if (adjustedCurrentNode->isInHTMLNamespace())
    28512861        return false;
    2852     if (HTMLElementStack::isMathMLTextIntegrationPoint(item)) {
     2862    if (HTMLElementStack::isMathMLTextIntegrationPoint(adjustedCurrentNode)) {
    28532863        if (token->type() == HTMLToken::StartTag
    28542864            && token->name() != MathMLNames::mglyphTag
     
    28582868            return false;
    28592869    }
    2860     if (item->hasTagName(MathMLNames::annotation_xmlTag)
     2870    if (adjustedCurrentNode->hasTagName(MathMLNames::annotation_xmlTag)
    28612871        && token->type() == HTMLToken::StartTag
    28622872        && token->name() == SVGNames::svgTag)
    28632873        return false;
    2864     if (HTMLElementStack::isHTMLIntegrationPoint(item)) {
     2874    if (HTMLElementStack::isHTMLIntegrationPoint(adjustedCurrentNode)) {
    28652875        if (token->type() == HTMLToken::StartTag)
    28662876            return false;
     
    28752885void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
    28762886{
     2887    HTMLStackItem* adjustedCurrentNode = adjustedCurrentStackItem();
     2888   
    28772889    switch (token->type()) {
    28782890    case HTMLToken::Uninitialized:
     
    29282940            return;
    29292941        }
    2930         const AtomicString& currentNamespace = m_tree.currentStackItem()->namespaceURI();
     2942        const AtomicString& currentNamespace = adjustedCurrentNode->namespaceURI();
    29312943        if (currentNamespace == MathMLNames::mathmlNamespaceURI)
    29322944            adjustMathMLAttributes(*token);
     
    29402952    }
    29412953    case HTMLToken::EndTag: {
    2942         if (m_tree.currentStackItem()->namespaceURI() == SVGNames::svgNamespaceURI)
     2954        if (adjustedCurrentNode->namespaceURI() == SVGNames::svgNamespaceURI)
    29432955            adjustSVGTagNameCase(*token);
    29442956
  • trunk/Source/WebCore/html/parser/HTMLTreeBuilder.h

    r165708 r176630  
    3333#include "HTMLFormattingElementList.h"
    3434#include "HTMLParserOptions.h"
     35#include "HTMLStackItem.h"
    3536#include "HTMLTokenizer.h"
    3637#include <wtf/Noncopyable.h>
     
    171172    inline bool shouldProcessTokenInForeignContent(AtomicHTMLToken*);
    172173    void processTokenInForeignContent(AtomicHTMLToken*);
     174   
     175    inline HTMLStackItem* adjustedCurrentStackItem() const;
    173176
    174177    Vector<Attribute> attributesForIsindexInput(AtomicHTMLToken*);
     
    202205
    203206        DocumentFragment* fragment() const { return m_fragment; }
    204         Element* contextElement() const { ASSERT(m_fragment); return m_contextElement; }
     207        Element* contextElement() const { ASSERT(m_fragment); return m_contextElementStackItem->element(); }
     208        HTMLStackItem* contextElementStackItem() const { ASSERT(m_fragment); return m_contextElementStackItem.get(); }
    205209
    206210    private:
    207211        DocumentFragment* m_fragment;
    208         Element* m_contextElement;
     212        RefPtr<HTMLStackItem> m_contextElementStackItem;
    209213    };
    210214
Note: See TracChangeset for help on using the changeset viewer.