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 |