Commit 64c95337 authored by benjamin@webkit.org's avatar benjamin@webkit.org

Add a nicer way to iterate over all the attributes of an element

https://bugs.webkit.org/show_bug.cgi?id=127266

Reviewed by Geoffrey Garen.

When using Element::attributeAt() in a loop, the compiler had to generate two kinds of
accessor:
-If the element data is unique, the length and data comes from the attribute Vector.
-If the element data is shared, the data comes from the tail of elementData itself.

The choice was done for every access, which caused the assembly to be a little
hard to follow.
This patch unify the data access by doing everything as a array pointer with offset (getting
that data from Vector when necessary).

To make it easier to do the right thing, a new iterator was added so that range-based loops
can replace all the faulty cases.

* css/SelectorChecker.cpp:
(WebCore::anyAttributeMatches):
* css/SelectorChecker.h:
(WebCore::SelectorChecker::checkExactAttribute):
* dom/DatasetDOMStringMap.cpp:
(WebCore::DatasetDOMStringMap::getNames):
(WebCore::DatasetDOMStringMap::item):
(WebCore::DatasetDOMStringMap::contains):
* dom/Element.cpp:
(WebCore::Element::normalizeAttributes):
(WebCore::Element::detachAllAttrNodesFromElement):
(WebCore::Element::cloneAttributesFromElement):
* dom/Element.h:
(WebCore::Element::attributesIterator):
* dom/ElementData.cpp:
(WebCore::ElementData::isEquivalent):
(WebCore::ElementData::findAttributeIndexByNameSlowCase):
* dom/ElementData.h:
(WebCore::AttributeConstIterator::AttributeConstIterator):
(WebCore::AttributeConstIterator::operator*):
(WebCore::AttributeConstIterator::operator->):
(WebCore::AttributeConstIterator::operator++):
(WebCore::AttributeConstIterator::operator==):
(WebCore::AttributeConstIterator::operator!=):
(WebCore::AttributeIteratorAccessor::AttributeIteratorAccessor):
(WebCore::AttributeIteratorAccessor::begin):
(WebCore::AttributeIteratorAccessor::end):
(WebCore::ElementData::attributesIterator):
* dom/Node.cpp:
(WebCore::Node::isDefaultNamespace):
(WebCore::Node::lookupNamespaceURI):
(WebCore::Node::lookupNamespacePrefix):
(WebCore::Node::compareDocumentPosition):
* dom/StyledElement.cpp:
(WebCore::StyledElement::makePresentationAttributeCacheKey):
(WebCore::StyledElement::rebuildPresentationAttributeStyle):
* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::appendElement):
* editing/markup.cpp:
(WebCore::completeURLs):
(WebCore::StyledMarkupAccumulator::appendElement):
* html/HTMLEmbedElement.cpp:
(WebCore::HTMLEmbedElement::parametersForPlugin):
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::parametersForPlugin):
* inspector/DOMPatchSupport.cpp:
(WebCore::DOMPatchSupport::innerPatchNode):
(WebCore::DOMPatchSupport::createDigest):
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::setAttributesAsText):
(WebCore::InspectorDOMAgent::buildArrayForElementAttributes):
* inspector/InspectorNodeFinder.cpp:
(WebCore::InspectorNodeFinder::matchesElement):
* page/PageSerializer.cpp:
(WebCore::isCharsetSpecifyingNode):
* xml/XPathNodeSet.cpp:
(WebCore::XPath::NodeSet::traversalSort):
* xml/XPathStep.cpp:
(WebCore::XPath::Step::nodesInAxis):
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::XMLDocumentParser):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@162394 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent bdf5d1d4
2014-01-20 Benjamin Poulain <benjamin@webkit.org>
Add a nicer way to iterate over all the attributes of an element
https://bugs.webkit.org/show_bug.cgi?id=127266
Reviewed by Geoffrey Garen.
When using Element::attributeAt() in a loop, the compiler had to generate two kinds of
accessor:
-If the element data is unique, the length and data comes from the attribute Vector.
-If the element data is shared, the data comes from the tail of elementData itself.
The choice was done for every access, which caused the assembly to be a little
hard to follow.
This patch unify the data access by doing everything as a array pointer with offset (getting
that data from Vector when necessary).
To make it easier to do the right thing, a new iterator was added so that range-based loops
can replace all the faulty cases.
* css/SelectorChecker.cpp:
(WebCore::anyAttributeMatches):
* css/SelectorChecker.h:
(WebCore::SelectorChecker::checkExactAttribute):
* dom/DatasetDOMStringMap.cpp:
(WebCore::DatasetDOMStringMap::getNames):
(WebCore::DatasetDOMStringMap::item):
(WebCore::DatasetDOMStringMap::contains):
* dom/Element.cpp:
(WebCore::Element::normalizeAttributes):
(WebCore::Element::detachAllAttrNodesFromElement):
(WebCore::Element::cloneAttributesFromElement):
* dom/Element.h:
(WebCore::Element::attributesIterator):
* dom/ElementData.cpp:
(WebCore::ElementData::isEquivalent):
(WebCore::ElementData::findAttributeIndexByNameSlowCase):
* dom/ElementData.h:
(WebCore::AttributeConstIterator::AttributeConstIterator):
(WebCore::AttributeConstIterator::operator*):
(WebCore::AttributeConstIterator::operator->):
(WebCore::AttributeConstIterator::operator++):
(WebCore::AttributeConstIterator::operator==):
(WebCore::AttributeConstIterator::operator!=):
(WebCore::AttributeIteratorAccessor::AttributeIteratorAccessor):
(WebCore::AttributeIteratorAccessor::begin):
(WebCore::AttributeIteratorAccessor::end):
(WebCore::ElementData::attributesIterator):
* dom/Node.cpp:
(WebCore::Node::isDefaultNamespace):
(WebCore::Node::lookupNamespaceURI):
(WebCore::Node::lookupNamespacePrefix):
(WebCore::Node::compareDocumentPosition):
* dom/StyledElement.cpp:
(WebCore::StyledElement::makePresentationAttributeCacheKey):
(WebCore::StyledElement::rebuildPresentationAttributeStyle):
* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::appendElement):
* editing/markup.cpp:
(WebCore::completeURLs):
(WebCore::StyledMarkupAccumulator::appendElement):
* html/HTMLEmbedElement.cpp:
(WebCore::HTMLEmbedElement::parametersForPlugin):
* html/HTMLObjectElement.cpp:
(WebCore::HTMLObjectElement::parametersForPlugin):
* inspector/DOMPatchSupport.cpp:
(WebCore::DOMPatchSupport::innerPatchNode):
(WebCore::DOMPatchSupport::createDigest):
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::setAttributesAsText):
(WebCore::InspectorDOMAgent::buildArrayForElementAttributes):
* inspector/InspectorNodeFinder.cpp:
(WebCore::InspectorNodeFinder::matchesElement):
* page/PageSerializer.cpp:
(WebCore::isCharsetSpecifyingNode):
* xml/XPathNodeSet.cpp:
(WebCore::XPath::NodeSet::traversalSort):
* xml/XPathStep.cpp:
(WebCore::XPath::Step::nodesInAxis):
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::XMLDocumentParser):
2014-01-20 Gyuyoung Kim <gyuyoung.kim@samsung.com>
Do refactor in collectGradientAttributes() and renderStyleForLengthResolve()
......@@ -342,9 +342,7 @@ static bool attributeValueMatches(const Attribute& attribute, CSSSelector::Match
static bool anyAttributeMatches(Element* element, const CSSSelector* selector, const QualifiedName& selectorAttr, bool caseSensitive)
{
ASSERT(element->hasAttributesWithoutUpdate());
for (size_t i = 0, count = element->attributeCount(); i < count; ++i) {
const Attribute& attribute = element->attributeAt(i);
for (const Attribute& attribute : element->attributesIterator()) {
if (!attribute.matches(selectorAttr.prefix(), element->isHTMLElement() ? selector->attributeCanonicalLocalName() : selectorAttr.localName(), selectorAttr.namespaceURI()))
continue;
......
......@@ -131,9 +131,7 @@ inline bool SelectorChecker::checkExactAttribute(const Element* element, const C
if (!element->hasAttributesWithoutUpdate())
return false;
const AtomicString& localName = element->isHTMLElement() ? selector->attributeCanonicalLocalName() : selectorAttributeName.localName();
unsigned size = element->attributeCount();
for (unsigned i = 0; i < size; ++i) {
const Attribute& attribute = element->attributeAt(i);
for (const Attribute& attribute : element->attributesIterator()) {
if (attribute.matches(selectorAttributeName.prefix(), localName, selectorAttributeName.namespaceURI()) && (!value || attribute.value().impl() == value))
return true;
}
......
......@@ -138,9 +138,7 @@ void DatasetDOMStringMap::getNames(Vector<String>& names)
if (!m_element.hasAttributes())
return;
unsigned length = m_element.attributeCount();
for (unsigned i = 0; i < length; i++) {
const Attribute& attribute = m_element.attributeAt(i);
for (const Attribute& attribute : m_element.attributesIterator()) {
if (isValidAttributeName(attribute.localName()))
names.append(convertAttributeNameToPropertyName(attribute.localName()));
}
......@@ -151,9 +149,7 @@ String DatasetDOMStringMap::item(const String& name)
if (!m_element.hasAttributes())
return String();
unsigned length = m_element.attributeCount();
for (unsigned i = 0; i < length; i++) {
const Attribute& attribute = m_element.attributeAt(i);
for (const Attribute& attribute : m_element.attributesIterator()) {
if (propertyNameMatchesAttributeName(name, attribute.localName()))
return attribute.value();
}
......@@ -166,9 +162,7 @@ bool DatasetDOMStringMap::contains(const String& name)
if (!m_element.hasAttributes())
return false;
unsigned length = m_element.attributeCount();
for (unsigned i = 0; i < length; i++) {
const Attribute& attribute = m_element.attributeAt(i);
for (const Attribute& attribute : m_element.attributesIterator()) {
if (propertyNameMatchesAttributeName(name, attribute.localName()))
return true;
}
......
......@@ -2314,8 +2314,8 @@ void Element::normalizeAttributes()
{
if (!hasAttributes())
return;
for (unsigned i = 0; i < attributeCount(); ++i) {
if (RefPtr<Attr> attr = attrIfExists(attributeAt(i).name()))
for (const Attribute& attribute : attributesIterator()) {
if (RefPtr<Attr> attr = attrIfExists(attribute.name()))
attr->normalize();
}
}
......@@ -2916,8 +2916,7 @@ void Element::detachAllAttrNodesFromElement()
AttrNodeList* attrNodeList = attrNodeListForElement(this);
ASSERT(attrNodeList);
for (unsigned i = 0; i < attributeCount(); ++i) {
const Attribute& attribute = attributeAt(i);
for (const Attribute& attribute : attributesIterator()) {
if (RefPtr<Attr> attrNode = findAttrNodeInList(*attrNodeList, attribute.name()))
attrNode->detachFromElementWithValue(attribute.value());
}
......@@ -3038,9 +3037,7 @@ void Element::cloneAttributesFromElement(const Element& other)
else
m_elementData = other.m_elementData->makeUniqueCopy();
unsigned length = m_elementData->length();
for (unsigned i = 0; i < length; ++i) {
const Attribute& attribute = const_cast<const ElementData*>(m_elementData.get())->attributeAt(i);
for (const Attribute& attribute : attributesIterator()) {
attributeChanged(attribute.name(), attribute.value(), ModifiedByCloning);
}
}
......
......@@ -186,6 +186,7 @@ public:
// Internal methods that assume the existence of attribute storage, one should use hasAttributes()
// before calling them.
AttributeIteratorAccessor attributesIterator() const { return elementData()->attributesIterator(); }
unsigned attributeCount() const;
const Attribute& attributeAt(unsigned index) const;
const Attribute* findAttributeByName(const QualifiedName&) const;
......
......@@ -163,12 +163,10 @@ bool ElementData::isEquivalent(const ElementData* other) const
if (!other)
return isEmpty();
unsigned len = length();
if (len != other->length())
if (length() != other->length())
return false;
for (unsigned i = 0; i < len; i++) {
const Attribute& attribute = attributeAt(i);
for (const Attribute& attribute : attributesIterator()) {
const Attribute* otherAttr = other->findAttributeByName(attribute.name());
if (!otherAttr || attribute.value() != otherAttr->value())
return false;
......@@ -180,8 +178,10 @@ bool ElementData::isEquivalent(const ElementData* other) const
unsigned ElementData::findAttributeIndexByNameSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
{
// Continue to checking case-insensitively and/or full namespaced names if necessary:
for (unsigned i = 0; i < length(); ++i) {
const Attribute& attribute = attributeAt(i);
const Attribute* attributes = attributeBase();
unsigned length = this->length();
for (unsigned i = 0; i < length; ++i) {
const Attribute& attribute = attributes[i];
if (!attribute.name().hasPrefix()) {
if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute.localName()))
return i;
......
......@@ -37,6 +37,41 @@ class ShareableElementData;
class StyleProperties;
class UniqueElementData;
class AttributeConstIterator {
public:
AttributeConstIterator(const Attribute* array, unsigned offset)
: m_array(array)
, m_offset(offset)
{
}
const Attribute& operator*() const { return m_array[m_offset]; }
const Attribute* operator->() const { return &m_array[m_offset]; }
AttributeConstIterator& operator++() { ++m_offset; return *this; }
bool operator==(const AttributeConstIterator& other) const { return m_offset == other.m_offset; }
bool operator!=(const AttributeConstIterator& other) const { return !(*this == other); }
private:
const Attribute* m_array;
unsigned m_offset;
};
class AttributeIteratorAccessor {
public:
AttributeIteratorAccessor(const Attribute* array, unsigned size)
: m_array(array)
, m_size(size)
{
}
AttributeConstIterator begin() const { return AttributeConstIterator(m_array, 0); }
AttributeConstIterator end() const { return AttributeConstIterator(m_array, m_size); }
private:
const Attribute* m_array;
unsigned m_size;
};
class ElementData : public RefCounted<ElementData> {
WTF_MAKE_FAST_ALLOCATED;
public:
......@@ -61,6 +96,7 @@ public:
unsigned length() const;
bool isEmpty() const { return !length(); }
AttributeIteratorAccessor attributesIterator() const;
const Attribute& attributeAt(unsigned index) const;
const Attribute* findAttributeByName(const QualifiedName&) const;
unsigned findAttributeIndexByName(const QualifiedName&) const;
......@@ -208,6 +244,15 @@ inline const StyleProperties* ElementData::presentationAttributeStyle() const
return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
}
inline AttributeIteratorAccessor ElementData::attributesIterator() const
{
if (isUnique()) {
const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueElementData*>(this)->m_attributeVector;
return AttributeIteratorAccessor(attributeVector.data(), attributeVector.size());
}
return AttributeIteratorAccessor(static_cast<const ShareableElementData*>(this)->m_attributeArray, arraySize());
}
inline const Attribute* ElementData::findAttributeByName(const AtomicString& name, bool shouldIgnoreAttributeCase) const
{
unsigned index = findAttributeIndexByName(name, shouldIgnoreAttributeCase);
......
......@@ -1133,9 +1133,7 @@ bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const
return elem->namespaceURI() == namespaceURI;
if (elem->hasAttributes()) {
for (unsigned i = 0; i < elem->attributeCount(); i++) {
const Attribute& attribute = elem->attributeAt(i);
for (const Attribute& attribute : elem->attributesIterator()) {
if (attribute.localName() == xmlnsAtom)
return attribute.value() == namespaceURI;
}
......@@ -1217,8 +1215,7 @@ String Node::lookupNamespaceURI(const String &prefix) const
return elem->namespaceURI();
if (elem->hasAttributes()) {
for (unsigned i = 0; i < elem->attributeCount(); i++) {
const Attribute& attribute = elem->attributeAt(i);
for (const Attribute& attribute : elem->attributesIterator()) {
if (attribute.prefix() == xmlnsAtom && attribute.localName() == prefix) {
if (!attribute.value().isEmpty())
......@@ -1273,9 +1270,7 @@ String Node::lookupNamespacePrefix(const AtomicString &_namespaceURI, const Elem
ASSERT(isElementNode());
const Element* thisElement = toElement(this);
if (thisElement->hasAttributes()) {
for (unsigned i = 0; i < thisElement->attributeCount(); i++) {
const Attribute& attribute = thisElement->attributeAt(i);
for (const Attribute& attribute : thisElement->attributesIterator()) {
if (attribute.prefix() == xmlnsAtom && attribute.value() == _namespaceURI
&& originalElement->lookupNamespaceURI(attribute.localName()) == _namespaceURI)
return attribute.localName();
......@@ -1426,14 +1421,12 @@ unsigned short Node::compareDocumentPosition(Node* otherNode)
// We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
Element* owner1 = attr1->ownerElement();
owner1->synchronizeAllAttributes();
unsigned length = owner1->attributeCount();
for (unsigned i = 0; i < length; ++i) {
// If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
for (const Attribute& attribute : owner1->attributesIterator()) {
// If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
// implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
// the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
// when comparing two attributes of the same element, and inserting or removing additional attributes might change
// the order between existing attributes.
const Attribute& attribute = owner1->attributeAt(i);
if (attr1->qualifiedName() == attribute.name())
return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
if (attr2->qualifiedName() == attribute.name())
......
......@@ -285,9 +285,7 @@ void StyledElement::makePresentationAttributeCacheKey(PresentationAttributeCache
// Interpretation of the size attributes on <input> depends on the type attribute.
if (hasTagName(inputTag))
return;
unsigned size = attributeCount();
for (unsigned i = 0; i < size; ++i) {
const Attribute& attribute = attributeAt(i);
for (const Attribute& attribute : attributesIterator()) {
if (!isPresentationAttribute(attribute.name()))
continue;
if (!attribute.namespaceURI().isNull())
......@@ -335,11 +333,8 @@ void StyledElement::rebuildPresentationAttributeStyle()
presentationAttributeCacheCleaner().didHitPresentationAttributeCache();
} else {
style = MutableStyleProperties::create(isSVGElement() ? SVGAttributeMode : CSSQuirksMode);
unsigned size = attributeCount();
for (unsigned i = 0; i < size; ++i) {
const Attribute& attribute = attributeAt(i);
for (const Attribute& attribute : attributesIterator())
collectStyleForPresentationAttribute(attribute.name(), attribute.value(), static_cast<MutableStyleProperties&>(*style));
}
}
// ShareableElementData doesn't store presentation attribute style, so make sure we have a UniqueElementData.
......
......@@ -426,9 +426,8 @@ void MarkupAccumulator::appendElement(StringBuilder& result, const Element& elem
appendOpenTag(result, element, namespaces);
if (element.hasAttributes()) {
unsigned length = element.attributeCount();
for (unsigned int i = 0; i < length; i++)
appendAttribute(result, element, element.attributeAt(i), namespaces);
for (const Attribute& attribute : element.attributesIterator())
appendAttribute(result, element, attribute, namespaces);
}
// Give an opportunity to subclasses to add their own attributes.
......
......@@ -102,9 +102,7 @@ static void completeURLs(DocumentFragment* fragment, const String& baseURL)
for (auto& element : descendantsOfType<Element>(*fragment)) {
if (!element.hasAttributes())
continue;
unsigned length = element.attributeCount();
for (unsigned i = 0; i < length; i++) {
const Attribute& attribute = element.attributeAt(i);
for (const Attribute& attribute : element.attributesIterator()) {
if (element.isURLAttribute(attribute) && !attribute.value().isEmpty())
changes.append(AttributeChange(&element, attribute.name(), URL(parsedBaseURL, attribute.value()).string()));
}
......@@ -290,15 +288,15 @@ void StyledMarkupAccumulator::appendElement(StringBuilder& out, const Element& e
const bool documentIsHTML = element.document().isHTMLDocument();
appendOpenTag(out, element, 0);
const unsigned length = element.hasAttributes() ? element.attributeCount() : 0;
const bool shouldAnnotateOrForceInline = element.isHTMLElement() && (shouldAnnotate() || addDisplayInline);
const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldApplyWrappingStyle(element);
for (unsigned i = 0; i < length; ++i) {
const Attribute& attribute = element.attributeAt(i);
// We'll handle the style attribute separately, below.
if (attribute.name() == styleAttr && shouldOverrideStyleAttr)
continue;
appendAttribute(out, element, attribute, 0);
if (element.hasAttributes()) {
for (const Attribute& attribute : element.attributesIterator()) {
// We'll handle the style attribute separately, below.
if (attribute.name() == styleAttr && shouldOverrideStyleAttr)
continue;
appendAttribute(out, element, attribute, 0);
}
}
if (shouldOverrideStyleAttr) {
......
......@@ -120,8 +120,7 @@ void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<St
if (!hasAttributes())
return;
for (unsigned i = 0; i < attributeCount(); ++i) {
const Attribute& attribute = attributeAt(i);
for (const Attribute& attribute : attributesIterator()) {
paramNames.append(attribute.localName().string());
paramValues.append(attribute.value().string());
}
......
......@@ -202,8 +202,7 @@ void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<S
// Turn the attributes of the <object> element into arrays, but don't override <param> values.
if (hasAttributes()) {
for (unsigned i = 0; i < attributeCount(); ++i) {
const Attribute& attribute = attributeAt(i);
for (const Attribute& attribute : attributesIterator()) {
const AtomicString& name = attribute.name().localName();
if (!uniqueParamNames.contains(name.impl())) {
paramNames.append(name.string());
......
......@@ -197,9 +197,7 @@ bool DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, Excep
// FIXME: Create a function in Element for copying properties. cloneDataFromElement() is close but not enough for this case.
if (newElement->hasAttributesWithoutUpdate()) {
size_t numAttrs = newElement->attributeCount();
for (size_t i = 0; i < numAttrs; ++i) {
const Attribute& attribute = newElement->attributeAt(i);
for (const Attribute& attribute : newElement->attributesIterator()) {
if (!m_domEditor->setAttribute(oldElement, attribute.name().localName(), attribute.value(), ec))
return false;
}
......@@ -433,10 +431,8 @@ PassOwnPtr<DOMPatchSupport::Digest> DOMPatchSupport::createDigest(Node* node, Un
Element* element = toElement(node);
if (element->hasAttributesWithoutUpdate()) {
size_t numAttrs = element->attributeCount();
SHA1 attrsSHA1;
for (size_t i = 0; i < numAttrs; ++i) {
const Attribute& attribute = element->attributeAt(i);
for (const Attribute& attribute : element->attributesIterator()) {
addStringToSHA1(attrsSHA1, attribute.name().toString());
addStringToSHA1(attrsSHA1, attribute.value());
}
......
......@@ -679,10 +679,8 @@ void InspectorDOMAgent::setAttributesAsText(ErrorString* errorString, int elemen
}
bool foundOriginalAttribute = false;
unsigned numAttrs = childElement->attributeCount();
for (unsigned i = 0; i < numAttrs; ++i) {
for (const Attribute& attribute : childElement->attributesIterator()) {
// Add attribute pair
const Attribute& attribute = childElement->attributeAt(i);
foundOriginalAttribute = foundOriginalAttribute || (name && attribute.name().toString() == *name);
if (!m_domEditor->setAttribute(element, attribute.name().toString(), attribute.value(), errorString))
return;
......@@ -1322,10 +1320,8 @@ PassRefPtr<Inspector::TypeBuilder::Array<String>> InspectorDOMAgent::buildArrayF
// Go through all attributes and serialize them.
if (!element->hasAttributes())
return attributesValue.release();
unsigned numAttrs = element->attributeCount();
for (unsigned i = 0; i < numAttrs; ++i) {
for (const Attribute& attribute : element->attributesIterator()) {
// Add attribute pair
const Attribute& attribute = element->attributeAt(i);
attributesValue->addItem(attribute.name().toString());
attributesValue->addItem(attribute.value());
}
......
......@@ -122,9 +122,8 @@ bool InspectorNodeFinder::matchesElement(const Element& element)
if (!element.hasAttributes())
return false;
unsigned numAttrs = element.attributeCount();
for (unsigned i = 0; i < numAttrs; ++i) {
if (matchesAttribute(element.attributeAt(i)))
for (const Attribute& attribute : element.attributesIterator()) {
if (matchesAttribute(attribute))
return true;
}
......
......@@ -74,8 +74,7 @@ static bool isCharsetSpecifyingNode(const Node& node)
return false;
HTMLMetaCharsetParser::AttributeList attributes;
if (element.hasAttributes()) {
for (unsigned i = 0; i < element.attributeCount(); ++i) {
const Attribute& attribute = element.attributeAt(i);
for (const Attribute& attribute : element.attributesIterator()) {
// FIXME: We should deal appropriately with the attribute if they have a namespace.
attributes.append(std::make_pair(attribute.name().toString(), attribute.value().string()));
}
......
......@@ -218,9 +218,8 @@ void NodeSet::traversalSort() const
if (!element->hasAttributes())
continue;
unsigned attributeCount = element->attributeCount();
for (unsigned i = 0; i < attributeCount; ++i) {
RefPtr<Attr> attr = element->attrIfExists(element->attributeAt(i).name());
for (const Attribute& attribute : element->attributesIterator()) {
RefPtr<Attr> attr = element->attrIfExists(attribute.name());
if (attr && nodes.contains(attr.get()))
sortedNodes.append(attr);
}
......
......@@ -361,8 +361,8 @@ void Step::nodesInAxis(Node& context, NodeSet& nodes) const
if (!contextElement.hasAttributes())
return;
for (unsigned i = 0; i < contextElement.attributeCount(); ++i) {
RefPtr<Attr> attr = contextElement.ensureAttr(contextElement.attributeAt(i).name());
for (const Attribute& attribute : contextElement.attributesIterator()) {
RefPtr<Attr> attr = contextElement.ensureAttr(attribute.name());
if (nodeMatches(*attr, AttributeAxis, m_nodeTest))
nodes.append(attr.release());
}
......
......@@ -628,8 +628,7 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parent
for (; !elemStack.isEmpty(); elemStack.removeLast()) {
Element* element = elemStack.last();
if (element->hasAttributes()) {
for (unsigned i = 0; i < element->attributeCount(); i++) {
const Attribute& attribute = element->attributeAt(i);
for (const Attribute& attribute : element->attributesIterator()) {
if (attribute.localName() == xmlnsAtom)
m_defaultNamespaceURI = attribute.value();
else if (attribute.prefix() == xmlnsAtom)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment