| 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 |