Changeset 154779 in webkit


Ignore:
Timestamp:
Aug 28, 2013 3:25:19 PM (11 years ago)
Author:
rwlbuis@webkit.org
Message:

Namespace prefix is blindly followed when serializing
https://bugs.webkit.org/show_bug.cgi?id=19121
Serializer doesn't handling inconsistent prefixes properly
https://bugs.webkit.org/show_bug.cgi?id=117764
Attribute namespaces are serialized as if they were element ones
https://bugs.webkit.org/show_bug.cgi?id=22958

Reviewed by Ryosuke Niwa.

Source/WebCore:

Add code to make sure unique prefixes and namespace declarations are generated.
Unique prefix generation happens when:

  • the same prefix is used to map to different namespaces or
  • no prefix is given but the attribute is in a namespace.

This is done in order to not violate constraints listed in http://www.w3.org/TR/xml-names11/. In general
the pseudo code listed in http://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#normalizeDocumentAlgo
is used, doing the following for attributes:
if the attribute has a namespace then

if the attribute has no prefix OR prefix is not declared OR conflicts with existing prefix mapping to different NS then

try to find the matching in-scope declaration by looking up the prefix in the namespace -> prefix mapping, if found use that prefix
else if the attribute prefix is not null AND not mapped in-scope, declare the prefix
else generate a unique prefix for the namespace

To keep track of in-scope namespaces a prefix to namespace mapping is used.

Tests: fast/dom/XMLSerializer-attribute-namespace-prefix-conflicts.html

fast/dom/XMLSerializer-same-prefix-different-namespaces-conflict.html
fast/dom/XMLSerializer-setAttributeNS-namespace-no-prefix.html
svg/custom/xlink-prefix-generation-in-attributes.html

  • editing/MarkupAccumulator.cpp:

(WebCore::MarkupAccumulator::MarkupAccumulator):
(WebCore::MarkupAccumulator::shouldAddNamespaceAttribute):
(WebCore::MarkupAccumulator::appendNamespace):
(WebCore::MarkupAccumulator::generateUniquePrefix):
(WebCore::MarkupAccumulator::appendAttribute):

  • editing/MarkupAccumulator.h:

LayoutTests:

Add tests to make sure unique prefixes and namespace declarations are generated for the
case when the same prefix is used to map to different namespaces. All testcases are based
on the testcases attached to the bugs.

  • fast/dom/XMLSerializer-attribute-namespace-prefix-conflicts-expected.txt: Added.
  • fast/dom/XMLSerializer-attribute-namespace-prefix-conflicts.html: Added.
  • fast/dom/XMLSerializer-same-prefix-different-namespaces-conflict-expected.txt: Added.
  • fast/dom/XMLSerializer-same-prefix-different-namespaces-conflict.html: Added.
  • fast/dom/XMLSerializer-setAttributeNS-namespace-no-prefix-expected.txt: Added.
  • fast/dom/XMLSerializer-setAttributeNS-namespace-no-prefix.html: Added.
  • svg/custom/xlink-prefix-generation-in-attributes-expected.txt: Added.
  • svg/custom/xlink-prefix-generation-in-attributes.html: Added.
