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

Side by Side Diff: Source/core/dom/SelectorQuery.cpp

Issue 208423010: Remove SelectorCheckerFastPath (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: const Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/SelectorQuery.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved. 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2014 Samsung Electronics. All rights reserved. 3 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 12 matching lines...) Expand all
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "config.h" 27 #include "config.h"
28 #include "core/dom/SelectorQuery.h" 28 #include "core/dom/SelectorQuery.h"
29 29
30 #include "bindings/v8/ExceptionState.h" 30 #include "bindings/v8/ExceptionState.h"
31 #include "core/css/parser/BisonCSSParser.h" 31 #include "core/css/parser/BisonCSSParser.h"
32 #include "core/css/SelectorChecker.h" 32 #include "core/css/SelectorChecker.h"
33 #include "core/css/SelectorCheckerFastPath.h"
34 #include "core/css/SiblingTraversalStrategies.h" 33 #include "core/css/SiblingTraversalStrategies.h"
35 #include "core/dom/Document.h" 34 #include "core/dom/Document.h"
36 #include "core/dom/ElementTraversal.h" 35 #include "core/dom/ElementTraversal.h"
37 #include "core/dom/Node.h" 36 #include "core/dom/Node.h"
38 #include "core/dom/StaticNodeList.h" 37 #include "core/dom/StaticNodeList.h"
39 #include "core/dom/shadow/ElementShadow.h" 38 #include "core/dom/shadow/ElementShadow.h"
40 #include "core/dom/shadow/ShadowRoot.h" 39 #include "core/dom/shadow/ShadowRoot.h"
41 40
42 namespace WebCore { 41 namespace WebCore {
43 42
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 ASSERT(m_selectors.isEmpty()); 102 ASSERT(m_selectors.isEmpty());
104 103
105 unsigned selectorCount = 0; 104 unsigned selectorCount = 0;
106 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) 105 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector))
107 selectorCount++; 106 selectorCount++;
108 107
109 m_crossesTreeBoundary = false; 108 m_crossesTreeBoundary = false;
110 m_selectors.reserveInitialCapacity(selectorCount); 109 m_selectors.reserveInitialCapacity(selectorCount);
111 unsigned index = 0; 110 unsigned index = 0;
112 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector), ++index) { 111 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector), ++index) {
113 m_selectors.uncheckedAppend(SelectorData(*selector, SelectorCheckerFastP ath::canUse(*selector))); 112 m_selectors.uncheckedAppend(selector);
114 m_crossesTreeBoundary |= selectorList.hasCombinatorCrossingTreeBoundaryA t(index); 113 m_crossesTreeBoundary |= selectorList.hasCombinatorCrossingTreeBoundaryA t(index);
115 } 114 }
116 } 115 }
117 116
118 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const 117 inline bool SelectorDataList::selectorMatches(const CSSSelector& selector, Eleme nt& element, const ContainerNode& rootNode) const
119 { 118 {
120 if (selectorData.isFastCheckable && !element.isSVGElement()) {
121 SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, e lement);
122 if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::V isitedMatchDisabled))
123 return false;
124 return selectorCheckerFastPath.matches();
125 }
126
127 SelectorChecker selectorChecker(element.document(), SelectorChecker::Queryin gRules); 119 SelectorChecker selectorChecker(element.document(), SelectorChecker::Queryin gRules);
128 SelectorChecker::SelectorCheckingContext selectorCheckingContext(selectorDat a.selector, &element, SelectorChecker::VisitedMatchDisabled); 120 SelectorChecker::SelectorCheckingContext selectorCheckingContext(selector, & element, SelectorChecker::VisitedMatchDisabled);
129 selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTre eScope; 121 selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTre eScope;
130 selectorCheckingContext.scope = !rootNode.isDocumentNode() ? &rootNode : 0; 122 selectorCheckingContext.scope = !rootNode.isDocumentNode() ? &rootNode : 0;
131 return selectorChecker.match(selectorCheckingContext, DOMSiblingTraversalStr ategy()) == SelectorChecker::SelectorMatches; 123 return selectorChecker.match(selectorCheckingContext, DOMSiblingTraversalStr ategy()) == SelectorChecker::SelectorMatches;
132 } 124 }
133 125
134 bool SelectorDataList::matches(Element& targetElement) const 126 bool SelectorDataList::matches(Element& targetElement) const
135 { 127 {
136 unsigned selectorCount = m_selectors.size(); 128 unsigned selectorCount = m_selectors.size();
137 for (unsigned i = 0; i < selectorCount; ++i) { 129 for (unsigned i = 0; i < selectorCount; ++i) {
138 if (selectorMatches(m_selectors[i], targetElement, targetElement)) 130 if (selectorMatches(*m_selectors[i], targetElement, targetElement))
139 return true; 131 return true;
140 } 132 }
141 133
142 return false; 134 return false;
143 } 135 }
144 136
145 PassRefPtr<NodeList> SelectorDataList::queryAll(ContainerNode& rootNode) const 137 PassRefPtr<NodeList> SelectorDataList::queryAll(ContainerNode& rootNode) const
146 { 138 {
147 Vector<RefPtr<Node> > result; 139 Vector<RefPtr<Node> > result;
148 execute<AllElementsSelectorQueryTrait>(rootNode, result); 140 execute<AllElementsSelectorQueryTrait>(rootNode, result);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 template <typename SelectorQueryTrait> 200 template <typename SelectorQueryTrait>
209 void SelectorDataList::findTraverseRootsAndExecute(ContainerNode& rootNode, type name SelectorQueryTrait::OutputType& output) const 201 void SelectorDataList::findTraverseRootsAndExecute(ContainerNode& rootNode, type name SelectorQueryTrait::OutputType& output) const
210 { 202 {
211 // We need to return the matches in document order. To use id lookup while t here is possiblity of multiple matches 203 // We need to return the matches in document order. To use id lookup while t here is possiblity of multiple matches
212 // we would need to sort the results. For now, just traverse the document in that case. 204 // we would need to sort the results. For now, just traverse the document in that case.
213 ASSERT(m_selectors.size() == 1); 205 ASSERT(m_selectors.size() == 1);
214 206
215 bool isRightmostSelector = true; 207 bool isRightmostSelector = true;
216 bool startFromParent = false; 208 bool startFromParent = false;
217 209
218 for (const CSSSelector* selector = &m_selectors[0].selector; selector; selec tor = selector->tagHistory()) { 210 for (const CSSSelector* selector = m_selectors[0]; selector; selector = sele ctor->tagHistory()) {
219 if (selector->m_match == CSSSelector::Id && !rootNode.document().contain sMultipleElementsWithId(selector->value())) { 211 if (selector->m_match == CSSSelector::Id && !rootNode.document().contain sMultipleElementsWithId(selector->value())) {
220 Element* element = rootNode.treeScope().getElementById(selector->val ue()); 212 Element* element = rootNode.treeScope().getElementById(selector->val ue());
221 ContainerNode* adjustedNode = &rootNode; 213 ContainerNode* adjustedNode = &rootNode;
222 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf (&rootNode))) 214 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf (&rootNode)))
223 adjustedNode = element; 215 adjustedNode = element;
224 else if (!element || isRightmostSelector) 216 else if (!element || isRightmostSelector)
225 adjustedNode = 0; 217 adjustedNode = 0;
226 if (isRightmostSelector) { 218 if (isRightmostSelector) {
227 executeForTraverseRoot<SelectorQueryTrait>(m_selectors[0], adjus tedNode, MatchesTraverseRoots, rootNode, output); 219 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], adju stedNode, MatchesTraverseRoots, rootNode, output);
228 return; 220 return;
229 } 221 }
230 222
231 if (startFromParent && adjustedNode) 223 if (startFromParent && adjustedNode)
232 adjustedNode = adjustedNode->parentNode(); 224 adjustedNode = adjustedNode->parentNode();
233 225
234 executeForTraverseRoot<SelectorQueryTrait>(m_selectors[0], adjustedN ode, DoesNotMatchTraverseRoots, rootNode, output); 226 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], adjusted Node, DoesNotMatchTraverseRoots, rootNode, output);
235 return; 227 return;
236 } 228 }
237 229
238 // If we have both CSSSelector::Id and CSSSelector::Class at the same ti me, we should use Id 230 // If we have both CSSSelector::Id and CSSSelector::Class at the same ti me, we should use Id
239 // to find traverse root. 231 // to find traverse root.
240 if (!SelectorQueryTrait::shouldOnlyMatchFirstElement && !startFromParent && selector->m_match == CSSSelector::Class) { 232 if (!SelectorQueryTrait::shouldOnlyMatchFirstElement && !startFromParent && selector->m_match == CSSSelector::Class) {
241 if (isRightmostSelector) { 233 if (isRightmostSelector) {
242 ClassElementList<AllElements> traverseRoots(rootNode, selector-> value()); 234 ClassElementList<AllElements> traverseRoots(rootNode, selector-> value());
243 executeForTraverseRoots<SelectorQueryTrait>(m_selectors[0], trav erseRoots, MatchesTraverseRoots, rootNode, output); 235 executeForTraverseRoots<SelectorQueryTrait>(*m_selectors[0], tra verseRoots, MatchesTraverseRoots, rootNode, output);
244 return; 236 return;
245 } 237 }
246 // Since there exists some ancestor element which has the class name , we need to see all children of rootNode. 238 // Since there exists some ancestor element which has the class name , we need to see all children of rootNode.
247 if (ancestorHasClassName(rootNode, selector->value())) { 239 if (ancestorHasClassName(rootNode, selector->value())) {
248 executeForTraverseRoot<SelectorQueryTrait>(m_selectors[0], &root Node, DoesNotMatchTraverseRoots, rootNode, output); 240 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], &roo tNode, DoesNotMatchTraverseRoots, rootNode, output);
249 return; 241 return;
250 } 242 }
251 243
252 ClassElementList<OnlyRoots> traverseRoots(rootNode, selector->value( )); 244 ClassElementList<OnlyRoots> traverseRoots(rootNode, selector->value( ));
253 executeForTraverseRoots<SelectorQueryTrait>(m_selectors[0], traverse Roots, DoesNotMatchTraverseRoots, rootNode, output); 245 executeForTraverseRoots<SelectorQueryTrait>(*m_selectors[0], travers eRoots, DoesNotMatchTraverseRoots, rootNode, output);
254 return; 246 return;
255 } 247 }
256 248
257 if (selector->relation() == CSSSelector::SubSelector) 249 if (selector->relation() == CSSSelector::SubSelector)
258 continue; 250 continue;
259 isRightmostSelector = false; 251 isRightmostSelector = false;
260 if (selector->relation() == CSSSelector::DirectAdjacent || selector->rel ation() == CSSSelector::IndirectAdjacent) 252 if (selector->relation() == CSSSelector::DirectAdjacent || selector->rel ation() == CSSSelector::IndirectAdjacent)
261 startFromParent = true; 253 startFromParent = true;
262 else 254 else
263 startFromParent = false; 255 startFromParent = false;
264 } 256 }
265 257
266 executeForTraverseRoot<SelectorQueryTrait>(m_selectors[0], &rootNode, DoesNo tMatchTraverseRoots, rootNode, output); 258 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], &rootNode, DoesN otMatchTraverseRoots, rootNode, output);
267 } 259 }
268 260
269 template <typename SelectorQueryTrait> 261 template <typename SelectorQueryTrait>
270 void SelectorDataList::executeForTraverseRoot(const SelectorData& selector, Cont ainerNode* traverseRoot, MatchTraverseRootState matchTraverseRoot, ContainerNode & rootNode, typename SelectorQueryTrait::OutputType& output) const 262 void SelectorDataList::executeForTraverseRoot(const CSSSelector& selector, Conta inerNode* traverseRoot, MatchTraverseRootState matchTraverseRoot, ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
271 { 263 {
272 if (!traverseRoot) 264 if (!traverseRoot)
273 return; 265 return;
274 266
275 if (matchTraverseRoot) { 267 if (matchTraverseRoot) {
276 if (selectorMatches(selector, toElement(*traverseRoot), rootNode)) 268 if (selectorMatches(selector, toElement(*traverseRoot), rootNode))
277 SelectorQueryTrait::appendElement(output, toElement(*traverseRoot)); 269 SelectorQueryTrait::appendElement(output, toElement(*traverseRoot));
278 return; 270 return;
279 } 271 }
280 272
281 for (Element* element = ElementTraversal::firstWithin(*traverseRoot); elemen t; element = ElementTraversal::next(*element, traverseRoot)) { 273 for (Element* element = ElementTraversal::firstWithin(*traverseRoot); elemen t; element = ElementTraversal::next(*element, traverseRoot)) {
282 if (selectorMatches(selector, *element, rootNode)) { 274 if (selectorMatches(selector, *element, rootNode)) {
283 SelectorQueryTrait::appendElement(output, *element); 275 SelectorQueryTrait::appendElement(output, *element);
284 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 276 if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
285 return; 277 return;
286 } 278 }
287 } 279 }
288 } 280 }
289 281
290 template <typename SelectorQueryTrait, typename SimpleElementListType> 282 template <typename SelectorQueryTrait, typename SimpleElementListType>
291 void SelectorDataList::executeForTraverseRoots(const SelectorData& selector, Sim pleElementListType& traverseRoots, MatchTraverseRootState matchTraverseRoots, Co ntainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const 283 void SelectorDataList::executeForTraverseRoots(const CSSSelector& selector, Simp leElementListType& traverseRoots, MatchTraverseRootState matchTraverseRoots, Con tainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const
292 { 284 {
293 if (traverseRoots.isEmpty()) 285 if (traverseRoots.isEmpty())
294 return; 286 return;
295 287
296 if (matchTraverseRoots) { 288 if (matchTraverseRoots) {
297 while (!traverseRoots.isEmpty()) { 289 while (!traverseRoots.isEmpty()) {
298 Element& element = *traverseRoots.next(); 290 Element& element = *traverseRoots.next();
299 if (selectorMatches(selector, element, rootNode)) { 291 if (selectorMatches(selector, element, rootNode)) {
300 SelectorQueryTrait::appendElement(output, element); 292 SelectorQueryTrait::appendElement(output, element);
301 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 293 if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
(...skipping 12 matching lines...) Expand all
314 return; 306 return;
315 } 307 }
316 } 308 }
317 } 309 }
318 } 310 }
319 311
320 template <typename SelectorQueryTrait> 312 template <typename SelectorQueryTrait>
321 bool SelectorDataList::selectorListMatches(ContainerNode& rootNode, Element& ele ment, typename SelectorQueryTrait::OutputType& output) const 313 bool SelectorDataList::selectorListMatches(ContainerNode& rootNode, Element& ele ment, typename SelectorQueryTrait::OutputType& output) const
322 { 314 {
323 for (unsigned i = 0; i < m_selectors.size(); ++i) { 315 for (unsigned i = 0; i < m_selectors.size(); ++i) {
324 if (selectorMatches(m_selectors[i], element, rootNode)) { 316 if (selectorMatches(*m_selectors[i], element, rootNode)) {
325 SelectorQueryTrait::appendElement(output, element); 317 SelectorQueryTrait::appendElement(output, element);
326 return true; 318 return true;
327 } 319 }
328 } 320 }
329 return false; 321 return false;
330 } 322 }
331 323
332 template <typename SelectorQueryTrait> 324 template <typename SelectorQueryTrait>
333 void SelectorDataList::executeSlow(ContainerNode& rootNode, typename SelectorQue ryTrait::OutputType& output) const 325 void SelectorDataList::executeSlow(ContainerNode& rootNode, typename SelectorQue ryTrait::OutputType& output) const
334 { 326 {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 if (!canUseFastQuery(rootNode)) { 405 if (!canUseFastQuery(rootNode)) {
414 if (m_crossesTreeBoundary) 406 if (m_crossesTreeBoundary)
415 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output ); 407 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output );
416 else 408 else
417 executeSlow<SelectorQueryTrait>(rootNode, output); 409 executeSlow<SelectorQueryTrait>(rootNode, output);
418 return; 410 return;
419 } 411 }
420 412
421 ASSERT(m_selectors.size() == 1); 413 ASSERT(m_selectors.size() == 1);
422 414
423 const SelectorData& selector = m_selectors[0]; 415 const CSSSelector& selector = *m_selectors[0];
424 const CSSSelector& firstSelector = selector.selector; 416 const CSSSelector& firstSelector = selector;
425 417
426 // Fast path for querySelector*('#id'), querySelector*('tag#id'). 418 // Fast path for querySelector*('#id'), querySelector*('tag#id').
427 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { 419 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) {
428 const AtomicString& idToMatch = idSelector->value(); 420 const AtomicString& idToMatch = idSelector->value();
429 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) { 421 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) {
430 const Vector<Element*>& elements = rootNode.treeScope().getAllElemen tsById(idToMatch); 422 const Vector<Element*>& elements = rootNode.treeScope().getAllElemen tsById(idToMatch);
431 size_t count = elements.size(); 423 size_t count = elements.size();
432 for (size_t i = 0; i < count; ++i) { 424 for (size_t i = 0; i < count; ++i) {
433 Element& element = *elements[i]; 425 Element& element = *elements[i];
434 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootN ode))) 426 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootN ode)))
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 m_entries.add(selectors, selectorQuery.release()); 509 m_entries.add(selectors, selectorQuery.release());
518 return rawSelectorQuery; 510 return rawSelectorQuery;
519 } 511 }
520 512
521 void SelectorQueryCache::invalidate() 513 void SelectorQueryCache::invalidate()
522 { 514 {
523 m_entries.clear(); 515 m_entries.clear();
524 } 516 }
525 517
526 } 518 }
OLDNEW
« no previous file with comments | « Source/core/dom/SelectorQuery.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698