Merge from Chromium at DEPS revision r200144

This commit was generated by merge_to_master.py.

Change-Id: I52995489013675af682cee321f417f624396b584
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index cd5ec55..e8645e2 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -53,9 +53,10 @@
 #include "core/dom/NodeTraversal.h"
 #include "core/dom/PseudoElement.h"
 #include "core/dom/SelectorQuery.h"
-#include "core/dom/ShadowRoot.h"
 #include "core/dom/Text.h"
 #include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/dom/shadow/InsertionPoint.h"
+#include "core/dom/shadow/ShadowRoot.h"
 #include "core/editing/FrameSelection.h"
 #include "core/editing/TextIterator.h"
 #include "core/editing/htmlediting.h"
@@ -71,7 +72,6 @@
 #include "core/html/HTMLTableRowsCollection.h"
 #include "core/html/VoidCallback.h"
 #include "core/html/parser/HTMLParserIdioms.h"
-#include "core/html/shadow/InsertionPoint.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "core/page/FocusController.h"
 #include "core/page/Frame.h"
@@ -289,18 +289,27 @@
 PassRefPtr<Attr> Element::detachAttribute(size_t index)
 {
     ASSERT(elementData());
+    const Attribute* attribute = elementData()->attributeItem(index);
+    RefPtr<Attr> attrNode = attrIfExists(attribute->name());
+    if (attrNode)
+        detachAttrNodeAtIndex(attrNode.get(), index);
+    else {
+        attrNode = Attr::create(document(), attribute->name(), attribute->value());
+        removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
+    }
+    return attrNode.release();
+}
+
+void Element::detachAttrNodeAtIndex(Attr* attr, size_t index)
+{
+    ASSERT(attr);
+    ASSERT(elementData());
 
     const Attribute* attribute = elementData()->attributeItem(index);
     ASSERT(attribute);
-
-    RefPtr<Attr> attrNode = attrIfExists(attribute->name());
-    if (attrNode)
-        detachAttrNodeFromElementWithValue(attrNode.get(), attribute->value());
-    else
-        attrNode = Attr::create(document(), attribute->name(), attribute->value());
-
+    ASSERT(attribute->name() == attr->qualifiedName());
+    detachAttrNodeFromElementWithValue(attr, attribute->value());
     removeAttributeInternal(index, NotInSynchronizationOfLazyAttribute);
-    return attrNode.release();
 }
 
 void Element::removeAttribute(const QualifiedName& name)
@@ -1443,12 +1452,10 @@
             change = Force;
         }
 
-        if (change != Force) {
-            if (styleChangeType() >= FullStyleChange)
-                change = Force;
-            else
-                change = localChange;
-        }
+        if (styleChangeType() == FullStyleChange)
+            change = Force;
+        else if (change != Force)
+            change = localChange;
     }
     StyleResolverParentPusher parentPusher(this);
 
@@ -1800,13 +1807,15 @@
 
     synchronizeAttribute(attr->qualifiedName());
 
-    size_t index = elementData()->getAttributeItemIndex(attr->qualifiedName());
+    size_t index = elementData()->getAttrIndex(attr);
     if (index == notFound) {
         ec = NOT_FOUND_ERR;
         return 0;
     }
 
-    return detachAttribute(index);
+    RefPtr<Attr> guard(attr);
+    detachAttrNodeAtIndex(attr, index);
+    return guard.release();
 }
 
 bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionCode& ec)
@@ -2336,31 +2345,6 @@
     return 0;
 }
 
-// ElementTraversal API
-Element* Element::firstElementChild() const
-{
-    return ElementTraversal::firstWithin(this);
-}
-
-Element* Element::lastElementChild() const
-{
-    Node* n = lastChild();
-    while (n && !n->isElementNode())
-        n = n->previousSibling();
-    return toElement(n);
-}
-
-unsigned Element::childElementCount() const
-{
-    unsigned count = 0;
-    Node* n = firstChild();
-    while (n) {
-        count += n->isElementNode();
-        n = n->nextSibling();
-    }
-    return count;
-}
-
 bool Element::matchesReadOnlyPseudoClass() const
 {
     return false;
@@ -3113,6 +3097,16 @@
         info.addMember(*attributeItem(i), "*attributeItem");
 }
 
+size_t ElementData::getAttrIndex(Attr* attr) const
+{
+    // This relies on the fact that Attr's QualifiedName == the Attribute's name.
+    for (unsigned i = 0; i < length(); ++i) {
+        if (attributeItem(i)->name() == attr->qualifiedName())
+            return i;
+    }
+    return notFound;
+}
+
 size_t ElementData::getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
 {
     // Continue to checking case-insensitively and/or full namespaced names if necessary: