OLD | NEW |
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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 return false; | 246 return false; |
247 | 247 |
248 for (Element* element = &toElement(rootNode); element; | 248 for (Element* element = &toElement(rootNode); element; |
249 element = element->parentElement()) { | 249 element = element->parentElement()) { |
250 if (element->hasClass() && element->classNames().contains(className)) | 250 if (element->hasClass() && element->classNames().contains(className)) |
251 return true; | 251 return true; |
252 } | 252 } |
253 return false; | 253 return false; |
254 } | 254 } |
255 | 255 |
256 // If returns true, traversalRoots has the elements that may match the selector
query. | 256 // If returns true, traversalRoots has the elements that may match the selector |
| 257 // query. |
257 // | 258 // |
258 // If returns false, traversalRoots has the rootNode parameter or descendants of
rootNode representing | 259 // If returns false, traversalRoots has the rootNode parameter or descendants of |
259 // the subtree for which we can limit the querySelector traversal. | 260 // rootNode representing the subtree for which we can limit the querySelector |
| 261 // traversal. |
260 // | 262 // |
261 // The travseralRoots may be empty, regardless of the returned bool value, if th
is method finds that the selectors won't | 263 // The travseralRoots may be empty, regardless of the returned bool value, if |
262 // match any element. | 264 // this method finds that the selectors won't match any element. |
263 template <typename SelectorQueryTrait> | 265 template <typename SelectorQueryTrait> |
264 void SelectorDataList::findTraverseRootsAndExecute( | 266 void SelectorDataList::findTraverseRootsAndExecute( |
265 ContainerNode& rootNode, | 267 ContainerNode& rootNode, |
266 typename SelectorQueryTrait::OutputType& output) const { | 268 typename SelectorQueryTrait::OutputType& output) const { |
267 // We need to return the matches in document order. To use id lookup while the
re is possiblity of multiple matches | 269 // We need to return the matches in document order. To use id lookup while |
268 // we would need to sort the results. For now, just traverse the document in t
hat case. | 270 // there is possiblity of multiple matches we would need to sort the |
| 271 // results. For now, just traverse the document in that case. |
269 DCHECK_EQ(m_selectors.size(), 1u); | 272 DCHECK_EQ(m_selectors.size(), 1u); |
270 | 273 |
271 bool isRightmostSelector = true; | 274 bool isRightmostSelector = true; |
272 bool startFromParent = false; | 275 bool startFromParent = false; |
273 | 276 |
274 for (const CSSSelector* selector = m_selectors[0]; selector; | 277 for (const CSSSelector* selector = m_selectors[0]; selector; |
275 selector = selector->tagHistory()) { | 278 selector = selector->tagHistory()) { |
276 if (selector->match() == CSSSelector::Id && rootNode.isInTreeScope() && | 279 if (selector->match() == CSSSelector::Id && rootNode.isInTreeScope() && |
277 !rootNode.containingTreeScope().containsMultipleElementsWithId( | 280 !rootNode.containingTreeScope().containsMultipleElementsWithId( |
278 selector->value())) { | 281 selector->value())) { |
(...skipping 14 matching lines...) Expand all Loading... |
293 | 296 |
294 if (startFromParent && adjustedNode) | 297 if (startFromParent && adjustedNode) |
295 adjustedNode = adjustedNode->parentNode(); | 298 adjustedNode = adjustedNode->parentNode(); |
296 | 299 |
297 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], adjustedNode, | 300 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], adjustedNode, |
298 DoesNotMatchTraverseRoots, | 301 DoesNotMatchTraverseRoots, |
299 rootNode, output); | 302 rootNode, output); |
300 return; | 303 return; |
301 } | 304 } |
302 | 305 |
303 // If we have both CSSSelector::Id and CSSSelector::Class at the same time,
we should use Id | 306 // If we have both CSSSelector::Id and CSSSelector::Class at the same time, |
304 // to find traverse root. | 307 // we should use Id to find traverse root. |
305 if (!SelectorQueryTrait::shouldOnlyMatchFirstElement && !startFromParent && | 308 if (!SelectorQueryTrait::shouldOnlyMatchFirstElement && !startFromParent && |
306 selector->match() == CSSSelector::Class) { | 309 selector->match() == CSSSelector::Class) { |
307 if (isRightmostSelector) { | 310 if (isRightmostSelector) { |
308 ClassElementList<AllElements> traverseRoots(rootNode, | 311 ClassElementList<AllElements> traverseRoots(rootNode, |
309 selector->value()); | 312 selector->value()); |
310 executeForTraverseRoots<SelectorQueryTrait>( | 313 executeForTraverseRoots<SelectorQueryTrait>( |
311 *m_selectors[0], traverseRoots, MatchesTraverseRoots, rootNode, | 314 *m_selectors[0], traverseRoots, MatchesTraverseRoots, rootNode, |
312 output); | 315 output); |
313 return; | 316 return; |
314 } | 317 } |
315 // Since there exists some ancestor element which has the class name, we n
eed to see all children of rootNode. | 318 // Since there exists some ancestor element which has the class name, we |
| 319 // need to see all children of rootNode. |
316 if (ancestorHasClassName(rootNode, selector->value())) { | 320 if (ancestorHasClassName(rootNode, selector->value())) { |
317 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], &rootNode, | 321 executeForTraverseRoot<SelectorQueryTrait>(*m_selectors[0], &rootNode, |
318 DoesNotMatchTraverseRoots, | 322 DoesNotMatchTraverseRoots, |
319 rootNode, output); | 323 rootNode, output); |
320 return; | 324 return; |
321 } | 325 } |
322 | 326 |
323 ClassElementList<OnlyRoots> traverseRoots(rootNode, selector->value()); | 327 ClassElementList<OnlyRoots> traverseRoots(rootNode, selector->value()); |
324 executeForTraverseRoots<SelectorQueryTrait>( | 328 executeForTraverseRoots<SelectorQueryTrait>( |
325 *m_selectors[0], traverseRoots, DoesNotMatchTraverseRoots, rootNode, | 329 *m_selectors[0], traverseRoots, DoesNotMatchTraverseRoots, rootNode, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 void SelectorDataList::executeSlow( | 422 void SelectorDataList::executeSlow( |
419 ContainerNode& rootNode, | 423 ContainerNode& rootNode, |
420 typename SelectorQueryTrait::OutputType& output) const { | 424 typename SelectorQueryTrait::OutputType& output) const { |
421 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { | 425 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { |
422 if (selectorListMatches<SelectorQueryTrait>(rootNode, element, output) && | 426 if (selectorListMatches<SelectorQueryTrait>(rootNode, element, output) && |
423 SelectorQueryTrait::shouldOnlyMatchFirstElement) | 427 SelectorQueryTrait::shouldOnlyMatchFirstElement) |
424 return; | 428 return; |
425 } | 429 } |
426 } | 430 } |
427 | 431 |
428 // FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTr
aversingShadowTree, | 432 // FIXME: Move the following helper functions, authorShadowRootOf, |
429 // nextTraversingShadowTree to the best place, e.g. NodeTraversal. | 433 // firstWithinTraversingShadowTree, nextTraversingShadowTree to the best place, |
| 434 // e.g. NodeTraversal. |
430 static ShadowRoot* authorShadowRootOf(const ContainerNode& node) { | 435 static ShadowRoot* authorShadowRootOf(const ContainerNode& node) { |
431 if (!node.isElementNode() || !isShadowHost(&node)) | 436 if (!node.isElementNode() || !isShadowHost(&node)) |
432 return nullptr; | 437 return nullptr; |
433 | 438 |
434 ElementShadow* shadow = toElement(node).shadow(); | 439 ElementShadow* shadow = toElement(node).shadow(); |
435 DCHECK(shadow); | 440 DCHECK(shadow); |
436 for (ShadowRoot* shadowRoot = &shadow->oldestShadowRoot(); shadowRoot; | 441 for (ShadowRoot* shadowRoot = &shadow->oldestShadowRoot(); shadowRoot; |
437 shadowRoot = shadowRoot->youngerShadowRoot()) { | 442 shadowRoot = shadowRoot->youngerShadowRoot()) { |
438 if (shadowRoot->type() == ShadowRootType::V0 || | 443 if (shadowRoot->type() == ShadowRootType::V0 || |
439 shadowRoot->type() == ShadowRootType::Open) | 444 shadowRoot->type() == ShadowRootType::Open) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 } | 532 } |
528 return; | 533 return; |
529 } | 534 } |
530 | 535 |
531 DCHECK_EQ(m_selectors.size(), 1u); | 536 DCHECK_EQ(m_selectors.size(), 1u); |
532 DCHECK(!rootNode.document().inQuirksMode()); | 537 DCHECK(!rootNode.document().inQuirksMode()); |
533 | 538 |
534 const CSSSelector& selector = *m_selectors[0]; | 539 const CSSSelector& selector = *m_selectors[0]; |
535 const CSSSelector& firstSelector = selector; | 540 const CSSSelector& firstSelector = selector; |
536 | 541 |
537 // Fast path for querySelector*('#id'), querySelector*('tag#id'), querySelecto
r*('tag[id=example]'). | 542 // Fast path for querySelector*('#id'), querySelector*('tag#id'), |
| 543 // querySelector*('tag[id=example]'). |
538 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { | 544 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { |
539 const AtomicString& idToMatch = idSelector->value(); | 545 const AtomicString& idToMatch = idSelector->value(); |
540 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) { | 546 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) { |
541 const HeapVector<Member<Element>>& elements = | 547 const HeapVector<Member<Element>>& elements = |
542 rootNode.treeScope().getAllElementsById(idToMatch); | 548 rootNode.treeScope().getAllElementsById(idToMatch); |
543 size_t count = elements.size(); | 549 size_t count = elements.size(); |
544 for (size_t i = 0; i < count; ++i) { | 550 for (size_t i = 0; i < count; ++i) { |
545 Element& element = *elements[i]; | 551 Element& element = *elements[i]; |
546 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootNode))) | 552 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootNode))) |
547 continue; | 553 continue; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 | 643 |
638 return m_entries.add(selectors, SelectorQuery::adopt(std::move(selectorList))) | 644 return m_entries.add(selectors, SelectorQuery::adopt(std::move(selectorList))) |
639 .storedValue->value.get(); | 645 .storedValue->value.get(); |
640 } | 646 } |
641 | 647 |
642 void SelectorQueryCache::invalidate() { | 648 void SelectorQueryCache::invalidate() { |
643 m_entries.clear(); | 649 m_entries.clear(); |
644 } | 650 } |
645 | 651 |
646 } // namespace blink | 652 } // namespace blink |
OLD | NEW |