Changeset 133492 in webkit
- Timestamp:
- Nov 5, 2012 10:06:23 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r133490 r133492 1 2012-11-05 Andreas Kling <kling@webkit.org> 2 3 Decouple Attr logic from ElementAttributeData. 4 <http://webkit.org/b/101126> 5 6 Reviewed by Antti Koivisto. 7 8 Move all logic dealing with Attr DOM nodes from ElementAttributeData to Element. 9 This makes more sense since an Attr is tied to a single Element, but an ElementAttributeData 10 can be shared by any number of Elements at a given time. 11 12 Also updated naming convention from just "Attr" to "Attr node" in the code I was touching. 13 "Attr" is way too generic, and has been historically confused with WebCore::Attribute a lot. 14 15 * dom/Element.h: 16 * dom/ElementAttributeData.h: 17 * dom/Element.cpp: 18 (WebCore::attrNodeListMap): 19 (WebCore::attrNodeListForElement): 20 (WebCore::ensureAttrNodeListForElement): 21 (WebCore::removeAttrNodeListForElement): 22 (WebCore::findAttrNodeInList): 23 (WebCore::Element::~Element): 24 (WebCore::Element::detachAttribute): 25 (WebCore::Element::setAttributeNode): 26 (WebCore::Element::removeAttributeInternal): 27 (WebCore::Element::getAttributeNode): 28 (WebCore::Element::getAttributeNodeNS): 29 (WebCore::Element::normalizeAttributes): 30 (WebCore::Element::attrIfExists): 31 (WebCore::Element::ensureAttr): 32 (WebCore::Element::detachAttrNodeFromElementWithValue): 33 (WebCore::Element::detachAllAttrNodesFromElement): 34 (WebCore::Element::cloneAttributesFromElement): 35 36 Move everything Attr-related into Element.cpp while simplifying some loops and remove 37 conditions that are no longer needed as they used to depend on having an attributeData(). 38 39 * dom/Node.h: 40 (WebCore::Node::hasSyntheticAttrChildNodes): 41 (WebCore::Node::setHasSyntheticAttrChildNodes): 42 43 Renamed the hasAttrList() node flag to hasSyntheticAttrChildNodes(). 44 45 * dom/Attr.cpp: 46 (WebCore::Attr::detachFromElementWithValue): 47 48 Remove awkward indirection and let the call site deal with removing the Attr node from 49 the Element's list of Attr nodes. 50 51 * dom/ElementAttributeData.cpp: 52 (WebCore::ElementAttributeData::clearAttributes): 53 54 Remove now-unused Element* argument. 55 1 56 2012-11-05 Hans Muller <hmuller@adobe.com> 2 57 -
trunk/Source/WebCore/dom/Attr.cpp
r133451 r133492 219 219 ASSERT(m_element); 220 220 ASSERT(m_standaloneValue.isNull()); 221 m_element->attributeData()->removeAttr(m_element, qualifiedName());222 221 m_standaloneValue = value; 223 222 m_element = 0; -
trunk/Source/WebCore/dom/Element.cpp
r133451 r133492 125 125 }; 126 126 127 typedef Vector<RefPtr<Attr> > AttrNodeList; 128 typedef HashMap<Element*, OwnPtr<AttrNodeList> > AttrNodeListMap; 129 130 static AttrNodeListMap& attrNodeListMap() 131 { 132 DEFINE_STATIC_LOCAL(AttrNodeListMap, map, ()); 133 return map; 134 } 135 136 static AttrNodeList* attrNodeListForElement(Element* element) 137 { 138 if (!element->hasSyntheticAttrChildNodes()) 139 return 0; 140 ASSERT(attrNodeListMap().contains(element)); 141 return attrNodeListMap().get(element); 142 } 143 144 static AttrNodeList* ensureAttrNodeListForElement(Element* element) 145 { 146 if (element->hasSyntheticAttrChildNodes()) { 147 ASSERT(attrNodeListMap().contains(element)); 148 return attrNodeListMap().get(element); 149 } 150 ASSERT(!attrNodeListMap().contains(element)); 151 element->setHasSyntheticAttrChildNodes(true); 152 AttrNodeListMap::AddResult result = attrNodeListMap().add(element, adoptPtr(new AttrNodeList)); 153 return result.iterator->value.get(); 154 } 155 156 static void removeAttrNodeListForElement(Element* element) 157 { 158 ASSERT(element->hasSyntheticAttrChildNodes()); 159 ASSERT(attrNodeListMap().contains(element)); 160 attrNodeListMap().remove(element); 161 element->setHasSyntheticAttrChildNodes(false); 162 } 163 164 static Attr* findAttrNodeInList(AttrNodeList* attrNodeList, const QualifiedName& name) 165 { 166 for (unsigned i = 0; i < attrNodeList->size(); ++i) { 167 if (attrNodeList->at(i)->qualifiedName() == name) 168 return attrNodeList->at(i).get(); 169 } 170 return 0; 171 } 172 127 173 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document) 128 174 { … … 146 192 } 147 193 148 if (hasAttrList()) { 149 ASSERT(m_attributeData); 150 m_attributeData->detachAttrObjectsFromElement(this); 151 } 194 if (hasSyntheticAttrChildNodes()) 195 detachAllAttrNodesFromElement(); 152 196 } 153 197 … … 208 252 ASSERT(attribute); 209 253 210 RefPtr<Attr> attr = attrIfExists(attribute->name());211 if (attr )212 attr->detachFromElementWithValue(attribute->value());254 RefPtr<Attr> attrNode = attrIfExists(attribute->name()); 255 if (attrNode) 256 detachAttrNodeFromElementWithValue(attrNode.get(), attribute->value()); 213 257 else 214 attr = Attr::create(document(), attribute->name(), attribute->value());258 attrNode = Attr::create(document(), attribute->name(), attribute->value()); 215 259 216 260 removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute); 217 return attr .release();261 return attrNode.release(); 218 262 } 219 263 … … 1485 1529 #endif 1486 1530 1487 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr , ExceptionCode& ec)1488 { 1489 if (!attr ) {1531 PassRefPtr<Attr> Element::setAttributeNode(Attr* attrNode, ExceptionCode& ec) 1532 { 1533 if (!attrNode) { 1490 1534 ec = TYPE_MISMATCH_ERR; 1491 1535 return 0; 1492 1536 } 1493 1537 1494 RefPtr<Attr> oldAttr = attrIfExists(attr->qualifiedName());1495 if (oldAttr .get() == attr)1496 return attr ; // This Attr is already attached to the element.1538 RefPtr<Attr> oldAttrNode = attrIfExists(attrNode->qualifiedName()); 1539 if (oldAttrNode.get() == attrNode) 1540 return attrNode; // This Attr is already attached to the element. 1497 1541 1498 1542 // INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object. 1499 1543 // The DOM user must explicitly clone Attr nodes to re-use them in other elements. 1500 if (attr ->ownerElement()) {1544 if (attrNode->ownerElement()) { 1501 1545 ec = INUSE_ATTRIBUTE_ERR; 1502 1546 return 0; … … 1506 1550 ElementAttributeData* attributeData = mutableAttributeData(); 1507 1551 1508 size_t index = attributeData->getAttributeItemIndex(attr ->qualifiedName());1552 size_t index = attributeData->getAttributeItemIndex(attrNode->qualifiedName()); 1509 1553 if (index != notFound) { 1510 if (oldAttr )1511 oldAttr->detachFromElementWithValue(attributeData->attributeItem(index)->value());1554 if (oldAttrNode) 1555 detachAttrNodeFromElementWithValue(oldAttrNode.get(), attributeData->attributeItem(index)->value()); 1512 1556 else 1513 oldAttr = Attr::create(document(), attr->qualifiedName(), attributeData->attributeItem(index)->value()); 1514 } 1515 1516 setAttributeInternal(index, attr->qualifiedName(), attr->value(), NotInSynchronizationOfLazyAttribute); 1517 attributeData->setAttr(this, attr->qualifiedName(), attr); 1518 return oldAttr.release(); 1557 oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), attributeData->attributeItem(index)->value()); 1558 } 1559 1560 setAttributeInternal(index, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute); 1561 1562 attrNode->attachToElement(this); 1563 ensureAttrNodeListForElement(this)->append(attrNode); 1564 1565 return oldAttrNode.release(); 1519 1566 } 1520 1567 … … 1589 1636 } 1590 1637 1591 if (hasAttrList()) { 1592 if (RefPtr<Attr> attr = attributeData->attrIfExists(this, name)) 1593 attr->detachFromElementWithValue(attributeData->attributeItem(index)->value()); 1594 } 1638 if (RefPtr<Attr> attrNode = attrIfExists(name)) 1639 detachAttrNodeFromElementWithValue(attrNode.get(), attributeData->attributeItem(index)->value()); 1595 1640 1596 1641 attributeData->removeAttribute(index); … … 1634 1679 if (!attributeData) 1635 1680 return 0; 1636 return attributeData->getAttributeNode(name, shouldIgnoreAttributeCase(this), this); 1681 const Attribute* attribute = attributeData->getAttributeItem(name, shouldIgnoreAttributeCase(this)); 1682 if (!attribute) 1683 return 0; 1684 return ensureAttr(attribute->name()); 1637 1685 } 1638 1686 … … 1642 1690 if (!attributeData) 1643 1691 return 0; 1644 return attributeData->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), this); 1692 const Attribute* attribute = attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI)); 1693 if (!attribute) 1694 return 0; 1695 return ensureAttr(attribute->name()); 1645 1696 } 1646 1697 … … 1878 1929 void Element::normalizeAttributes() 1879 1930 { 1880 if (!hasAttrList()) 1881 return; 1882 1883 const ElementAttributeData* attributeData = updatedAttributeData(); 1884 ASSERT(attributeData); 1885 1886 for (size_t i = 0; i < attributeData->length(); ++i) { 1887 if (RefPtr<Attr> attr = attrIfExists(attributeData->attributeItem(i)->name())) 1888 attr->normalize(); 1931 updateInvalidAttributes(); 1932 if (AttrNodeList* attrNodeList = attrNodeListForElement(this)) { 1933 for (unsigned i = 0; i < attrNodeList->size(); ++i) 1934 attrNodeList->at(i)->normalize(); 1889 1935 } 1890 1936 } … … 2336 2382 PassRefPtr<Attr> Element::attrIfExists(const QualifiedName& name) 2337 2383 { 2338 if (!hasAttrList()) 2339 return 0; 2340 ASSERT(attributeData()); 2341 return attributeData()->attrIfExists(this, name); 2384 if (AttrNodeList* attrNodeList = attrNodeListForElement(this)) 2385 return findAttrNodeInList(attrNodeList, name); 2386 return 0; 2342 2387 } 2343 2388 2344 2389 PassRefPtr<Attr> Element::ensureAttr(const QualifiedName& name) 2345 2390 { 2346 ASSERT(attributeData()); 2347 return attributeData()->ensureAttr(this, name); 2391 AttrNodeList* attrNodeList = ensureAttrNodeListForElement(this); 2392 RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, name); 2393 if (!attrNode) { 2394 attrNode = Attr::create(this, name); 2395 attrNodeList->append(attrNode); 2396 } 2397 return attrNode.release(); 2398 } 2399 2400 void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomicString& value) 2401 { 2402 ASSERT(hasSyntheticAttrChildNodes()); 2403 attrNode->detachFromElementWithValue(value); 2404 2405 AttrNodeList* attrNodeList = attrNodeListForElement(this); 2406 for (unsigned i = 0; i < attrNodeList->size(); ++i) { 2407 if (attrNodeList->at(i)->qualifiedName() == attrNode->qualifiedName()) { 2408 attrNodeList->remove(i); 2409 if (attrNodeList->isEmpty()) 2410 removeAttrNodeListForElement(this); 2411 return; 2412 } 2413 } 2414 ASSERT_NOT_REACHED(); 2415 } 2416 2417 void Element::detachAllAttrNodesFromElement() 2418 { 2419 AttrNodeList* attrNodeList = attrNodeListForElement(this); 2420 ASSERT(attrNodeList); 2421 2422 for (unsigned i = 0; i < attributeCount(); ++i) { 2423 const Attribute* attribute = attributeItem(i); 2424 if (RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, attribute->name())) 2425 attrNode->detachFromElementWithValue(attribute->value()); 2426 } 2427 2428 removeAttrNodeListForElement(this); 2348 2429 } 2349 2430 … … 2369 2450 void Element::cloneAttributesFromElement(const Element& other) 2370 2451 { 2452 if (hasSyntheticAttrChildNodes()) 2453 detachAllAttrNodesFromElement(); 2454 2371 2455 if (const ElementAttributeData* attributeData = other.updatedAttributeData()) 2372 2456 mutableAttributeData()->cloneDataFrom(*attributeData, other, *this); 2373 2457 else if (m_attributeData) { 2374 m_attributeData->clearAttributes( this);2458 m_attributeData->clearAttributes(); 2375 2459 m_attributeData.clear(); 2376 2460 } -
trunk/Source/WebCore/dom/Element.h
r133451 r133492 529 529 ElementRareData* ensureElementRareData(); 530 530 531 void detachAllAttrNodesFromElement(); 532 void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value); 533 531 534 RefPtr<ElementAttributeData> m_attributeData; 532 535 }; -
trunk/Source/WebCore/dom/ElementAttributeData.cpp
r133451 r133492 86 86 ASSERT(!isMutable()); 87 87 return adoptRef(new MutableElementAttributeData(static_cast<const ImmutableElementAttributeData&>(*this))); 88 }89 90 typedef Vector<RefPtr<Attr> > AttrList;91 typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;92 93 static AttrListMap& attrListMap()94 {95 DEFINE_STATIC_LOCAL(AttrListMap, map, ());96 return map;97 }98 99 static AttrList* attrListForElement(Element* element)100 {101 ASSERT(element);102 if (!element->hasAttrList())103 return 0;104 ASSERT(attrListMap().contains(element));105 return attrListMap().get(element);106 }107 108 static AttrList* ensureAttrListForElement(Element* element)109 {110 ASSERT(element);111 if (element->hasAttrList()) {112 ASSERT(attrListMap().contains(element));113 return attrListMap().get(element);114 }115 ASSERT(!attrListMap().contains(element));116 element->setHasAttrList();117 AttrListMap::AddResult result = attrListMap().add(element, adoptPtr(new AttrList));118 return result.iterator->value.get();119 }120 121 static void removeAttrListForElement(Element* element)122 {123 ASSERT(element);124 ASSERT(element->hasAttrList());125 ASSERT(attrListMap().contains(element));126 attrListMap().remove(element);127 element->clearHasAttrList();128 }129 130 static Attr* findAttrInList(AttrList* attrList, const QualifiedName& name)131 {132 for (unsigned i = 0; i < attrList->size(); ++i) {133 if (attrList->at(i)->qualifiedName() == name)134 return attrList->at(i).get();135 }136 return 0;137 }138 139 PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) const140 {141 if (AttrList* attrList = attrListForElement(element))142 return findAttrInList(attrList, name);143 return 0;144 }145 146 PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) const147 {148 AttrList* attrList = ensureAttrListForElement(element);149 RefPtr<Attr> attr = findAttrInList(attrList, name);150 if (!attr) {151 attr = Attr::create(element, name);152 attrList->append(attr);153 }154 return attr.release();155 }156 157 void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) const158 {159 AttrList* attrList = ensureAttrListForElement(element);160 161 if (findAttrInList(attrList, name))162 return;163 164 attrList->append(attr);165 attr->attachToElement(element);166 }167 168 void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) const169 {170 AttrList* attrList = attrListForElement(element);171 ASSERT(attrList);172 173 for (unsigned i = 0; i < attrList->size(); ++i) {174 if (attrList->at(i)->qualifiedName() == name) {175 attrList->remove(i);176 if (attrList->isEmpty())177 removeAttrListForElement(element);178 return;179 }180 }181 182 ASSERT_NOT_REACHED();183 88 } 184 89 … … 257 162 258 163 return true; 259 }260 261 void ElementAttributeData::detachAttrObjectsFromElement(Element* element) const262 {263 ASSERT(element->hasAttrList());264 265 for (unsigned i = 0; i < length(); ++i) {266 const Attribute* attribute = attributeItem(i);267 if (RefPtr<Attr> attr = attrIfExists(element, attribute->name()))268 attr->detachFromElementWithValue(attribute->value());269 }270 271 // The loop above should have cleaned out this element's Attr map.272 ASSERT(!element->hasAttrList());273 164 } 274 165 … … 323 214 targetElement.updateName(oldName, newName); 324 215 325 clearAttributes( &targetElement);216 clearAttributes(); 326 217 327 218 if (sourceData.isMutable()) … … 348 239 } 349 240 350 void ElementAttributeData::clearAttributes(Element* element) 351 { 352 ASSERT(isMutable()); 353 354 if (element->hasAttrList()) 355 detachAttrObjectsFromElement(element); 356 241 void ElementAttributeData::clearAttributes() 242 { 243 ASSERT(isMutable()); 357 244 clearClass(); 358 245 mutableAttributeVector().clear(); 359 246 } 360 247 361 PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const String& name, bool shouldIgnoreAttributeCase, Element* element) const 362 { 363 ASSERT(element); 364 const Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase); 365 if (!attribute) 366 return 0; 367 return ensureAttr(element, attribute->name()); 368 } 369 370 PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const QualifiedName& name, Element* element) const 371 { 372 ASSERT(element); 373 const Attribute* attribute = getAttributeItem(name); 374 if (!attribute) 375 return 0; 376 return ensureAttr(element, attribute->name()); 377 } 378 379 } 248 } -
trunk/Source/WebCore/dom/ElementAttributeData.h
r133451 r133492 34 34 namespace WebCore { 35 35 36 class Attr;37 36 class Element; 38 37 class ImmutableElementAttributeData; … … 70 69 bool isEmpty() const { return !length(); } 71 70 72 PassRefPtr<Attr> getAttributeNode(const String&, bool shouldIgnoreAttributeCase, Element*) const;73 PassRefPtr<Attr> getAttributeNode(const QualifiedName&, Element*) const;74 75 71 // Internal interface. 76 72 const Attribute* attributeItem(unsigned index) const; … … 90 86 bool isEquivalent(const ElementAttributeData* other) const; 91 87 92 void setAttr(Element*, const QualifiedName&, Attr*) const;93 void removeAttr(Element*, const QualifiedName&) const;94 PassRefPtr<Attr> attrIfExists(Element*, const QualifiedName&) const;95 PassRefPtr<Attr> ensureAttr(Element*, const QualifiedName&) const;96 void detachAttrObjectsFromElement(Element*) const;97 98 88 void reportMemoryUsage(MemoryObjectInfo*) const; 99 89 … … 130 120 size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const; 131 121 void cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement); 132 void clearAttributes( Element*);122 void clearAttributes(); 133 123 134 124 PassRefPtr<ElementAttributeData> makeMutableCopy() const; -
trunk/Source/WebCore/dom/Node.h
r133451 r133492 238 238 bool isShadowRoot() const { return getFlag(IsShadowRootFlag); } 239 239 bool inNamedFlow() const { return getFlag(InNamedFlowFlag); } 240 bool hasAttrList() const { return getFlag(HasAttrListFlag); }241 240 bool hasCustomCallbacks() const { return getFlag(HasCustomCallbacksFlag); } 241 242 bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); } 243 void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); } 242 244 243 245 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0. … … 355 357 void setInNamedFlow() { setFlag(InNamedFlowFlag); } 356 358 void clearInNamedFlow() { clearFlag(InNamedFlowFlag); } 357 358 void setHasAttrList() { setFlag(HasAttrListFlag); }359 void clearHasAttrList() { clearFlag(HasAttrListFlag); }360 359 361 360 bool hasScopedHTMLStyleChild() const { return getFlag(HasScopedHTMLStyleChildFlag); } … … 734 733 #endif 735 734 InNamedFlowFlag = 1 << 26, 736 Has AttrListFlag = 1 << 27,735 HasSyntheticAttrChildNodesFlag = 1 << 27, 737 736 HasCustomCallbacksFlag = 1 << 28, 738 737 HasScopedHTMLStyleChildFlag = 1 << 29,
Note: See TracChangeset
for help on using the changeset viewer.