Changeset 107570 in webkit
- Timestamp:
- Feb 13, 2012 7:02:44 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r107569 r107570 1 2012-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 1 90 2012-02-13 Alexei Filippov <alexeif@chromium.org> 2 91 -
trunk/Source/WebCore/dom/Attr.h
r106740 r107570 40 40 41 41 class Attr : public ContainerNode { 42 friend class ElementAttributeData; 42 43 friend class NamedNodeMap; 43 44 public: -
trunk/Source/WebCore/dom/Element.cpp
r107525 r107570 617 617 const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; 618 618 619 size_t index = ensureUpdatedAttribute s()->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); 621 621 setAttributeInternal(index, qName, value); 622 622 } … … 624 624 void Element::setAttribute(const QualifiedName& name, const AtomicString& value) 625 625 { 626 setAttributeInternal(ensureUpdatedAttribute s()->getAttributeItemIndex(name), name, value);626 setAttributeInternal(ensureUpdatedAttributeData()->getAttributeItemIndex(name), name, value); 627 627 } 628 628 629 629 inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value) 630 630 { 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; 632 633 if (value.isNull()) { 633 634 if (old) 634 m_attributeMap->removeAttribute(index);635 attributeData->removeAttribute(index, this); 635 636 return; 636 637 } 637 638 638 639 if (!old) { 639 m_attributeMap->addAttribute(createAttribute(name, value));640 attributeData->addAttribute(createAttribute(name, value), this); 640 641 return; 641 642 } … … 751 752 752 753 if (m_attributeMap) { 754 ElementAttributeData* attributeData = &m_attributeMap->m_attributeData; 753 755 m_attributeMap->m_element = this; 754 756 // If the element is created as result of a paste or drag-n-drop operation … … 757 759 unsigned i = 0; 758 760 while (i < m_attributeMap->length()) { 759 const QualifiedName& attributeName = m_attributeMap->m_attributes[i]->name();761 const QualifiedName& attributeName = attributeData->m_attributes[i]->name(); 760 762 if (isEventHandlerAttribute(attributeName)) { 761 m_attributeMap->m_attributes.remove(i);763 attributeData->m_attributes.remove(i); 762 764 continue; 763 765 } 764 766 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); 767 769 i++; 768 770 } … … 771 773 // attributeChanged mutates m_attributeMap. 772 774 Vector<RefPtr<Attribute> > attributes; 773 m_attributeMap->copyAttributesToVector(attributes);775 attributeData->copyAttributesToVector(attributes); 774 776 for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter) 775 777 attributeChanged(iter->get()); … … 1492 1494 void Element::removeAttribute(const String& name) 1493 1495 { 1494 if (!m_attributeMap) 1496 ElementAttributeData* attributeData = this->attributeData(); 1497 if (!attributeData) 1495 1498 return; 1496 1499 1497 1500 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; 1498 size_t index = m_attributeMap->getAttributeItemIndex(localName, false);1501 size_t index = attributeData->getAttributeItemIndex(localName, false); 1499 1502 if (index == notFound) 1500 1503 return; 1501 1504 1502 m_attributeMap->removeAttribute(index);1505 attributeData->removeAttribute(index, this); 1503 1506 } 1504 1507 … … 1527 1530 bool Element::hasAttribute(const String& name) const 1528 1531 { 1529 NamedNodeMap* attrs = updatedAttributes();1530 if (!attr s)1532 ElementAttributeData* attributeData = updatedAttributeData(); 1533 if (!attributeData) 1531 1534 return false; 1532 1535 … … 1534 1537 // there may be a way to remove it. 1535 1538 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; 1536 return attr s->getAttributeItem(localName, false);1539 return attributeData->getAttributeItem(localName, false); 1537 1540 } 1538 1541 1539 1542 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const 1540 1543 { 1541 NamedNodeMap* attrs = updatedAttributes();1542 if (!attr s)1544 ElementAttributeData* attributeData = updatedAttributeData(); 1545 if (!attributeData) 1543 1546 return false; 1544 return attr s->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));1547 return attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI)); 1545 1548 } 1546 1549 … … 1729 1732 void Element::normalizeAttributes() 1730 1733 { 1731 NamedNodeMap* attrs = updatedAttributes(); 1732 if (!attrs) 1733 return; 1734 1735 if (attrs->isEmpty()) 1734 ElementAttributeData* attributeData = updatedAttributeData(); 1735 if (!attributeData || attributeData->isEmpty()) 1736 1736 return; 1737 1737 1738 1738 Vector<RefPtr<Attribute> > attributeVector; 1739 attr s->copyAttributesToVector(attributeVector);1739 attributeData->copyAttributesToVector(attributeVector); 1740 1740 size_t numAttrs = attributeVector.size(); 1741 1741 for (size_t i = 0; i < numAttrs; ++i) { -
trunk/Source/WebCore/dom/Element.h
r107525 r107570 240 240 void parserSetAttributeMap(PassOwnPtr<NamedNodeMap>, FragmentScriptingPermission); 241 241 242 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }243 NamedNodeMap* ensureAttributeMap() const;244 245 242 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; 250 246 251 247 void setAttributesFromElement(const Element&); … … 548 544 { 549 545 updateInvalidAttributes(); 550 return ensureAttributeMap(); 546 if (!m_attributeMap) 547 createAttributeMap(); 548 return m_attributeMap.get(); 551 549 } 552 550 … … 557 555 } 558 556 557 inline ElementAttributeData* Element::ensureAttributeData() const 558 { 559 if (!m_attributeMap) 560 createAttributeMap(); 561 return m_attributeMap->attributeData(); 562 } 563 564 inline ElementAttributeData* Element::updatedAttributeData() const 565 { 566 updateInvalidAttributes(); 567 return attributeData(); 568 } 569 570 inline ElementAttributeData* Element::ensureUpdatedAttributeData() const 571 { 572 updateInvalidAttributes(); 573 return ensureAttributeData(); 574 } 575 559 576 inline void Element::setAttributesFromElement(const Element& other) 560 577 { 561 if ( NamedNodeMap* attributeMap = other.updatedAttributes())562 ensureUpdatedAttribute s()->setAttributes(*attributeMap);578 if (ElementAttributeData* attributeData = other.updatedAttributeData()) 579 ensureUpdatedAttributeData()->setAttributes(*attributeData, this); 563 580 } 564 581 … … 674 691 } 675 692 676 inline NamedNodeMap* Element::ensureAttributeMap() const677 {678 if (!m_attributeMap)679 createAttributeMap();680 return m_attributeMap.get();681 }682 683 693 inline void Element::updateInvalidAttributes() const 684 694 { -
trunk/Source/WebCore/dom/ElementAttributeData.cpp
r107484 r107570 27 27 #include "ElementAttributeData.h" 28 28 29 #include "Attr.h" 29 30 #include "StyledElement.h" 30 31 31 32 namespace WebCore { 33 34 ElementAttributeData::~ElementAttributeData() 35 { 36 detachAttributesFromElement(); 37 } 32 38 33 39 void ElementAttributeData::setClass(const String& className, bool shouldFoldCase) … … 36 42 } 37 43 38 StylePropertySet* ElementAttributeData::ensureInlineStyleDecl( Element* element)44 StylePropertySet* ElementAttributeData::ensureInlineStyleDecl(StyledElement* element) 39 45 { 40 46 if (!m_inlineStyleDecl) { … … 54 60 } 55 61 62 void 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()); 56 75 } 76 77 void 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 94 void 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 103 void ElementAttributeData::copyAttributesToVector(Vector<RefPtr<Attribute> >& copy) 104 { 105 copy = m_attributes; 106 } 107 108 size_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 129 void 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 158 void ElementAttributeData::clearAttributes() 159 { 160 clearClass(); 161 detachAttributesFromElement(); 162 m_attributes.clear(); 163 } 164 165 void 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 27 27 #define ElementAttributeData_h 28 28 29 #include "Attribute.h" 29 30 #include "SpaceSplitString.h" 30 31 #include "StylePropertySet.h" 32 #include <wtf/NotFound.h> 31 33 32 34 namespace WebCore { … … 36 38 class ElementAttributeData { 37 39 public: 40 ~ElementAttributeData(); 41 38 42 void clearClass() { m_classNames.clear(); } 39 43 void setClass(const String& className, bool shouldFoldCase); … … 44 48 45 49 StylePropertySet* inlineStyleDecl() { return m_inlineStyleDecl.get(); } 46 StylePropertySet* ensureInlineStyleDecl( Element*);50 StylePropertySet* ensureInlineStyleDecl(StyledElement*); 47 51 void destroyInlineStyleDecl(); 48 52 … … 50 54 void setAttributeStyle(PassRefPtr<StylePropertySet> style) { m_attributeStyle = style; } 51 55 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 52 69 private: 70 friend class Element; 53 71 friend class NamedNodeMap; 54 72 … … 57 75 } 58 76 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 59 86 RefPtr<StylePropertySet> m_inlineStyleDecl; 60 87 RefPtr<StylePropertySet> m_attributeStyle; 61 88 SpaceSplitString m_classNames; 62 89 AtomicString m_idForStyleResolution; 90 Vector<RefPtr<Attribute>, 4> m_attributes; 63 91 }; 92 93 inline 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 102 inline 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 110 inline 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). 120 inline 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 130 inline 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 } 64 149 65 150 } -
trunk/Source/WebCore/dom/NamedNodeMap.cpp
r106819 r107570 41 41 } 42 42 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 52 43 void NamedNodeMap::ref() 53 44 { … … 62 53 } 63 54 64 NamedNodeMap::~NamedNodeMap()65 {66 detachAttributesFromElement();67 }68 69 55 PassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const 70 56 { 71 Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element));57 Attribute* a = m_attributeData.getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); 72 58 if (!a) 73 59 return 0; … … 83 69 PassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode& ec) 84 70 { 85 Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element));71 Attribute* a = m_attributeData.getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); 86 72 if (!a) { 87 73 ec = NOT_FOUND_ERR; … … 136 122 if (oldAttribute) { 137 123 oldAttr = oldAttribute->createAttrIfNeeded(m_element); 138 replaceAttribute(index, attribute);124 m_attributeData.replaceAttribute(index, attribute, m_element); 139 125 } else 140 addAttribute(attribute);126 m_attributeData.addAttribute(attribute, m_element); 141 127 142 128 return oldAttr.release(); … … 158 144 } 159 145 160 RefPtr<Attr> attr = m_attribute s[index]->createAttrIfNeeded(m_element);146 RefPtr<Attr> attr = m_attributeData.m_attributes[index]->createAttrIfNeeded(m_element); 161 147 162 148 removeAttribute(index); … … 170 156 return 0; 171 157 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); 206 159 } 207 160 … … 213 166 // pointers to do things like create Attr objects. 214 167 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(); 299 169 } 300 170 -
trunk/Source/WebCore/dom/NamedNodeMap.h
r106819 r107570 26 26 #define NamedNodeMap_h 27 27 28 #include "Attribute.h"29 28 #include "ElementAttributeData.h" 30 29 #include "SpaceSplitString.h" 31 #include <wtf/NotFound.h>32 30 33 31 namespace WebCore { … … 44 42 return adoptPtr(new NamedNodeMap(element)); 45 43 } 46 47 ~NamedNodeMap();48 44 49 45 void ref(); … … 64 60 65 61 PassRefPtr<Node> item(unsigned index) const; 66 size_t length() const { return m_attribute s.size(); }67 bool isEmpty() const { return !length(); }62 size_t length() const { return m_attributeData.length(); } 63 bool isEmpty() const { return m_attributeData.isEmpty(); } 68 64 69 65 // Internal interface. 70 66 71 Attribute* attributeItem(unsigned index) const { return m_attribute s[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); } 74 70 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); } 79 73 80 74 // Used during parsing: only inserts if not already there. No error checking! … … 89 83 90 84 // 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); } 94 88 95 89 Element* element() const { return m_element; } … … 104 98 } 105 99 106 void detachAttributesFromElement();107 100 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); } 114 102 115 103 // FIXME: NamedNodeMap is being broken up into two classes, one containing data … … 119 107 120 108 Element* m_element; 121 Vector<RefPtr<Attribute>, 4> m_attributes;122 109 }; 123 124 inline Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) const125 {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) const133 {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) const143 {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 caller151 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).152 inline size_t NamedNodeMap::getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const153 {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 } else164 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 }180 110 181 111 } // namespace WebCore -
trunk/Source/WebCore/dom/StyledElement.cpp
r107554 r107570 125 125 } 126 126 clearAttributeStyleDirty(); 127 ensureAttributeData WithoutUpdate()->setAttributeStyle(style.release());127 ensureAttributeData()->setAttributeStyle(style.release()); 128 128 } 129 129 -
trunk/Source/WebCore/dom/StyledElement.h
r107554 r107570 41 41 42 42 StylePropertySet* inlineStyleDecl() const { return attributeData() ? attributeData()->inlineStyleDecl() : 0; } 43 StylePropertySet* ensureInlineStyleDecl() { return ensureAttributeData WithoutUpdate()->ensureInlineStyleDecl(this); }43 StylePropertySet* ensureInlineStyleDecl() { return ensureAttributeData()->ensureInlineStyleDecl(this); } 44 44 virtual CSSStyleDeclaration* style() OVERRIDE { return ensureInlineStyleDecl()->ensureCSSStyleDeclaration(); } 45 45 -
trunk/Source/WebCore/html/HTMLInputElement.cpp
r107555 r107570 548 548 549 549 if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) { 550 ASSERT(attribute Map());550 ASSERT(attributeData()); 551 551 if (Attribute* height = getAttributeItem(heightAttr)) 552 552 attributeChanged(height); -
trunk/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h
r106515 r107570 38 38 // that could cause the SVGElement to erroneously reset its properties. 39 39 // 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); 42 42 if (old && value.isNull()) 43 namedAttrMap->removeAttribute(old->name());43 attributeData->removeAttribute(old->name(), ownerElement); 44 44 else if (!old && !value.isNull()) 45 namedAttrMap->addAttribute(ownerElement->createAttribute(attrName, value));45 attributeData->addAttribute(ownerElement->createAttribute(attrName, value), ownerElement); 46 46 else if (old && !value.isNull()) 47 47 old->setValue(value); 48 49 48 } 50 49 }; -
trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp
r106515 r107570 139 139 QXmlStreamNamespaceDeclarations namespaces; 140 140 for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) { 141 if ( NamedNodeMap* attrs = element->updatedAttributes()) {141 if (ElementAttributeData* attrs = element->updatedAttributeData()) { 142 142 for (unsigned i = 0; i < attrs->length(); i++) { 143 143 Attribute* attr = attrs->attributeItem(i);
Note: See TracChangeset
for help on using the changeset viewer.