Changeset 107570 in webkit


Ignore:
Timestamp:
Feb 13, 2012 7:02:44 AM (12 years ago)
Author:
caio.oliveira@openbossa.org
Message:

Move attribute storage from NamedNodeMap to ElementAttributeData
https://bugs.webkit.org/show_bug.cgi?id=77674

Reviewed by Andreas Kling.

Move m_attributes vector from NamedNodeMap to ElementAttributeData. Make the
remaining callsites interact with ElementAttributeData if possible. The parsing
code is still interacting with NamedNodeMap, so some functions remained as
wrappers there. A next change will it use ElementAttributeData instead.

The code for DOM exported functions remained in NamedNodeMap. This implementation
should move to Element in a next change, too.

  • dom/Attr.h:

(Attr):

  • dom/Element.cpp:

(WebCore::Element::setAttribute):
(WebCore::Element::setAttributeInternal):
(WebCore::Element::parserSetAttributeMap):
(WebCore::Element::removeAttribute):
(WebCore::Element::hasAttribute):
(WebCore::Element::hasAttributeNS):
(WebCore::Element::normalizeAttributes):

  • dom/Element.h:

(Element):
(WebCore::Element::ensureUpdatedAttributes):
(WebCore::Element::ensureAttributeData):
(WebCore):
(WebCore::Element::updatedAttributeData):
(WebCore::Element::ensureUpdatedAttributeData):
These *AttributeData functions are the correct correct way for callers to touch
the details of attribute storage. The "updated" variants will update invalid
attributes before return.

(WebCore::Element::setAttributesFromElement):

  • dom/ElementAttributeData.cpp:

(WebCore::ElementAttributeData::~ElementAttributeData):
(WebCore):
(WebCore::ElementAttributeData::ensureInlineStyleDecl):
(WebCore::ElementAttributeData::addAttribute):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::detachAttributesFromElement):
(WebCore::ElementAttributeData::copyAttributesToVector):
(WebCore::ElementAttributeData::getAttributeItemIndexSlowCase):
(WebCore::ElementAttributeData::setAttributes): Make use of the assumption that
this will only be called with a valid Element, since the only call site is an
Element method.
(WebCore::ElementAttributeData::clearAttributes):
(WebCore::ElementAttributeData::replaceAttribute): Make use of the assumption
this will only be called with a valid Element, since the only call site return
early if there's no Element.

  • dom/ElementAttributeData.h:

(ElementAttributeData):
(WebCore::ElementAttributeData::length):
(WebCore::ElementAttributeData::isEmpty):
(WebCore::ElementAttributeData::attributeItem):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore):
(WebCore::ElementAttributeData::getAttributeItem):
(WebCore::ElementAttributeData::getAttributeItemIndex):

  • dom/NamedNodeMap.cpp:

(WebCore::NamedNodeMap::getNamedItem):
(WebCore::NamedNodeMap::removeNamedItem):
(WebCore::NamedNodeMap::setNamedItem):
(WebCore::NamedNodeMap::item):
(WebCore::NamedNodeMap::detachFromElement):

  • dom/NamedNodeMap.h:

(WebCore::NamedNodeMap::length):
(WebCore::NamedNodeMap::isEmpty):
(WebCore::NamedNodeMap::attributeItem):
(WebCore::NamedNodeMap::getAttributeItem):
(WebCore::NamedNodeMap::getAttributeItemIndex):
(WebCore::NamedNodeMap::shrinkToLength):
(WebCore::NamedNodeMap::reserveInitialCapacity):
(WebCore::NamedNodeMap::addAttribute):
(WebCore::NamedNodeMap::removeAttribute):
(NamedNodeMap):

  • dom/StyledElement.cpp:

(WebCore::StyledElement::updateAttributeStyle):

  • dom/StyledElement.h:

(WebCore::StyledElement::ensureInlineStyleDecl):

  • html/HTMLInputElement.cpp:

(WebCore::HTMLInputElement::updateType):

  • svg/properties/SVGAnimatedPropertySynchronizer.h:
  • xml/parser/XMLDocumentParserQt.cpp:

(WebCore::XMLDocumentParser::XMLDocumentParser):

