Chromium Code Reviews| 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 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 // We need to return the matches in document order. To use id lookup while | 237 // We need to return the matches in document order. To use id lookup while |
| 238 // there is possiblity of multiple matches we would need to sort the | 238 // there is possiblity of multiple matches we would need to sort the |
| 239 // results. For now, just traverse the document in that case. | 239 // results. For now, just traverse the document in that case. |
| 240 DCHECK_EQ(m_selectors.size(), 1u); | 240 DCHECK_EQ(m_selectors.size(), 1u); |
| 241 | 241 |
| 242 bool isRightmostSelector = true; | 242 bool isRightmostSelector = true; |
| 243 bool startFromParent = false; | 243 bool startFromParent = false; |
| 244 | 244 |
| 245 for (const CSSSelector* selector = m_selectors[0]; selector; | 245 for (const CSSSelector* selector = m_selectors[0]; selector; |
| 246 selector = selector->tagHistory()) { | 246 selector = selector->tagHistory()) { |
| 247 if (selector->match() == CSSSelector::Id && rootNode.isInTreeScope() && | 247 const AtomicString& value = selector->value(); |
|
esprehn
2017/03/29 19:59:43
We only take the fast path if rootNode.isConnected
| |
| 248 !rootNode.containingTreeScope().containsMultipleElementsWithId( | 248 |
| 249 selector->value())) { | 249 if (selector->match() == CSSSelector::Id && |
| 250 Element* element = | 250 !rootNode.containingTreeScope().containsMultipleElementsWithId(value)) { |
| 251 rootNode.containingTreeScope().getElementById(selector->value()); | 251 // Id selectors in the right most selector are handled by the caller, |
| 252 ContainerNode* adjustedNode = &rootNode; | 252 // we should never hit them here. |
| 253 if (element && element->isDescendantOf(&rootNode)) | 253 DCHECK(!isRightmostSelector); |
|
esprehn
2017/03/29 19:59:43
if element was null, then there's no element in th
| |
| 254 adjustedNode = element; | 254 Element* element = rootNode.containingTreeScope().getElementById(value); |
| 255 else if (!element || isRightmostSelector) | 255 if (!element) |
| 256 adjustedNode = nullptr; | |
| 257 if (isRightmostSelector) { | |
|
esprehn
2017/03/29 19:59:43
This code was not reachable, id selectors in the r
| |
| 258 if (!adjustedNode) | |
| 259 return; | |
| 260 element = toElement(adjustedNode); | |
| 261 if (selectorMatches(*m_selectors[0], *element, rootNode)) | |
| 262 SelectorQueryTrait::appendElement(output, *element); | |
| 263 return; | 256 return; |
| 264 } | 257 ContainerNode* start = &rootNode; |
| 265 | 258 if (element->isDescendantOf(&rootNode)) |
| 266 if (startFromParent && adjustedNode) | 259 start = element; |
| 267 adjustedNode = adjustedNode->parentNode(); | 260 if (startFromParent) |
| 268 | 261 start = start->parentNode(); |
| 269 executeForTraverseRoot<SelectorQueryTrait>(adjustedNode, rootNode, | 262 executeForTraverseRoot<SelectorQueryTrait>(start, rootNode, output); |
| 270 output); | |
| 271 return; | 263 return; |
| 272 } | 264 } |
| 273 | 265 |
| 274 // If we have both CSSSelector::Id and CSSSelector::Class at the same time, | 266 // If we have both CSSSelector::Id and CSSSelector::Class at the same time, |
| 275 // we should use Id to find traverse root. | 267 // we should use Id to find traverse root. |
| 276 if (!SelectorQueryTrait::shouldOnlyMatchFirstElement && !startFromParent && | 268 if (!SelectorQueryTrait::shouldOnlyMatchFirstElement && !startFromParent && |
| 277 selector->match() == CSSSelector::Class) { | 269 selector->match() == CSSSelector::Class) { |
| 278 if (isRightmostSelector) { | 270 if (isRightmostSelector) { |
| 279 ClassElementList<AllElements> traverseRoots(rootNode, | 271 ClassElementList<AllElements> traverseRoots(rootNode, value); |
| 280 selector->value()); | |
| 281 while (!traverseRoots.isEmpty()) { | 272 while (!traverseRoots.isEmpty()) { |
| 282 Element& element = *traverseRoots.next(); | 273 Element& element = *traverseRoots.next(); |
| 283 if (selectorMatches(*m_selectors[0], element, rootNode)) | 274 if (selectorMatches(*m_selectors[0], element, rootNode)) |
| 284 SelectorQueryTrait::appendElement(output, element); | 275 SelectorQueryTrait::appendElement(output, element); |
| 285 } | 276 } |
| 286 return; | 277 return; |
| 287 } | 278 } |
| 288 // Since there exists some ancestor element which has the class name, we | 279 // Since there exists some ancestor element which has the class name, we |
| 289 // need to see all children of rootNode. | 280 // need to see all children of rootNode. |
| 290 if (ancestorHasClassName(rootNode, selector->value())) | 281 if (ancestorHasClassName(rootNode, value)) |
| 291 break; | 282 break; |
| 292 | 283 |
| 293 ClassElementList<OnlyRoots> traverseRoots(rootNode, selector->value()); | 284 ClassElementList<OnlyRoots> traverseRoots(rootNode, value); |
| 294 while (!traverseRoots.isEmpty()) { | 285 while (!traverseRoots.isEmpty()) { |
| 295 for (Element& element : | 286 for (Element& element : |
| 296 ElementTraversal::descendantsOf(*traverseRoots.next())) { | 287 ElementTraversal::descendantsOf(*traverseRoots.next())) { |
| 297 if (selectorMatches(*m_selectors[0], element, rootNode)) | 288 if (selectorMatches(*m_selectors[0], element, rootNode)) |
| 298 SelectorQueryTrait::appendElement(output, element); | 289 SelectorQueryTrait::appendElement(output, element); |
| 299 } | 290 } |
| 300 } | 291 } |
| 301 return; | 292 return; |
| 302 } | 293 } |
| 303 | 294 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 return m_entries | 568 return m_entries |
| 578 .insert(selectors, SelectorQuery::adopt(std::move(selectorList))) | 569 .insert(selectors, SelectorQuery::adopt(std::move(selectorList))) |
| 579 .storedValue->value.get(); | 570 .storedValue->value.get(); |
| 580 } | 571 } |
| 581 | 572 |
| 582 void SelectorQueryCache::invalidate() { | 573 void SelectorQueryCache::invalidate() { |
| 583 m_entries.clear(); | 574 m_entries.clear(); |
| 584 } | 575 } |
| 585 | 576 |
| 586 } // namespace blink | 577 } // namespace blink |
| OLD | NEW |