Optimizations to Element::getAttribute
[WebKit-https.git] / WebCore / dom / NamedAttrMap.cpp
index d4ec598d88565a723b9ce2225ace81f7bbf8f19b..56b40b97a5287a5f205f62ad31b105b7723865da 100644 (file)
@@ -177,11 +177,33 @@ PassRefPtr<Node> NamedNodeMap::item(unsigned index) const
 Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
 {
     unsigned len = length();
+    bool doSlowCheck = shouldIgnoreAttributeCase;
+    
+    // Optimize for the case where the attribute exists and its name exactly matches.
     for (unsigned i = 0; i < len; ++i) {
-        if (!m_attributes[i]->name().hasPrefix() && m_attributes[i]->name().localName() == name)
-            return m_attributes[i].get();
-        if (shouldIgnoreAttributeCase ? equalIgnoringCase(m_attributes[i]->name().toString(), name) : name == m_attributes[i]->name().toString())
-            return m_attributes[i].get();
+        const QualifiedName& attrName = m_attributes[i]->name();
+        if (!attrName.hasPrefix()) {
+            if (name == attrName.localName())
+                return m_attributes[i].get();
+        } else
+            doSlowCheck = true;
+    }
+    
+    // Continue to checking case-insensitively and/or full namespaced names if necessary:
+    if (doSlowCheck) {
+        for (unsigned i = 0; i < len; ++i) {
+            const QualifiedName& attrName = m_attributes[i]->name();
+            if (!attrName.hasPrefix()) {
+                if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName()))
+                    return m_attributes[i].get();
+            } else {
+                // FIXME: Would be faster to do this comparison without calling toString, which
+                // generates a temporary string by concatenation. But this branch is only reached
+                // if the attribute name has a prefix, which is rare in HTML.
+                if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase))
+                    return m_attributes[i].get();
+            }
+        }
     }
     return 0;
 }