Location:
trunk/Source/WebCore
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r107569 r107570  
     12012-02-13  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
     2
     3        Move attribute storage from NamedNodeMap to ElementAttributeData
     4        https://bugs.webkit.org/show_bug.cgi?id=77674
     5
     6        Reviewed by Andreas Kling.
     7
     8        Move m_attributes vector from NamedNodeMap to ElementAttributeData. Make the
     9        remaining callsites interact with ElementAttributeData if possible. The parsing
     10        code is still interacting with NamedNodeMap, so some functions remained as
     11        wrappers there. A next change will it use ElementAttributeData instead.
     12
     13        The code for DOM exported functions remained in NamedNodeMap. This implementation
     14        should move to Element in a next change, too.
     15
     16        * dom/Attr.h:
     17        (Attr):
     18        * dom/Element.cpp:
     19        (WebCore::Element::setAttribute):
     20        (WebCore::Element::setAttributeInternal):
     21        (WebCore::Element::parserSetAttributeMap):
     22        (WebCore::Element::removeAttribute):
     23        (WebCore::Element::hasAttribute):
     24        (WebCore::Element::hasAttributeNS):
     25        (WebCore::Element::normalizeAttributes):
     26        * dom/Element.h:
     27        (Element):
     28        (WebCore::Element::ensureUpdatedAttributes):
     29        (WebCore::Element::ensureAttributeData):
     30        (WebCore):
     31        (WebCore::Element::updatedAttributeData):
     32        (WebCore::Element::ensureUpdatedAttributeData):
     33        These *AttributeData functions are the correct correct way for callers to touch
     34        the details of attribute storage. The "updated" variants will update invalid
     35        attributes before return.
     36
     37        (WebCore::Element::setAttributesFromElement):
     38        * dom/ElementAttributeData.cpp:
     39        (WebCore::ElementAttributeData::~ElementAttributeData):
     40        (WebCore):
     41        (WebCore::ElementAttributeData::ensureInlineStyleDecl):
     42        (WebCore::ElementAttributeData::addAttribute):
     43        (WebCore::ElementAttributeData::removeAttribute):
     44        (WebCore::ElementAttributeData::detachAttributesFromElement):
     45        (WebCore::ElementAttributeData::copyAttributesToVector):
     46        (WebCore::ElementAttributeData::getAttributeItemIndexSlowCase):
     47        (WebCore::ElementAttributeData::setAttributes): Make use of the assumption that
     48        this will only be called with a valid Element, since the only call site is an
     49        Element method.
     50        (WebCore::ElementAttributeData::clearAttributes):
     51        (WebCore::ElementAttributeData::replaceAttribute): Make use of the assumption
     52        this will only be called with a valid Element, since the only call site return
     53        early if there's no Element.
     54        * dom/ElementAttributeData.h:
     55        (ElementAttributeData):
     56        (WebCore::ElementAttributeData::length):
     57        (WebCore::ElementAttributeData::isEmpty):
     58        (WebCore::ElementAttributeData::attributeItem):
     59        (WebCore::ElementAttributeData::removeAttribute):
     60        (WebCore):
     61        (WebCore::ElementAttributeData::getAttributeItem):
     62        (WebCore::ElementAttributeData::getAttributeItemIndex):
     63        * dom/NamedNodeMap.cpp:
     64        (WebCore::NamedNodeMap::getNamedItem):
     65        (WebCore::NamedNodeMap::removeNamedItem):
     66        (WebCore::NamedNodeMap::setNamedItem):
     67        (WebCore::NamedNodeMap::item):
     68        (WebCore::NamedNodeMap::detachFromElement):
     69        * dom/NamedNodeMap.h:
     70        (WebCore::NamedNodeMap::length):
     71        (WebCore::NamedNodeMap::isEmpty):
     72        (WebCore::NamedNodeMap::attributeItem):
     73        (WebCore::NamedNodeMap::getAttributeItem):
     74        (WebCore::NamedNodeMap::getAttributeItemIndex):
     75        (WebCore::NamedNodeMap::shrinkToLength):
     76        (WebCore::NamedNodeMap::reserveInitialCapacity):
     77        (WebCore::NamedNodeMap::addAttribute):
     78        (WebCore::NamedNodeMap::removeAttribute):
     79        (NamedNodeMap):
     80        * dom/StyledElement.cpp:
     81        (WebCore::StyledElement::updateAttributeStyle):
     82        * dom/StyledElement.h:
     83        (WebCore::StyledElement::ensureInlineStyleDecl):
     84        * html/HTMLInputElement.cpp:
     85        (WebCore::HTMLInputElement::updateType):
     86        * svg/properties/SVGAnimatedPropertySynchronizer.h:
     87        * xml/parser/XMLDocumentParserQt.cpp:
     88        (WebCore::XMLDocumentParser::XMLDocumentParser):
     89
    1902012-02-13  Alexei Filippov  <alexeif@chromium.org>
    291
  • trunk/Source/WebCore/dom/Attr.h

    r106740 r107570  
    4040
    4141class Attr : public ContainerNode {
     42    friend class ElementAttributeData;
    4243    friend class NamedNodeMap;
    4344public:
  • trunk/Source/WebCore/dom/Element.cpp

    r107525 r107570  
    617617    const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    618618
    619     size_t index = ensureUpdatedAttributes()->getAttributeItemIndex(localName, false);
    620     const QualifiedName& qName = index != notFound ? m_attributeMap->attributeItem(index)->name() : QualifiedName(nullAtom, localName, nullAtom);
     619    size_t index = ensureUpdatedAttributeData()->getAttributeItemIndex(localName, false);
     620    const QualifiedName& qName = index != notFound ? attributeItem(index)->name() : QualifiedName(nullAtom, localName, nullAtom);
    621621    setAttributeInternal(index, qName, value);
    622622}
     
    624624void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
    625625{
    626     setAttributeInternal(ensureUpdatedAttributes()->getAttributeItemIndex(name), name, value);
     626    setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value);
    627627}
    628628
    629629inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value)
    630630{
    631     Attribute* old = index != notFound ? m_attributeMap->attributeItem(index) : 0;
     631    ElementAttributeData* attributeData = &m_attributeMap->m_attributeData;
     632    Attribute* old = index != notFound ? attributeData->attributeItem(index) : 0;
    632633    if (value.isNull()) {
    633634        if (old)
    634             m_attributeMap->removeAttribute(index);
     635            attributeData->removeAttribute(index, this);
    635636        return;
    636637    }
    637638
    638639    if (!old) {
    639         m_attributeMap->addAttribute(createAttribute(name, value));
     640        attributeData->addAttribute(createAttribute(name, value), this);
    640641        return;
    641642    }
     
    751752
    752753    if (m_attributeMap) {
     754        ElementAttributeData* attributeData = &m_attributeMap->m_attributeData;
    753755        m_attributeMap->m_element = this;
    754756        // If the element is created as result of a paste or drag-n-drop operation
     
    757759            unsigned i = 0;
    758760            while (i < m_attributeMap->length()) {
    759                 const QualifiedName& attributeName = m_attributeMap->m_attributes[i]->name();
     761                const QualifiedName& attributeName = attributeData->m_attributes[i]->name();
    760762                if (isEventHandlerAttribute(attributeName)) {
    761                     m_attributeMap->m_attributes.remove(i);
     763                    attributeData->m_attributes.remove(i);
    762764                    continue;
    763765                }
    764766
    765                 if (isAttributeToRemove(attributeName, m_attributeMap->m_attributes[i]->value()))
    766                     m_attributeMap->m_attributes[i]->setValue(nullAtom);
     767                if (isAttributeToRemove(attributeName, attributeData->m_attributes[i]->value()))
     768                    attributeData->m_attributes[i]->setValue(nullAtom);
    767769                i++;
    768770            }
     
    771773        // attributeChanged mutates m_attributeMap.
    772774        Vector<RefPtr<Attribute> > attributes;
    773         m_attributeMap->copyAttributesToVector(attributes);
     775        attributeData->copyAttributesToVector(attributes);
    774776        for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    775777            attributeChanged(iter->get());
     
    14921494void Element::removeAttribute(const String& name)
    14931495{
    1494     if (!m_attributeMap)
     1496    ElementAttributeData* attributeData = this->attributeData();
     1497    if (!attributeData)
    14951498        return;
    14961499
    14971500    String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    1498     size_t index = m_attributeMap->getAttributeItemIndex(localName, false);
     1501    size_t index = attributeData->getAttributeItemIndex(localName, false);
    14991502    if (index == notFound)
    15001503        return;
    15011504
    1502     m_attributeMap->removeAttribute(index);
     1505    attributeData->removeAttribute(index, this);
    15031506}
    15041507
     
    15271530bool Element::hasAttribute(const String& name) const
    15281531{
    1529     NamedNodeMap* attrs = updatedAttributes();
    1530     if (!attrs)
     1532    ElementAttributeData* attributeData = updatedAttributeData();
     1533    if (!attributeData)
    15311534        return false;
    15321535
     
    15341537    // there may be a way to remove it.
    15351538    String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    1536     return attrs->getAttributeItem(localName, false);
     1539    return attributeData->getAttributeItem(localName, false);
    15371540}
    15381541
    15391542bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
    15401543{
    1541     NamedNodeMap* attrs = updatedAttributes();
    1542     if (!attrs)
     1544    ElementAttributeData* attributeData = updatedAttributeData();
     1545    if (!attributeData)
    15431546        return false;
    1544     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
     1547    return attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
    15451548}
    15461549
     
    17291732void Element::normalizeAttributes()
    17301733{
    1731     NamedNodeMap* attrs = updatedAttributes();
    1732     if (!attrs)
    1733         return;
    1734 
    1735     if (attrs->isEmpty())
     1734    ElementAttributeData* attributeData = updatedAttributeData();
     1735    if (!attributeData || attributeData->isEmpty())
    17361736        return;
    17371737
    17381738    Vector<RefPtr<Attribute> > attributeVector;
    1739     attrs->copyAttributesToVector(attributeVector);
     1739    attributeData->copyAttributesToVector(attributeVector);
    17401740    size_t numAttrs = attributeVector.size();
    17411741    for (size_t i = 0; i < numAttrs; ++i) {
  • trunk/Source/WebCore/dom/Element.h

    r107525 r107570  
    240240    void parserSetAttributeMap(PassOwnPtr<NamedNodeMap>, FragmentScriptingPermission);
    241241
    242     NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
    243     NamedNodeMap* ensureAttributeMap() const;
    244 
    245242    ElementAttributeData* attributeData() const { return m_attributeMap ? m_attributeMap->attributeData() : 0; }
    246     ElementAttributeData* ensureAttributeData() const { return ensureUpdatedAttributes()->attributeData(); }
    247 
    248     // FIXME: This method should be removed once AttributeData is moved to Element.
    249     ElementAttributeData* ensureAttributeDataWithoutUpdate() const { return ensureAttributeMap()->attributeData(); }
     243    ElementAttributeData* ensureAttributeData() const;
     244    ElementAttributeData* updatedAttributeData() const;
     245    ElementAttributeData* ensureUpdatedAttributeData() const;
    250246
    251247    void setAttributesFromElement(const Element&);
     
    548544{
    549545    updateInvalidAttributes();
    550     return ensureAttributeMap();
     546    if (!m_attributeMap)
     547        createAttributeMap();
     548    return m_attributeMap.get();
    551549}
    552550
     
    557555}
    558556
     557inline ElementAttributeData* Element::ensureAttributeData() const
     558{
     559    if (!m_attributeMap)
     560        createAttributeMap();
     561    return m_attributeMap->attributeData();
     562}
     563
     564inline ElementAttributeData* Element::updatedAttributeData() const
     565{
     566    updateInvalidAttributes();
     567    return attributeData();
     568}
     569
     570inline ElementAttributeData* Element::ensureUpdatedAttributeData() const
     571{
     572    updateInvalidAttributes();
     573    return ensureAttributeData();
     574}
     575
    559576inline void Element::setAttributesFromElement(const Element& other)
    560577{
    561     if (NamedNodeMap* attributeMap = other.updatedAttributes())
    562         ensureUpdatedAttributes()->setAttributes(*attributeMap);
     578    if (ElementAttributeData* attributeData = other.updatedAttributeData())
     579        ensureUpdatedAttributeData()->setAttributes(*attributeData, this);
    563580}
    564581
     
    674691}
    675692
    676 inline NamedNodeMap* Element::ensureAttributeMap() const
    677 {
    678     if (!m_attributeMap)
    679         createAttributeMap();
    680     return m_attributeMap.get();
    681 }
    682 
    683693inline void Element::updateInvalidAttributes() const
    684694{
  • trunk/Source/WebCore/dom/ElementAttributeData.cpp

    r107484 r107570  
    2727#include "ElementAttributeData.h"
    2828
     29#include "Attr.h"
    2930#include "StyledElement.h"
    3031
    3132namespace WebCore {
     33
     34ElementAttributeData::~ElementAttributeData()
     35{
     36    detachAttributesFromElement();
     37}
    3238
    3339void ElementAttributeData::setClass(const String& className, bool shouldFoldCase)
     
    3642}
    3743
    38 StylePropertySet* ElementAttributeData::ensureInlineStyleDecl(Element* element)
     44StylePropertySet* ElementAttributeData::ensureInlineStyleDecl(StyledElement* element)
    3945{
    4046    if (!m_inlineStyleDecl) {
     
    5460}
    5561
     62void ElementAttributeData::addAttribute(PassRefPtr<Attribute> prpAttribute, Element* element)
     63{
     64    RefPtr<Attribute> attribute = prpAttribute;
     65
     66    if (element)
     67        element->willModifyAttribute(attribute->name(), nullAtom, attribute->value());
     68
     69    m_attributes.append(attribute);
     70    if (Attr* attr = attribute->attr())
     71        attr->m_element = element;
     72
     73    if (element)
     74        element->didModifyAttribute(attribute.get());
    5675}
     76
     77void ElementAttributeData::removeAttribute(size_t index, Element* element)
     78{
     79    ASSERT(index < length());
     80
     81    RefPtr<Attribute> attribute = m_attributes[index];
     82
     83    if (element)
     84        element->willRemoveAttribute(attribute->name(), attribute->value());
     85
     86    if (Attr* attr = attribute->attr())
     87        attr->m_element = 0;
     88    m_attributes.remove(index);
     89
     90    if (element)
     91        element->didRemoveAttribute(attribute.get());
     92}
     93
     94void ElementAttributeData::detachAttributesFromElement()
     95{
     96    size_t size = m_attributes.size();
     97    for (size_t i = 0; i < size; i++) {
     98        if (Attr* attr = m_attributes[i]->attr())
     99            attr->m_element = 0;
     100    }
     101}
     102
     103void ElementAttributeData::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy)
     104{
     105    copy = m_attributes;
     106}
     107
     108size_t ElementAttributeData::getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const
     109{
     110    unsigned len = length();
     111
     112    // Continue to checking case-insensitively and/or full namespaced names if necessary:
     113    for (unsigned i = 0; i < len; ++i) {
     114        const QualifiedName& attrName = m_attributes[i]->name();
     115        if (!attrName.hasPrefix()) {
     116            if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName()))
     117                return i;
     118        } else {
     119            // FIXME: Would be faster to do this comparison without calling toString, which
     120            // generates a temporary string by concatenation. But this branch is only reached
     121            // if the attribute name has a prefix, which is rare in HTML.
     122            if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase))
     123                return i;
     124        }
     125    }
     126    return notFound;
     127}
     128
     129void ElementAttributeData::setAttributes(const ElementAttributeData& other, Element* element)
     130{
     131    ASSERT(element);
     132
     133    // If assigning the map changes the id attribute, we need to call
     134    // updateId.
     135    Attribute* oldId = getAttributeItem(element->document()->idAttributeName());
     136    Attribute* newId = other.getAttributeItem(element->document()->idAttributeName());
     137
     138    if (oldId || newId)
     139        element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
     140
     141    Attribute* oldName = getAttributeItem(HTMLNames::nameAttr);
     142    Attribute* newName = other.getAttributeItem(HTMLNames::nameAttr);
     143
     144    if (oldName || newName)
     145        element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom);
     146
     147    clearAttributes();
     148    unsigned newLength = other.length();
     149    m_attributes.resize(newLength);
     150
     151    // FIXME: These loops can probably be combined.
     152    for (unsigned i = 0; i < newLength; i++)
     153        m_attributes[i] = other.m_attributes[i]->clone();
     154    for (unsigned i = 0; i < newLength; i++)
     155        element->attributeChanged(m_attributes[i].get());
     156}
     157
     158void ElementAttributeData::clearAttributes()
     159{
     160    clearClass();
     161    detachAttributesFromElement();
     162    m_attributes.clear();
     163}
     164
     165void ElementAttributeData::replaceAttribute(size_t index, PassRefPtr<Attribute> prpAttribute, Element* element)
     166{
     167    ASSERT(element);
     168    ASSERT(index < length());
     169
     170    RefPtr<Attribute> attribute = prpAttribute;
     171    Attribute* old = m_attributes[index].get();
     172
     173    element->willModifyAttribute(attribute->name(), old->value(), attribute->value());
     174
     175    if (Attr* attr = old->attr())
     176        attr->m_element = 0;
     177    m_attributes[index] = attribute;
     178    if (Attr* attr = attribute->attr())
     179        attr->m_element = element;
     180
     181    element->didModifyAttribute(attribute.get());
     182}
     183
     184}
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r107484 r107570  
    2727#define ElementAttributeData_h
    2828
     29#include "Attribute.h"
    2930#include "SpaceSplitString.h"
    3031#include "StylePropertySet.h"
     32#include <wtf/NotFound.h>
    3133
    3234namespace WebCore {
     
    3638class ElementAttributeData {
    3739public:
     40    ~ElementAttributeData();
     41
    3842    void clearClass() { m_classNames.clear(); }
    3943    void setClass(const String& className, bool shouldFoldCase);
     
    4448
    4549    StylePropertySet* inlineStyleDecl() { return m_inlineStyleDecl.get(); }
    46     StylePropertySet* ensureInlineStyleDecl(Element*);
     50    StylePropertySet* ensureInlineStyleDecl(StyledElement*);
    4751    void destroyInlineStyleDecl();
    4852
     
    5054    void setAttributeStyle(PassRefPtr<StylePropertySet> style) { m_attributeStyle = style; }
    5155
     56    size_t length() const { return m_attributes.size(); }
     57    bool isEmpty() const { return m_attributes.isEmpty(); }
     58
     59    // Internal interface.
     60    Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); }
     61    Attribute* getAttributeItem(const QualifiedName&) const;
     62    size_t getAttributeItemIndex(const QualifiedName&) const;
     63
     64    // These functions do no error checking.
     65    void addAttribute(PassRefPtr<Attribute>, Element*);
     66    void removeAttribute(const QualifiedName&, Element*);
     67    void removeAttribute(size_t index, Element*);
     68
    5269private:
     70    friend class Element;
    5371    friend class NamedNodeMap;
    5472
     
    5775    }
    5876
     77    void detachAttributesFromElement();
     78    void copyAttributesToVector(Vector<RefPtr<Attribute> >&);
     79    Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
     80    size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const;
     81    size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
     82    void setAttributes(const ElementAttributeData& other, Element*);
     83    void clearAttributes();
     84    void replaceAttribute(size_t index, PassRefPtr<Attribute>, Element*);
     85
    5986    RefPtr<StylePropertySet> m_inlineStyleDecl;
    6087    RefPtr<StylePropertySet> m_attributeStyle;
    6188    SpaceSplitString m_classNames;
    6289    AtomicString m_idForStyleResolution;
     90    Vector<RefPtr<Attribute>, 4> m_attributes;
    6391};
     92
     93inline void ElementAttributeData::removeAttribute(const QualifiedName& name, Element* element)
     94{
     95    size_t index = getAttributeItemIndex(name);
     96    if (index == notFound)
     97        return;
     98
     99    removeAttribute(index, element);
     100}
     101
     102inline Attribute* ElementAttributeData::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
     103{
     104    size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
     105    if (index != notFound)
     106        return m_attributes[index].get();
     107    return 0;
     108}
     109
     110inline Attribute* ElementAttributeData::getAttributeItem(const QualifiedName& name) const
     111{
     112    size_t index = getAttributeItemIndex(name);
     113    if (index != notFound)
     114        return m_attributes[index].get();
     115    return 0;
     116}
     117
     118// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
     119// can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
     120inline size_t ElementAttributeData::getAttributeItemIndex(const QualifiedName& name) const
     121{
     122    size_t len = length();
     123    for (unsigned i = 0; i < len; ++i) {
     124        if (m_attributes[i]->name().matches(name))
     125            return i;
     126    }
     127    return notFound;
     128}
     129
     130inline size_t ElementAttributeData::getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const
     131{
     132    unsigned len = length();
     133    bool doSlowCheck = shouldIgnoreAttributeCase;
     134
     135    // Optimize for the case where the attribute exists and its name exactly matches.
     136    for (unsigned i = 0; i < len; ++i) {
     137        const QualifiedName& attrName = m_attributes[i]->name();
     138        if (!attrName.hasPrefix()) {
     139            if (name == attrName.localName())
     140                return i;
     141        } else
     142            doSlowCheck = true;
     143    }
     144
     145    if (doSlowCheck)
     146        return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
     147    return notFound;
     148}
    64149
    65150}
  • trunk/Source/WebCore/dom/NamedNodeMap.cpp

    r106819 r107570  
    4141}
    4242
    43 inline void NamedNodeMap::detachAttributesFromElement()
    44 {
    45     size_t size = m_attributes.size();
    46     for (size_t i = 0; i < size; i++) {
    47         if (Attr* attr = m_attributes[i]->attr())
    48             attr->m_element = 0;
    49     }
    50 }
    51 
    5243void NamedNodeMap::ref()
    5344{
     
    6253}
    6354
    64 NamedNodeMap::~NamedNodeMap()
    65 {
    66     detachAttributesFromElement();
    67 }
    68 
    6955PassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const
    7056{
    71     Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element));
     57    Attribute* a = m_attributeData.getAttributeItem(name, shouldIgnoreAttributeCase(m_element));
    7258    if (!a)
    7359        return 0;
     
    8369PassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode& ec)
    8470{
    85     Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element));
     71    Attribute* a = m_attributeData.getAttributeItem(name, shouldIgnoreAttributeCase(m_element));
    8672    if (!a) {
    8773        ec = NOT_FOUND_ERR;
     
    136122    if (oldAttribute) {
    137123        oldAttr = oldAttribute->createAttrIfNeeded(m_element);
    138         replaceAttribute(index, attribute);
     124        m_attributeData.replaceAttribute(index, attribute, m_element);
    139125    } else
    140         addAttribute(attribute);
     126        m_attributeData.addAttribute(attribute, m_element);
    141127
    142128    return oldAttr.release();
     
    158144    }
    159145
    160     RefPtr<Attr> attr = m_attributes[index]->createAttrIfNeeded(m_element);
     146    RefPtr<Attr> attr = m_attributeData.m_attributes[index]->createAttrIfNeeded(m_element);
    161147
    162148    removeAttribute(index);
     
    170156        return 0;
    171157
    172     return m_attributes[index]->createAttrIfNeeded(m_element);
    173 }
    174 
    175 void NamedNodeMap::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy)
    176 {
    177     copy = m_attributes;
    178 }
    179 
    180 size_t NamedNodeMap::getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const
    181 {
    182     unsigned len = length();
    183 
    184     // Continue to checking case-insensitively and/or full namespaced names if necessary:
    185     for (unsigned i = 0; i < len; ++i) {
    186         const QualifiedName& attrName = m_attributes[i]->name();
    187         if (!attrName.hasPrefix()) {
    188             if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName()))
    189                 return i;
    190         } else {
    191             // FIXME: Would be faster to do this comparison without calling toString, which
    192             // generates a temporary string by concatenation. But this branch is only reached
    193             // if the attribute name has a prefix, which is rare in HTML.
    194             if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase))
    195                 return i;
    196         }
    197     }
    198     return notFound;
    199 }
    200 
    201 void NamedNodeMap::clearAttributes()
    202 {
    203     attributeData()->clearClass();
    204     detachAttributesFromElement();
    205     m_attributes.clear();
     158    return m_attributeData.m_attributes[index]->createAttrIfNeeded(m_element);
    206159}
    207160
     
    213166    // pointers to do things like create Attr objects.
    214167    m_element = 0;
    215     clearAttributes();
    216 }
    217 
    218 void NamedNodeMap::setAttributes(const NamedNodeMap& other)
    219 {
    220     // clone all attributes in the other map, but attach to our element
    221     if (!m_element)
    222         return;
    223 
    224     // If assigning the map changes the id attribute, we need to call
    225     // updateId.
    226     Attribute* oldId = getAttributeItem(m_element->document()->idAttributeName());
    227     Attribute* newId = other.getAttributeItem(m_element->document()->idAttributeName());
    228 
    229     if (oldId || newId)
    230         m_element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    231 
    232     Attribute* oldName = getAttributeItem(HTMLNames::nameAttr);
    233     Attribute* newName = other.getAttributeItem(HTMLNames::nameAttr);
    234 
    235     if (oldName || newName)
    236         m_element->updateName(oldName ? oldName->value() : nullAtom, newName ? newName->value() : nullAtom);
    237 
    238     clearAttributes();
    239     unsigned newLength = other.length();
    240     m_attributes.resize(newLength);
    241 
    242     // FIXME: These loops can probably be combined.
    243     for (unsigned i = 0; i < newLength; i++)
    244         m_attributes[i] = other.m_attributes[i]->clone();
    245     for (unsigned i = 0; i < newLength; i++)
    246         m_element->attributeChanged(m_attributes[i].get());
    247 }
    248 
    249 void NamedNodeMap::addAttribute(PassRefPtr<Attribute> prpAttribute)
    250 {
    251     RefPtr<Attribute> attribute = prpAttribute;
    252 
    253     if (m_element)
    254         m_element->willModifyAttribute(attribute->name(), nullAtom, attribute->value());
    255 
    256     m_attributes.append(attribute);
    257     if (Attr* attr = attribute->attr())
    258         attr->m_element = m_element;
    259 
    260     if (m_element)
    261         m_element->didModifyAttribute(attribute.get());
    262 }
    263 
    264 void NamedNodeMap::removeAttribute(size_t index)
    265 {
    266     ASSERT(index < length());
    267 
    268     RefPtr<Attribute> attribute = m_attributes[index];
    269 
    270     if (m_element)
    271         m_element->willRemoveAttribute(attribute->name(), attribute->value());
    272 
    273     if (Attr* attr = attribute->attr())
    274         attr->m_element = 0;
    275     m_attributes.remove(index);
    276 
    277     if (m_element)
    278         m_element->didRemoveAttribute(attribute.get());
    279 }
    280 
    281 void NamedNodeMap::replaceAttribute(size_t index, PassRefPtr<Attribute> prpAttribute)
    282 {
    283     ASSERT(index < length());
    284 
    285     RefPtr<Attribute> attribute = prpAttribute;
    286     Attribute* old = m_attributes[index].get();
    287 
    288     if (m_element)
    289         m_element->willModifyAttribute(attribute->name(), old->value(), attribute->value());
    290 
    291     if (Attr* attr = old->attr())
    292         attr->m_element = 0;
    293     m_attributes[index] = attribute;
    294     if (Attr* attr = attribute->attr())
    295         attr->m_element = m_element;
    296 
    297     if (m_element)
    298         m_element->didModifyAttribute(attribute.get());
     168    m_attributeData.clearAttributes();
    299169}
    300170
  • trunk/Source/WebCore/dom/NamedNodeMap.h

    r106819 r107570  
    2626#define NamedNodeMap_h
    2727
    28 #include "Attribute.h"
    2928#include "ElementAttributeData.h"
    3029#include "SpaceSplitString.h"
    31 #include <wtf/NotFound.h>
    3230
    3331namespace WebCore {
     
    4442        return adoptPtr(new NamedNodeMap(element));
    4543    }
    46 
    47     ~NamedNodeMap();
    4844
    4945    void ref();
     
    6460
    6561    PassRefPtr<Node> item(unsigned index) const;
    66     size_t length() const { return m_attributes.size(); }
    67     bool isEmpty() const { return !length(); }
     62    size_t length() const { return m_attributeData.length(); }
     63    bool isEmpty() const { return m_attributeData.isEmpty(); }
    6864
    6965    // Internal interface.
    7066
    71     Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); }
    72     Attribute* getAttributeItem(const QualifiedName&) const;
    73     size_t getAttributeItemIndex(const QualifiedName&) const;
     67    Attribute* attributeItem(unsigned index) const { return m_attributeData.attributeItem(index); }
     68    Attribute* getAttributeItem(const QualifiedName& name) const { return m_attributeData.getAttributeItem(name); }
     69    size_t getAttributeItemIndex(const QualifiedName& name) const { return m_attributeData.getAttributeItemIndex(name); }
    7470
    75     void copyAttributesToVector(Vector<RefPtr<Attribute> >&);
    76 
    77     void shrinkToLength() { m_attributes.shrinkCapacity(length()); }
    78     void reserveInitialCapacity(unsigned capacity) { m_attributes.reserveInitialCapacity(capacity); }
     71    void shrinkToLength() { m_attributeData.m_attributes.shrinkCapacity(length()); }
     72    void reserveInitialCapacity(unsigned capacity) { m_attributeData.m_attributes.reserveInitialCapacity(capacity); }
    7973
    8074    // Used during parsing: only inserts if not already there. No error checking!
     
    8983
    9084    // These functions do no error checking.
    91     void addAttribute(PassRefPtr<Attribute>);
    92     void removeAttribute(const QualifiedName&);
    93     void removeAttribute(size_t index);
     85    void addAttribute(PassRefPtr<Attribute> attribute) { m_attributeData.addAttribute(attribute, m_element); }
     86    void removeAttribute(const QualifiedName& name) { m_attributeData.removeAttribute(name, m_element); }
     87    void removeAttribute(size_t index) { m_attributeData.removeAttribute(index, m_element); }
    9488
    9589    Element* element() const { return m_element; }
     
    10498    }
    10599
    106     void detachAttributesFromElement();
    107100    void detachFromElement();
    108     Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
    109     size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const;
    110     size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
    111     void setAttributes(const NamedNodeMap&);
    112     void clearAttributes();
    113     void replaceAttribute(size_t index, PassRefPtr<Attribute>);
     101    Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const { return m_attributeData.getAttributeItem(name, shouldIgnoreAttributeCase); }
    114102
    115103    // FIXME: NamedNodeMap is being broken up into two classes, one containing data
     
    119107
    120108    Element* m_element;
    121     Vector<RefPtr<Attribute>, 4> m_attributes;
    122109};
    123 
    124 inline Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) const
    125 {
    126     size_t index = getAttributeItemIndex(name);
    127     if (index != notFound)
    128         return m_attributes[index].get();
    129     return 0;
    130 }
    131 
    132 inline size_t NamedNodeMap::getAttributeItemIndex(const QualifiedName& name) const
    133 {
    134     size_t len = length();
    135     for (unsigned i = 0; i < len; ++i) {
    136         if (m_attributes[i]->name().matches(name))
    137             return i;
    138     }
    139     return notFound;
    140 }
    141 
    142 inline Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
    143 {
    144     size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
    145     if (index != notFound)
    146         return m_attributes[index].get();
    147     return 0;
    148 }
    149 
    150 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
    151 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
    152 inline size_t NamedNodeMap::getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const
    153 {
    154     unsigned len = length();
    155     bool doSlowCheck = shouldIgnoreAttributeCase;
    156 
    157     // Optimize for the case where the attribute exists and its name exactly matches.
    158     for (unsigned i = 0; i < len; ++i) {
    159         const QualifiedName& attrName = m_attributes[i]->name();
    160         if (!attrName.hasPrefix()) {
    161             if (name == attrName.localName())
    162                 return i;
    163         } else
    164             doSlowCheck = true;
    165     }
    166 
    167     if (doSlowCheck)
    168         return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
    169     return notFound;
    170 }
    171 
    172 inline void NamedNodeMap::removeAttribute(const QualifiedName& name)
    173 {
    174     size_t index = getAttributeItemIndex(name);
    175     if (index == notFound)
    176         return;
    177 
    178     removeAttribute(index);
    179 }
    180110
    181111} // namespace WebCore
  • trunk/Source/WebCore/dom/StyledElement.cpp

    r107554 r107570  
    125125    }
    126126    clearAttributeStyleDirty();
    127     ensureAttributeDataWithoutUpdate()->setAttributeStyle(style.release());
     127    ensureAttributeData()->setAttributeStyle(style.release());
    128128}
    129129
  • trunk/Source/WebCore/dom/StyledElement.h

    r107554 r107570  
    4141
    4242    StylePropertySet* inlineStyleDecl() const { return attributeData() ? attributeData()->inlineStyleDecl() : 0; }
    43     StylePropertySet* ensureInlineStyleDecl() { return ensureAttributeDataWithoutUpdate()->ensureInlineStyleDecl(this); }
     43    StylePropertySet* ensureInlineStyleDecl() { return ensureAttributeData()->ensureInlineStyleDecl(this); }
    4444    virtual CSSStyleDeclaration* style() OVERRIDE { return ensureInlineStyleDecl()->ensureCSSStyleDeclaration(); }
    4545
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r107555 r107570  
    548548
    549549    if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
    550         ASSERT(attributeMap());
     550        ASSERT(attributeData());
    551551        if (Attribute* height = getAttributeItem(heightAttr))
    552552            attributeChanged(height);
  • trunk/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h

    r106515 r107570  
    3838        // that could cause the SVGElement to erroneously reset its properties.
    3939        // svg/dom/SVGStringList-basics.xhtml exercises this behavior.
    40         NamedNodeMap* namedAttrMap = ownerElement->ensureUpdatedAttributes();
    41         Attribute* old = namedAttrMap->getAttributeItem(attrName);
     40        ElementAttributeData* attributeData = ownerElement->ensureUpdatedAttributeData();
     41        Attribute* old = attributeData->getAttributeItem(attrName);
    4242        if (old && value.isNull())
    43             namedAttrMap->removeAttribute(old->name());
     43            attributeData->removeAttribute(old->name(), ownerElement);
    4444        else if (!old && !value.isNull())
    45             namedAttrMap->addAttribute(ownerElement->createAttribute(attrName, value));
     45            attributeData->addAttribute(ownerElement->createAttribute(attrName, value), ownerElement);
    4646        else if (old && !value.isNull())
    4747            old->setValue(value);
    48 
    4948    }
    5049};
  • trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp

    r106515 r107570  
    139139    QXmlStreamNamespaceDeclarations namespaces;
    140140    for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {
    141         if (NamedNodeMap* attrs = element->updatedAttributes()) {
     141        if (ElementAttributeData* attrs = element->updatedAttributeData()) {
    142142            for (unsigned i = 0; i < attrs->length(); i++) {
    143143                Attribute* attr = attrs->attributeItem(i);
Note: See TracChangeset for help on using the changeset viewer.