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

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

Issue 2392343005: Reflow comments in core/css (Closed)
Patch Set: Revert clang-format Created 4 years, 2 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
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.
6 * All rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 7 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> 8 * 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/) 9 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
10 * (http://www.torchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. 11 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 12 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11 * 13 *
12 * This library is free software; you can redistribute it and/or 14 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public 15 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either 16 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version. 17 * version 2 of the License, or (at your option) any later version.
16 * 18 *
17 * This library is distributed in the hope that it will be useful, 19 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 if (element.tagQName().localNameUpper() != tagQName.localNameUpper()) 97 if (element.tagQName().localNameUpper() != tagQName.localNameUpper())
96 return false; 98 return false;
97 } 99 }
98 const AtomicString& namespaceURI = tagQName.namespaceURI(); 100 const AtomicString& namespaceURI = tagQName.namespaceURI();
99 return namespaceURI == starAtom || namespaceURI == element.namespaceURI(); 101 return namespaceURI == starAtom || namespaceURI == element.namespaceURI();
100 } 102 }
101 103
102 static Element* parentElement( 104 static Element* parentElement(
103 const SelectorChecker::SelectorCheckingContext& context) { 105 const SelectorChecker::SelectorCheckingContext& context) {
104 // - If context.scope is a shadow root, we should walk up to its shadow host. 106 // - If context.scope is a shadow root, we should walk up to its shadow host.
105 // - If context.scope is some element in some shadow tree and querySelector in itialized the context, 107 // - If context.scope is some element in some shadow tree and querySelector
106 // e.g. shadowRoot.querySelector(':host *'), 108 // initialized the context, e.g. shadowRoot.querySelector(':host *'),
107 // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host. 109 // (a) context.element has the same treescope as context.scope, need to walk
110 // up to its shadow host.
108 // (b) Otherwise, should not walk up from a shadow root to a shadow host. 111 // (b) Otherwise, should not walk up from a shadow root to a shadow host.
109 if (context.scope && 112 if (context.scope &&
110 (context.scope == context.element->containingShadowRoot() || 113 (context.scope == context.element->containingShadowRoot() ||
111 context.scope->treeScope() == context.element->treeScope())) 114 context.scope->treeScope() == context.element->treeScope()))
112 return context.element->parentOrShadowHostElement(); 115 return context.element->parentOrShadowHostElement();
113 return context.element->parentElement(); 116 return context.element->parentElement();
114 } 117 }
115 118
116 static const HTMLSlotElement* findSlotElementInScope( 119 static const HTMLSlotElement* findSlotElementInScope(
117 const SelectorChecker::SelectorCheckingContext& context) { 120 const SelectorChecker::SelectorCheckingContext& context) {
(...skipping 11 matching lines...) Expand all
129 132
130 static bool scopeContainsLastMatchedElement( 133 static bool scopeContainsLastMatchedElement(
131 const SelectorChecker::SelectorCheckingContext& context) { 134 const SelectorChecker::SelectorCheckingContext& context) {
132 // If this context isn't scoped, skip checking. 135 // If this context isn't scoped, skip checking.
133 if (!context.scope) 136 if (!context.scope)
134 return true; 137 return true;
135 138
136 if (context.scope->treeScope() == context.element->treeScope()) 139 if (context.scope->treeScope() == context.element->treeScope())
137 return true; 140 return true;
138 141
139 // Because Blink treats a shadow host's TreeScope as a separate one from its d escendent shadow roots, 142 // Because Blink treats a shadow host's TreeScope as a separate one from its
140 // if the last matched element is a shadow host, the condition above isn't met , even though it 143 // descendent shadow roots, if the last matched element is a shadow host, the
141 // should be. 144 // condition above isn't met, even though it should be.
142 return context.element == context.scope->ownerShadowHost() && 145 return context.element == context.scope->ownerShadowHost() &&
143 (!context.previousElement || 146 (!context.previousElement ||
144 context.previousElement->isInDescendantTreeOf(context.element)); 147 context.previousElement->isInDescendantTreeOf(context.element));
145 } 148 }
146 149
147 static inline bool nextSelectorExceedsScope( 150 static inline bool nextSelectorExceedsScope(
148 const SelectorChecker::SelectorCheckingContext& context) { 151 const SelectorChecker::SelectorCheckingContext& context) {
149 if (context.scope && context.scope->isInShadowTree()) 152 if (context.scope && context.scope->isInShadowTree())
150 return context.element == context.scope->ownerShadowHost(); 153 return context.element == context.scope->ownerShadowHost();
151 154
152 return false; 155 return false;
153 } 156 }
154 157
155 static bool shouldMatchHoverOrActive( 158 static bool shouldMatchHoverOrActive(
156 const SelectorChecker::SelectorCheckingContext& context) { 159 const SelectorChecker::SelectorCheckingContext& context) {
157 // If we're in quirks mode, then :hover and :active should never match anchors with no 160 // If we're in quirks mode, then :hover and :active should never match anchors
158 // href and *:hover and *:active should not match anything. This is specified in 161 // with no href and *:hover and *:active should not match anything. This is
159 // https://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk 162 // specified in https://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk
160 if (!context.element->document().inQuirksMode()) 163 if (!context.element->document().inQuirksMode())
161 return true; 164 return true;
162 if (context.isSubSelector) 165 if (context.isSubSelector)
163 return true; 166 return true;
164 if (context.element->isLink()) 167 if (context.element->isLink())
165 return true; 168 return true;
166 const CSSSelector* selector = context.selector; 169 const CSSSelector* selector = context.selector;
167 while (selector->relation() == CSSSelector::SubSelector && 170 while (selector->relation() == CSSSelector::SubSelector &&
168 selector->tagHistory()) { 171 selector->tagHistory()) {
169 selector = selector->tagHistory(); 172 selector = selector->tagHistory();
(...skipping 20 matching lines...) Expand all
190 193
191 static bool isLastOfType(Element& element, const QualifiedName& type) { 194 static bool isLastOfType(Element& element, const QualifiedName& type) {
192 return !ElementTraversal::nextSibling(element, HasTagName(type)); 195 return !ElementTraversal::nextSibling(element, HasTagName(type));
193 } 196 }
194 197
195 // Recursive check of selectors and combinators 198 // Recursive check of selectors and combinators
196 // It can return 4 different values: 199 // It can return 4 different values:
197 // * SelectorMatches - the selector matches the element e 200 // * SelectorMatches - the selector matches the element e
198 // * SelectorFailsLocally - the selector fails for the element e 201 // * SelectorFailsLocally - the selector fails for the element e
199 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e 202 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
200 // * SelectorFailsCompletely - the selector fails for e and any sibling or ance stor of e 203 // * SelectorFailsCompletely - the selector fails for e and any sibling or
204 // ancestor of e
201 SelectorChecker::Match SelectorChecker::matchSelector( 205 SelectorChecker::Match SelectorChecker::matchSelector(
202 const SelectorCheckingContext& context, 206 const SelectorCheckingContext& context,
203 MatchResult& result) const { 207 MatchResult& result) const {
204 MatchResult subResult; 208 MatchResult subResult;
205 if (!checkOne(context, subResult)) 209 if (!checkOne(context, subResult))
206 return SelectorFailsLocally; 210 return SelectorFailsLocally;
207 211
208 if (subResult.dynamicPseudo != PseudoIdNone) 212 if (subResult.dynamicPseudo != PseudoIdNone)
209 result.dynamicPseudo = subResult.dynamicPseudo; 213 result.dynamicPseudo = subResult.dynamicPseudo;
210 214
(...skipping 21 matching lines...) Expand all
232 } 236 }
233 if (match == SelectorMatches) 237 if (match == SelectorMatches)
234 result.specificity += subResult.specificity; 238 result.specificity += subResult.specificity;
235 return match; 239 return match;
236 } 240 }
237 241
238 static inline SelectorChecker::SelectorCheckingContext 242 static inline SelectorChecker::SelectorCheckingContext
239 prepareNextContextForRelation( 243 prepareNextContextForRelation(
240 const SelectorChecker::SelectorCheckingContext& context) { 244 const SelectorChecker::SelectorCheckingContext& context) {
241 SelectorChecker::SelectorCheckingContext nextContext(context); 245 SelectorChecker::SelectorCheckingContext nextContext(context);
242 ASSERT(context.selector->tagHistory()); 246 DCHECK(context.selector->tagHistory());
243 nextContext.selector = context.selector->tagHistory(); 247 nextContext.selector = context.selector->tagHistory();
244 return nextContext; 248 return nextContext;
245 } 249 }
246 250
247 SelectorChecker::Match SelectorChecker::matchForSubSelector( 251 SelectorChecker::Match SelectorChecker::matchForSubSelector(
248 const SelectorCheckingContext& context, 252 const SelectorCheckingContext& context,
249 MatchResult& result) const { 253 MatchResult& result) const {
250 SelectorCheckingContext nextContext = prepareNextContextForRelation(context); 254 SelectorCheckingContext nextContext = prepareNextContextForRelation(context);
251 255
252 PseudoId dynamicPseudo = result.dynamicPseudo; 256 PseudoId dynamicPseudo = result.dynamicPseudo;
(...skipping 30 matching lines...) Expand all
283 return element.parentOrShadowHostElement(); 287 return element.parentOrShadowHostElement();
284 } 288 }
285 289
286 SelectorChecker::Match SelectorChecker::matchForRelation( 290 SelectorChecker::Match SelectorChecker::matchForRelation(
287 const SelectorCheckingContext& context, 291 const SelectorCheckingContext& context,
288 MatchResult& result) const { 292 MatchResult& result) const {
289 SelectorCheckingContext nextContext = prepareNextContextForRelation(context); 293 SelectorCheckingContext nextContext = prepareNextContextForRelation(context);
290 294
291 CSSSelector::RelationType relation = context.selector->relation(); 295 CSSSelector::RelationType relation = context.selector->relation();
292 296
293 // Disable :visited matching when we see the first link or try to match anythi ng else than an ancestors. 297 // Disable :visited matching when we see the first link or try to match
298 // anything else than an ancestors.
294 if (!context.isSubSelector && 299 if (!context.isSubSelector &&
295 (context.element->isLink() || 300 (context.element->isLink() ||
296 (relation != CSSSelector::Descendant && relation != CSSSelector::Child))) 301 (relation != CSSSelector::Descendant && relation != CSSSelector::Child)))
297 nextContext.visitedMatchType = VisitedMatchDisabled; 302 nextContext.visitedMatchType = VisitedMatchDisabled;
298 303
299 nextContext.inRightmostCompound = false; 304 nextContext.inRightmostCompound = false;
300 nextContext.isSubSelector = false; 305 nextContext.isSubSelector = false;
301 nextContext.previousElement = context.element; 306 nextContext.previousElement = context.element;
302 nextContext.pseudoId = PseudoIdNone; 307 nextContext.pseudoId = PseudoIdNone;
303 308
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 match == SelectorFailsCompletely) 378 match == SelectorFailsCompletely)
374 return match; 379 return match;
375 } 380 }
376 return SelectorFailsAllSiblings; 381 return SelectorFailsAllSiblings;
377 382
378 case CSSSelector::ShadowPseudo: { 383 case CSSSelector::ShadowPseudo: {
379 if (!m_isUARule && !m_isQuerySelector && 384 if (!m_isUARule && !m_isQuerySelector &&
380 context.selector->getPseudoType() == CSSSelector::PseudoShadow) 385 context.selector->getPseudoType() == CSSSelector::PseudoShadow)
381 Deprecation::countDeprecation(context.element->document(), 386 Deprecation::countDeprecation(context.element->document(),
382 UseCounter::CSSSelectorPseudoShadow); 387 UseCounter::CSSSelectorPseudoShadow);
383 // If we're in the same tree-scope as the scoping element, then following a shadow descendant combinator would escape that and thus the scope. 388 // If we're in the same tree-scope as the scoping element, then following
389 // a shadow descendant combinator would escape that and thus the scope.
384 if (context.scope && context.scope->ownerShadowHost() && 390 if (context.scope && context.scope->ownerShadowHost() &&
385 context.scope->ownerShadowHost()->treeScope() == 391 context.scope->ownerShadowHost()->treeScope() ==
386 context.element->treeScope()) 392 context.element->treeScope())
387 return SelectorFailsCompletely; 393 return SelectorFailsCompletely;
388 394
389 Element* shadowHost = context.element->ownerShadowHost(); 395 Element* shadowHost = context.element->ownerShadowHost();
390 if (!shadowHost) 396 if (!shadowHost)
391 return SelectorFailsCompletely; 397 return SelectorFailsCompletely;
392 nextContext.element = shadowHost; 398 nextContext.element = shadowHost;
393 return matchSelector(nextContext, result); 399 return matchSelector(nextContext, result);
394 } 400 }
395 401
396 case CSSSelector::ShadowDeep: { 402 case CSSSelector::ShadowDeep: {
397 if (!m_isUARule && !m_isQuerySelector) 403 if (!m_isUARule && !m_isQuerySelector)
398 Deprecation::countDeprecation(context.element->document(), 404 Deprecation::countDeprecation(context.element->document(),
399 UseCounter::CSSDeepCombinator); 405 UseCounter::CSSDeepCombinator);
400 if (ShadowRoot* root = context.element->containingShadowRoot()) { 406 if (ShadowRoot* root = context.element->containingShadowRoot()) {
401 if (root->type() == ShadowRootType::UserAgent) 407 if (root->type() == ShadowRootType::UserAgent)
402 return SelectorFailsCompletely; 408 return SelectorFailsCompletely;
403 } 409 }
404 410
405 if (context.selector->relationIsAffectedByPseudoContent()) { 411 if (context.selector->relationIsAffectedByPseudoContent()) {
406 // TODO(kochi): closed mode tree should be handled as well for ::content . 412 // TODO(kochi): closed mode tree should be handled as well for
413 // ::content.
407 for (Element* element = context.element; element; 414 for (Element* element = context.element; element;
408 element = element->parentOrShadowHostElement()) { 415 element = element->parentOrShadowHostElement()) {
409 if (matchForPseudoContent(nextContext, *element, result) == 416 if (matchForPseudoContent(nextContext, *element, result) ==
410 SelectorMatches) { 417 SelectorMatches) {
411 if (context.element->isInShadowTree()) 418 if (context.element->isInShadowTree())
412 UseCounter::count(context.element->document(), 419 UseCounter::count(context.element->document(),
413 UseCounter::CSSDeepCombinatorAndShadow); 420 UseCounter::CSSDeepCombinatorAndShadow);
414 return SelectorMatches; 421 return SelectorMatches;
415 } 422 }
416 } 423 }
(...skipping 21 matching lines...) Expand all
438 if (!slot) 445 if (!slot)
439 return SelectorFailsCompletely; 446 return SelectorFailsCompletely;
440 447
441 nextContext.element = const_cast<HTMLSlotElement*>(slot); 448 nextContext.element = const_cast<HTMLSlotElement*>(slot);
442 return matchSelector(nextContext, result); 449 return matchSelector(nextContext, result);
443 } 450 }
444 451
445 case CSSSelector::SubSelector: 452 case CSSSelector::SubSelector:
446 break; 453 break;
447 } 454 }
448 ASSERT_NOT_REACHED(); 455 NOTREACHED();
449 return SelectorFailsCompletely; 456 return SelectorFailsCompletely;
450 } 457 }
451 458
452 SelectorChecker::Match SelectorChecker::matchForPseudoContent( 459 SelectorChecker::Match SelectorChecker::matchForPseudoContent(
453 const SelectorCheckingContext& context, 460 const SelectorCheckingContext& context,
454 const Element& element, 461 const Element& element,
455 MatchResult& result) const { 462 MatchResult& result) const {
456 HeapVector<Member<InsertionPoint>, 8> insertionPoints; 463 HeapVector<Member<InsertionPoint>, 8> insertionPoints;
457 collectDestinationInsertionPoints(element, insertionPoints); 464 collectDestinationInsertionPoints(element, insertionPoints);
458 SelectorCheckingContext nextContext(context); 465 SelectorCheckingContext nextContext(context);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 if (value.length() < selectorValue.length()) 529 if (value.length() < selectorValue.length())
523 return false; 530 return false;
524 if (!value.startsWith(selectorValue, caseSensitivity)) 531 if (!value.startsWith(selectorValue, caseSensitivity))
525 return false; 532 return false;
526 // It they start the same, check for exact match or following '-': 533 // It they start the same, check for exact match or following '-':
527 if (value.length() != selectorValue.length() && 534 if (value.length() != selectorValue.length() &&
528 value[selectorValue.length()] != '-') 535 value[selectorValue.length()] != '-')
529 return false; 536 return false;
530 return true; 537 return true;
531 default: 538 default:
532 ASSERT_NOT_REACHED(); 539 NOTREACHED();
533 return false; 540 return false;
534 } 541 }
535 } 542 }
536 543
537 static bool anyAttributeMatches(Element& element, 544 static bool anyAttributeMatches(Element& element,
538 CSSSelector::MatchType match, 545 CSSSelector::MatchType match,
539 const CSSSelector& selector) { 546 const CSSSelector& selector) {
540 const QualifiedName& selectorAttr = selector.attribute(); 547 const QualifiedName& selectorAttr = selector.attribute();
541 ASSERT(selectorAttr.localName() != 548 // Should not be possible from the CSS grammar.
542 starAtom); // Should not be possible from the CSS grammar. 549 DCHECK_NE(selectorAttr.localName(), starAtom);
543 550
544 // Synchronize the attribute in case it is lazy-computed. 551 // Synchronize the attribute in case it is lazy-computed.
545 // Currently all lazy properties have a null namespace, so only pass localName (). 552 // Currently all lazy properties have a null namespace, so only pass
553 // localName().
546 element.synchronizeAttribute(selectorAttr.localName()); 554 element.synchronizeAttribute(selectorAttr.localName());
547 555
548 const AtomicString& selectorValue = selector.value(); 556 const AtomicString& selectorValue = selector.value();
549 TextCaseSensitivity caseSensitivity = 557 TextCaseSensitivity caseSensitivity =
550 (selector.attributeMatch() == CSSSelector::CaseInsensitive) 558 (selector.attributeMatch() == CSSSelector::CaseInsensitive)
551 ? TextCaseASCIIInsensitive 559 ? TextCaseASCIIInsensitive
552 : TextCaseSensitive; 560 : TextCaseSensitive;
553 561
554 AttributeCollection attributes = element.attributesWithoutUpdate(); 562 AttributeCollection attributes = element.attributesWithoutUpdate();
555 for (const auto& attributeItem : attributes) { 563 for (const auto& attributeItem : attributes) {
(...skipping 28 matching lines...) Expand all
584 } 592 }
585 if (selectorAttr.namespaceURI() != starAtom) 593 if (selectorAttr.namespaceURI() != starAtom)
586 return false; 594 return false;
587 } 595 }
588 596
589 return false; 597 return false;
590 } 598 }
591 599
592 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, 600 bool SelectorChecker::checkOne(const SelectorCheckingContext& context,
593 MatchResult& result) const { 601 MatchResult& result) const {
594 ASSERT(context.element); 602 DCHECK(context.element);
595 Element& element = *context.element; 603 Element& element = *context.element;
596 ASSERT(context.selector); 604 DCHECK(context.selector);
597 const CSSSelector& selector = *context.selector; 605 const CSSSelector& selector = *context.selector;
598 606
599 // Only :host and :host-context() should match the host: http://drafts.csswg.o rg/css-scoping/#host-element 607 // Only :host and :host-context() should match the host:
608 // http://drafts.csswg.org/css-scoping/#host-element
600 if (context.scope && context.scope->ownerShadowHost() == element && 609 if (context.scope && context.scope->ownerShadowHost() == element &&
601 (!selector.isHostPseudoClass() && !context.treatShadowHostAsNormalScope && 610 (!selector.isHostPseudoClass() && !context.treatShadowHostAsNormalScope &&
602 selector.match() != CSSSelector::PseudoElement)) 611 selector.match() != CSSSelector::PseudoElement))
603 return false; 612 return false;
604 613
605 switch (selector.match()) { 614 switch (selector.match()) {
606 case CSSSelector::Tag: 615 case CSSSelector::Tag:
607 return matchesTagName(element, selector.tagQName()); 616 return matchesTagName(element, selector.tagQName());
608 case CSSSelector::Class: 617 case CSSSelector::Class:
609 return element.hasClass() && 618 return element.hasClass() &&
(...skipping 11 matching lines...) Expand all
621 case CSSSelector::AttributeBegin: 630 case CSSSelector::AttributeBegin:
622 case CSSSelector::AttributeEnd: 631 case CSSSelector::AttributeEnd:
623 return anyAttributeMatches(element, selector.match(), selector); 632 return anyAttributeMatches(element, selector.match(), selector);
624 633
625 case CSSSelector::PseudoClass: 634 case CSSSelector::PseudoClass:
626 return checkPseudoClass(context, result); 635 return checkPseudoClass(context, result);
627 case CSSSelector::PseudoElement: 636 case CSSSelector::PseudoElement:
628 return checkPseudoElement(context, result); 637 return checkPseudoElement(context, result);
629 638
630 default: 639 default:
631 ASSERT_NOT_REACHED(); 640 NOTREACHED();
632 return false; 641 return false;
633 } 642 }
634 } 643 }
635 644
636 bool SelectorChecker::checkPseudoNot(const SelectorCheckingContext& context, 645 bool SelectorChecker::checkPseudoNot(const SelectorCheckingContext& context,
637 MatchResult& result) const { 646 MatchResult& result) const {
638 const CSSSelector& selector = *context.selector; 647 const CSSSelector& selector = *context.selector;
639 648
640 SelectorCheckingContext subContext(context); 649 SelectorCheckingContext subContext(context);
641 subContext.isSubSelector = true; 650 subContext.isSubSelector = true;
642 ASSERT(selector.selectorList()); 651 DCHECK(selector.selectorList());
643 for (subContext.selector = selector.selectorList()->first(); 652 for (subContext.selector = selector.selectorList()->first();
644 subContext.selector; 653 subContext.selector;
645 subContext.selector = subContext.selector->tagHistory()) { 654 subContext.selector = subContext.selector->tagHistory()) {
646 // :not cannot nest. I don't really know why this is a 655 // :not cannot nest. I don't really know why this is a
647 // restriction in CSS3, but it is, so let's honor it. 656 // restriction in CSS3, but it is, so let's honor it.
648 // the parser enforces that this never occurs 657 // the parser enforces that this never occurs
649 ASSERT(subContext.selector->getPseudoType() != CSSSelector::PseudoNot); 658 DCHECK_NE(subContext.selector->getPseudoType(), CSSSelector::PseudoNot);
650 // We select between :visited and :link when applying. We don't know which o ne applied (or not) yet. 659 // We select between :visited and :link when applying. We don't know which
660 // one applied (or not) yet.
651 if (subContext.selector->getPseudoType() == CSSSelector::PseudoVisited || 661 if (subContext.selector->getPseudoType() == CSSSelector::PseudoVisited ||
652 (subContext.selector->getPseudoType() == CSSSelector::PseudoLink && 662 (subContext.selector->getPseudoType() == CSSSelector::PseudoLink &&
653 subContext.visitedMatchType == VisitedMatchEnabled)) 663 subContext.visitedMatchType == VisitedMatchEnabled))
654 return true; 664 return true;
655 if (m_mode == SharingRules) { 665 if (m_mode == SharingRules) {
656 // context.scope is not available if m_mode == SharingRules. 666 // context.scope is not available if m_mode == SharingRules.
657 // We cannot determine whether :host or :scope matches a given element or not. 667 // We cannot determine whether :host or :scope matches a given element or
668 // not.
658 if (subContext.selector->isHostPseudoClass() || 669 if (subContext.selector->isHostPseudoClass() ||
659 subContext.selector->getPseudoType() == CSSSelector::PseudoScope) 670 subContext.selector->getPseudoType() == CSSSelector::PseudoScope)
660 return true; 671 return true;
661 // :hover, :active, :focus, :-webkit-drag relies on setting flags on 672 // :hover, :active, :focus, :-webkit-drag relies on setting flags on
662 // ComputedStyle even if the whole selector may not match. That 673 // ComputedStyle even if the whole selector may not match. That
663 // means we cannot share style between elements which may fail 674 // means we cannot share style between elements which may fail
664 // matching the same selector for different reasons. An example is 675 // matching the same selector for different reasons. An example is
665 // [attr]:hover which both fail for :hover, but an element without 676 // [attr]:hover which both fail for :hover, but an element without
666 // attr won't reach the :hover selector, hence not setting the bit. 677 // attr won't reach the :hover selector, hence not setting the bit.
667 if (subContext.selector->isUserActionPseudoClass()) 678 if (subContext.selector->isUserActionPseudoClass())
668 return true; 679 return true;
669 } 680 }
670 if (!checkOne(subContext, result)) 681 if (!checkOne(subContext, result))
671 return true; 682 return true;
672 } 683 }
673 return false; 684 return false;
674 } 685 }
675 686
676 bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context, 687 bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context,
677 MatchResult& result) const { 688 MatchResult& result) const {
678 Element& element = *context.element; 689 Element& element = *context.element;
679 const CSSSelector& selector = *context.selector; 690 const CSSSelector& selector = *context.selector;
680 691
681 if (context.hasScrollbarPseudo) { 692 if (context.hasScrollbarPseudo) {
682 // CSS scrollbars match a specific subset of pseudo classes, and they have s pecialized rules for each 693 // CSS scrollbars match a specific subset of pseudo classes, and they have
694 // specialized rules for each
683 // (since there are no elements involved). 695 // (since there are no elements involved).
684 return checkScrollbarPseudoClass(context, result); 696 return checkScrollbarPseudoClass(context, result);
685 } 697 }
686 698
687 switch (selector.getPseudoType()) { 699 switch (selector.getPseudoType()) {
688 case CSSSelector::PseudoNot: 700 case CSSSelector::PseudoNot:
689 return checkPseudoNot(context, result); 701 return checkPseudoNot(context, result);
690 case CSSSelector::PseudoEmpty: { 702 case CSSSelector::PseudoEmpty: {
691 bool result = true; 703 bool result = true;
692 for (Node* n = element.firstChild(); n; n = n->nextSibling()) { 704 for (Node* n = element.firstChild(); n; n = n->nextSibling()) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 if (!parent->isFinishedParsingChildren()) 821 if (!parent->isFinishedParsingChildren())
810 return false; 822 return false;
811 return selector.matchNth(NthIndexCache::nthLastOfTypeIndex(element)); 823 return selector.matchNth(NthIndexCache::nthLastOfTypeIndex(element));
812 } 824 }
813 break; 825 break;
814 case CSSSelector::PseudoTarget: 826 case CSSSelector::PseudoTarget:
815 return element == element.document().cssTarget(); 827 return element == element.document().cssTarget();
816 case CSSSelector::PseudoAny: { 828 case CSSSelector::PseudoAny: {
817 SelectorCheckingContext subContext(context); 829 SelectorCheckingContext subContext(context);
818 subContext.isSubSelector = true; 830 subContext.isSubSelector = true;
819 ASSERT(selector.selectorList()); 831 DCHECK(selector.selectorList());
820 for (subContext.selector = selector.selectorList()->first(); 832 for (subContext.selector = selector.selectorList()->first();
821 subContext.selector; 833 subContext.selector;
822 subContext.selector = CSSSelectorList::next(*subContext.selector)) { 834 subContext.selector = CSSSelectorList::next(*subContext.selector)) {
823 if (match(subContext)) 835 if (match(subContext))
824 return true; 836 return true;
825 } 837 }
826 } break; 838 } break;
827 case CSSSelector::PseudoAutofill: 839 case CSSSelector::PseudoAutofill:
828 return element.isFormControlElement() && 840 return element.isFormControlElement() &&
829 toHTMLFormControlElement(element).isAutofilled(); 841 toHTMLFormControlElement(element).isAutofilled();
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 const AtomicString& argument = selector.argument(); 958 const AtomicString& argument = selector.argument();
947 if (value.isEmpty() || 959 if (value.isEmpty() ||
948 !value.startsWith(argument, TextCaseASCIIInsensitive)) 960 !value.startsWith(argument, TextCaseASCIIInsensitive))
949 break; 961 break;
950 if (value.length() != argument.length() && 962 if (value.length() != argument.length() &&
951 value[argument.length()] != '-') 963 value[argument.length()] != '-')
952 break; 964 break;
953 return true; 965 return true;
954 } 966 }
955 case CSSSelector::PseudoFullScreen: 967 case CSSSelector::PseudoFullScreen:
956 // While a Document is in the fullscreen state, and the document's current fullscreen 968 // While a Document is in the fullscreen state, and the document's current
957 // element is an element in the document, the 'full-screen' pseudoclass ap plies to 969 // fullscreen element is an element in the document, the 'full-screen'
958 // that element. Also, an <iframe>, <object> or <embed> element whose chil d browsing 970 // pseudoclass applies to that element. Also, an <iframe>, <object> or
959 // context's Document is in the fullscreen state has the 'full-screen' pse udoclass applied. 971 // <embed> element whose child browsing context's Document is in the
972 // fullscreen state has the 'full-screen' pseudoclass applied.
960 if (isHTMLFrameElementBase(element) && 973 if (isHTMLFrameElementBase(element) &&
961 element.containsFullScreenElement()) 974 element.containsFullScreenElement())
962 return true; 975 return true;
963 return Fullscreen::isCurrentFullScreenElement(element); 976 return Fullscreen::isCurrentFullScreenElement(element);
964 case CSSSelector::PseudoFullScreenAncestor: 977 case CSSSelector::PseudoFullScreenAncestor:
965 return element.containsFullScreenElement(); 978 return element.containsFullScreenElement();
966 case CSSSelector::PseudoInRange: 979 case CSSSelector::PseudoInRange:
967 if (m_mode == ResolvingStyle) 980 if (m_mode == ResolvingStyle)
968 element.document().setContainsValidityStyleRules(); 981 element.document().setContainsValidityStyleRules();
969 return element.isInRange(); 982 return element.isInRange();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 case CSSSelector::PseudoIncrement: 1026 case CSSSelector::PseudoIncrement:
1014 case CSSSelector::PseudoStart: 1027 case CSSSelector::PseudoStart:
1015 case CSSSelector::PseudoEnd: 1028 case CSSSelector::PseudoEnd:
1016 case CSSSelector::PseudoDoubleButton: 1029 case CSSSelector::PseudoDoubleButton:
1017 case CSSSelector::PseudoSingleButton: 1030 case CSSSelector::PseudoSingleButton:
1018 case CSSSelector::PseudoNoButton: 1031 case CSSSelector::PseudoNoButton:
1019 case CSSSelector::PseudoCornerPresent: 1032 case CSSSelector::PseudoCornerPresent:
1020 return false; 1033 return false;
1021 case CSSSelector::PseudoUnknown: 1034 case CSSSelector::PseudoUnknown:
1022 default: 1035 default:
1023 ASSERT_NOT_REACHED(); 1036 NOTREACHED();
1024 break; 1037 break;
1025 } 1038 }
1026 return false; 1039 return false;
1027 } 1040 }
1028 1041
1029 bool SelectorChecker::checkPseudoElement(const SelectorCheckingContext& context, 1042 bool SelectorChecker::checkPseudoElement(const SelectorCheckingContext& context,
1030 MatchResult& result) const { 1043 MatchResult& result) const {
1031 const CSSSelector& selector = *context.selector; 1044 const CSSSelector& selector = *context.selector;
1032 Element& element = *context.element; 1045 Element& element = *context.element;
1033 1046
(...skipping 25 matching lines...) Expand all
1059 return root->type() == ShadowRootType::UserAgent && 1072 return root->type() == ShadowRootType::UserAgent &&
1060 element.shadowPseudoId() == selector.value(); 1073 element.shadowPseudoId() == selector.value();
1061 return false; 1074 return false;
1062 case CSSSelector::PseudoSlotted: { 1075 case CSSSelector::PseudoSlotted: {
1063 SelectorCheckingContext subContext(context); 1076 SelectorCheckingContext subContext(context);
1064 subContext.isSubSelector = true; 1077 subContext.isSubSelector = true;
1065 subContext.scope = nullptr; 1078 subContext.scope = nullptr;
1066 subContext.treatShadowHostAsNormalScope = false; 1079 subContext.treatShadowHostAsNormalScope = false;
1067 1080
1068 // ::slotted() only allows one compound selector. 1081 // ::slotted() only allows one compound selector.
1069 ASSERT(selector.selectorList()->first()); 1082 DCHECK(selector.selectorList()->first());
1070 ASSERT(!CSSSelectorList::next(*selector.selectorList()->first())); 1083 DCHECK(!CSSSelectorList::next(*selector.selectorList()->first()));
1071 subContext.selector = selector.selectorList()->first(); 1084 subContext.selector = selector.selectorList()->first();
1072 return match(subContext); 1085 return match(subContext);
1073 } 1086 }
1074 case CSSSelector::PseudoContent: 1087 case CSSSelector::PseudoContent:
1075 return element.isInShadowTree() && element.isInsertionPoint(); 1088 return element.isInShadowTree() && element.isInsertionPoint();
1076 case CSSSelector::PseudoShadow: 1089 case CSSSelector::PseudoShadow:
1077 return element.isInShadowTree() && context.previousElement; 1090 return element.isInShadowTree() && context.previousElement;
1078 default: 1091 default:
1079 if (m_mode == SharingRules) 1092 if (m_mode == SharingRules)
1080 return true; 1093 return true;
1081 ASSERT(m_mode != QueryingRules); 1094 DCHECK_NE(m_mode, QueryingRules);
1082 result.dynamicPseudo = CSSSelector::pseudoId(selector.getPseudoType()); 1095 result.dynamicPseudo = CSSSelector::pseudoId(selector.getPseudoType());
1083 ASSERT(result.dynamicPseudo != PseudoIdNone); 1096 DCHECK_NE(result.dynamicPseudo, PseudoIdNone);
1084 return true; 1097 return true;
1085 } 1098 }
1086 } 1099 }
1087 1100
1088 bool SelectorChecker::checkPseudoHost(const SelectorCheckingContext& context, 1101 bool SelectorChecker::checkPseudoHost(const SelectorCheckingContext& context,
1089 MatchResult& result) const { 1102 MatchResult& result) const {
1090 const CSSSelector& selector = *context.selector; 1103 const CSSSelector& selector = *context.selector;
1091 Element& element = *context.element; 1104 Element& element = *context.element;
1092 1105
1093 if (m_mode == SharingRules) 1106 if (m_mode == SharingRules)
1094 return true; 1107 return true;
1095 // :host only matches a shadow host when :host is in a shadow tree of the shad ow host. 1108 // :host only matches a shadow host when :host is in a shadow tree of the
1109 // shadow host.
1096 if (!context.scope) 1110 if (!context.scope)
1097 return false; 1111 return false;
1098 const ContainerNode* shadowHost = context.scope->ownerShadowHost(); 1112 const ContainerNode* shadowHost = context.scope->ownerShadowHost();
1099 if (!shadowHost || shadowHost != element) 1113 if (!shadowHost || shadowHost != element)
1100 return false; 1114 return false;
1101 ASSERT(element.shadow()); 1115 DCHECK(element.shadow());
1102 1116
1103 // For the case with no parameters, i.e. just :host. 1117 // For the case with no parameters, i.e. just :host.
1104 if (!selector.selectorList()) 1118 if (!selector.selectorList())
1105 return true; 1119 return true;
1106 1120
1107 SelectorCheckingContext subContext(context); 1121 SelectorCheckingContext subContext(context);
1108 subContext.isSubSelector = true; 1122 subContext.isSubSelector = true;
1109 1123
1110 bool matched = false; 1124 bool matched = false;
1111 unsigned maxSpecificity = 0; 1125 unsigned maxSpecificity = 0;
1112 1126
1113 // If one of simple selectors matches an element, returns SelectorMatches. Jus t "OR". 1127 // If one of simple selectors matches an element, returns SelectorMatches.
1128 // Just "OR".
1114 for (subContext.selector = selector.selectorList()->first(); 1129 for (subContext.selector = selector.selectorList()->first();
1115 subContext.selector; 1130 subContext.selector;
1116 subContext.selector = CSSSelectorList::next(*subContext.selector)) { 1131 subContext.selector = CSSSelectorList::next(*subContext.selector)) {
1117 subContext.treatShadowHostAsNormalScope = true; 1132 subContext.treatShadowHostAsNormalScope = true;
1118 subContext.scope = context.scope; 1133 subContext.scope = context.scope;
1119 // Use FlatTreeTraversal to traverse a composed ancestor list of a given ele ment. 1134 // Use FlatTreeTraversal to traverse a composed ancestor list of a given
1135 // element.
1120 Element* nextElement = &element; 1136 Element* nextElement = &element;
1121 SelectorCheckingContext hostContext(subContext); 1137 SelectorCheckingContext hostContext(subContext);
1122 do { 1138 do {
1123 MatchResult subResult; 1139 MatchResult subResult;
1124 hostContext.element = nextElement; 1140 hostContext.element = nextElement;
1125 if (match(hostContext, subResult)) { 1141 if (match(hostContext, subResult)) {
1126 matched = true; 1142 matched = true;
1127 // Consider div:host(div:host(div:host(div:host...))). 1143 // Consider div:host(div:host(div:host(div:host...))).
1128 maxSpecificity = 1144 maxSpecificity =
1129 std::max(maxSpecificity, hostContext.selector->specificity() + 1145 std::max(maxSpecificity, hostContext.selector->specificity() +
(...skipping 20 matching lines...) Expand all
1150 } 1166 }
1151 1167
1152 bool SelectorChecker::checkScrollbarPseudoClass( 1168 bool SelectorChecker::checkScrollbarPseudoClass(
1153 const SelectorCheckingContext& context, 1169 const SelectorCheckingContext& context,
1154 MatchResult& result) const { 1170 MatchResult& result) const {
1155 const CSSSelector& selector = *context.selector; 1171 const CSSSelector& selector = *context.selector;
1156 1172
1157 if (selector.getPseudoType() == CSSSelector::PseudoNot) 1173 if (selector.getPseudoType() == CSSSelector::PseudoNot)
1158 return checkPseudoNot(context, result); 1174 return checkPseudoNot(context, result);
1159 1175
1160 // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventua lly :window-inactive should become a real 1176 // FIXME: This is a temporary hack for resizers and scrollbar corners.
1177 // Eventually :window-inactive should become a real
1161 // pseudo class and just apply to everything. 1178 // pseudo class and just apply to everything.
1162 if (selector.getPseudoType() == CSSSelector::PseudoWindowInactive) 1179 if (selector.getPseudoType() == CSSSelector::PseudoWindowInactive)
1163 return !context.element->document().page()->focusController().isActive(); 1180 return !context.element->document().page()->focusController().isActive();
1164 1181
1165 if (!m_scrollbar) 1182 if (!m_scrollbar)
1166 return false; 1183 return false;
1167 1184
1168 switch (selector.getPseudoType()) { 1185 switch (selector.getPseudoType()) {
1169 case CSSSelector::PseudoEnabled: 1186 case CSSSelector::PseudoEnabled:
1170 return m_scrollbar->enabled(); 1187 return m_scrollbar->enabled();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1270 }
1254 1271
1255 bool SelectorChecker::matchesFocusPseudoClass(const Element& element) { 1272 bool SelectorChecker::matchesFocusPseudoClass(const Element& element) {
1256 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element), 1273 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element),
1257 CSSSelector::PseudoFocus)) 1274 CSSSelector::PseudoFocus))
1258 return true; 1275 return true;
1259 return element.isFocused() && isFrameFocused(element); 1276 return element.isFocused() && isFrameFocused(element);
1260 } 1277 }
1261 1278
1262 } // namespace blink 1279 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/css/SelectorChecker.h ('k') | third_party/WebKit/Source/core/css/SelectorFilter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698