Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: third_party/WebKit/Source/core/dom/DocumentOrderedMap.cpp

Issue 1555653002: Handle some failing DocumentOrderedMap ID lookups across tree removals. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add test Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 43
44 PassOwnPtrWillBeRawPtr<DocumentOrderedMap> DocumentOrderedMap::create() 44 PassOwnPtrWillBeRawPtr<DocumentOrderedMap> DocumentOrderedMap::create()
45 { 45 {
46 return adoptPtrWillBeNoop(new DocumentOrderedMap); 46 return adoptPtrWillBeNoop(new DocumentOrderedMap);
47 } 47 }
48 48
49 DocumentOrderedMap::DocumentOrderedMap() 49 DocumentOrderedMap::DocumentOrderedMap()
50 { 50 {
51 } 51 }
52 52
53 DocumentOrderedMap::~DocumentOrderedMap() 53 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentOrderedMap);
54
55 #if ENABLE(ASSERT)
56 void DocumentOrderedMap::enterTreeRemoveScope()
esprehn 2016/01/05 07:48:33 no need for the methods, put the class in Document
sof 2016/01/05 07:53:37 That's what ps#1 did, but then I got worried about
54 { 57 {
58 m_treeRemovalScopeLevel++;
55 } 59 }
56 60
61 void DocumentOrderedMap::leaveTreeRemoveScope()
62 {
63 ASSERT(m_treeRemovalScopeLevel);
64 m_treeRemovalScopeLevel--;
65 }
66 #endif
67
57 inline bool keyMatchesId(const AtomicString& key, const Element& element) 68 inline bool keyMatchesId(const AtomicString& key, const Element& element)
58 { 69 {
59 return element.getIdAttribute() == key; 70 return element.getIdAttribute() == key;
60 } 71 }
61 72
62 inline bool keyMatchesMapName(const AtomicString& key, const Element& element) 73 inline bool keyMatchesMapName(const AtomicString& key, const Element& element)
63 { 74 {
64 return isHTMLMapElement(element) && toHTMLMapElement(element).getName() == k ey; 75 return isHTMLMapElement(element) && toHTMLMapElement(element).getName() == k ey;
65 } 76 }
66 77
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 } else { 118 } else {
108 if (entry->element == element) { 119 if (entry->element == element) {
109 ASSERT(entry->orderedList.isEmpty() || entry->orderedList.first() == element); 120 ASSERT(entry->orderedList.isEmpty() || entry->orderedList.first() == element);
110 entry->element = entry->orderedList.size() > 1 ? entry->orderedList[ 1] : nullptr; 121 entry->element = entry->orderedList.size() > 1 ? entry->orderedList[ 1] : nullptr;
111 } 122 }
112 entry->count--; 123 entry->count--;
113 entry->orderedList.clear(); 124 entry->orderedList.clear();
114 } 125 }
115 } 126 }
116 127
117 #if ENABLE(ASSERT)
118 void DocumentOrderedMap::willRemoveId(const AtomicString& key)
119 {
120 ASSERT(m_removingId.isNull() || key.isNull());
121 m_removingId = key;
122 }
123 #endif
124
125 template<bool keyMatches(const AtomicString&, const Element&)> 128 template<bool keyMatches(const AtomicString&, const Element&)>
126 inline Element* DocumentOrderedMap::get(const AtomicString& key, const TreeScope * scope) const 129 inline Element* DocumentOrderedMap::get(const AtomicString& key, const TreeScope * scope) const
127 { 130 {
128 ASSERT(key); 131 ASSERT(key);
129 ASSERT(scope); 132 ASSERT(scope);
130 133
131 MapEntry* entry = m_map.get(key); 134 MapEntry* entry = m_map.get(key);
132 if (!entry) 135 if (!entry)
133 return 0; 136 return 0;
134 137
135 ASSERT(entry->count); 138 ASSERT(entry->count);
136 if (entry->element) 139 if (entry->element)
137 return entry->element; 140 return entry->element;
138 141
139 // Iterate to find the node that matches. Nothing will match iff an element 142 // Iterate to find the node that matches. Nothing will match iff an element
140 // with children having duplicate IDs is being removed -- the tree traversal 143 // with children having duplicate IDs is being removed -- the tree traversal
141 // will be over an updated tree not having that element. In all other cases, 144 // will be over an updated tree not having that subtree. In all other cases,
142 // a match is expected. 145 // a match is expected.
143 //
144 // Such calls to get()/getElementById() while handling element removals will
145 // legitimately happen when e.g., adjusting form ID associations. Quietly
146 // allow those lookups to (expectedly) fail by having the tree scope removal
147 // register the element ID it is in the process of removing.
148 for (Element& element : ElementTraversal::startsAfter(scope->rootNode())) { 146 for (Element& element : ElementTraversal::startsAfter(scope->rootNode())) {
149 if (!keyMatches(key, element)) 147 if (!keyMatches(key, element))
150 continue; 148 continue;
151 entry->element = &element; 149 entry->element = &element;
152 return &element; 150 return &element;
153 } 151 }
154 ASSERT(key == m_removingId); 152 // As get()/getElementById() can legitimately be called while handling eleme nt
153 // removals, allow failure iff we're in the scope of node removals.
154 ASSERT(m_treeRemovalScopeLevel);
155 return 0; 155 return 0;
156 } 156 }
157 157
158 Element* DocumentOrderedMap::getElementById(const AtomicString& key, const TreeS cope* scope) const 158 Element* DocumentOrderedMap::getElementById(const AtomicString& key, const TreeS cope* scope) const
159 { 159 {
160 return get<keyMatchesId>(key, scope); 160 return get<keyMatchesId>(key, scope);
161 } 161 }
162 162
163 const WillBeHeapVector<RawPtrWillBeMember<Element>>& DocumentOrderedMap::getAllE lementsById(const AtomicString& key, const TreeScope* scope) const 163 const WillBeHeapVector<RawPtrWillBeMember<Element>>& DocumentOrderedMap::getAllE lementsById(const AtomicString& key, const TreeScope* scope) const
164 { 164 {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 212
213 DEFINE_TRACE(DocumentOrderedMap::MapEntry) 213 DEFINE_TRACE(DocumentOrderedMap::MapEntry)
214 { 214 {
215 visitor->trace(element); 215 visitor->trace(element);
216 #if ENABLE(OILPAN) 216 #if ENABLE(OILPAN)
217 visitor->trace(orderedList); 217 visitor->trace(orderedList);
218 #endif 218 #endif
219 } 219 }
220 220
221 } // namespace blink 221 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698