Changeset 252230 in webkit


Ignore:
Timestamp:
Nov 7, 2019 6:52:40 PM (4 years ago)
Author:
commit-queue@webkit.org
Message:

Default NamepaceURI must be gotten from the topmost parent before the SVG <foreignObject>
https://bugs.webkit.org/show_bug.cgi?id=203868

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2019-11-07
Reviewed by Ryosuke Niwa.

Source/WebCore:

Ensure that we don't cross boundaries from HTML to SVG when traversing
the tree of nodes upward. We need to stop at the foreignObject if it is
one of the ancestors of the contextElement.

Tests: svg/foreignObject/foreign-object-dynamic-parsing.svg

  • html/HTMLTableCellElement.cpp:

(WebCore::HTMLTableCellElement::HTMLTableCellElement):
This assertion should not fire if the tag has a prefix like <h:th> or
<h:td> where 'h' is a defined namespace.

  • xml/parser/XMLDocumentParser.cpp:

(WebCore::XMLDocumentParser::parseDocumentFragment):
Stop at the first SVG <foreignObject> ancestor when calculating the
defaultNamespaceURI.

  • xml/parser/XMLDocumentParser.h:
  • xml/parser/XMLDocumentParserLibxml2.cpp:

(WebCore::XMLDocumentParser::XMLDocumentParser):

(WebCore::XMLDocumentParser::startElementNs):
We need to special case setting the namespaceURI of the SVGElmenets. The
defaultNamespaceURI can be wrong for them if the context element is an
HTML element, <div> for example, and the innerHTML is set to something
like: '<svg><rect/></svg>'.

