OLD | NEW |
---|---|
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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 ShadowRoot* root = element->containingShadowRoot(); | 71 ShadowRoot* root = element->containingShadowRoot(); |
72 if (!root || root->type() != ShadowRoot::UserAgentShadowRoot) | 72 if (!root || root->type() != ShadowRoot::UserAgentShadowRoot) |
73 return false; | 73 return false; |
74 | 74 |
75 if (element->shadowPseudoId() != selector.value()) | 75 if (element->shadowPseudoId() != selector.value()) |
76 return false; | 76 return false; |
77 | 77 |
78 return true; | 78 return true; |
79 } | 79 } |
80 | 80 |
81 Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const | 81 static Element* parentElement(const SelectorChecker::SelectorCheckingContext& co ntext) |
82 { | 82 { |
83 // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host. | 83 // If context.scope is a shadow root, we should walk up to its shadow host. |
84 if (allowToCrossBoundary) | 84 if (context.scope && context.scope == context.element->containingShadowRoot( )) |
esprehn
2014/06/27 08:05:51
Why don't we need the ScopeIsShadowRoot stuff anym
kochi
2014/06/30 02:44:06
The flag used to mean that a context's scope was s
| |
85 return context.element->parentOrShadowHostElement(); | 85 return context.element->parentOrShadowHostElement(); |
86 | 86 |
87 // If context.scope is a shadow root, we should walk up to its shadow host. | |
88 if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot) && con text.scope == context.element->containingShadowRoot()) | |
89 return context.element->parentOrShadowHostElement(); | |
90 | |
91 if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope) | |
esprehn
2014/06/27 08:05:51
Why is this not needed now?
kochi
2014/06/30 02:44:06
Now the condition will never be met.
This conditi
| |
92 return context.element->parentElement(); | |
93 | |
94 // If context.scope is some element in some shadow tree and querySelector in itialized the context, | 87 // If context.scope is some element in some shadow tree and querySelector in itialized the context, |
95 // e.g. shadowRoot.querySelector(':host *'), | 88 // e.g. shadowRoot.querySelector(':host *'), |
96 // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host. | 89 // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host. |
97 // (b) Otherwise, should not walk up from a shadow root to a shadow host. | 90 // (b) Otherwise, should not walk up from a shadow root to a shadow host. |
98 if (context.scope && context.scope->treeScope() == context.element->treeScop e()) | 91 if (context.scope && context.scope->treeScope() == context.element->treeScop e()) |
99 return context.element->parentOrShadowHostElement(); | 92 return context.element->parentOrShadowHostElement(); |
100 | 93 |
101 return context.element->parentElement(); | 94 return context.element->parentElement(); |
102 } | 95 } |
103 | 96 |
104 bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingCont ext& context) const | 97 static bool scopeContainsLastMatchedElement(const SelectorChecker::SelectorCheck ingContext& context) |
105 { | 98 { |
106 if (!(context.behaviorAtBoundary & SelectorChecker::ScopeContainsLastMatched Element)) | 99 if (!(context.contextFlags & SelectorChecker::ScopeContainsLastMatchedElemen t)) |
107 return true; | 100 return true; |
108 | 101 |
109 ASSERT(context.scope); | 102 ASSERT(context.scope); |
110 // If behaviorAtBoundary is not ScopeIsShadowRoot, we can use "contains". | 103 // If the scope is not a Shadow root, we can use "contains". |
111 if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot)) | 104 if (!context.scope->isShadowRoot()) |
112 return context.scope->contains(context.element); | 105 return context.scope->contains(context.element); |
113 | 106 |
114 // If a given element is scope, i.e. shadow host, matches. | 107 // If a given element is scope, i.e. shadow host, matches. |
115 if (context.element == context.scope->shadowHost() && (!context.previousElem ent || context.previousElement->isInDescendantTreeOf(context.element))) | 108 if (context.element == context.scope->shadowHost() && (!context.previousElem ent || context.previousElement->isInDescendantTreeOf(context.element))) |
116 return true; | 109 return true; |
117 | 110 |
118 ShadowRoot* root = context.element->containingShadowRoot(); | 111 // If the containing shadow root is scope, matches. |
119 if (!root) | 112 return context.element->containingShadowRoot() == context.scope; |
120 return false; | |
121 | |
122 // If a host of the containing shadow root is scope, matches. | |
123 return root == context.scope; | |
124 } | 113 } |
125 | 114 |
126 static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheck ingContext& context) | 115 static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheck ingContext& context) |
127 { | 116 { |
128 if (context.scope && context.scope->isInShadowTree()) | 117 if (context.scope && context.scope->isInShadowTree()) |
129 return context.element == context.scope->shadowHost(); | 118 return context.element == context.scope->shadowHost(); |
130 | 119 |
131 return false; | 120 return false; |
132 } | 121 } |
133 | 122 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 for (; nextContext.element; nextContext.element = ElementTraversal::prev iousSibling(*nextContext.element)) { | 323 for (; nextContext.element; nextContext.element = ElementTraversal::prev iousSibling(*nextContext.element)) { |
335 Match match = this->match(nextContext, siblingTraversalStrategy, res ult); | 324 Match match = this->match(nextContext, siblingTraversalStrategy, res ult); |
336 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) | 325 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) |
337 return match; | 326 return match; |
338 }; | 327 }; |
339 return SelectorFailsAllSiblings; | 328 return SelectorFailsAllSiblings; |
340 | 329 |
341 case CSSSelector::ShadowPseudo: | 330 case CSSSelector::ShadowPseudo: |
342 { | 331 { |
343 // 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. | 332 // 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. |
344 if (context.scope && context.scope->shadowHost() && context.scope->s hadowHost()->treeScope() == context.element->treeScope() && (context.behaviorAtB oundary & BoundaryBehaviorMask) != StaysWithinTreeScope) | 333 if (context.scope && context.scope->shadowHost() && context.scope->s hadowHost()->treeScope() == context.element->treeScope()) |
345 return SelectorFailsCompletely; | 334 return SelectorFailsCompletely; |
346 | 335 |
347 Element* shadowHost = context.element->shadowHost(); | 336 Element* shadowHost = context.element->shadowHost(); |
348 if (!shadowHost) | 337 if (!shadowHost) |
349 return SelectorFailsCompletely; | 338 return SelectorFailsCompletely; |
350 nextContext.element = shadowHost; | 339 nextContext.element = shadowHost; |
351 nextContext.isSubSelector = false; | 340 nextContext.isSubSelector = false; |
352 nextContext.elementStyle = 0; | 341 nextContext.elementStyle = 0; |
353 return this->match(nextContext, siblingTraversalStrategy, result); | 342 return this->match(nextContext, siblingTraversalStrategy, result); |
354 } | 343 } |
355 | 344 |
356 case CSSSelector::ShadowDeep: | 345 case CSSSelector::ShadowDeep: |
357 { | 346 { |
358 nextContext.isSubSelector = false; | 347 nextContext.isSubSelector = false; |
359 nextContext.elementStyle = 0; | 348 nextContext.elementStyle = 0; |
360 for (nextContext.element = parentElement(context, true); nextContext .element; nextContext.element = parentElement(nextContext, true)) { | 349 for (nextContext.element = context.element->parentOrShadowHostElemen t(); nextContext.element; nextContext.element = nextContext.element->parentOrSha dowHostElement()) { |
361 Match match = this->match(nextContext, siblingTraversalStrategy, result); | 350 Match match = this->match(nextContext, siblingTraversalStrategy, result); |
362 if (match == SelectorMatches || match == SelectorFailsCompletely ) | 351 if (match == SelectorMatches || match == SelectorFailsCompletely ) |
363 return match; | 352 return match; |
364 if (nextSelectorExceedsScope(nextContext)) | 353 if (nextSelectorExceedsScope(nextContext)) |
365 return SelectorFailsCompletely; | 354 return SelectorFailsCompletely; |
366 } | 355 } |
367 return SelectorFailsCompletely; | 356 return SelectorFailsCompletely; |
368 } | 357 } |
369 | 358 |
370 case CSSSelector::SubSelector: | 359 case CSSSelector::SubSelector: |
371 ASSERT_NOT_REACHED(); | 360 ASSERT_NOT_REACHED(); |
372 } | 361 } |
373 | 362 |
374 ASSERT_NOT_REACHED(); | 363 ASSERT_NOT_REACHED(); |
375 return SelectorFailsCompletely; | 364 return SelectorFailsCompletely; |
376 } | 365 } |
377 | 366 |
378 template<typename SiblingTraversalStrategy> | 367 template<typename SiblingTraversalStrategy> |
379 SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* element, const SiblingTraversalStrategy& siblingTraversalStrategy, SelectorChec kingContext& nextContext, MatchResult* result) const | 368 SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* element, const SiblingTraversalStrategy& siblingTraversalStrategy, SelectorChec kingContext& nextContext, MatchResult* result) const |
380 { | 369 { |
381 ASSERT(element); | 370 ASSERT(element); |
382 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; | 371 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; |
383 | |
384 const ContainerNode* scope = nextContext.scope; | |
385 BehaviorAtBoundary behaviorAtBoundary = nextContext.behaviorAtBoundary; | |
386 | |
387 collectDestinationInsertionPoints(*element, insertionPoints); | 372 collectDestinationInsertionPoints(*element, insertionPoints); |
388 for (size_t i = 0; i < insertionPoints.size(); ++i) { | 373 for (size_t i = 0; i < insertionPoints.size(); ++i) { |
389 nextContext.element = insertionPoints[i]; | 374 nextContext.element = insertionPoints[i]; |
390 | 375 if (m_mode == SharingRules) |
391 // If a given scope is a shadow host of an insertion point but behaviorA tBoundary doesn't have ScopeIsShadowRoot, | |
392 // we need to update behaviorAtBoundary to make selectors like ":host > ::content" work correctly. | |
393 if (m_mode == SharingRules) { | |
394 nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(beh aviorAtBoundary | ScopeIsShadowRoot); | |
395 nextContext.scope = insertionPoints[i]->containingShadowRoot(); | 376 nextContext.scope = insertionPoints[i]->containingShadowRoot(); |
396 } else if (scope == insertionPoints[i]->containingShadowRoot() && !(beha viorAtBoundary & ScopeIsShadowRoot)) { | |
397 nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(beh aviorAtBoundary | ScopeIsShadowRoot); | |
398 } else { | |
399 nextContext.behaviorAtBoundary = behaviorAtBoundary; | |
400 } | |
401 | |
402 nextContext.isSubSelector = false; | 377 nextContext.isSubSelector = false; |
403 nextContext.elementStyle = 0; | 378 nextContext.elementStyle = 0; |
404 if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatc hes) | 379 if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatc hes) |
405 return SelectorMatches; | 380 return SelectorMatches; |
406 } | 381 } |
407 return SelectorFailsLocally; | 382 return SelectorFailsLocally; |
408 } | 383 } |
409 | 384 |
410 template<typename CharType> | 385 template<typename CharType> |
411 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned le ngth) | 386 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned le ngth) |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
527 } | 502 } |
528 | 503 |
529 template<typename SiblingTraversalStrategy> | 504 template<typename SiblingTraversalStrategy> |
530 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const | 505 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const |
531 { | 506 { |
532 ASSERT(context.element); | 507 ASSERT(context.element); |
533 Element& element = *context.element; | 508 Element& element = *context.element; |
534 ASSERT(context.selector); | 509 ASSERT(context.selector); |
535 const CSSSelector& selector = *context.selector; | 510 const CSSSelector& selector = *context.selector; |
536 | 511 |
537 bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.b ehaviorAtBoundary, context.scope); | 512 bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.s cope); |
538 | 513 |
539 // Only :host and :ancestor should match the host: http://drafts.csswg.org/c ss-scoping/#host-element | 514 // Only :host and :ancestor should match the host: http://drafts.csswg.org/c ss-scoping/#host-element |
540 if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass() | 515 if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass() |
541 && !(context.behaviorAtBoundary & TreatShadowHostAsNormalScope)) | 516 && !(context.contextFlags & TreatShadowHostAsNormalScope)) |
542 return false; | 517 return false; |
543 | 518 |
544 if (selector.match() == CSSSelector::Tag) | 519 if (selector.match() == CSSSelector::Tag) |
545 return SelectorChecker::tagMatches(element, selector.tagQName()); | 520 return SelectorChecker::tagMatches(element, selector.tagQName()); |
546 | 521 |
547 if (selector.match() == CSSSelector::Class) | 522 if (selector.match() == CSSSelector::Class) |
548 return element.hasClass() && element.classNames().contains(selector.valu e()); | 523 return element.hasClass() && element.classNames().contains(selector.valu e()); |
549 | 524 |
550 if (selector.match() == CSSSelector::Id) | 525 if (selector.match() == CSSSelector::Id) |
551 return element.hasID() && element.idForStyleResolution() == selector.val ue(); | 526 return element.hasID() && element.idForStyleResolution() == selector.val ue(); |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
940 return true; | 915 return true; |
941 | 916 |
942 SelectorCheckingContext subContext(context); | 917 SelectorCheckingContext subContext(context); |
943 subContext.isSubSelector = true; | 918 subContext.isSubSelector = true; |
944 | 919 |
945 bool matched = false; | 920 bool matched = false; |
946 unsigned maxSpecificity = 0; | 921 unsigned maxSpecificity = 0; |
947 | 922 |
948 // If one of simple selectors matches an element, returns Select orMatches. Just "OR". | 923 // If one of simple selectors matches an element, returns Select orMatches. Just "OR". |
949 for (subContext.selector = selector.selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) { | 924 for (subContext.selector = selector.selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) { |
950 subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHos tParameter; | 925 subContext.contextFlags = TreatShadowHostAsNormalScope; |
951 subContext.scope = context.scope; | 926 subContext.scope = context.scope; |
952 // Use NodeRenderingTraversal to traverse a composed ancesto r list of a given element. | 927 // Use NodeRenderingTraversal to traverse a composed ancesto r list of a given element. |
953 Element* nextElement = &element; | 928 Element* nextElement = &element; |
954 SelectorCheckingContext hostContext(subContext); | 929 SelectorCheckingContext hostContext(subContext); |
955 do { | 930 do { |
956 MatchResult subResult; | 931 MatchResult subResult; |
957 hostContext.element = nextElement; | 932 hostContext.element = nextElement; |
958 if (match(hostContext, siblingTraversalStrategy, &subRes ult) == SelectorMatches) { | 933 if (match(hostContext, siblingTraversalStrategy, &subRes ult) == SelectorMatches) { |
959 matched = true; | 934 matched = true; |
960 // Consider div:host(div:host(div:host(div:host...)) ). | 935 // Consider div:host(div:host(div:host(div:host...)) ). |
961 maxSpecificity = std::max(maxSpecificity, hostContex t.selector->specificity() + subResult.specificity); | 936 maxSpecificity = std::max(maxSpecificity, hostContex t.selector->specificity() + subResult.specificity); |
962 break; | 937 break; |
963 } | 938 } |
964 hostContext.behaviorAtBoundary = DoesNotCrossBoundary; | 939 hostContext.contextFlags = DefaultBehavior; |
965 hostContext.scope = 0; | 940 hostContext.scope = 0; |
966 | 941 |
967 if (selector.pseudoType() == CSSSelector::PseudoHost) | 942 if (selector.pseudoType() == CSSSelector::PseudoHost) |
968 break; | 943 break; |
969 | 944 |
970 hostContext.elementStyle = 0; | 945 hostContext.elementStyle = 0; |
971 nextElement = NodeRenderingTraversal::parentElement(next Element); | 946 nextElement = NodeRenderingTraversal::parentElement(next Element); |
972 } while (nextElement); | 947 } while (nextElement); |
973 } | 948 } |
974 if (matched) { | 949 if (matched) { |
(...skipping 19 matching lines...) Expand all Loading... | |
994 case CSSSelector::PseudoUnknown: | 969 case CSSSelector::PseudoUnknown: |
995 case CSSSelector::PseudoNotParsed: | 970 case CSSSelector::PseudoNotParsed: |
996 default: | 971 default: |
997 ASSERT_NOT_REACHED(); | 972 ASSERT_NOT_REACHED(); |
998 break; | 973 break; |
999 } | 974 } |
1000 return false; | 975 return false; |
1001 } else if (selector.match() == CSSSelector::PseudoElement && selector.pseudo Type() == CSSSelector::PseudoCue) { | 976 } else if (selector.match() == CSSSelector::PseudoElement && selector.pseudo Type() == CSSSelector::PseudoCue) { |
1002 SelectorCheckingContext subContext(context); | 977 SelectorCheckingContext subContext(context); |
1003 subContext.isSubSelector = true; | 978 subContext.isSubSelector = true; |
1004 subContext.behaviorAtBoundary = StaysWithinTreeScope; | 979 subContext.contextFlags = DefaultBehavior; |
1005 | 980 |
1006 const CSSSelector* contextSelector = context.selector; | 981 const CSSSelector* contextSelector = context.selector; |
1007 ASSERT(contextSelector); | 982 ASSERT(contextSelector); |
1008 for (subContext.selector = contextSelector->selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) { | 983 for (subContext.selector = contextSelector->selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) { |
1009 if (match(subContext, siblingTraversalStrategy) == SelectorMatches) | 984 if (match(subContext, siblingTraversalStrategy) == SelectorMatches) |
1010 return true; | 985 return true; |
1011 } | 986 } |
1012 return false; | 987 return false; |
1013 } | 988 } |
1014 // ### add the rest of the checks... | 989 // ### add the rest of the checks... |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1150 return element.focused() && isFrameFocused(element); | 1125 return element.focused() && isFrameFocused(element); |
1151 } | 1126 } |
1152 | 1127 |
1153 template | 1128 template |
1154 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const; | 1129 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const; |
1155 | 1130 |
1156 template | 1131 template |
1157 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; | 1132 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; |
1158 | 1133 |
1159 } | 1134 } |
OLD | NEW |