| 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 return element; | 97 return element; |
| 98 } | 98 } |
| 99 return nullptr; | 99 return nullptr; |
| 100 } | 100 } |
| 101 | 101 |
| 102 const AtomicString& m_className; | 102 const AtomicString& m_className; |
| 103 Member<ContainerNode> m_rootNode; | 103 Member<ContainerNode> m_rootNode; |
| 104 Member<Element> m_currentElement; | 104 Member<Element> m_currentElement; |
| 105 }; | 105 }; |
| 106 | 106 |
| 107 void SelectorDataList::initialize(const CSSSelectorList& selectorList) { | 107 inline bool selectorMatches(const CSSSelector& selector, |
| 108 DCHECK(m_selectors.isEmpty()); | 108 Element& element, |
| 109 | 109 const ContainerNode& rootNode) { |
| 110 unsigned selectorCount = 0; | |
| 111 for (const CSSSelector* selector = selectorList.first(); selector; | |
| 112 selector = CSSSelectorList::next(*selector)) | |
| 113 selectorCount++; | |
| 114 | |
| 115 m_usesDeepCombinatorOrShadowPseudo = false; | |
| 116 m_needsUpdatedDistribution = false; | |
| 117 m_selectors.reserveInitialCapacity(selectorCount); | |
| 118 for (const CSSSelector* selector = selectorList.first(); selector; | |
| 119 selector = CSSSelectorList::next(*selector)) { | |
| 120 if (selector->matchesPseudoElement()) | |
| 121 continue; | |
| 122 m_selectors.uncheckedAppend(selector); | |
| 123 m_usesDeepCombinatorOrShadowPseudo |= | |
| 124 selector->hasDeepCombinatorOrShadowPseudo(); | |
| 125 m_needsUpdatedDistribution |= selector->needsUpdatedDistribution(); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 inline bool SelectorDataList::selectorMatches( | |
| 130 const CSSSelector& selector, | |
| 131 Element& element, | |
| 132 const ContainerNode& rootNode) const { | |
| 133 SelectorChecker::Init init; | 110 SelectorChecker::Init init; |
| 134 init.mode = SelectorChecker::QueryingRules; | 111 init.mode = SelectorChecker::QueryingRules; |
| 135 SelectorChecker checker(init); | 112 SelectorChecker checker(init); |
| 136 SelectorChecker::SelectorCheckingContext context( | 113 SelectorChecker::SelectorCheckingContext context( |
| 137 &element, SelectorChecker::VisitedMatchDisabled); | 114 &element, SelectorChecker::VisitedMatchDisabled); |
| 138 context.selector = &selector; | 115 context.selector = &selector; |
| 139 context.scope = &rootNode; | 116 context.scope = &rootNode; |
| 140 return checker.match(context); | 117 return checker.match(context); |
| 141 } | 118 } |
| 142 | 119 |
| 143 bool SelectorDataList::matches(Element& targetElement) const { | 120 bool SelectorQuery::matches(Element& targetElement) const { |
| 144 if (m_needsUpdatedDistribution) | 121 if (m_needsUpdatedDistribution) |
| 145 targetElement.updateDistribution(); | 122 targetElement.updateDistribution(); |
| 146 | 123 |
| 147 for (const auto& selector : m_selectors) { | 124 for (const auto& selector : m_selectors) { |
| 148 if (selectorMatches(*selector, targetElement, targetElement)) | 125 if (selectorMatches(*selector, targetElement, targetElement)) |
| 149 return true; | 126 return true; |
| 150 } | 127 } |
| 151 | 128 |
| 152 return false; | 129 return false; |
| 153 } | 130 } |
| 154 | 131 |
| 155 Element* SelectorDataList::closest(Element& targetElement) const { | 132 Element* SelectorQuery::closest(Element& targetElement) const { |
| 156 if (m_selectors.size() == 0) | 133 if (m_selectors.size() == 0) |
| 157 return nullptr; | 134 return nullptr; |
| 158 if (m_needsUpdatedDistribution) | 135 if (m_needsUpdatedDistribution) |
| 159 targetElement.updateDistribution(); | 136 targetElement.updateDistribution(); |
| 160 | 137 |
| 161 for (Element* currentElement = &targetElement; currentElement; | 138 for (Element* currentElement = &targetElement; currentElement; |
| 162 currentElement = currentElement->parentElement()) { | 139 currentElement = currentElement->parentElement()) { |
| 163 for (const auto& selector : m_selectors) { | 140 for (const auto& selector : m_selectors) { |
| 164 if (selectorMatches(*selector, *currentElement, targetElement)) | 141 if (selectorMatches(*selector, *currentElement, targetElement)) |
| 165 return currentElement; | 142 return currentElement; |
| 166 } | 143 } |
| 167 } | 144 } |
| 168 return nullptr; | 145 return nullptr; |
| 169 } | 146 } |
| 170 | 147 |
| 171 StaticElementList* SelectorDataList::queryAll(ContainerNode& rootNode) const { | 148 StaticElementList* SelectorQuery::queryAll(ContainerNode& rootNode) const { |
| 172 HeapVector<Member<Element>> result; | 149 HeapVector<Member<Element>> result; |
| 173 execute<AllElementsSelectorQueryTrait>(rootNode, result); | 150 execute<AllElementsSelectorQueryTrait>(rootNode, result); |
| 174 return StaticElementList::adopt(result); | 151 return StaticElementList::adopt(result); |
| 175 } | 152 } |
| 176 | 153 |
| 177 Element* SelectorDataList::queryFirst(ContainerNode& rootNode) const { | 154 Element* SelectorQuery::queryFirst(ContainerNode& rootNode) const { |
| 178 Element* matchedElement = nullptr; | 155 Element* matchedElement = nullptr; |
| 179 execute<SingleElementSelectorQueryTrait>(rootNode, matchedElement); | 156 execute<SingleElementSelectorQueryTrait>(rootNode, matchedElement); |
| 180 return matchedElement; | 157 return matchedElement; |
| 181 } | 158 } |
| 182 | 159 |
| 183 template <typename SelectorQueryTrait> | 160 template <typename SelectorQueryTrait> |
| 184 void SelectorDataList::collectElementsByClassName( | 161 static void collectElementsByClassName( |
| 185 ContainerNode& rootNode, | 162 ContainerNode& rootNode, |
| 186 const AtomicString& className, | 163 const AtomicString& className, |
| 187 typename SelectorQueryTrait::OutputType& output) const { | 164 typename SelectorQueryTrait::OutputType& output) { |
| 188 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { | 165 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { |
| 189 if (element.hasClass() && element.classNames().contains(className)) { | 166 if (element.hasClass() && element.classNames().contains(className)) { |
| 190 SelectorQueryTrait::appendElement(output, element); | 167 SelectorQueryTrait::appendElement(output, element); |
| 191 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) | 168 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 192 return; | 169 return; |
| 193 } | 170 } |
| 194 } | 171 } |
| 195 } | 172 } |
| 196 | 173 |
| 197 inline bool matchesTagName(const QualifiedName& tagName, | 174 inline bool matchesTagName(const QualifiedName& tagName, |
| 198 const Element& element) { | 175 const Element& element) { |
| 199 if (tagName == anyQName()) | 176 if (tagName == anyQName()) |
| 200 return true; | 177 return true; |
| 201 if (element.hasLocalName(tagName.localName())) | 178 if (element.hasLocalName(tagName.localName())) |
| 202 return true; | 179 return true; |
| 203 // Non-html elements in html documents are normalized to their camel-cased | 180 // Non-html elements in html documents are normalized to their camel-cased |
| 204 // version during parsing if applicable. Yet, type selectors are lower-cased | 181 // version during parsing if applicable. Yet, type selectors are lower-cased |
| 205 // for selectors in html documents. Compare the upper case converted names | 182 // for selectors in html documents. Compare the upper case converted names |
| 206 // instead to allow matching SVG elements like foreignObject. | 183 // instead to allow matching SVG elements like foreignObject. |
| 207 if (!element.isHTMLElement() && element.document().isHTMLDocument()) | 184 if (!element.isHTMLElement() && element.document().isHTMLDocument()) |
| 208 return element.tagQName().localNameUpper() == tagName.localNameUpper(); | 185 return element.tagQName().localNameUpper() == tagName.localNameUpper(); |
| 209 return false; | 186 return false; |
| 210 } | 187 } |
| 211 | 188 |
| 212 template <typename SelectorQueryTrait> | 189 template <typename SelectorQueryTrait> |
| 213 void SelectorDataList::collectElementsByTagName( | 190 static void collectElementsByTagName( |
| 214 ContainerNode& rootNode, | 191 ContainerNode& rootNode, |
| 215 const QualifiedName& tagName, | 192 const QualifiedName& tagName, |
| 216 typename SelectorQueryTrait::OutputType& output) const { | 193 typename SelectorQueryTrait::OutputType& output) { |
| 217 DCHECK_EQ(tagName.namespaceURI(), starAtom); | 194 DCHECK_EQ(tagName.namespaceURI(), starAtom); |
| 218 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { | 195 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { |
| 219 if (matchesTagName(tagName, element)) { | 196 if (matchesTagName(tagName, element)) { |
| 220 SelectorQueryTrait::appendElement(output, element); | 197 SelectorQueryTrait::appendElement(output, element); |
| 221 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) | 198 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 222 return; | 199 return; |
| 223 } | 200 } |
| 224 } | 201 } |
| 225 } | 202 } |
| 226 | 203 |
| 227 inline bool SelectorDataList::canUseFastQuery( | 204 inline bool SelectorQuery::canUseFastQuery( |
| 228 const ContainerNode& rootNode) const { | 205 const ContainerNode& rootNode) const { |
| 229 if (m_usesDeepCombinatorOrShadowPseudo) | 206 if (m_usesDeepCombinatorOrShadowPseudo) |
| 230 return false; | 207 return false; |
| 231 if (m_needsUpdatedDistribution) | 208 if (m_needsUpdatedDistribution) |
| 232 return false; | 209 return false; |
| 233 if (rootNode.document().inQuirksMode()) | 210 if (rootNode.document().inQuirksMode()) |
| 234 return false; | 211 return false; |
| 235 if (!rootNode.isConnected()) | 212 if (!rootNode.isConnected()) |
| 236 return false; | 213 return false; |
| 237 return m_selectors.size() == 1; | 214 return m_selectors.size() == 1; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 253 // If returns true, traversalRoots has the elements that may match the selector | 230 // If returns true, traversalRoots has the elements that may match the selector |
| 254 // query. | 231 // query. |
| 255 // | 232 // |
| 256 // If returns false, traversalRoots has the rootNode parameter or descendants of | 233 // If returns false, traversalRoots has the rootNode parameter or descendants of |
| 257 // rootNode representing the subtree for which we can limit the querySelector | 234 // rootNode representing the subtree for which we can limit the querySelector |
| 258 // traversal. | 235 // traversal. |
| 259 // | 236 // |
| 260 // The travseralRoots may be empty, regardless of the returned bool value, if | 237 // The travseralRoots may be empty, regardless of the returned bool value, if |
| 261 // this method finds that the selectors won't match any element. | 238 // this method finds that the selectors won't match any element. |
| 262 template <typename SelectorQueryTrait> | 239 template <typename SelectorQueryTrait> |
| 263 void SelectorDataList::findTraverseRootsAndExecute( | 240 void SelectorQuery::findTraverseRootsAndExecute( |
| 264 ContainerNode& rootNode, | 241 ContainerNode& rootNode, |
| 265 typename SelectorQueryTrait::OutputType& output) const { | 242 typename SelectorQueryTrait::OutputType& output) const { |
| 266 // We need to return the matches in document order. To use id lookup while | 243 // We need to return the matches in document order. To use id lookup while |
| 267 // there is possiblity of multiple matches we would need to sort the | 244 // there is possiblity of multiple matches we would need to sort the |
| 268 // results. For now, just traverse the document in that case. | 245 // results. For now, just traverse the document in that case. |
| 269 DCHECK_EQ(m_selectors.size(), 1u); | 246 DCHECK_EQ(m_selectors.size(), 1u); |
| 270 | 247 |
| 271 bool isRightmostSelector = true; | 248 bool isRightmostSelector = true; |
| 272 bool startFromParent = false; | 249 bool startFromParent = false; |
| 273 | 250 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 startFromParent = true; | 313 startFromParent = true; |
| 337 else | 314 else |
| 338 startFromParent = false; | 315 startFromParent = false; |
| 339 } | 316 } |
| 340 | 317 |
| 341 executeForTraverseRoot<SelectorQueryTrait>( | 318 executeForTraverseRoot<SelectorQueryTrait>( |
| 342 *m_selectors[0], &rootNode, DoesNotMatchTraverseRoots, rootNode, output); | 319 *m_selectors[0], &rootNode, DoesNotMatchTraverseRoots, rootNode, output); |
| 343 } | 320 } |
| 344 | 321 |
| 345 template <typename SelectorQueryTrait> | 322 template <typename SelectorQueryTrait> |
| 346 void SelectorDataList::executeForTraverseRoot( | 323 void SelectorQuery::executeForTraverseRoot( |
| 347 const CSSSelector& selector, | 324 const CSSSelector& selector, |
| 348 ContainerNode* traverseRoot, | 325 ContainerNode* traverseRoot, |
| 349 MatchTraverseRootState matchTraverseRoot, | 326 MatchTraverseRootState matchTraverseRoot, |
| 350 ContainerNode& rootNode, | 327 ContainerNode& rootNode, |
| 351 typename SelectorQueryTrait::OutputType& output) const { | 328 typename SelectorQueryTrait::OutputType& output) const { |
| 352 if (!traverseRoot) | 329 if (!traverseRoot) |
| 353 return; | 330 return; |
| 354 | 331 |
| 355 if (matchTraverseRoot) { | 332 if (matchTraverseRoot) { |
| 356 if (selectorMatches(selector, toElement(*traverseRoot), rootNode)) | 333 if (selectorMatches(selector, toElement(*traverseRoot), rootNode)) |
| 357 SelectorQueryTrait::appendElement(output, toElement(*traverseRoot)); | 334 SelectorQueryTrait::appendElement(output, toElement(*traverseRoot)); |
| 358 return; | 335 return; |
| 359 } | 336 } |
| 360 | 337 |
| 361 for (Element& element : ElementTraversal::descendantsOf(*traverseRoot)) { | 338 for (Element& element : ElementTraversal::descendantsOf(*traverseRoot)) { |
| 362 if (selectorMatches(selector, element, rootNode)) { | 339 if (selectorMatches(selector, element, rootNode)) { |
| 363 SelectorQueryTrait::appendElement(output, element); | 340 SelectorQueryTrait::appendElement(output, element); |
| 364 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) | 341 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 365 return; | 342 return; |
| 366 } | 343 } |
| 367 } | 344 } |
| 368 } | 345 } |
| 369 | 346 |
| 370 template <typename SelectorQueryTrait, typename SimpleElementListType> | 347 template <typename SelectorQueryTrait, typename SimpleElementListType> |
| 371 void SelectorDataList::executeForTraverseRoots( | 348 void SelectorQuery::executeForTraverseRoots( |
| 372 const CSSSelector& selector, | 349 const CSSSelector& selector, |
| 373 SimpleElementListType& traverseRoots, | 350 SimpleElementListType& traverseRoots, |
| 374 MatchTraverseRootState matchTraverseRoots, | 351 MatchTraverseRootState matchTraverseRoots, |
| 375 ContainerNode& rootNode, | 352 ContainerNode& rootNode, |
| 376 typename SelectorQueryTrait::OutputType& output) const { | 353 typename SelectorQueryTrait::OutputType& output) const { |
| 377 if (traverseRoots.isEmpty()) | 354 if (traverseRoots.isEmpty()) |
| 378 return; | 355 return; |
| 379 | 356 |
| 380 if (matchTraverseRoots) { | 357 if (matchTraverseRoots) { |
| 381 while (!traverseRoots.isEmpty()) { | 358 while (!traverseRoots.isEmpty()) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 395 if (selectorMatches(selector, element, rootNode)) { | 372 if (selectorMatches(selector, element, rootNode)) { |
| 396 SelectorQueryTrait::appendElement(output, element); | 373 SelectorQueryTrait::appendElement(output, element); |
| 397 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) | 374 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 398 return; | 375 return; |
| 399 } | 376 } |
| 400 } | 377 } |
| 401 } | 378 } |
| 402 } | 379 } |
| 403 | 380 |
| 404 template <typename SelectorQueryTrait> | 381 template <typename SelectorQueryTrait> |
| 405 bool SelectorDataList::selectorListMatches( | 382 bool SelectorQuery::selectorListMatches( |
| 406 ContainerNode& rootNode, | 383 ContainerNode& rootNode, |
| 407 Element& element, | 384 Element& element, |
| 408 typename SelectorQueryTrait::OutputType& output) const { | 385 typename SelectorQueryTrait::OutputType& output) const { |
| 409 for (const auto& selector : m_selectors) { | 386 for (const auto& selector : m_selectors) { |
| 410 if (selectorMatches(*selector, element, rootNode)) { | 387 if (selectorMatches(*selector, element, rootNode)) { |
| 411 SelectorQueryTrait::appendElement(output, element); | 388 SelectorQueryTrait::appendElement(output, element); |
| 412 return true; | 389 return true; |
| 413 } | 390 } |
| 414 } | 391 } |
| 415 return false; | 392 return false; |
| 416 } | 393 } |
| 417 | 394 |
| 418 template <typename SelectorQueryTrait> | 395 template <typename SelectorQueryTrait> |
| 419 void SelectorDataList::executeSlow( | 396 void SelectorQuery::executeSlow( |
| 420 ContainerNode& rootNode, | 397 ContainerNode& rootNode, |
| 421 typename SelectorQueryTrait::OutputType& output) const { | 398 typename SelectorQueryTrait::OutputType& output) const { |
| 422 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { | 399 for (Element& element : ElementTraversal::descendantsOf(rootNode)) { |
| 423 if (selectorListMatches<SelectorQueryTrait>(rootNode, element, output) && | 400 if (selectorListMatches<SelectorQueryTrait>(rootNode, element, output) && |
| 424 SelectorQueryTrait::shouldOnlyMatchFirstElement) | 401 SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 425 return; | 402 return; |
| 426 } | 403 } |
| 427 } | 404 } |
| 428 | 405 |
| 429 // FIXME: Move the following helper functions, authorShadowRootOf, | 406 // FIXME: Move the following helper functions, authorShadowRootOf, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 youngerShadowRoot->type() == ShadowRootType::Open); | 450 youngerShadowRoot->type() == ShadowRootType::Open); |
| 474 return youngerShadowRoot; | 451 return youngerShadowRoot; |
| 475 } | 452 } |
| 476 | 453 |
| 477 current = &shadowRoot->host(); | 454 current = &shadowRoot->host(); |
| 478 } | 455 } |
| 479 return nullptr; | 456 return nullptr; |
| 480 } | 457 } |
| 481 | 458 |
| 482 template <typename SelectorQueryTrait> | 459 template <typename SelectorQueryTrait> |
| 483 void SelectorDataList::executeSlowTraversingShadowTree( | 460 void SelectorQuery::executeSlowTraversingShadowTree( |
| 484 ContainerNode& rootNode, | 461 ContainerNode& rootNode, |
| 485 typename SelectorQueryTrait::OutputType& output) const { | 462 typename SelectorQueryTrait::OutputType& output) const { |
| 486 for (ContainerNode* node = firstWithinTraversingShadowTree(rootNode); node; | 463 for (ContainerNode* node = firstWithinTraversingShadowTree(rootNode); node; |
| 487 node = nextTraversingShadowTree(*node, &rootNode)) { | 464 node = nextTraversingShadowTree(*node, &rootNode)) { |
| 488 if (!node->isElementNode()) | 465 if (!node->isElementNode()) |
| 489 continue; | 466 continue; |
| 490 Element* element = toElement(node); | 467 Element* element = toElement(node); |
| 491 if (selectorListMatches<SelectorQueryTrait>(rootNode, *element, output) && | 468 if (selectorListMatches<SelectorQueryTrait>(rootNode, *element, output) && |
| 492 SelectorQueryTrait::shouldOnlyMatchFirstElement) | 469 SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 493 return; | 470 return; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 506 selector->attribute() == idAttr && | 483 selector->attribute() == idAttr && |
| 507 selector->attributeMatch() == CSSSelector::CaseSensitive) | 484 selector->attributeMatch() == CSSSelector::CaseSensitive) |
| 508 return selector; | 485 return selector; |
| 509 if (selector->relation() != CSSSelector::SubSelector) | 486 if (selector->relation() != CSSSelector::SubSelector) |
| 510 break; | 487 break; |
| 511 } | 488 } |
| 512 return nullptr; | 489 return nullptr; |
| 513 } | 490 } |
| 514 | 491 |
| 515 template <typename SelectorQueryTrait> | 492 template <typename SelectorQueryTrait> |
| 516 void SelectorDataList::execute( | 493 void SelectorQuery::execute( |
| 517 ContainerNode& rootNode, | 494 ContainerNode& rootNode, |
| 518 typename SelectorQueryTrait::OutputType& output) const { | 495 typename SelectorQueryTrait::OutputType& output) const { |
| 519 if (m_selectors.isEmpty()) | 496 if (m_selectors.isEmpty()) |
| 520 return; | 497 return; |
| 521 | 498 |
| 522 if (!canUseFastQuery(rootNode)) { | 499 if (!canUseFastQuery(rootNode)) { |
| 523 if (m_needsUpdatedDistribution) | 500 if (m_needsUpdatedDistribution) |
| 524 rootNode.updateDistribution(); | 501 rootNode.updateDistribution(); |
| 525 if (m_usesDeepCombinatorOrShadowPseudo) { | 502 if (m_usesDeepCombinatorOrShadowPseudo) { |
| 526 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output); | 503 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 findTraverseRootsAndExecute<SelectorQueryTrait>(rootNode, output); | 566 findTraverseRootsAndExecute<SelectorQueryTrait>(rootNode, output); |
| 590 } | 567 } |
| 591 | 568 |
| 592 std::unique_ptr<SelectorQuery> SelectorQuery::adopt( | 569 std::unique_ptr<SelectorQuery> SelectorQuery::adopt( |
| 593 CSSSelectorList selectorList) { | 570 CSSSelectorList selectorList) { |
| 594 return WTF::wrapUnique(new SelectorQuery(std::move(selectorList))); | 571 return WTF::wrapUnique(new SelectorQuery(std::move(selectorList))); |
| 595 } | 572 } |
| 596 | 573 |
| 597 SelectorQuery::SelectorQuery(CSSSelectorList selectorList) { | 574 SelectorQuery::SelectorQuery(CSSSelectorList selectorList) { |
| 598 m_selectorList = std::move(selectorList); | 575 m_selectorList = std::move(selectorList); |
| 599 m_selectors.initialize(m_selectorList); | 576 DCHECK(m_selectors.isEmpty()); |
| 600 } | |
| 601 | 577 |
| 602 bool SelectorQuery::matches(Element& element) const { | 578 unsigned selectorCount = 0; |
| 603 return m_selectors.matches(element); | 579 for (const CSSSelector* selector = m_selectorList.first(); selector; |
| 604 } | 580 selector = CSSSelectorList::next(*selector)) |
| 581 selectorCount++; |
| 605 | 582 |
| 606 Element* SelectorQuery::closest(Element& element) const { | 583 m_usesDeepCombinatorOrShadowPseudo = false; |
| 607 return m_selectors.closest(element); | 584 m_needsUpdatedDistribution = false; |
| 608 } | 585 m_selectors.reserveInitialCapacity(selectorCount); |
| 609 | 586 for (const CSSSelector* selector = m_selectorList.first(); selector; |
| 610 StaticElementList* SelectorQuery::queryAll(ContainerNode& rootNode) const { | 587 selector = CSSSelectorList::next(*selector)) { |
| 611 return m_selectors.queryAll(rootNode); | 588 if (selector->matchesPseudoElement()) |
| 612 } | 589 continue; |
| 613 | 590 m_selectors.uncheckedAppend(selector); |
| 614 Element* SelectorQuery::queryFirst(ContainerNode& rootNode) const { | 591 m_usesDeepCombinatorOrShadowPseudo |= |
| 615 return m_selectors.queryFirst(rootNode); | 592 selector->hasDeepCombinatorOrShadowPseudo(); |
| 593 m_needsUpdatedDistribution |= selector->needsUpdatedDistribution(); |
| 594 } |
| 616 } | 595 } |
| 617 | 596 |
| 618 SelectorQuery* SelectorQueryCache::add(const AtomicString& selectors, | 597 SelectorQuery* SelectorQueryCache::add(const AtomicString& selectors, |
| 619 const Document& document, | 598 const Document& document, |
| 620 ExceptionState& exceptionState) { | 599 ExceptionState& exceptionState) { |
| 621 HashMap<AtomicString, std::unique_ptr<SelectorQuery>>::iterator it = | 600 HashMap<AtomicString, std::unique_ptr<SelectorQuery>>::iterator it = |
| 622 m_entries.find(selectors); | 601 m_entries.find(selectors); |
| 623 if (it != m_entries.end()) | 602 if (it != m_entries.end()) |
| 624 return it->value.get(); | 603 return it->value.get(); |
| 625 | 604 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 641 return m_entries | 620 return m_entries |
| 642 .insert(selectors, SelectorQuery::adopt(std::move(selectorList))) | 621 .insert(selectors, SelectorQuery::adopt(std::move(selectorList))) |
| 643 .storedValue->value.get(); | 622 .storedValue->value.get(); |
| 644 } | 623 } |
| 645 | 624 |
| 646 void SelectorQueryCache::invalidate() { | 625 void SelectorQueryCache::invalidate() { |
| 647 m_entries.clear(); | 626 m_entries.clear(); |
| 648 } | 627 } |
| 649 | 628 |
| 650 } // namespace blink | 629 } // namespace blink |
| OLD | NEW |