Index: third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp |
diff --git a/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp b/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp |
index c13bfb337347d487f2331ebbdd28ed051a575e5d..9668c7cf86a6e4ad4a9ccf48fd80de0b400261e1 100644 |
--- a/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp |
+++ b/third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp |
@@ -41,6 +41,20 @@ namespace blink { |
using namespace HTMLNames; |
+ |
+PassOwnPtrWillBeRawPtr<DocumentOrderedMap> DocumentOrderedMap::create() |
+{ |
+ return adoptPtrWillBeNoop(new DocumentOrderedMap); |
+} |
+ |
+DocumentOrderedMap::DocumentOrderedMap() |
+{ |
+} |
+ |
+DocumentOrderedMap::~DocumentOrderedMap() |
+{ |
+} |
+ |
inline bool keyMatchesId(const AtomicString& key, const Element& element) |
{ |
return element.getIdAttribute() == key; |
@@ -61,11 +75,6 @@ inline bool keyMatchesLabelForAttribute(const AtomicString& key, const Element& |
return isHTMLLabelElement(element) && element.getAttribute(forAttr) == key; |
} |
-PassOwnPtrWillBeRawPtr<DocumentOrderedMap> DocumentOrderedMap::create() |
-{ |
- return adoptPtrWillBeNoop(new DocumentOrderedMap()); |
-} |
- |
void DocumentOrderedMap::add(const AtomicString& key, Element* element) |
{ |
ASSERT(key); |
@@ -106,6 +115,14 @@ void DocumentOrderedMap::remove(const AtomicString& key, Element* element) |
} |
} |
+#if ENABLE(ASSERT) |
+void DocumentOrderedMap::willRemoveId(const AtomicString& key) |
+{ |
+ ASSERT(m_removingId.isNull() || key.isNull()); |
+ m_removingId = key; |
+} |
+#endif |
+ |
template<bool keyMatches(const AtomicString&, const Element&)> |
inline Element* DocumentOrderedMap::get(const AtomicString& key, const TreeScope* scope) const |
{ |
@@ -120,14 +137,22 @@ inline Element* DocumentOrderedMap::get(const AtomicString& key, const TreeScope |
if (entry->element) |
return entry->element; |
- // We know there's at least one node that matches; iterate to find the first one. |
+ // Iterate to find the node that matches. Nothing will match iff an element |
+ // with children having duplicate IDs is being removed -- the tree traversal |
+ // will be over an updated tree not having that element. In all other cases, |
+ // a match is expected. |
+ // |
+ // Such calls to get()/getElementById() while handling element removals will |
+ // legitimately happen when e.g., adjusting form ID associations. Quietly |
+ // allow those lookups to (expectedly) fail by having the tree scope removal |
+ // register the element ID it is in the process of removing. |
for (Element& element : ElementTraversal::startsAfter(scope->rootNode())) { |
if (!keyMatches(key, element)) |
continue; |
entry->element = &element; |
return &element; |
} |
- ASSERT_NOT_REACHED(); |
+ ASSERT(key == m_removingId); |
return 0; |
} |