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

Side by Side Diff: Source/core/css/SelectorChecker.cpp

Issue 313303002: Change shadow style's scope from Shadow Host to Shadow Root (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix merge failure Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/css/SelectorChecker.h ('k') | Source/core/css/TreeBoundaryCrossingRules.cpp » ('j') | 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) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 76
77 return true; 77 return true;
78 } 78 }
79 79
80 Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const 80 Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const
81 { 81 {
82 // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host. 82 // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host.
83 if (allowToCrossBoundary) 83 if (allowToCrossBoundary)
84 return context.element->parentOrShadowHostElement(); 84 return context.element->parentOrShadowHostElement();
85 85
86 // If context.scope is a shadow host, we should walk up from a shadow root t o its shadow host. 86 // If context.scope is a shadow root, we should walk up to its shadow host.
87 if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost) && con text.scope == context.element->shadowHost()) 87 if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot) && con text.scope == context.element->containingShadowRoot())
88 return context.element->parentOrShadowHostElement(); 88 return context.element->parentOrShadowHostElement();
89 89
90 if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope) 90 if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope)
91 return context.element->parentElement(); 91 return context.element->parentElement();
92 92
93 // If context.scope is some element in some shadow tree and querySelector in itialized the context, 93 // If context.scope is some element in some shadow tree and querySelector in itialized the context,
94 // e.g. shadowRoot.querySelector(':host *'), 94 // e.g. shadowRoot.querySelector(':host *'),
95 // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host. 95 // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host.
96 // (b) Otherwise, should not walk up from a shadow root to a shadow host. 96 // (b) Otherwise, should not walk up from a shadow root to a shadow host.
97 if (context.scope && context.scope->treeScope() == context.element->treeScop e()) 97 if (context.scope && context.scope->treeScope() == context.element->treeScop e())
98 return context.element->parentOrShadowHostElement(); 98 return context.element->parentOrShadowHostElement();
99 99
100 return context.element->parentElement(); 100 return context.element->parentElement();
101 } 101 }
102 102
103 bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingCont ext& context) const 103 bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingCont ext& context) const
104 { 104 {
105 if (!(context.behaviorAtBoundary & SelectorChecker::ScopeContainsLastMatched Element)) 105 if (!(context.behaviorAtBoundary & SelectorChecker::ScopeContainsLastMatched Element))
106 return true; 106 return true;
107 107
108 ASSERT(context.scope); 108 ASSERT(context.scope);
109 // If behaviorAtBoundary is not ScopeIsShadowHost, we can use "contains". 109 // If behaviorAtBoundary is not ScopeIsShadowRoot, we can use "contains".
110 if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost)) 110 if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot))
111 return context.scope->contains(context.element); 111 return context.scope->contains(context.element);
112 112
113 // If a given element is scope, i.e. shadow host, matches. 113 // If a given element is scope, i.e. shadow host, matches.
114 if (context.element == context.scope && (!context.previousElement || context .previousElement->isInDescendantTreeOf(context.element))) 114 if (context.element == context.scope->shadowHost() && (!context.previousElem ent || context.previousElement->isInDescendantTreeOf(context.element)))
115 return true; 115 return true;
116 116
117 ShadowRoot* root = context.element->containingShadowRoot(); 117 ShadowRoot* root = context.element->containingShadowRoot();
118 if (!root) 118 if (!root)
119 return false; 119 return false;
120 120
121 // If a host of the containing shadow root is scope, matches. 121 // If a host of the containing shadow root is scope, matches.
122 return root->host() == context.scope; 122 return root == context.scope;
123 } 123 }
124 124
125 static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheck ingContext& context) 125 static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheck ingContext& context)
126 { 126 {
127 if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope) 127 if (context.scope && context.scope->isInShadowTree())
128 return context.element == context.scope; 128 return context.element == context.scope->shadowHost();
129 129
130 if (context.scope && context.scope->isInShadowTree())
131 return context.element == context.scope->containingShadowRoot()->host();
132 return false; 130 return false;
133 } 131 }
134 132
135 // Recursive check of selectors and combinators 133 // Recursive check of selectors and combinators
136 // It can return 4 different values: 134 // It can return 4 different values:
137 // * SelectorMatches - the selector matches the element e 135 // * SelectorMatches - the selector matches the element e
138 // * SelectorFailsLocally - the selector fails for the element e 136 // * SelectorFailsLocally - the selector fails for the element e
139 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e 137 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
140 // * SelectorFailsCompletely - the selector fails for e and any sibling or ance stor of e 138 // * SelectorFailsCompletely - the selector fails for e and any sibling or ance stor of e
141 template<typename SiblingTraversalStrategy> 139 template<typename SiblingTraversalStrategy>
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 for (; nextContext.element; nextContext.element = ElementTraversal::prev iousSibling(*nextContext.element)) { 333 for (; nextContext.element; nextContext.element = ElementTraversal::prev iousSibling(*nextContext.element)) {
336 Match match = this->match(nextContext, siblingTraversalStrategy, res ult); 334 Match match = this->match(nextContext, siblingTraversalStrategy, res ult);
337 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) 335 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely)
338 return match; 336 return match;
339 }; 337 };
340 return SelectorFailsAllSiblings; 338 return SelectorFailsAllSiblings;
341 339
342 case CSSSelector::ShadowPseudo: 340 case CSSSelector::ShadowPseudo:
343 { 341 {
344 // If we're in the same tree-scope as the scoping element, then foll owing a shadow descendant combinator would escape that and thus the scope. 342 // If we're in the same tree-scope as the scoping element, then foll owing a shadow descendant combinator would escape that and thus the scope.
345 if (context.scope && context.scope->treeScope() == context.element-> treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithi nTreeScope) 343 if (context.scope && context.scope->shadowHost() && context.scope->s hadowHost()->treeScope() == context.element->treeScope() && (context.behaviorAtB oundary & BoundaryBehaviorMask) != StaysWithinTreeScope)
346 return SelectorFailsCompletely; 344 return SelectorFailsCompletely;
347 345
348 Element* shadowHost = context.element->shadowHost(); 346 Element* shadowHost = context.element->shadowHost();
349 if (!shadowHost) 347 if (!shadowHost)
350 return SelectorFailsCompletely; 348 return SelectorFailsCompletely;
351 nextContext.element = shadowHost; 349 nextContext.element = shadowHost;
352 nextContext.isSubSelector = false; 350 nextContext.isSubSelector = false;
353 nextContext.elementStyle = 0; 351 nextContext.elementStyle = 0;
354 return this->match(nextContext, siblingTraversalStrategy, result); 352 return this->match(nextContext, siblingTraversalStrategy, result);
355 } 353 }
(...skipping 26 matching lines...) Expand all
382 ASSERT(element); 380 ASSERT(element);
383 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; 381 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
384 382
385 const ContainerNode* scope = nextContext.scope; 383 const ContainerNode* scope = nextContext.scope;
386 BehaviorAtBoundary behaviorAtBoundary = nextContext.behaviorAtBoundary; 384 BehaviorAtBoundary behaviorAtBoundary = nextContext.behaviorAtBoundary;
387 385
388 collectDestinationInsertionPoints(*element, insertionPoints); 386 collectDestinationInsertionPoints(*element, insertionPoints);
389 for (size_t i = 0; i < insertionPoints.size(); ++i) { 387 for (size_t i = 0; i < insertionPoints.size(); ++i) {
390 nextContext.element = insertionPoints[i]; 388 nextContext.element = insertionPoints[i];
391 389
392 // If a given scope is a shadow host of an insertion point but behaviorA tBoundary doesn't have ScopeIsShadowHost, 390 // If a given scope is a shadow host of an insertion point but behaviorA tBoundary doesn't have ScopeIsShadowRoot,
393 // we need to update behaviorAtBoundary to make selectors like ":host > ::content" work correctly. 391 // we need to update behaviorAtBoundary to make selectors like ":host > ::content" work correctly.
394 if (m_mode == SharingRules) { 392 if (m_mode == SharingRules) {
395 nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(beh aviorAtBoundary | ScopeIsShadowHost); 393 nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(beh aviorAtBoundary | ScopeIsShadowRoot);
396 nextContext.scope = insertionPoints[i]->containingShadowRoot()->shad owHost(); 394 nextContext.scope = insertionPoints[i]->containingShadowRoot();
397 } else if (scope == insertionPoints[i]->containingShadowRoot()->shadowHo st() && !(behaviorAtBoundary & ScopeIsShadowHost)) 395 } else if (scope == insertionPoints[i]->containingShadowRoot() && !(beha viorAtBoundary & ScopeIsShadowRoot)) {
398 nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(beh aviorAtBoundary | ScopeIsShadowHost); 396 nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(beh aviorAtBoundary | ScopeIsShadowRoot);
399 else 397 } else {
400 nextContext.behaviorAtBoundary = behaviorAtBoundary; 398 nextContext.behaviorAtBoundary = behaviorAtBoundary;
399 }
401 400
402 nextContext.isSubSelector = false; 401 nextContext.isSubSelector = false;
403 nextContext.elementStyle = 0; 402 nextContext.elementStyle = 0;
404 if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatc hes) 403 if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatc hes)
405 return SelectorMatches; 404 return SelectorMatches;
406 } 405 }
407 return SelectorFailsLocally; 406 return SelectorFailsLocally;
408 } 407 }
409 408
410 template<typename CharType> 409 template<typename CharType>
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const 529 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const
531 { 530 {
532 ASSERT(context.element); 531 ASSERT(context.element);
533 Element& element = *context.element; 532 Element& element = *context.element;
534 ASSERT(context.selector); 533 ASSERT(context.selector);
535 const CSSSelector& selector = *context.selector; 534 const CSSSelector& selector = *context.selector;
536 535
537 bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.b ehaviorAtBoundary, context.scope); 536 bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.b ehaviorAtBoundary, context.scope);
538 537
539 // Only :host and :ancestor should match the host: http://drafts.csswg.org/c ss-scoping/#host-element 538 // Only :host and :ancestor should match the host: http://drafts.csswg.org/c ss-scoping/#host-element
540 if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass()) 539 if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass()
540 && !(context.behaviorAtBoundary & TreatShadowHostAsNormalScope))
541 return false; 541 return false;
542 542
543 if (selector.match() == CSSSelector::Tag) 543 if (selector.match() == CSSSelector::Tag)
544 return SelectorChecker::tagMatches(element, selector.tagQName()); 544 return SelectorChecker::tagMatches(element, selector.tagQName());
545 545
546 if (selector.match() == CSSSelector::Class) 546 if (selector.match() == CSSSelector::Class)
547 return element.hasClass() && element.classNames().contains(selector.valu e()); 547 return element.hasClass() && element.classNames().contains(selector.valu e());
548 548
549 if (selector.match() == CSSSelector::Id) 549 if (selector.match() == CSSSelector::Id)
550 return element.hasID() && element.idForStyleResolution() == selector.val ue(); 550 return element.hasID() && element.idForStyleResolution() == selector.val ue();
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 break; 922 break;
923 923
924 case CSSSelector::PseudoHost: 924 case CSSSelector::PseudoHost:
925 case CSSSelector::PseudoHostContext: 925 case CSSSelector::PseudoHostContext:
926 { 926 {
927 if (m_mode == SharingRules) 927 if (m_mode == SharingRules)
928 return true; 928 return true;
929 // :host only matches a shadow host when :host is in a shadow tr ee of the shadow host. 929 // :host only matches a shadow host when :host is in a shadow tr ee of the shadow host.
930 if (!context.scope) 930 if (!context.scope)
931 return false; 931 return false;
932 const ContainerNode* shadowHost = (context.behaviorAtBoundary & ScopeIsShadowHost) ? context.scope : (context.scope->isInShadowTree() ? context. scope->shadowHost() : 0); 932 const ContainerNode* shadowHost = context.scope->shadowHost();
933 if (!shadowHost || shadowHost != element) 933 if (!shadowHost || shadowHost != element)
934 return false; 934 return false;
935 ASSERT(element.shadow()); 935 ASSERT(element.shadow());
936 936
937 // For empty parameter case, i.e. just :host or :host(). 937 // For empty parameter case, i.e. just :host or :host().
938 if (!selector.selectorList()) // Use *'s specificity. So just 0. 938 if (!selector.selectorList()) // Use *'s specificity. So just 0.
939 return true; 939 return true;
940 940
941 SelectorCheckingContext subContext(context); 941 SelectorCheckingContext subContext(context);
942 subContext.isSubSelector = true; 942 subContext.isSubSelector = true;
943 943
944 bool matched = false; 944 bool matched = false;
945 unsigned maxSpecificity = 0; 945 unsigned maxSpecificity = 0;
946 946
947 // If one of simple selectors matches an element, returns Select orMatches. Just "OR". 947 // If one of simple selectors matches an element, returns Select orMatches. Just "OR".
948 for (subContext.selector = selector.selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) { 948 for (subContext.selector = selector.selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) {
949 subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHos tParameter; 949 subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHos tParameter;
950 subContext.scope = shadowHost; 950 subContext.scope = context.scope;
951 // Use NodeRenderingTraversal to traverse a composed ancesto r list of a given element. 951 // Use NodeRenderingTraversal to traverse a composed ancesto r list of a given element.
952 Element* nextElement = &element; 952 Element* nextElement = &element;
953 SelectorCheckingContext hostContext(subContext); 953 SelectorCheckingContext hostContext(subContext);
954 do { 954 do {
955 MatchResult subResult; 955 MatchResult subResult;
956 hostContext.element = nextElement; 956 hostContext.element = nextElement;
957 if (match(hostContext, siblingTraversalStrategy, &subRes ult) == SelectorMatches) { 957 if (match(hostContext, siblingTraversalStrategy, &subRes ult) == SelectorMatches) {
958 matched = true; 958 matched = true;
959 // Consider div:host(div:host(div:host(div:host...)) ). 959 // Consider div:host(div:host(div:host(div:host...)) ).
960 maxSpecificity = std::max(maxSpecificity, hostContex t.selector->specificity() + subResult.specificity); 960 maxSpecificity = std::max(maxSpecificity, hostContex t.selector->specificity() + subResult.specificity);
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 return element.focused() && isFrameFocused(element); 1149 return element.focused() && isFrameFocused(element);
1150 } 1150 }
1151 1151
1152 template 1152 template
1153 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const; 1153 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const;
1154 1154
1155 template 1155 template
1156 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; 1156 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const;
1157 1157
1158 } 1158 }
OLDNEW
« no previous file with comments | « Source/core/css/SelectorChecker.h ('k') | Source/core/css/TreeBoundaryCrossingRules.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698