Location:
trunk
Files:
8 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r154778 r154779  
     12013-08-28  Rob Buis  <rwlbuis@webkit.org>
     2
     3        Namespace prefix is blindly followed when serializing
     4        https://bugs.webkit.org/show_bug.cgi?id=19121
     5        Serializer doesn't handling inconsistent prefixes properly
     6        https://bugs.webkit.org/show_bug.cgi?id=117764
     7        Attribute namespaces are serialized as if they were element ones
     8        https://bugs.webkit.org/show_bug.cgi?id=22958
     9
     10        Reviewed by Ryosuke Niwa.
     11
     12        Add tests to make sure unique prefixes and namespace declarations are generated for the
     13        case when the same prefix is used to map to different namespaces. All testcases are based
     14        on the testcases attached to the bugs.
     15
     16        * fast/dom/XMLSerializer-attribute-namespace-prefix-conflicts-expected.txt: Added.
     17        * fast/dom/XMLSerializer-attribute-namespace-prefix-conflicts.html: Added.
     18        * fast/dom/XMLSerializer-same-prefix-different-namespaces-conflict-expected.txt: Added.
     19        * fast/dom/XMLSerializer-same-prefix-different-namespaces-conflict.html: Added.
     20        * fast/dom/XMLSerializer-setAttributeNS-namespace-no-prefix-expected.txt: Added.
     21        * fast/dom/XMLSerializer-setAttributeNS-namespace-no-prefix.html: Added.
     22        * svg/custom/xlink-prefix-generation-in-attributes-expected.txt: Added.
     23        * svg/custom/xlink-prefix-generation-in-attributes.html: Added.
     24
    1252013-08-28  Sam White  <samuel_white@apple.com>
    226
  • trunk/Source/WebCore/ChangeLog

    r154778 r154779  
     12013-08-28  Rob Buis  <rwlbuis@webkit.org>
     2
     3        Namespace prefix is blindly followed when serializing
     4        https://bugs.webkit.org/show_bug.cgi?id=19121
     5        Serializer doesn't handling inconsistent prefixes properly
     6        https://bugs.webkit.org/show_bug.cgi?id=117764
     7        Attribute namespaces are serialized as if they were element ones
     8        https://bugs.webkit.org/show_bug.cgi?id=22958
     9
     10        Reviewed by Ryosuke Niwa.
     11
     12        Add code to make sure unique prefixes and namespace declarations are generated.
     13        Unique prefix generation happens when:
     14        - the same prefix is used to map to different namespaces or
     15        - no prefix is given but the attribute is in a namespace.
     16
     17        This is done in order to not violate constraints listed in http://www.w3.org/TR/xml-names11/. In general
     18        the pseudo code listed in http://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#normalizeDocumentAlgo
     19        is used, doing the following for attributes:
     20        if the attribute has a namespace then
     21          if the attribute has no prefix OR prefix is not declared OR conflicts with existing prefix mapping to different NS then
     22            try to find the matching in-scope declaration by looking up the prefix in the namespace -> prefix mapping, if found use that prefix
     23            else if the attribute prefix is not null AND not mapped in-scope, declare the prefix
     24            else generate a unique prefix for the namespace
     25
     26        To keep track of in-scope namespaces a prefix to namespace mapping is used.
     27
     28        Tests: fast/dom/XMLSerializer-attribute-namespace-prefix-conflicts.html
     29               fast/dom/XMLSerializer-same-prefix-different-namespaces-conflict.html
     30               fast/dom/XMLSerializer-setAttributeNS-namespace-no-prefix.html
     31               svg/custom/xlink-prefix-generation-in-attributes.html
     32
     33        * editing/MarkupAccumulator.cpp:
     34        (WebCore::MarkupAccumulator::MarkupAccumulator):
     35        (WebCore::MarkupAccumulator::shouldAddNamespaceAttribute):
     36        (WebCore::MarkupAccumulator::appendNamespace):
     37        (WebCore::MarkupAccumulator::generateUniquePrefix):
     38        (WebCore::MarkupAccumulator::appendAttribute):
     39        * editing/MarkupAccumulator.h:
     40
    1412013-08-28  Sam White  <samuel_white@apple.com>
    242
  • trunk/Source/WebCore/editing/MarkupAccumulator.cpp

    r153826 r154779  
    106106    , m_resolveURLsMethod(resolveUrlsMethod)
    107107    , m_fragmentSerialization(fragmentSerialization)
     108    , m_prefixLevel(0)
    108109{
    109110}
     
    288289    if (attribute.name() == xmlnsPrefixAttr) {
    289290        namespaces.set(attribute.localName().impl(), attribute.value().impl());
     291        namespaces.set(attribute.value().impl(), attribute.localName().impl());
    290292        return false;
    291293    }
     
    310312    AtomicStringImpl* pre = prefix.isEmpty() ? emptyAtom.impl() : prefix.impl();
    311313    AtomicStringImpl* foundNS = namespaces.get(pre);
    312     if (foundNS != namespaceURI.impl() && !namespaces.get(namespaceURI.impl())) {
     314    if (foundNS != namespaceURI.impl()) {
    313315        namespaces.set(pre, namespaceURI.impl());
     316        // Add namespace to prefix pair so we can do constraint checking later.
     317        if (inXMLFragmentSerialization() && !prefix.isEmpty())
     318            namespaces.set(namespaceURI.impl(), pre);
     319        // Make sure xml prefix and namespace are always known to uphold the constraints listed at http://www.w3.org/TR/xml-names11/#xmlReserved.
     320        if (namespaceURI.impl() == XMLNames::xmlNamespaceURI.impl())
     321            return;
    314322        result.append(' ');
    315323        result.append(xmlnsAtom.string());
     
    467475}
    468476
     477void MarkupAccumulator::generateUniquePrefix(QualifiedName& prefixedName, const Namespaces& namespaces)
     478{
     479    // http://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#normalizeDocumentAlgo
     480    // Find a prefix following the pattern "NS" + index (starting at 1) and make sure this
     481    // prefix is not declared in the current scope.
     482    StringBuilder builder;
     483    do {
     484        builder.clear();
     485        builder.append("NS");
     486        builder.appendNumber(++m_prefixLevel);
     487        const AtomicString& name = builder.toAtomicString();
     488        if (!namespaces.get(name.impl())) {
     489            prefixedName.setPrefix(name);
     490            return;
     491        }
     492    } while (true);
     493}
     494
    469495void MarkupAccumulator::appendAttribute(StringBuilder& result, Element* element, const Attribute& attribute, Namespaces* namespaces)
    470496{
     
    477503        result.append(attribute.name().localName());
    478504    else {
    479         if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) {
    480             if (!attribute.prefix())
    481                 prefixedName.setPrefix(xlinkAtom);
    482         } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) {
    483             if (!attribute.prefix())
    484                 prefixedName.setPrefix(xmlAtom);
    485         } else if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) {
    486             if (attribute.name() != XMLNSNames::xmlnsAttr && !attribute.prefix())
    487                 prefixedName.setPrefix(xmlnsAtom);
     505        if (!attribute.namespaceURI().isEmpty()) {
     506            AtomicStringImpl* foundNS = namespaces && attribute.prefix().impl() ? namespaces->get(attribute.prefix().impl()) : 0;
     507            bool prefixIsAlreadyMappedToOtherNS = foundNS && foundNS != attribute.namespaceURI().impl();
     508            if (attribute.prefix().isEmpty() || !foundNS || prefixIsAlreadyMappedToOtherNS) {
     509                if (AtomicStringImpl* prefix = namespaces ? namespaces->get(attribute.namespaceURI().impl()) : 0)
     510                    prefixedName.setPrefix(AtomicString(prefix));
     511                else {
     512                    bool shouldBeDeclaredUsingAppendNamespace = !attribute.prefix().isEmpty() && !foundNS;
     513                    if (!shouldBeDeclaredUsingAppendNamespace && attribute.localName() != xmlnsAtom && namespaces)
     514                        generateUniquePrefix(prefixedName, *namespaces);
     515                }
     516            }
    488517        }
    489518        result.append(prefixedName.toString());
  • trunk/Source/WebCore/editing/MarkupAccumulator.h

    r153508 r154779  
    113113    void serializeNodesWithNamespaces(Node* targetNode, Node* nodeToSkip, EChildrenOnly, const Namespaces*, Vector<QualifiedName>* tagNamesToSkip);
    114114    bool inXMLFragmentSerialization() const { return m_fragmentSerialization == XMLFragmentSerialization; }
     115    void generateUniquePrefix(QualifiedName&, const Namespaces&);
    115116
    116117    StringBuilder m_markup;
    117118    const EAbsoluteURLs m_resolveURLsMethod;
    118119    EFragmentSerialization m_fragmentSerialization;
     120    unsigned m_prefixLevel;
    119121};
    120122
Note: See TracChangeset for help on using the changeset viewer.