| 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 | 100 |
| 101 void SelectorDataList::initialize(const CSSSelectorList& selectorList) | 101 void SelectorDataList::initialize(const CSSSelectorList& selectorList) |
| 102 { | 102 { |
| 103 ASSERT(m_selectors.isEmpty()); | 103 ASSERT(m_selectors.isEmpty()); |
| 104 | 104 |
| 105 unsigned selectorCount = 0; | 105 unsigned selectorCount = 0; |
| 106 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(*selector)) | 106 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(*selector)) |
| 107 selectorCount++; | 107 selectorCount++; |
| 108 | 108 |
| 109 m_crossesTreeBoundary = false; | 109 m_crossesTreeBoundary = false; |
| 110 m_needsUpdatedDistribution = false; |
| 110 m_selectors.reserveInitialCapacity(selectorCount); | 111 m_selectors.reserveInitialCapacity(selectorCount); |
| 111 unsigned index = 0; | 112 unsigned index = 0; |
| 112 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(*selector), ++index) { | 113 for (const CSSSelector* selector = selectorList.first(); selector; selector
= CSSSelectorList::next(*selector), ++index) { |
| 113 m_selectors.uncheckedAppend(selector); | 114 m_selectors.uncheckedAppend(selector); |
| 114 m_crossesTreeBoundary |= selectorList.selectorCrossesTreeScopes(index); | 115 m_crossesTreeBoundary |= selectorList.selectorCrossesTreeScopes(index); |
| 116 m_needsUpdatedDistribution |= selectorList.selectorNeedsUpdatedDistribut
ion(index); |
| 115 } | 117 } |
| 116 } | 118 } |
| 117 | 119 |
| 118 inline bool SelectorDataList::selectorMatches(const CSSSelector& selector, Eleme
nt& element, const ContainerNode& rootNode) const | 120 inline bool SelectorDataList::selectorMatches(const CSSSelector& selector, Eleme
nt& element, const ContainerNode& rootNode) const |
| 119 { | 121 { |
| 120 SelectorChecker selectorChecker(SelectorChecker::QueryingRules); | 122 SelectorChecker selectorChecker(SelectorChecker::QueryingRules); |
| 121 SelectorChecker::SelectorCheckingContext selectorCheckingContext(&element, S
electorChecker::VisitedMatchDisabled); | 123 SelectorChecker::SelectorCheckingContext selectorCheckingContext(&element, S
electorChecker::VisitedMatchDisabled); |
| 122 selectorCheckingContext.selector = &selector; | 124 selectorCheckingContext.selector = &selector; |
| 123 selectorCheckingContext.scope = !rootNode.isDocumentNode() ? &rootNode : 0; | 125 selectorCheckingContext.scope = !rootNode.isDocumentNode() ? &rootNode : 0; |
| 124 if (selectorCheckingContext.scope) | 126 if (selectorCheckingContext.scope) |
| 125 selectorCheckingContext.scopeContainsLastMatchedElement = true; | 127 selectorCheckingContext.scopeContainsLastMatchedElement = true; |
| 126 return selectorChecker.match(selectorCheckingContext); | 128 return selectorChecker.match(selectorCheckingContext); |
| 127 } | 129 } |
| 128 | 130 |
| 129 bool SelectorDataList::matches(Element& targetElement) const | 131 bool SelectorDataList::matches(Element& targetElement) const |
| 130 { | 132 { |
| 133 if (m_needsUpdatedDistribution) |
| 134 targetElement.updateDistribution(); |
| 135 |
| 131 unsigned selectorCount = m_selectors.size(); | 136 unsigned selectorCount = m_selectors.size(); |
| 132 for (unsigned i = 0; i < selectorCount; ++i) { | 137 for (unsigned i = 0; i < selectorCount; ++i) { |
| 133 if (selectorMatches(*m_selectors[i], targetElement, targetElement)) | 138 if (selectorMatches(*m_selectors[i], targetElement, targetElement)) |
| 134 return true; | 139 return true; |
| 135 } | 140 } |
| 136 | 141 |
| 137 return false; | 142 return false; |
| 138 } | 143 } |
| 139 | 144 |
| 140 Element* SelectorDataList::closest(Element& targetElement) const | 145 Element* SelectorDataList::closest(Element& targetElement) const |
| 141 { | 146 { |
| 147 if (m_needsUpdatedDistribution) |
| 148 targetElement.updateDistribution(); |
| 149 |
| 142 unsigned selectorCount = m_selectors.size(); | 150 unsigned selectorCount = m_selectors.size(); |
| 143 for (Element* currentElement = &targetElement; currentElement; currentElemen
t = currentElement->parentElement()) { | 151 for (Element* currentElement = &targetElement; currentElement; currentElemen
t = currentElement->parentElement()) { |
| 144 for (unsigned i = 0; i < selectorCount; ++i) { | 152 for (unsigned i = 0; i < selectorCount; ++i) { |
| 145 if (selectorMatches(*m_selectors[i], *currentElement, targetElement)
) | 153 if (selectorMatches(*m_selectors[i], *currentElement, targetElement)
) |
| 146 return currentElement; | 154 return currentElement; |
| 147 } | 155 } |
| 148 } | 156 } |
| 149 return nullptr; | 157 return nullptr; |
| 150 } | 158 } |
| 151 | 159 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 if (matchesTagName(tagName, element)) { | 208 if (matchesTagName(tagName, element)) { |
| 201 SelectorQueryTrait::appendElement(output, element); | 209 SelectorQueryTrait::appendElement(output, element); |
| 202 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) | 210 if (SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 203 return; | 211 return; |
| 204 } | 212 } |
| 205 } | 213 } |
| 206 } | 214 } |
| 207 | 215 |
| 208 inline bool SelectorDataList::canUseFastQuery(const ContainerNode& rootNode) con
st | 216 inline bool SelectorDataList::canUseFastQuery(const ContainerNode& rootNode) con
st |
| 209 { | 217 { |
| 210 return m_selectors.size() == 1 && !m_crossesTreeBoundary && rootNode.inDocum
ent() && !rootNode.document().inQuirksMode(); | 218 if (m_crossesTreeBoundary) |
| 219 return false; |
| 220 if (m_needsUpdatedDistribution) |
| 221 return false; |
| 222 if (rootNode.document().inQuirksMode()) |
| 223 return false; |
| 224 if (!rootNode.inDocument()) |
| 225 return false; |
| 226 return m_selectors.size() == 1; |
| 211 } | 227 } |
| 212 | 228 |
| 213 inline bool ancestorHasClassName(ContainerNode& rootNode, const AtomicString& cl
assName) | 229 inline bool ancestorHasClassName(ContainerNode& rootNode, const AtomicString& cl
assName) |
| 214 { | 230 { |
| 215 if (!rootNode.isElementNode()) | 231 if (!rootNode.isElementNode()) |
| 216 return false; | 232 return false; |
| 217 | 233 |
| 218 for (Element* element = &toElement(rootNode); element; element = element->pa
rentElement()) { | 234 for (Element* element = &toElement(rootNode); element; element = element->pa
rentElement()) { |
| 219 if (element->hasClass() && element->classNames().contains(className)) | 235 if (element->hasClass() && element->classNames().contains(className)) |
| 220 return true; | 236 return true; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 if (selector->relation() != CSSSelector::SubSelector) | 448 if (selector->relation() != CSSSelector::SubSelector) |
| 433 break; | 449 break; |
| 434 } | 450 } |
| 435 return 0; | 451 return 0; |
| 436 } | 452 } |
| 437 | 453 |
| 438 template <typename SelectorQueryTrait> | 454 template <typename SelectorQueryTrait> |
| 439 void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTr
ait::OutputType& output) const | 455 void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTr
ait::OutputType& output) const |
| 440 { | 456 { |
| 441 if (!canUseFastQuery(rootNode)) { | 457 if (!canUseFastQuery(rootNode)) { |
| 458 if (m_needsUpdatedDistribution) |
| 459 rootNode.updateDistribution(); |
| 442 if (m_crossesTreeBoundary) { | 460 if (m_crossesTreeBoundary) { |
| 443 rootNode.updateDistribution(); | |
| 444 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output
); | 461 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output
); |
| 445 } else { | 462 } else { |
| 446 executeSlow<SelectorQueryTrait>(rootNode, output); | 463 executeSlow<SelectorQueryTrait>(rootNode, output); |
| 447 } | 464 } |
| 448 return; | 465 return; |
| 449 } | 466 } |
| 450 | 467 |
| 451 ASSERT(m_selectors.size() == 1); | 468 ASSERT(m_selectors.size() == 1); |
| 452 | 469 |
| 453 const CSSSelector& selector = *m_selectors[0]; | 470 const CSSSelector& selector = *m_selectors[0]; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 | 570 |
| 554 return m_entries.add(selectors, SelectorQuery::adopt(selectorList)).storedVa
lue->value.get(); | 571 return m_entries.add(selectors, SelectorQuery::adopt(selectorList)).storedVa
lue->value.get(); |
| 555 } | 572 } |
| 556 | 573 |
| 557 void SelectorQueryCache::invalidate() | 574 void SelectorQueryCache::invalidate() |
| 558 { | 575 { |
| 559 m_entries.clear(); | 576 m_entries.clear(); |
| 560 } | 577 } |
| 561 | 578 |
| 562 } | 579 } |
| OLD | NEW |