LayoutTests:

  • svg/foreignObject/foreign-object-dynamic-parsing-expected.svg: Added.
  • svg/foreignObject/foreign-object-dynamic-parsing.svg: Added.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r252228 r252230  
     12019-11-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Default NamepaceURI must be gotten from the topmost parent before the SVG <foreignObject>
     4        https://bugs.webkit.org/show_bug.cgi?id=203868
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * svg/foreignObject/foreign-object-dynamic-parsing-expected.svg: Added.
     9        * svg/foreignObject/foreign-object-dynamic-parsing.svg: Added.
     10
    1112019-11-07  Chris Dumez  <cdumez@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r252227 r252230  
     12019-11-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
     2
     3        Default NamepaceURI must be gotten from the topmost parent before the SVG <foreignObject>
     4        https://bugs.webkit.org/show_bug.cgi?id=203868
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Ensure that we don't cross boundaries from HTML to SVG when traversing
     9        the tree of nodes upward. We need to stop at the foreignObject if it is
     10        one of the ancestors of the contextElement.
     11
     12        Tests: svg/foreignObject/foreign-object-dynamic-parsing.svg
     13
     14        * html/HTMLTableCellElement.cpp:
     15        (WebCore::HTMLTableCellElement::HTMLTableCellElement):
     16        This assertion should not fire if the tag has a prefix like <h:th> or
     17        <h:td> where 'h' is a defined namespace.
     18
     19        * xml/parser/XMLDocumentParser.cpp:
     20        (WebCore::XMLDocumentParser::parseDocumentFragment):
     21        Stop at the first SVG <foreignObject> ancestor when calculating the
     22        defaultNamespaceURI.
     23
     24        * xml/parser/XMLDocumentParser.h:
     25        * xml/parser/XMLDocumentParserLibxml2.cpp:
     26        (WebCore::XMLDocumentParser::XMLDocumentParser):
     27
     28        (WebCore::XMLDocumentParser::startElementNs):
     29        We need to special case setting the namespaceURI of the SVGElmenets. The
     30        defaultNamespaceURI can be wrong for them if the context element is an
     31        HTML element, <div> for example, and the innerHTML is set to something
     32        like: '<svg><rect/></svg>'.
     33
    1342019-11-07  Chris Dumez  <cdumez@apple.com>
    235
  • trunk/Source/WebCore/html/HTMLTableCellElement.cpp

    r246490 r252230  
    5858    : HTMLTablePartElement(tagName, document)
    5959{
    60     ASSERT(tagName == thTag || tagName == tdTag);
     60    ASSERT(hasLocalName(thTag->localName()) || hasLocalName(tdTag->localName()));
    6161}
    6262
  • trunk/Source/WebCore/xml/parser/XMLDocumentParser.cpp

    r248846 r252230  
    3232#include "DocumentFragment.h"
    3333#include "DocumentType.h"
     34#include "ElementAncestorIterator.h"
    3435#include "Frame.h"
    3536#include "FrameLoader.h"
     
    4445#include "ResourceRequest.h"
    4546#include "ResourceResponse.h"
     47#include "SVGForeignObjectElement.h"
    4648#include "SVGNames.h"
    4749#include "SVGStyleElement.h"
     
    5153#include "TextResourceDecoder.h"
    5254#include "TreeDepthLimit.h"
     55#include "XMLNSNames.h"
    5356#include <wtf/Ref.h>
    5457#include <wtf/Threading.h>
     
    270273    }
    271274
    272     auto parser = XMLDocumentParser::create(fragment, contextElement, parserContentPolicy);
     275    HashMap<AtomString, AtomString> prefixToNamespaceMap;
     276    AtomString defaultNamespaceURI;
     277    bool stopLookingForDefaultNamespaceURI = false;
     278   
     279    for (auto& element : elementLineage(contextElement)) {
     280        if (is<SVGForeignObjectElement>(element))
     281            stopLookingForDefaultNamespaceURI = true;
     282        else if (!stopLookingForDefaultNamespaceURI)
     283            defaultNamespaceURI = element.namespaceURI();
     284
     285        if (!element.hasAttributes())
     286            continue;
     287
     288        for (const Attribute& attribute : element.attributesIterator()) {
     289            if (attribute.prefix() == xmlnsAtom())
     290                prefixToNamespaceMap.set(attribute.localName(), attribute.value());
     291            else if (!stopLookingForDefaultNamespaceURI && attribute.prefix() == xmlnsAtom())
     292                defaultNamespaceURI = attribute.value();
     293        }
     294    }
     295
     296    auto parser = XMLDocumentParser::create(fragment, WTFMove(prefixToNamespaceMap), defaultNamespaceURI, parserContentPolicy);
    273297    bool wellFormed = parser->appendFragmentSource(chunk);
    274298    // Do not call finish(). The finish() and doEnd() implementations touch the main document and loader and can cause crashes in the fragment case.
  • trunk/Source/WebCore/xml/parser/XMLDocumentParser.h

    r246490 r252230  
    6868        return adoptRef(*new XMLDocumentParser(document, view));
    6969    }
    70     static Ref<XMLDocumentParser> create(DocumentFragment& fragment, Element* element, ParserContentPolicy parserContentPolicy)
     70    static Ref<XMLDocumentParser> create(DocumentFragment& fragment, HashMap<AtomString, AtomString>&& prefixToNamespaceMap, const AtomString& defaultNamespaceURI, ParserContentPolicy parserContentPolicy)
    7171    {
    72         return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy));
     72        return adoptRef(*new XMLDocumentParser(fragment, WTFMove(prefixToNamespaceMap), defaultNamespaceURI, parserContentPolicy));
    7373    }
    7474
     
    9090private:
    9191    explicit XMLDocumentParser(Document&, FrameView* = nullptr);
    92     XMLDocumentParser(DocumentFragment&, Element*, ParserContentPolicy);
     92    XMLDocumentParser(DocumentFragment&, HashMap<AtomString, AtomString>&&, const AtomString&, ParserContentPolicy);
    9393
    9494    void insert(SegmentedString&&) final;
     
    181181
    182182    bool m_parsingFragment { false };
     183
     184    HashMap<AtomString, AtomString> m_prefixToNamespaceMap;
    183185    AtomString m_defaultNamespaceURI;
    184186
    185     HashMap<AtomString, AtomString> m_prefixToNamespaceMap;
    186187    SegmentedString m_pendingSrc;
    187188};
  • trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp

    r248846 r252230  
    572572}
    573573
    574 XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parentElement, ParserContentPolicy parserContentPolicy)
     574XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, HashMap<AtomString, AtomString>&& prefixToNamespaceMap, const AtomString& defaultNamespaceURI, ParserContentPolicy parserContentPolicy)
    575575    : ScriptableDocumentParser(fragment.document(), parserContentPolicy)
    576576    , m_pendingCallbacks(makeUnique<PendingCallbacks>())
     
    578578    , m_scriptStartPosition(TextPosition::belowRangePosition())
    579579    , m_parsingFragment(true)
     580    , m_prefixToNamespaceMap(WTFMove(prefixToNamespaceMap))
     581    , m_defaultNamespaceURI(defaultNamespaceURI)
    580582{
    581583    fragment.ref();
    582 
    583     // Add namespaces based on the parent node
    584     Vector<Element*> elemStack;
    585     while (parentElement) {
    586         elemStack.append(parentElement);
    587 
    588         ContainerNode* node = parentElement->parentNode();
    589         if (!is<Element>(node))
    590             break;
    591         parentElement = downcast<Element>(node);
    592     }
    593 
    594     if (elemStack.isEmpty())
    595         return;
    596 
    597     // FIXME: Share code with isDefaultNamespace() per http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syntax.html#parsing-xhtml-fragments
    598     for (; !elemStack.isEmpty(); elemStack.removeLast()) {
    599         Element* element = elemStack.last();
    600         if (element->hasAttributes()) {
    601             for (const Attribute& attribute : element->attributesIterator()) {
    602                 if (attribute.localName() == xmlnsAtom())
    603                     m_defaultNamespaceURI = attribute.value();
    604                 else if (attribute.prefix() == xmlnsAtom())
    605                     m_prefixToNamespaceMap.set(attribute.localName(), attribute.value());
    606             }
    607         }
    608     }
    609 
    610     if (m_defaultNamespaceURI.isNull())
    611         m_defaultNamespaceURI = parentElement->namespaceURI();
    612584}
    613585
     
    770742        if (!prefix.isNull())
    771743            uri = m_prefixToNamespaceMap.get(prefix);
     744        else if (is<SVGElement>(m_currentNode) || localName == SVGNames::svgTag->localName())
     745            uri = SVGNames::svgNamespaceURI;
    772746        else
    773747            uri = m_defaultNamespaceURI;
Note: See TracChangeset for help on using the changeset viewer.