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 17 matching lines...) Expand all Loading... |
28 #include "config.h" | 28 #include "config.h" |
29 #include "core/css/SelectorChecker.h" | 29 #include "core/css/SelectorChecker.h" |
30 | 30 |
31 #include "HTMLNames.h" | 31 #include "HTMLNames.h" |
32 #include "core/css/CSSSelectorList.h" | 32 #include "core/css/CSSSelectorList.h" |
33 #include "core/css/SiblingTraversalStrategies.h" | 33 #include "core/css/SiblingTraversalStrategies.h" |
34 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
35 #include "core/dom/ElementTraversal.h" | 35 #include "core/dom/ElementTraversal.h" |
36 #include "core/dom/FullscreenElementStack.h" | 36 #include "core/dom/FullscreenElementStack.h" |
37 #include "core/dom/NodeRenderStyle.h" | 37 #include "core/dom/NodeRenderStyle.h" |
38 #include "core/dom/SiblingRuleHelper.h" | |
39 #include "core/dom/Text.h" | 38 #include "core/dom/Text.h" |
40 #include "core/dom/shadow/InsertionPoint.h" | 39 #include "core/dom/shadow/InsertionPoint.h" |
41 #include "core/dom/shadow/ShadowRoot.h" | 40 #include "core/dom/shadow/ShadowRoot.h" |
42 #include "core/editing/FrameSelection.h" | 41 #include "core/editing/FrameSelection.h" |
43 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
44 #include "core/html/HTMLDocument.h" | 43 #include "core/html/HTMLDocument.h" |
45 #include "core/html/HTMLFrameElementBase.h" | 44 #include "core/html/HTMLFrameElementBase.h" |
46 #include "core/html/HTMLInputElement.h" | 45 #include "core/html/HTMLInputElement.h" |
47 #include "core/html/HTMLOptionElement.h" | 46 #include "core/html/HTMLOptionElement.h" |
48 #include "core/html/parser/HTMLParserIdioms.h" | 47 #include "core/html/parser/HTMLParserIdioms.h" |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 nextContext.isSubSelector = false; | 272 nextContext.isSubSelector = false; |
274 nextContext.elementStyle = 0; | 273 nextContext.elementStyle = 0; |
275 return match(nextContext, siblingTraversalStrategy, result); | 274 return match(nextContext, siblingTraversalStrategy, result); |
276 } | 275 } |
277 | 276 |
278 case CSSSelector::ShadowContent: | 277 case CSSSelector::ShadowContent: |
279 return matchForShadowDistributed(context.element, siblingTraversalStrate
gy, nextContext, result); | 278 return matchForShadowDistributed(context.element, siblingTraversalStrate
gy, nextContext, result); |
280 | 279 |
281 case CSSSelector::DirectAdjacent: | 280 case CSSSelector::DirectAdjacent: |
282 if (m_mode == ResolvingStyle) { | 281 if (m_mode == ResolvingStyle) { |
283 if (Node* parent = context.element->parentElementOrShadowRoot()) | 282 if (ContainerNode* parent = context.element->parentElementOrShadowRo
ot()) |
284 SiblingRuleHelper(parent).setChildrenAffectedByDirectAdjacentRul
es(); | 283 parent->setChildrenAffectedByDirectAdjacentRules(); |
285 } | 284 } |
286 nextContext.element = ElementTraversal::previousSibling(*context.element
); | 285 nextContext.element = ElementTraversal::previousSibling(*context.element
); |
287 if (!nextContext.element) | 286 if (!nextContext.element) |
288 return SelectorFailsAllSiblings; | 287 return SelectorFailsAllSiblings; |
289 nextContext.isSubSelector = false; | 288 nextContext.isSubSelector = false; |
290 nextContext.elementStyle = 0; | 289 nextContext.elementStyle = 0; |
291 return match(nextContext, siblingTraversalStrategy, result); | 290 return match(nextContext, siblingTraversalStrategy, result); |
292 | 291 |
293 case CSSSelector::IndirectAdjacent: | 292 case CSSSelector::IndirectAdjacent: |
294 if (m_mode == ResolvingStyle) { | 293 if (m_mode == ResolvingStyle) { |
295 if (Node* parent = context.element->parentElementOrShadowRoot()) | 294 if (ContainerNode* parent = context.element->parentElementOrShadowRo
ot()) |
296 SiblingRuleHelper(parent).setChildrenAffectedByIndirectAdjacentR
ules(); | 295 parent->setChildrenAffectedByIndirectAdjacentRules(); |
297 } | 296 } |
298 nextContext.element = ElementTraversal::previousSibling(*context.element
); | 297 nextContext.element = ElementTraversal::previousSibling(*context.element
); |
299 nextContext.isSubSelector = false; | 298 nextContext.isSubSelector = false; |
300 nextContext.elementStyle = 0; | 299 nextContext.elementStyle = 0; |
301 for (; nextContext.element; nextContext.element = ElementTraversal::prev
iousSibling(*nextContext.element)) { | 300 for (; nextContext.element; nextContext.element = ElementTraversal::prev
iousSibling(*nextContext.element)) { |
302 Match match = this->match(nextContext, siblingTraversalStrategy, res
ult); | 301 Match match = this->match(nextContext, siblingTraversalStrategy, res
ult); |
303 if (match == SelectorMatches || match == SelectorFailsAllSiblings ||
match == SelectorFailsCompletely) | 302 if (match == SelectorMatches || match == SelectorFailsAllSiblings ||
match == SelectorFailsCompletely) |
304 return match; | 303 return match; |
305 }; | 304 }; |
306 return SelectorFailsAllSiblings; | 305 return SelectorFailsAllSiblings; |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 element.setStyleAffectedByEmpty(); | 557 element.setStyleAffectedByEmpty(); |
559 if (context.elementStyle) | 558 if (context.elementStyle) |
560 context.elementStyle->setEmptyState(result); | 559 context.elementStyle->setEmptyState(result); |
561 else if (element.renderStyle() && (element.document().styleE
ngine()->usesSiblingRules() || element.renderStyle()->unique())) | 560 else if (element.renderStyle() && (element.document().styleE
ngine()->usesSiblingRules() || element.renderStyle()->unique())) |
562 element.renderStyle()->setEmptyState(result); | 561 element.renderStyle()->setEmptyState(result); |
563 } | 562 } |
564 return result; | 563 return result; |
565 } | 564 } |
566 case CSSSelector::PseudoFirstChild: | 565 case CSSSelector::PseudoFirstChild: |
567 // first-child matches the first child that is an element | 566 // first-child matches the first child that is an element |
568 if (Node* parent = element.parentElementOrShadowRoot()) { | 567 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
569 bool result = siblingTraversalStrategy.isFirstChild(element); | 568 bool result = siblingTraversalStrategy.isFirstChild(element); |
570 if (m_mode == ResolvingStyle) { | 569 if (m_mode == ResolvingStyle) { |
571 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); | 570 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); |
572 SiblingRuleHelper(parent).setChildrenAffectedByFirstChildRul
es(); | 571 parent->setChildrenAffectedByFirstChildRules(); |
573 if (result && childStyle) | 572 if (result && childStyle) |
574 childStyle->setFirstChildState(); | 573 childStyle->setFirstChildState(); |
575 } | 574 } |
576 return result; | 575 return result; |
577 } | 576 } |
578 break; | 577 break; |
579 case CSSSelector::PseudoFirstOfType: | 578 case CSSSelector::PseudoFirstOfType: |
580 // first-of-type matches the first element of its type | 579 // first-of-type matches the first element of its type |
581 if (Node* parent = element.parentElementOrShadowRoot()) { | 580 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
582 bool result = siblingTraversalStrategy.isFirstOfType(element, el
ement.tagQName()); | 581 bool result = siblingTraversalStrategy.isFirstOfType(element, el
ement.tagQName()); |
583 if (m_mode == ResolvingStyle) | 582 if (m_mode == ResolvingStyle) |
584 SiblingRuleHelper(parent).setChildrenAffectedByForwardPositi
onalRules(); | 583 parent->setChildrenAffectedByForwardPositionalRules(); |
585 return result; | 584 return result; |
586 } | 585 } |
587 break; | 586 break; |
588 case CSSSelector::PseudoLastChild: | 587 case CSSSelector::PseudoLastChild: |
589 // last-child matches the last child that is an element | 588 // last-child matches the last child that is an element |
590 if (Node* parent = element.parentElementOrShadowRoot()) { | 589 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
591 SiblingRuleHelper helper(parent); | 590 bool result = parent->isFinishedParsingChildren() && siblingTrav
ersalStrategy.isLastChild(element); |
592 bool result = helper.isFinishedParsingChildren() && siblingTrave
rsalStrategy.isLastChild(element); | |
593 if (m_mode == ResolvingStyle) { | 591 if (m_mode == ResolvingStyle) { |
594 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); | 592 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); |
595 helper.setChildrenAffectedByLastChildRules(); | 593 parent->setChildrenAffectedByLastChildRules(); |
596 if (result && childStyle) | 594 if (result && childStyle) |
597 childStyle->setLastChildState(); | 595 childStyle->setLastChildState(); |
598 } | 596 } |
599 return result; | 597 return result; |
600 } | 598 } |
601 break; | 599 break; |
602 case CSSSelector::PseudoLastOfType: | 600 case CSSSelector::PseudoLastOfType: |
603 // last-of-type matches the last element of its type | 601 // last-of-type matches the last element of its type |
604 if (Node* parent = element.parentElementOrShadowRoot()) { | 602 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
605 SiblingRuleHelper helper(parent); | |
606 if (m_mode == ResolvingStyle) | 603 if (m_mode == ResolvingStyle) |
607 helper.setChildrenAffectedByBackwardPositionalRules(); | 604 parent->setChildrenAffectedByBackwardPositionalRules(); |
608 if (!helper.isFinishedParsingChildren()) | 605 if (!parent->isFinishedParsingChildren()) |
609 return false; | 606 return false; |
610 return siblingTraversalStrategy.isLastOfType(element, element.ta
gQName()); | 607 return siblingTraversalStrategy.isLastOfType(element, element.ta
gQName()); |
611 } | 608 } |
612 break; | 609 break; |
613 case CSSSelector::PseudoOnlyChild: | 610 case CSSSelector::PseudoOnlyChild: |
614 if (Node* parent = element.parentElementOrShadowRoot()) { | 611 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
615 SiblingRuleHelper helper(parent); | |
616 bool firstChild = siblingTraversalStrategy.isFirstChild(element)
; | 612 bool firstChild = siblingTraversalStrategy.isFirstChild(element)
; |
617 bool onlyChild = firstChild && helper.isFinishedParsingChildren(
) && siblingTraversalStrategy.isLastChild(element); | 613 bool onlyChild = firstChild && parent->isFinishedParsingChildren
() && siblingTraversalStrategy.isLastChild(element); |
618 if (m_mode == ResolvingStyle) { | 614 if (m_mode == ResolvingStyle) { |
619 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); | 615 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); |
620 helper.setChildrenAffectedByFirstChildRules(); | 616 parent->setChildrenAffectedByFirstChildRules(); |
621 helper.setChildrenAffectedByLastChildRules(); | 617 parent->setChildrenAffectedByLastChildRules(); |
622 if (firstChild && childStyle) | 618 if (firstChild && childStyle) |
623 childStyle->setFirstChildState(); | 619 childStyle->setFirstChildState(); |
624 if (onlyChild && childStyle) | 620 if (onlyChild && childStyle) |
625 childStyle->setLastChildState(); | 621 childStyle->setLastChildState(); |
626 } | 622 } |
627 return onlyChild; | 623 return onlyChild; |
628 } | 624 } |
629 break; | 625 break; |
630 case CSSSelector::PseudoOnlyOfType: | 626 case CSSSelector::PseudoOnlyOfType: |
631 // FIXME: This selector is very slow. | 627 // FIXME: This selector is very slow. |
632 if (Node* parent = element.parentElementOrShadowRoot()) { | 628 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
633 SiblingRuleHelper helper(parent); | |
634 if (m_mode == ResolvingStyle) { | 629 if (m_mode == ResolvingStyle) { |
635 helper.setChildrenAffectedByForwardPositionalRules(); | 630 parent->setChildrenAffectedByForwardPositionalRules(); |
636 helper.setChildrenAffectedByBackwardPositionalRules(); | 631 parent->setChildrenAffectedByBackwardPositionalRules(); |
637 } | 632 } |
638 if (!helper.isFinishedParsingChildren()) | 633 if (!parent->isFinishedParsingChildren()) |
639 return false; | 634 return false; |
640 return siblingTraversalStrategy.isFirstOfType(element, element.t
agQName()) && siblingTraversalStrategy.isLastOfType(element, element.tagQName())
; | 635 return siblingTraversalStrategy.isFirstOfType(element, element.t
agQName()) && siblingTraversalStrategy.isLastOfType(element, element.tagQName())
; |
641 } | 636 } |
642 break; | 637 break; |
643 case CSSSelector::PseudoNthChild: | 638 case CSSSelector::PseudoNthChild: |
644 if (!selector.parseNth()) | 639 if (!selector.parseNth()) |
645 break; | 640 break; |
646 if (Node* parent = element.parentElementOrShadowRoot()) { | 641 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
647 int count = 1 + siblingTraversalStrategy.countElementsBefore(ele
ment); | 642 int count = 1 + siblingTraversalStrategy.countElementsBefore(ele
ment); |
648 if (m_mode == ResolvingStyle) { | 643 if (m_mode == ResolvingStyle) { |
649 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); | 644 RenderStyle* childStyle = context.elementStyle ? context.ele
mentStyle : element.renderStyle(); |
650 element.setChildIndex(count); | 645 element.setChildIndex(count); |
651 if (childStyle) | 646 if (childStyle) |
652 childStyle->setUnique(); | 647 childStyle->setUnique(); |
653 SiblingRuleHelper(parent).setChildrenAffectedByForwardPositi
onalRules(); | 648 parent->setChildrenAffectedByForwardPositionalRules(); |
654 } | 649 } |
655 | 650 |
656 if (selector.matchNth(count)) | 651 if (selector.matchNth(count)) |
657 return true; | 652 return true; |
658 } | 653 } |
659 break; | 654 break; |
660 case CSSSelector::PseudoNthOfType: | 655 case CSSSelector::PseudoNthOfType: |
661 if (!selector.parseNth()) | 656 if (!selector.parseNth()) |
662 break; | 657 break; |
663 if (Node* parent = element.parentElementOrShadowRoot()) { | 658 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
664 int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefo
re(element, element.tagQName()); | 659 int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefo
re(element, element.tagQName()); |
665 if (m_mode == ResolvingStyle) | 660 if (m_mode == ResolvingStyle) |
666 SiblingRuleHelper(parent).setChildrenAffectedByForwardPositi
onalRules(); | 661 parent->setChildrenAffectedByForwardPositionalRules(); |
667 | 662 |
668 if (selector.matchNth(count)) | 663 if (selector.matchNth(count)) |
669 return true; | 664 return true; |
670 } | 665 } |
671 break; | 666 break; |
672 case CSSSelector::PseudoNthLastChild: | 667 case CSSSelector::PseudoNthLastChild: |
673 if (!selector.parseNth()) | 668 if (!selector.parseNth()) |
674 break; | 669 break; |
675 if (Node* parent = element.parentElementOrShadowRoot()) { | 670 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
676 SiblingRuleHelper helper(parent); | |
677 if (m_mode == ResolvingStyle) | 671 if (m_mode == ResolvingStyle) |
678 helper.setChildrenAffectedByBackwardPositionalRules(); | 672 parent->setChildrenAffectedByBackwardPositionalRules(); |
679 if (!helper.isFinishedParsingChildren()) | 673 if (!parent->isFinishedParsingChildren()) |
680 return false; | 674 return false; |
681 int count = 1 + siblingTraversalStrategy.countElementsAfter(elem
ent); | 675 int count = 1 + siblingTraversalStrategy.countElementsAfter(elem
ent); |
682 if (selector.matchNth(count)) | 676 if (selector.matchNth(count)) |
683 return true; | 677 return true; |
684 } | 678 } |
685 break; | 679 break; |
686 case CSSSelector::PseudoNthLastOfType: | 680 case CSSSelector::PseudoNthLastOfType: |
687 if (!selector.parseNth()) | 681 if (!selector.parseNth()) |
688 break; | 682 break; |
689 if (Node* parent = element.parentElementOrShadowRoot()) { | 683 if (ContainerNode* parent = element.parentElementOrShadowRoot()) { |
690 SiblingRuleHelper helper(parent); | |
691 if (m_mode == ResolvingStyle) | 684 if (m_mode == ResolvingStyle) |
692 helper.setChildrenAffectedByBackwardPositionalRules(); | 685 parent->setChildrenAffectedByBackwardPositionalRules(); |
693 if (!helper.isFinishedParsingChildren()) | 686 if (!parent->isFinishedParsingChildren()) |
694 return false; | 687 return false; |
695 | 688 |
696 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfte
r(element, element.tagQName()); | 689 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfte
r(element, element.tagQName()); |
697 if (selector.matchNth(count)) | 690 if (selector.matchNth(count)) |
698 return true; | 691 return true; |
699 } | 692 } |
700 break; | 693 break; |
701 case CSSSelector::PseudoTarget: | 694 case CSSSelector::PseudoTarget: |
702 if (element == element.document().cssTarget()) | 695 if (element == element.document().cssTarget()) |
703 return true; | 696 return true; |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 return element.focused() && isFrameFocused(element); | 1096 return element.focused() && isFrameFocused(element); |
1104 } | 1097 } |
1105 | 1098 |
1106 template | 1099 template |
1107 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst DOMSiblingTraversalStrategy&, MatchResult*) const; | 1100 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst DOMSiblingTraversalStrategy&, MatchResult*) const; |
1108 | 1101 |
1109 template | 1102 template |
1110 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; | 1103 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; |
1111 | 1104 |
1112 } | 1105 } |
OLD | NEW |