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. |
| 11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
| 12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
| 13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
| 14 * | 14 * |
| 15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #include "core/dom/SelectorQuery.h" | 27 #include "core/dom/SelectorQuery.h" |
| 28 | 28 |
| 29 #include "bindings/core/v8/ExceptionState.h" | 29 #include "bindings/core/v8/ExceptionState.h" |
| 30 #include "core/HTMLNames.h" | |
| 30 #include "core/css/SelectorChecker.h" | 31 #include "core/css/SelectorChecker.h" |
| 31 #include "core/css/parser/CSSParser.h" | 32 #include "core/css/parser/CSSParser.h" |
| 32 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
| 33 #include "core/dom/ElementTraversal.h" | 34 #include "core/dom/ElementTraversal.h" |
| 34 #include "core/dom/ExceptionCode.h" | 35 #include "core/dom/ExceptionCode.h" |
| 35 #include "core/dom/Node.h" | 36 #include "core/dom/Node.h" |
| 36 #include "core/dom/StaticNodeList.h" | 37 #include "core/dom/StaticNodeList.h" |
| 37 #include "core/dom/shadow/ElementShadow.h" | 38 #include "core/dom/shadow/ElementShadow.h" |
| 38 #include "core/dom/shadow/ShadowRoot.h" | 39 #include "core/dom/shadow/ShadowRoot.h" |
| 39 #include "wtf/PtrUtil.h" | 40 #include "wtf/PtrUtil.h" |
| 40 #include <memory> | 41 #include <memory> |
| 41 | 42 |
| 42 namespace blink { | 43 namespace blink { |
| 43 | 44 |
| 45 using namespace HTMLNames; | |
| 46 | |
| 44 struct SingleElementSelectorQueryTrait { | 47 struct SingleElementSelectorQueryTrait { |
| 45 typedef Element* OutputType; | 48 typedef Element* OutputType; |
| 46 static const bool shouldOnlyMatchFirstElement = true; | 49 static const bool shouldOnlyMatchFirstElement = true; |
| 47 ALWAYS_INLINE static void appendElement(OutputType& output, Element& element ) | 50 ALWAYS_INLINE static void appendElement(OutputType& output, Element& element ) |
| 48 { | 51 { |
| 49 DCHECK(!output); | 52 DCHECK(!output); |
| 50 output = &element; | 53 output = &element; |
| 51 } | 54 } |
| 52 }; | 55 }; |
| 53 | 56 |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 437 { | 440 { |
| 438 for (ContainerNode* node = firstWithinTraversingShadowTree(rootNode); node; node = nextTraversingShadowTree(*node, &rootNode)) { | 441 for (ContainerNode* node = firstWithinTraversingShadowTree(rootNode); node; node = nextTraversingShadowTree(*node, &rootNode)) { |
| 439 if (!node->isElementNode()) | 442 if (!node->isElementNode()) |
| 440 continue; | 443 continue; |
| 441 Element* element = toElement(node); | 444 Element* element = toElement(node); |
| 442 if (selectorListMatches<SelectorQueryTrait>(rootNode, *element, output) && SelectorQueryTrait::shouldOnlyMatchFirstElement) | 445 if (selectorListMatches<SelectorQueryTrait>(rootNode, *element, output) && SelectorQueryTrait::shouldOnlyMatchFirstElement) |
| 443 return; | 446 return; |
| 444 } | 447 } |
| 445 } | 448 } |
| 446 | 449 |
| 447 const CSSSelector* SelectorDataList::selectorForIdLookup(const CSSSelector& firs tSelector) const | 450 static const CSSSelector* selectorForIdLookup(const CSSSelector& firstSelector) |
| 448 { | 451 { |
| 449 for (const CSSSelector* selector = &firstSelector; selector; selector = sele ctor->tagHistory()) { | 452 for (const CSSSelector* selector = &firstSelector; selector; selector = sele ctor->tagHistory()) { |
| 450 if (selector->match() == CSSSelector::Id) | 453 if (selector->match() == CSSSelector::Id) |
| 451 return selector; | 454 return selector; |
| 455 // We only use the fast path when in standards mode where #id selectors | |
| 456 // are case sensitive, so we need the same behavior for [id=value]. | |
| 457 if (selector->match() == CSSSelector::AttributeExact | |
| 458 && selector->attribute() == idAttr | |
| 459 && selector->attributeMatch() == CSSSelector::CaseSensitive) | |
| 460 return selector; | |
|
sashab
2016/07/12 01:37:03
Would it be worth adding a StyleResolverStats for
esprehn
2016/07/12 01:39:15
It would be worth adding some metrics, but StyleRe
| |
| 452 if (selector->relation() != CSSSelector::SubSelector) | 461 if (selector->relation() != CSSSelector::SubSelector) |
| 453 break; | 462 break; |
| 454 } | 463 } |
| 455 return nullptr; | 464 return nullptr; |
| 456 } | 465 } |
| 457 | 466 |
| 458 template <typename SelectorQueryTrait> | 467 template <typename SelectorQueryTrait> |
| 459 void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTr ait::OutputType& output) const | 468 void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTr ait::OutputType& output) const |
| 460 { | 469 { |
| 461 if (m_selectors.isEmpty()) | 470 if (m_selectors.isEmpty()) |
| 462 return; | 471 return; |
| 463 | 472 |
| 464 if (!canUseFastQuery(rootNode)) { | 473 if (!canUseFastQuery(rootNode)) { |
| 465 if (m_needsUpdatedDistribution) | 474 if (m_needsUpdatedDistribution) |
| 466 rootNode.updateDistribution(); | 475 rootNode.updateDistribution(); |
| 467 if (m_usesDeepCombinatorOrShadowPseudo) { | 476 if (m_usesDeepCombinatorOrShadowPseudo) { |
| 468 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output ); | 477 executeSlowTraversingShadowTree<SelectorQueryTrait>(rootNode, output ); |
| 469 } else { | 478 } else { |
| 470 executeSlow<SelectorQueryTrait>(rootNode, output); | 479 executeSlow<SelectorQueryTrait>(rootNode, output); |
| 471 } | 480 } |
| 472 return; | 481 return; |
| 473 } | 482 } |
| 474 | 483 |
| 475 DCHECK_EQ(m_selectors.size(), 1u); | 484 DCHECK_EQ(m_selectors.size(), 1u); |
| 485 DCHECK(!rootNode.document().inQuirksMode()); | |
| 476 | 486 |
| 477 const CSSSelector& selector = *m_selectors[0]; | 487 const CSSSelector& selector = *m_selectors[0]; |
| 478 const CSSSelector& firstSelector = selector; | 488 const CSSSelector& firstSelector = selector; |
| 479 | 489 |
| 480 // Fast path for querySelector*('#id'), querySelector*('tag#id'). | 490 // Fast path for querySelector*('#id'), querySelector*('tag#id'), querySelec tor*('tag[id=example]'). |
| 481 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { | 491 if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { |
| 482 const AtomicString& idToMatch = idSelector->value(); | 492 const AtomicString& idToMatch = idSelector->value(); |
| 483 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) { | 493 if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) { |
| 484 const HeapVector<Member<Element>>& elements = rootNode.treeScope().g etAllElementsById(idToMatch); | 494 const HeapVector<Member<Element>>& elements = rootNode.treeScope().g etAllElementsById(idToMatch); |
| 485 size_t count = elements.size(); | 495 size_t count = elements.size(); |
| 486 for (size_t i = 0; i < count; ++i) { | 496 for (size_t i = 0; i < count; ++i) { |
| 487 Element& element = *elements[i]; | 497 Element& element = *elements[i]; |
| 488 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootN ode))) | 498 if (!(isTreeScopeRoot(rootNode) || element.isDescendantOf(&rootN ode))) |
| 489 continue; | 499 continue; |
| 490 if (selectorMatches(selector, element, rootNode)) { | 500 if (selectorMatches(selector, element, rootNode)) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 | 587 |
| 578 return m_entries.add(selectors, SelectorQuery::adopt(std::move(selectorList) )).storedValue->value.get(); | 588 return m_entries.add(selectors, SelectorQuery::adopt(std::move(selectorList) )).storedValue->value.get(); |
| 579 } | 589 } |
| 580 | 590 |
| 581 void SelectorQueryCache::invalidate() | 591 void SelectorQueryCache::invalidate() |
| 582 { | 592 { |
| 583 m_entries.clear(); | 593 m_entries.clear(); |
| 584 } | 594 } |
| 585 | 595 |
| 586 } // namespace blink | 596 } // namespace blink |
| OLD | NEW |