Diff
Modified: trunk/Source/WebCore/ChangeLog (133491 => 133492)
--- trunk/Source/WebCore/ChangeLog 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/ChangeLog 2012-11-05 18:06:23 UTC (rev 133492)
@@ -1,3 +1,58 @@
+2012-11-05 Andreas Kling <[email protected]>
+
+ Decouple Attr logic from ElementAttributeData.
+ <http://webkit.org/b/101126>
+
+ Reviewed by Antti Koivisto.
+
+ Move all logic dealing with Attr DOM nodes from ElementAttributeData to Element.
+ This makes more sense since an Attr is tied to a single Element, but an ElementAttributeData
+ can be shared by any number of Elements at a given time.
+
+ Also updated naming convention from just "Attr" to "Attr node" in the code I was touching.
+ "Attr" is way too generic, and has been historically confused with WebCore::Attribute a lot.
+
+ * dom/Element.h:
+ * dom/ElementAttributeData.h:
+ * dom/Element.cpp:
+ (WebCore::attrNodeListMap):
+ (WebCore::attrNodeListForElement):
+ (WebCore::ensureAttrNodeListForElement):
+ (WebCore::removeAttrNodeListForElement):
+ (WebCore::findAttrNodeInList):
+ (WebCore::Element::~Element):
+ (WebCore::Element::detachAttribute):
+ (WebCore::Element::setAttributeNode):
+ (WebCore::Element::removeAttributeInternal):
+ (WebCore::Element::getAttributeNode):
+ (WebCore::Element::getAttributeNodeNS):
+ (WebCore::Element::normalizeAttributes):
+ (WebCore::Element::attrIfExists):
+ (WebCore::Element::ensureAttr):
+ (WebCore::Element::detachAttrNodeFromElementWithValue):
+ (WebCore::Element::detachAllAttrNodesFromElement):
+ (WebCore::Element::cloneAttributesFromElement):
+
+ Move everything Attr-related into Element.cpp while simplifying some loops and remove
+ conditions that are no longer needed as they used to depend on having an attributeData().
+
+ * dom/Node.h:
+ (WebCore::Node::hasSyntheticAttrChildNodes):
+ (WebCore::Node::setHasSyntheticAttrChildNodes):
+
+ Renamed the hasAttrList() node flag to hasSyntheticAttrChildNodes().
+
+ * dom/Attr.cpp:
+ (WebCore::Attr::detachFromElementWithValue):
+
+ Remove awkward indirection and let the call site deal with removing the Attr node from
+ the Element's list of Attr nodes.
+
+ * dom/ElementAttributeData.cpp:
+ (WebCore::ElementAttributeData::clearAttributes):
+
+ Remove now-unused Element* argument.
+
2012-11-05 Hans Muller <[email protected]>
[CSS Exclusions] Polygon edges should span colinear vertices
Modified: trunk/Source/WebCore/dom/Attr.cpp (133491 => 133492)
--- trunk/Source/WebCore/dom/Attr.cpp 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/dom/Attr.cpp 2012-11-05 18:06:23 UTC (rev 133492)
@@ -218,7 +218,6 @@
{
ASSERT(m_element);
ASSERT(m_standaloneValue.isNull());
- m_element->attributeData()->removeAttr(m_element, qualifiedName());
m_standaloneValue = value;
m_element = 0;
}
Modified: trunk/Source/WebCore/dom/Element.cpp (133491 => 133492)
--- trunk/Source/WebCore/dom/Element.cpp 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/dom/Element.cpp 2012-11-05 18:06:23 UTC (rev 133492)
@@ -124,6 +124,52 @@
StyleResolver* m_pushedStyleResolver;
};
+typedef Vector<RefPtr<Attr> > AttrNodeList;
+typedef HashMap<Element*, OwnPtr<AttrNodeList> > AttrNodeListMap;
+
+static AttrNodeListMap& attrNodeListMap()
+{
+ DEFINE_STATIC_LOCAL(AttrNodeListMap, map, ());
+ return map;
+}
+
+static AttrNodeList* attrNodeListForElement(Element* element)
+{
+ if (!element->hasSyntheticAttrChildNodes())
+ return 0;
+ ASSERT(attrNodeListMap().contains(element));
+ return attrNodeListMap().get(element);
+}
+
+static AttrNodeList* ensureAttrNodeListForElement(Element* element)
+{
+ if (element->hasSyntheticAttrChildNodes()) {
+ ASSERT(attrNodeListMap().contains(element));
+ return attrNodeListMap().get(element);
+ }
+ ASSERT(!attrNodeListMap().contains(element));
+ element->setHasSyntheticAttrChildNodes(true);
+ AttrNodeListMap::AddResult result = attrNodeListMap().add(element, adoptPtr(new AttrNodeList));
+ return result.iterator->value.get();
+}
+
+static void removeAttrNodeListForElement(Element* element)
+{
+ ASSERT(element->hasSyntheticAttrChildNodes());
+ ASSERT(attrNodeListMap().contains(element));
+ attrNodeListMap().remove(element);
+ element->setHasSyntheticAttrChildNodes(false);
+}
+
+static Attr* findAttrNodeInList(AttrNodeList* attrNodeList, const QualifiedName& name)
+{
+ for (unsigned i = 0; i < attrNodeList->size(); ++i) {
+ if (attrNodeList->at(i)->qualifiedName() == name)
+ return attrNodeList->at(i).get();
+ }
+ return 0;
+}
+
PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
{
return adoptRef(new Element(tagName, document, CreateElement));
@@ -145,10 +191,8 @@
elementRareData()->m_shadow.clear();
}
- if (hasAttrList()) {
- ASSERT(m_attributeData);
- m_attributeData->detachAttrObjectsFromElement(this);
- }
+ if (hasSyntheticAttrChildNodes())
+ detachAllAttrNodesFromElement();
}
inline ElementRareData* Element::elementRareData() const
@@ -207,14 +251,14 @@
const Attribute* attribute = attributeData()->attributeItem(index);
ASSERT(attribute);
- RefPtr<Attr> attr = attrIfExists(attribute->name());
- if (attr)
- attr->detachFromElementWithValue(attribute->value());
+ RefPtr<Attr> attrNode = attrIfExists(attribute->name());
+ if (attrNode)
+ detachAttrNodeFromElementWithValue(attrNode.get(), attribute->value());
else
- attr = Attr::create(document(), attribute->name(), attribute->value());
+ attrNode = Attr::create(document(), attribute->name(), attribute->value());
removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
- return attr.release();
+ return attrNode.release();
}
void Element::removeAttribute(const QualifiedName& name)
@@ -1484,20 +1528,20 @@
}
#endif
-PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
+PassRefPtr<Attr> Element::setAttributeNode(Attr* attrNode, ExceptionCode& ec)
{
- if (!attr) {
+ if (!attrNode) {
ec = TYPE_MISMATCH_ERR;
return 0;
}
- RefPtr<Attr> oldAttr = attrIfExists(attr->qualifiedName());
- if (oldAttr.get() == attr)
- return attr; // This Attr is already attached to the element.
+ RefPtr<Attr> oldAttrNode = attrIfExists(attrNode->qualifiedName());
+ if (oldAttrNode.get() == attrNode)
+ return attrNode; // This Attr is already attached to the element.
// INUSE_ATTRIBUTE_ERR: Raised if node is an Attr that is already an attribute of another Element object.
// The DOM user must explicitly clone Attr nodes to re-use them in other elements.
- if (attr->ownerElement()) {
+ if (attrNode->ownerElement()) {
ec = INUSE_ATTRIBUTE_ERR;
return 0;
}
@@ -1505,17 +1549,20 @@
updateInvalidAttributes();
ElementAttributeData* attributeData = mutableAttributeData();
- size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
+ size_t index = attributeData->getAttributeItemIndex(attrNode->qualifiedName());
if (index != notFound) {
- if (oldAttr)
- oldAttr->detachFromElementWithValue(attributeData->attributeItem(index)->value());
+ if (oldAttrNode)
+ detachAttrNodeFromElementWithValue(oldAttrNode.get(), attributeData->attributeItem(index)->value());
else
- oldAttr = Attr::create(document(), attr->qualifiedName(), attributeData->attributeItem(index)->value());
+ oldAttrNode = Attr::create(document(), attrNode->qualifiedName(), attributeData->attributeItem(index)->value());
}
- setAttributeInternal(index, attr->qualifiedName(), attr->value(), NotInSynchronizationOfLazyAttribute);
- attributeData->setAttr(this, attr->qualifiedName(), attr);
- return oldAttr.release();
+ setAttributeInternal(index, attrNode->qualifiedName(), attrNode->value(), NotInSynchronizationOfLazyAttribute);
+
+ attrNode->attachToElement(this);
+ ensureAttrNodeListForElement(this)->append(attrNode);
+
+ return oldAttrNode.release();
}
PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
@@ -1588,10 +1635,8 @@
willModifyAttribute(name, valueBeingRemoved, nullAtom);
}
- if (hasAttrList()) {
- if (RefPtr<Attr> attr = attributeData->attrIfExists(this, name))
- attr->detachFromElementWithValue(attributeData->attributeItem(index)->value());
- }
+ if (RefPtr<Attr> attrNode = attrIfExists(name))
+ detachAttrNodeFromElementWithValue(attrNode.get(), attributeData->attributeItem(index)->value());
attributeData->removeAttribute(index);
@@ -1633,7 +1678,10 @@
const ElementAttributeData* attributeData = updatedAttributeData();
if (!attributeData)
return 0;
- return attributeData->getAttributeNode(name, shouldIgnoreAttributeCase(this), this);
+ const Attribute* attribute = attributeData->getAttributeItem(name, shouldIgnoreAttributeCase(this));
+ if (!attribute)
+ return 0;
+ return ensureAttr(attribute->name());
}
PassRefPtr<Attr> Element::getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName)
@@ -1641,7 +1689,10 @@
const ElementAttributeData* attributeData = updatedAttributeData();
if (!attributeData)
return 0;
- return attributeData->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), this);
+ const Attribute* attribute = attributeData->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
+ if (!attribute)
+ return 0;
+ return ensureAttr(attribute->name());
}
bool Element::hasAttribute(const AtomicString& name) const
@@ -1877,15 +1928,10 @@
void Element::normalizeAttributes()
{
- if (!hasAttrList())
- return;
-
- const ElementAttributeData* attributeData = updatedAttributeData();
- ASSERT(attributeData);
-
- for (size_t i = 0; i < attributeData->length(); ++i) {
- if (RefPtr<Attr> attr = attrIfExists(attributeData->attributeItem(i)->name()))
- attr->normalize();
+ updateInvalidAttributes();
+ if (AttrNodeList* attrNodeList = attrNodeListForElement(this)) {
+ for (unsigned i = 0; i < attrNodeList->size(); ++i)
+ attrNodeList->at(i)->normalize();
}
}
@@ -2335,18 +2381,53 @@
PassRefPtr<Attr> Element::attrIfExists(const QualifiedName& name)
{
- if (!hasAttrList())
- return 0;
- ASSERT(attributeData());
- return attributeData()->attrIfExists(this, name);
+ if (AttrNodeList* attrNodeList = attrNodeListForElement(this))
+ return findAttrNodeInList(attrNodeList, name);
+ return 0;
}
PassRefPtr<Attr> Element::ensureAttr(const QualifiedName& name)
{
- ASSERT(attributeData());
- return attributeData()->ensureAttr(this, name);
+ AttrNodeList* attrNodeList = ensureAttrNodeListForElement(this);
+ RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, name);
+ if (!attrNode) {
+ attrNode = Attr::create(this, name);
+ attrNodeList->append(attrNode);
+ }
+ return attrNode.release();
}
+void Element::detachAttrNodeFromElementWithValue(Attr* attrNode, const AtomicString& value)
+{
+ ASSERT(hasSyntheticAttrChildNodes());
+ attrNode->detachFromElementWithValue(value);
+
+ AttrNodeList* attrNodeList = attrNodeListForElement(this);
+ for (unsigned i = 0; i < attrNodeList->size(); ++i) {
+ if (attrNodeList->at(i)->qualifiedName() == attrNode->qualifiedName()) {
+ attrNodeList->remove(i);
+ if (attrNodeList->isEmpty())
+ removeAttrNodeListForElement(this);
+ return;
+ }
+ }
+ ASSERT_NOT_REACHED();
+}
+
+void Element::detachAllAttrNodesFromElement()
+{
+ AttrNodeList* attrNodeList = attrNodeListForElement(this);
+ ASSERT(attrNodeList);
+
+ for (unsigned i = 0; i < attributeCount(); ++i) {
+ const Attribute* attribute = attributeItem(i);
+ if (RefPtr<Attr> attrNode = findAttrNodeInList(attrNodeList, attribute->name()))
+ attrNode->detachFromElementWithValue(attribute->value());
+ }
+
+ removeAttrNodeListForElement(this);
+}
+
bool Element::willRecalcStyle(StyleChange)
{
ASSERT(hasCustomCallbacks());
@@ -2368,10 +2449,13 @@
void Element::cloneAttributesFromElement(const Element& other)
{
+ if (hasSyntheticAttrChildNodes())
+ detachAllAttrNodesFromElement();
+
if (const ElementAttributeData* attributeData = other.updatedAttributeData())
mutableAttributeData()->cloneDataFrom(*attributeData, other, *this);
else if (m_attributeData) {
- m_attributeData->clearAttributes(this);
+ m_attributeData->clearAttributes();
m_attributeData.clear();
}
}
Modified: trunk/Source/WebCore/dom/Element.h (133491 => 133492)
--- trunk/Source/WebCore/dom/Element.h 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/dom/Element.h 2012-11-05 18:06:23 UTC (rev 133492)
@@ -528,6 +528,9 @@
ElementRareData* elementRareData() const;
ElementRareData* ensureElementRareData();
+ void detachAllAttrNodesFromElement();
+ void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
+
RefPtr<ElementAttributeData> m_attributeData;
};
Modified: trunk/Source/WebCore/dom/ElementAttributeData.cpp (133491 => 133492)
--- trunk/Source/WebCore/dom/ElementAttributeData.cpp 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/dom/ElementAttributeData.cpp 2012-11-05 18:06:23 UTC (rev 133492)
@@ -87,101 +87,6 @@
return adoptRef(new MutableElementAttributeData(static_cast<const ImmutableElementAttributeData&>(*this)));
}
-typedef Vector<RefPtr<Attr> > AttrList;
-typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;
-
-static AttrListMap& attrListMap()
-{
- DEFINE_STATIC_LOCAL(AttrListMap, map, ());
- return map;
-}
-
-static AttrList* attrListForElement(Element* element)
-{
- ASSERT(element);
- if (!element->hasAttrList())
- return 0;
- ASSERT(attrListMap().contains(element));
- return attrListMap().get(element);
-}
-
-static AttrList* ensureAttrListForElement(Element* element)
-{
- ASSERT(element);
- if (element->hasAttrList()) {
- ASSERT(attrListMap().contains(element));
- return attrListMap().get(element);
- }
- ASSERT(!attrListMap().contains(element));
- element->setHasAttrList();
- AttrListMap::AddResult result = attrListMap().add(element, adoptPtr(new AttrList));
- return result.iterator->value.get();
-}
-
-static void removeAttrListForElement(Element* element)
-{
- ASSERT(element);
- ASSERT(element->hasAttrList());
- ASSERT(attrListMap().contains(element));
- attrListMap().remove(element);
- element->clearHasAttrList();
-}
-
-static Attr* findAttrInList(AttrList* attrList, const QualifiedName& name)
-{
- for (unsigned i = 0; i < attrList->size(); ++i) {
- if (attrList->at(i)->qualifiedName() == name)
- return attrList->at(i).get();
- }
- return 0;
-}
-
-PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) const
-{
- if (AttrList* attrList = attrListForElement(element))
- return findAttrInList(attrList, name);
- return 0;
-}
-
-PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) const
-{
- AttrList* attrList = ensureAttrListForElement(element);
- RefPtr<Attr> attr = findAttrInList(attrList, name);
- if (!attr) {
- attr = Attr::create(element, name);
- attrList->append(attr);
- }
- return attr.release();
-}
-
-void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) const
-{
- AttrList* attrList = ensureAttrListForElement(element);
-
- if (findAttrInList(attrList, name))
- return;
-
- attrList->append(attr);
- attr->attachToElement(element);
-}
-
-void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) const
-{
- AttrList* attrList = attrListForElement(element);
- ASSERT(attrList);
-
- for (unsigned i = 0; i < attrList->size(); ++i) {
- if (attrList->at(i)->qualifiedName() == name) {
- attrList->remove(i);
- if (attrList->isEmpty())
- removeAttrListForElement(element);
- return;
- }
- }
-
- ASSERT_NOT_REACHED();
-}
-
StylePropertySet* ElementAttributeData::ensureInlineStyle(StyledElement* element)
{
ASSERT(isMutable());
@@ -258,20 +163,6 @@
return true;
}
-void ElementAttributeData::detachAttrObjectsFromElement(Element* element) const
-{
- ASSERT(element->hasAttrList());
-
- for (unsigned i = 0; i < length(); ++i) {
- const Attribute* attribute = attributeItem(i);
- if (RefPtr<Attr> attr = attrIfExists(element, attribute->name()))
- attr->detachFromElementWithValue(attribute->value());
- }
-
- // The loop above should have cleaned out this element's Attr map.
- ASSERT(!element->hasAttrList());
-}
-
void ElementAttributeData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
size_t actualSize = m_isMutable ? sizeof(ElementAttributeData) : sizeForImmutableElementAttributeDataWithAttributeCount(m_arraySize);
@@ -322,7 +213,7 @@
if (!oldName.isNull() || !newName.isNull())
targetElement.updateName(oldName, newName);
- clearAttributes(&targetElement);
+ clearAttributes();
if (sourceData.isMutable())
mutableAttributeVector() = sourceData.mutableAttributeVector();
@@ -347,33 +238,11 @@
}
}
-void ElementAttributeData::clearAttributes(Element* element)
+void ElementAttributeData::clearAttributes()
{
ASSERT(isMutable());
-
- if (element->hasAttrList())
- detachAttrObjectsFromElement(element);
-
clearClass();
mutableAttributeVector().clear();
}
-PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const String& name, bool shouldIgnoreAttributeCase, Element* element) const
-{
- ASSERT(element);
- const Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase);
- if (!attribute)
- return 0;
- return ensureAttr(element, attribute->name());
}
-
-PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const QualifiedName& name, Element* element) const
-{
- ASSERT(element);
- const Attribute* attribute = getAttributeItem(name);
- if (!attribute)
- return 0;
- return ensureAttr(element, attribute->name());
-}
-
-}
Modified: trunk/Source/WebCore/dom/ElementAttributeData.h (133491 => 133492)
--- trunk/Source/WebCore/dom/ElementAttributeData.h 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/dom/ElementAttributeData.h 2012-11-05 18:06:23 UTC (rev 133492)
@@ -33,7 +33,6 @@
namespace WebCore {
-class Attr;
class Element;
class ImmutableElementAttributeData;
class MutableElementAttributeData;
@@ -69,9 +68,6 @@
size_t length() const;
bool isEmpty() const { return !length(); }
- PassRefPtr<Attr> getAttributeNode(const String&, bool shouldIgnoreAttributeCase, Element*) const;
- PassRefPtr<Attr> getAttributeNode(const QualifiedName&, Element*) const;
-
// Internal interface.
const Attribute* attributeItem(unsigned index) const;
const Attribute* getAttributeItem(const QualifiedName&) const;
@@ -89,12 +85,6 @@
bool isEquivalent(const ElementAttributeData* other) const;
- void setAttr(Element*, const QualifiedName&, Attr*) const;
- void removeAttr(Element*, const QualifiedName&) const;
- PassRefPtr<Attr> attrIfExists(Element*, const QualifiedName&) const;
- PassRefPtr<Attr> ensureAttr(Element*, const QualifiedName&) const;
- void detachAttrObjectsFromElement(Element*) const;
-
void reportMemoryUsage(MemoryObjectInfo*) const;
bool isMutable() const { return m_isMutable; }
@@ -129,7 +119,7 @@
const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
void cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement);
- void clearAttributes(Element*);
+ void clearAttributes();
PassRefPtr<ElementAttributeData> makeMutableCopy() const;
Modified: trunk/Source/WebCore/dom/Node.h (133491 => 133492)
--- trunk/Source/WebCore/dom/Node.h 2012-11-05 18:01:23 UTC (rev 133491)
+++ trunk/Source/WebCore/dom/Node.h 2012-11-05 18:06:23 UTC (rev 133492)
@@ -237,9 +237,11 @@
bool isDocumentNode() const;
bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
- bool hasAttrList() const { return getFlag(HasAttrListFlag); }
bool hasCustomCallbacks() const { return getFlag(HasCustomCallbacksFlag); }
+ bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); }
+ void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); }
+
// If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0.
Element* shadowHost() const;
// If this node is in a shadow tree, returns its shadow host. Otherwise, returns this.
@@ -355,9 +357,6 @@
void setInNamedFlow() { setFlag(InNamedFlowFlag); }
void clearInNamedFlow() { clearFlag(InNamedFlowFlag); }
- void setHasAttrList() { setFlag(HasAttrListFlag); }
- void clearHasAttrList() { clearFlag(HasAttrListFlag); }
-
bool hasScopedHTMLStyleChild() const { return getFlag(HasScopedHTMLStyleChildFlag); }
void setHasScopedHTMLStyleChild(bool flag) { setFlag(flag, HasScopedHTMLStyleChildFlag); }
@@ -733,7 +732,7 @@
DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag,
#endif
InNamedFlowFlag = 1 << 26,
- HasAttrListFlag = 1 << 27,
+ HasSyntheticAttrChildNodesFlag = 1 << 27,
HasCustomCallbacksFlag = 1 << 28,
HasScopedHTMLStyleChildFlag = 1 << 29,
HasEventTargetDataFlag = 1 << 30,