| 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 |