Index: Source/core/dom/Element.cpp |
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
index d7b4a1239835cec7ba4f6b992c0368b535cda941..726da802089e1035f4304140596422fe4b8e292f 100644 |
--- a/Source/core/dom/Element.cpp |
+++ b/Source/core/dom/Element.cpp |
@@ -2533,14 +2533,15 @@ void Element::normalizeAttributes() |
{ |
if (!hasAttributes()) |
return; |
- // attributeCount() cannot be cached before the loop because the attributes |
- // list is altered while iterating. |
- AttributeCollection attributes = this->attributes(); |
- AttributeCollection::const_iterator end = attributes.end(); |
- for (AttributeCollection::const_iterator it = attributes.begin(); it < end; ++it) { |
- if (RefPtrWillBeRawPtr<Attr> attr = attrIfExists(it->name())) |
- attr->normalize(); |
- } |
+ WillBeHeapVector<RefPtrWillBeMember<Attr> >* attrNodes = attrNodeList(); |
+ if (!attrNodes) |
+ return; |
+ // Copy the Attr Vector because Node::normalize() can fire synchronous JS |
+ // events (e.g. DOMSubtreeModified) and a JS listener could add / remove |
+ // attributes while we are iterating. |
+ WillBeHeapVector<RefPtrWillBeMember<Attr> > attrNodesCopy(*attrNodes); |
+ for (size_t i = 0; i < attrNodesCopy.size(); ++i) |
+ attrNodesCopy[i]->normalize(); |
} |
void Element::updatePseudoElement(PseudoId pseudoId, StyleRecalcChange change) |