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

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

Issue 149513011: Pass around CSSSelector by reference instead of pointer (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 10 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
« no previous file with comments | « Source/core/dom/SelectorQuery.h ('k') | Source/core/dom/shadow/ElementShadow.cpp » ('j') | 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 const AtomicString& m_className; 94 const AtomicString& m_className;
95 ContainerNode& m_rootNode; 95 ContainerNode& m_rootNode;
96 Element* m_currentElement; 96 Element* m_currentElement;
97 }; 97 };
98 98
99 void SelectorDataList::initialize(const CSSSelectorList& selectorList) 99 void SelectorDataList::initialize(const CSSSelectorList& selectorList)
100 { 100 {
101 ASSERT(m_selectors.isEmpty()); 101 ASSERT(m_selectors.isEmpty());
102 102
103 unsigned selectorCount = 0; 103 unsigned selectorCount = 0;
104 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) 104 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector))
105 selectorCount++; 105 selectorCount++;
106 106
107 m_selectors.reserveInitialCapacity(selectorCount); 107 m_selectors.reserveInitialCapacity(selectorCount);
108 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) 108 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector))
109 m_selectors.uncheckedAppend(SelectorData(selector, SelectorCheckerFastPa th::canUse(selector))); 109 m_selectors.uncheckedAppend(SelectorData(*selector, SelectorCheckerFastP ath::canUse(*selector)));
110 } 110 }
111 111
112 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const 112 inline bool SelectorDataList::selectorMatches(const SelectorData& selectorData, Element& element, const ContainerNode& rootNode) const
113 { 113 {
114 if (selectorData.isFastCheckable && !element.isSVGElement()) { 114 if (selectorData.isFastCheckable && !element.isSVGElement()) {
115 SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, e lement); 115 SelectorCheckerFastPath selectorCheckerFastPath(selectorData.selector, e lement);
116 if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::V isitedMatchDisabled)) 116 if (!selectorCheckerFastPath.matchesRightmostSelector(SelectorChecker::V isitedMatchDisabled))
117 return false; 117 return false;
118 return selectorCheckerFastPath.matches(); 118 return selectorCheckerFastPath.matches();
119 } 119 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 // the subtree for which we can limit the querySelector traversal. 198 // the subtree for which we can limit the querySelector traversal.
199 // 199 //
200 // The travseralRoots may be empty, regardless of the returned bool value, if th is method finds that the selectors won't 200 // The travseralRoots may be empty, regardless of the returned bool value, if th is method finds that the selectors won't
201 // match any element. 201 // match any element.
202 template <typename SelectorQueryTrait> 202 template <typename SelectorQueryTrait>
203 void SelectorDataList::findTraverseRootsAndExecute(ContainerNode& rootNode, type name SelectorQueryTrait::OutputType& output) const 203 void SelectorDataList::findTraverseRootsAndExecute(ContainerNode& rootNode, type name SelectorQueryTrait::OutputType& output) const
204 { 204 {
205 // We need to return the matches in document order. To use id lookup while t here is possiblity of multiple matches 205 // We need to return the matches in document order. To use id lookup while t here is possiblity of multiple matches
206 // we would need to sort the results. For now, just traverse the document in that case. 206 // we would need to sort the results. For now, just traverse the document in that case.
207 ASSERT(m_selectors.size() == 1); 207 ASSERT(m_selectors.size() == 1);
208 ASSERT(m_selectors[0].selector);
209 208
210 bool isRightmostSelector = true; 209 bool isRightmostSelector = true;
211 bool startFromParent = false; 210 bool startFromParent = false;
212 211
213 for (const CSSSelector* selector = m_selectors[0].selector; selector; select or = selector->tagHistory()) { 212 for (const CSSSelector* selector = &m_selectors[0].selector; selector; selec tor = selector->tagHistory()) {
214 if (selector->m_match == CSSSelector::Id && !rootNode.document().contain sMultipleElementsWithId(selector->value())) { 213 if (selector->m_match == CSSSelector::Id && !rootNode.document().contain sMultipleElementsWithId(selector->value())) {
215 Element* element = rootNode.treeScope().getElementById(selector->val ue()); 214 Element* element = rootNode.treeScope().getElementById(selector->val ue());
216 ContainerNode* adjustedNode = &rootNode; 215 ContainerNode* adjustedNode = &rootNode;
217 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf (&rootNode))) 216 if (element && (isTreeScopeRoot(rootNode) || element->isDescendantOf (&rootNode)))
218 adjustedNode = element; 217 adjustedNode = element;
219 else if (!element || isRightmostSelector) 218 else if (!element || isRightmostSelector)
220 adjustedNode = 0; 219 adjustedNode = 0;
221 if (isRightmostSelector) { 220 if (isRightmostSelector) {
222 executeForTraverseRoot<SelectorQueryTrait>(m_selectors[0], adjus tedNode, MatchesTraverseRoots, rootNode, output); 221 executeForTraverseRoot<SelectorQueryTrait>(m_selectors[0], adjus tedNode, MatchesTraverseRoots, rootNode, output);
223 return; 222 return;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 if (selectorMatches(m_selectors[i], *element, rootNode)) { 321 if (selectorMatches(m_selectors[i], *element, rootNode)) {
323 SelectorQueryTrait::appendElement(output, *element); 322 SelectorQueryTrait::appendElement(output, *element);
324 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 323 if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
325 return; 324 return;
326 break; 325 break;
327 } 326 }
328 } 327 }
329 } 328 }
330 } 329 }
331 330
332 const CSSSelector* SelectorDataList::selectorForIdLookup(const CSSSelector* firs tSelector) const 331 const CSSSelector* SelectorDataList::selectorForIdLookup(const CSSSelector& firs tSelector) const
333 { 332 {
334 for (const CSSSelector* selector = firstSelector; selector; selector = selec tor->tagHistory()) { 333 for (const CSSSelector* selector = &firstSelector; selector; selector = sele ctor->tagHistory()) {
335 if (selector->m_match == CSSSelector::Id) 334 if (selector->m_match == CSSSelector::Id)
336 return selector; 335 return selector;
337 if (selector->relation() != CSSSelector::SubSelector) 336 if (selector->relation() != CSSSelector::SubSelector)
338 break; 337 break;
339 } 338 }
340 return 0; 339 return 0;
341 } 340 }
342 341
343 template <typename SelectorQueryTrait> 342 template <typename SelectorQueryTrait>
344 void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTr ait::OutputType& output) const 343 void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTr ait::OutputType& output) const
345 { 344 {
346 if (!canUseFastQuery(rootNode)) { 345 if (!canUseFastQuery(rootNode)) {
347 executeSlow<SelectorQueryTrait>(rootNode, output); 346 executeSlow<SelectorQueryTrait>(rootNode, output);
348 return; 347 return;
349 } 348 }
350 349
351 ASSERT(m_selectors.size() == 1); 350 ASSERT(m_selectors.size() == 1);
352 ASSERT(m_selectors[0].selector);
353 351
354 const SelectorData& selector = m_selectors[0]; 352 const SelectorData& selector = m_selectors[0];
355 const CSSSelector* firstSelector = selector.selector; 353 const CSSSelector& firstSelector = selector.selector;
356 354
357 // Fast path for querySelector*('#id'), querySelector*('tag#id'). 355 // Fast path for querySelector*('#id'), querySelector*('tag#id').
358 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { 356 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) {
359 const AtomicString& idToMatch = idSelector->value(); 357 const AtomicString& idToMatch = idSelector->value();
360 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) { 358 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) {
361 const Vector<Element*>& elements = rootNode.treeScope().getAllElemen tsById(idToMatch); 359 const Vector<Element*>& elements = rootNode.treeScope().getAllElemen tsById(idToMatch);
362 size_t count = elements.size(); 360 size_t count = elements.size();
363 for (size_t i = 0; i < count; ++i) { 361 for (size_t i = 0; i < count; ++i) {
364 Element& element = *elements[i]; 362 Element& element = *elements[i];
365 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootN ode))) 363 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootN ode)))
366 continue; 364 continue;
367 if (selectorMatches(selector, element, rootNode)) { 365 if (selectorMatches(selector, element, rootNode)) {
368 SelectorQueryTrait::appendElement(output, element); 366 SelectorQueryTrait::appendElement(output, element);
369 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) 367 if (SelectorQueryTrait::shouldOnlyMatchFirstElement)
370 return; 368 return;
371 } 369 }
372 } 370 }
373 return; 371 return;
374 } 372 }
375 Element* element = rootNode.treeScope().getElementById(idToMatch); 373 Element* element = rootNode.treeScope().getElementById(idToMatch);
376 if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(& rootNode))) 374 if (!element || !(isTreeScopeRoot(rootNode) || element->isDescendantOf(& rootNode)))
377 return; 375 return;
378 if (selectorMatches(selector, *element, rootNode)) 376 if (selectorMatches(selector, *element, rootNode))
379 SelectorQueryTrait::appendElement(output, *element); 377 SelectorQueryTrait::appendElement(output, *element);
380 return; 378 return;
381 } 379 }
382 380
383 if (!firstSelector->tagHistory()) { 381 if (!firstSelector.tagHistory()) {
384 // Fast path for querySelector*('.foo'), and querySelector*('div'). 382 // Fast path for querySelector*('.foo'), and querySelector*('div').
385 switch (firstSelector->m_match) { 383 switch (firstSelector.m_match) {
386 case CSSSelector::Class: 384 case CSSSelector::Class:
387 collectElementsByClassName<SelectorQueryTrait>(rootNode, firstSelect or->value(), output); 385 collectElementsByClassName<SelectorQueryTrait>(rootNode, firstSelect or.value(), output);
388 return; 386 return;
389 case CSSSelector::Tag: 387 case CSSSelector::Tag:
390 collectElementsByTagName<SelectorQueryTrait>(rootNode, firstSelector ->tagQName(), output); 388 collectElementsByTagName<SelectorQueryTrait>(rootNode, firstSelector .tagQName(), output);
391 return; 389 return;
392 default: 390 default:
393 break; // If we need another fast path, add here. 391 break; // If we need another fast path, add here.
394 } 392 }
395 } 393 }
396 394
397 findTraverseRootsAndExecute<SelectorQueryTrait>(rootNode, output); 395 findTraverseRootsAndExecute<SelectorQueryTrait>(rootNode, output);
398 } 396 }
399 397
400 SelectorQuery::SelectorQuery(const CSSSelectorList& selectorList) 398 SelectorQuery::SelectorQuery(const CSSSelectorList& selectorList)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 m_entries.add(selectors, selectorQuery.release()); 446 m_entries.add(selectors, selectorQuery.release());
449 return rawSelectorQuery; 447 return rawSelectorQuery;
450 } 448 }
451 449
452 void SelectorQueryCache::invalidate() 450 void SelectorQueryCache::invalidate()
453 { 451 {
454 m_entries.clear(); 452 m_entries.clear();
455 } 453 }
456 454
457 } 455 }
OLDNEW
« no previous file with comments | « Source/core/dom/SelectorQuery.h ('k') | Source/core/dom/shadow/ElementShadow.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698