Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: third_party/WebKit/Source/core/dom/SelectorQuery.cpp

Issue 2139843002: Allow [id=X] selectors to use the querySelector ID fast path. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix assert. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/dom/SelectorQuery.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/SelectorQuery.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698