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 21 matching lines...) Expand all Loading... |
32 #include "HTMLNames.h" | 32 #include "HTMLNames.h" |
33 #include "core/dom/Element.h" | 33 #include "core/dom/Element.h" |
34 #include "core/html/HTMLDocument.h" | 34 #include "core/html/HTMLDocument.h" |
35 | 35 |
36 namespace WebCore { | 36 namespace WebCore { |
37 | 37 |
38 using namespace HTMLNames; | 38 using namespace HTMLNames; |
39 | 39 |
40 namespace { | 40 namespace { |
41 | 41 |
42 template <bool checkValue(const Element&, const CSSSelector*)> | 42 template <bool checkValue(const Element&, const CSSSelector&)> |
43 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*
& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOr
SubselectorMatchElement) | 43 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*
& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOr
SubselectorMatchElement) |
44 { | 44 { |
45 for (; element; element = element->parentElement()) { | 45 for (; element; element = element->parentElement()) { |
46 if (checkValue(*element, selector)) { | 46 if (checkValue(*element, *selector)) { |
47 if (selector->relation() == CSSSelector::Descendant) | 47 if (selector->relation() == CSSSelector::Descendant) |
48 topChildOrSubselector = 0; | 48 topChildOrSubselector = 0; |
49 else if (!topChildOrSubselector) { | 49 else if (!topChildOrSubselector) { |
50 ASSERT(selector->relation() == CSSSelector::Child || selector->r
elation() == CSSSelector::SubSelector); | 50 ASSERT(selector->relation() == CSSSelector::Child || selector->r
elation() == CSSSelector::SubSelector); |
51 topChildOrSubselector = selector; | 51 topChildOrSubselector = selector; |
52 topChildOrSubselectorMatchElement = element; | 52 topChildOrSubselectorMatchElement = element; |
53 } | 53 } |
54 if (selector->relation() != CSSSelector::SubSelector) | 54 if (selector->relation() != CSSSelector::SubSelector) |
55 element = element->parentElement(); | 55 element = element->parentElement(); |
56 selector = selector->tagHistory(); | 56 selector = selector->tagHistory(); |
57 return true; | 57 return true; |
58 } | 58 } |
59 if (topChildOrSubselector) { | 59 if (topChildOrSubselector) { |
60 // Child or subselector check failed. | 60 // Child or subselector check failed. |
61 // If the match element is null, topChildOrSubselector was also the
very topmost selector and had to match | 61 // If the match element is null, topChildOrSubselector was also the
very topmost selector and had to match |
62 // the original element we were checking. | 62 // the original element we were checking. |
63 if (!topChildOrSubselectorMatchElement) | 63 if (!topChildOrSubselectorMatchElement) |
64 return false; | 64 return false; |
65 // There may be other matches down the ancestor chain. | 65 // There may be other matches down the ancestor chain. |
66 // Rewind to the topmost child or subselector and the element it mat
ched, continue checking ancestors. | 66 // Rewind to the topmost child or subselector and the element it mat
ched, continue checking ancestors. |
67 selector = topChildOrSubselector; | 67 selector = topChildOrSubselector; |
68 element = topChildOrSubselectorMatchElement->parentElement(); | 68 element = topChildOrSubselectorMatchElement->parentElement(); |
69 topChildOrSubselector = 0; | 69 topChildOrSubselector = 0; |
70 return true; | 70 return true; |
71 } | 71 } |
72 } | 72 } |
73 return false; | 73 return false; |
74 } | 74 } |
75 | 75 |
76 inline bool checkClassValue(const Element& element, const CSSSelector* selector) | 76 inline bool checkClassValue(const Element& element, const CSSSelector& selector) |
77 { | 77 { |
78 return element.hasClass() && element.classNames().contains(selector->value()
); | 78 return element.hasClass() && element.classNames().contains(selector.value())
; |
79 } | 79 } |
80 | 80 |
81 inline bool checkIDValue(const Element& element, const CSSSelector* selector) | 81 inline bool checkIDValue(const Element& element, const CSSSelector& selector) |
82 { | 82 { |
83 return element.hasID() && element.idForStyleResolution() == selector->value(
); | 83 return element.hasID() && element.idForStyleResolution() == selector.value()
; |
84 } | 84 } |
85 | 85 |
86 inline bool checkExactAttributeValue(const Element& element, const CSSSelector*
selector) | 86 inline bool checkExactAttributeValue(const Element& element, const CSSSelector&
selector) |
87 { | 87 { |
88 return SelectorChecker::checkExactAttribute(element, selector->attribute(),
selector->value().impl()); | 88 return SelectorChecker::checkExactAttribute(element, selector.attribute(), s
elector.value().impl()); |
89 } | 89 } |
90 | 90 |
91 inline bool checkTagValue(const Element& element, const CSSSelector* selector) | 91 inline bool checkTagValue(const Element& element, const CSSSelector& selector) |
92 { | 92 { |
93 return SelectorChecker::tagMatches(element, selector->tagQName()); | 93 return SelectorChecker::tagMatches(element, selector.tagQName()); |
94 } | 94 } |
95 | 95 |
96 } | 96 } |
97 | 97 |
98 SelectorCheckerFastPath::SelectorCheckerFastPath(const CSSSelector* selector, co
nst Element& element) | 98 SelectorCheckerFastPath::SelectorCheckerFastPath(const CSSSelector& selector, co
nst Element& element) |
99 : m_selector(selector) | 99 : m_selector(selector) |
100 , m_element(element) | 100 , m_element(element) |
101 { | 101 { |
102 } | 102 } |
103 | 103 |
104 bool SelectorCheckerFastPath::matchesRightmostSelector(SelectorChecker::VisitedM
atchType visitedMatchType) const | 104 bool SelectorCheckerFastPath::matchesRightmostSelector(SelectorChecker::VisitedM
atchType visitedMatchType) const |
105 { | 105 { |
106 ASSERT(SelectorCheckerFastPath::canUse(m_selector)); | 106 ASSERT(SelectorCheckerFastPath::canUse(m_selector)); |
107 | 107 |
108 switch (m_selector->m_match) { | 108 switch (m_selector.m_match) { |
109 case CSSSelector::Tag: | 109 case CSSSelector::Tag: |
110 return checkTagValue(m_element, m_selector); | 110 return checkTagValue(m_element, m_selector); |
111 case CSSSelector::Class: | 111 case CSSSelector::Class: |
112 return checkClassValue(m_element, m_selector); | 112 return checkClassValue(m_element, m_selector); |
113 case CSSSelector::Id: | 113 case CSSSelector::Id: |
114 return checkIDValue(m_element, m_selector); | 114 return checkIDValue(m_element, m_selector); |
115 case CSSSelector::Exact: | 115 case CSSSelector::Exact: |
116 case CSSSelector::Set: | 116 case CSSSelector::Set: |
117 return checkExactAttributeValue(m_element, m_selector); | 117 return checkExactAttributeValue(m_element, m_selector); |
118 case CSSSelector::PseudoClass: | 118 case CSSSelector::PseudoClass: |
119 return commonPseudoClassSelectorMatches(visitedMatchType); | 119 return commonPseudoClassSelectorMatches(visitedMatchType); |
120 default: | 120 default: |
121 ASSERT_NOT_REACHED(); | 121 ASSERT_NOT_REACHED(); |
122 } | 122 } |
123 return false; | 123 return false; |
124 } | 124 } |
125 | 125 |
126 bool SelectorCheckerFastPath::matches() const | 126 bool SelectorCheckerFastPath::matches() const |
127 { | 127 { |
128 ASSERT(matchesRightmostSelector(SelectorChecker::VisitedMatchEnabled)); | 128 ASSERT(matchesRightmostSelector(SelectorChecker::VisitedMatchEnabled)); |
129 const CSSSelector* selector = m_selector; | 129 const CSSSelector* selector = &m_selector; |
130 const Element* element = &m_element; | 130 const Element* element = &m_element; |
131 | 131 |
132 const CSSSelector* topChildOrSubselector = 0; | 132 const CSSSelector* topChildOrSubselector = 0; |
133 const Element* topChildOrSubselectorMatchElement = 0; | 133 const Element* topChildOrSubselectorMatchElement = 0; |
134 if (selector->relation() == CSSSelector::Child || selector->relation() == CS
SSelector::SubSelector) | 134 if (selector->relation() == CSSSelector::Child || selector->relation() == CS
SSelector::SubSelector) |
135 topChildOrSubselector = selector; | 135 topChildOrSubselector = selector; |
136 | 136 |
137 if (selector->relation() != CSSSelector::SubSelector) | 137 if (selector->relation() != CSSSelector::SubSelector) |
138 element = element->parentElement(); | 138 element = element->parentElement(); |
139 | 139 |
(...skipping 24 matching lines...) Expand all Loading... |
164 } | 164 } |
165 } | 165 } |
166 return true; | 166 return true; |
167 } | 167 } |
168 | 168 |
169 static inline bool isFastCheckableRelation(CSSSelector::Relation relation) | 169 static inline bool isFastCheckableRelation(CSSSelector::Relation relation) |
170 { | 170 { |
171 return relation == CSSSelector::Descendant || relation == CSSSelector::Child
|| relation == CSSSelector::SubSelector; | 171 return relation == CSSSelector::Descendant || relation == CSSSelector::Child
|| relation == CSSSelector::SubSelector; |
172 } | 172 } |
173 | 173 |
174 static inline bool isFastCheckableMatch(const CSSSelector* selector) | 174 static inline bool isFastCheckableMatch(const CSSSelector& selector) |
175 { | 175 { |
176 if (selector->m_match == CSSSelector::Set) { | 176 if (selector.m_match == CSSSelector::Set) { |
177 // Style attribute is generated lazily but the fast path doesn't trigger
it. | 177 // Style attribute is generated lazily but the fast path doesn't trigger
it. |
178 // Disallow them here rather than making the fast path more branchy. | 178 // Disallow them here rather than making the fast path more branchy. |
179 return selector->attribute() != styleAttr; | 179 return selector.attribute() != styleAttr; |
180 } | 180 } |
181 if (selector->m_match == CSSSelector::Exact) | 181 if (selector.m_match == CSSSelector::Exact) |
182 return selector->attribute() != styleAttr && HTMLDocument::isCaseSensiti
veAttribute(selector->attribute()); | 182 return selector.attribute() != styleAttr && HTMLDocument::isCaseSensitiv
eAttribute(selector.attribute()); |
183 return selector->m_match == CSSSelector::Tag || selector->m_match == CSSSele
ctor::Id || selector->m_match == CSSSelector::Class; | 183 return selector.m_match == CSSSelector::Tag || selector.m_match == CSSSelect
or::Id || selector.m_match == CSSSelector::Class; |
184 } | 184 } |
185 | 185 |
186 static inline bool isFastCheckableRightmostSelector(const CSSSelector* selector) | 186 static inline bool isFastCheckableRightmostSelector(const CSSSelector& selector) |
187 { | 187 { |
188 if (!isFastCheckableRelation(selector->relation())) | 188 if (!isFastCheckableRelation(selector.relation())) |
189 return false; | 189 return false; |
190 return isFastCheckableMatch(selector) || SelectorChecker::isCommonPseudoClas
sSelector(selector); | 190 return isFastCheckableMatch(selector) || SelectorChecker::isCommonPseudoClas
sSelector(selector); |
191 } | 191 } |
192 | 192 |
193 bool SelectorCheckerFastPath::canUse(const CSSSelector* selector) | 193 bool SelectorCheckerFastPath::canUse(const CSSSelector& selector) |
194 { | 194 { |
195 if (!isFastCheckableRightmostSelector(selector)) | 195 if (!isFastCheckableRightmostSelector(selector)) |
196 return false; | 196 return false; |
197 for (selector = selector->tagHistory(); selector; selector = selector->tagHi
story()) { | 197 for (const CSSSelector* current = selector.tagHistory(); current; current =
current->tagHistory()) { |
198 if (!isFastCheckableRelation(selector->relation())) | 198 if (!isFastCheckableRelation(current->relation())) |
199 return false; | 199 return false; |
200 if (!isFastCheckableMatch(selector)) | 200 if (!isFastCheckableMatch(*current)) |
201 return false; | 201 return false; |
202 } | 202 } |
203 return true; | 203 return true; |
204 } | 204 } |
205 | 205 |
206 bool SelectorCheckerFastPath::commonPseudoClassSelectorMatches(SelectorChecker::
VisitedMatchType visitedMatchType) const | 206 bool SelectorCheckerFastPath::commonPseudoClassSelectorMatches(SelectorChecker::
VisitedMatchType visitedMatchType) const |
207 { | 207 { |
208 ASSERT(SelectorChecker::isCommonPseudoClassSelector(m_selector)); | 208 ASSERT(SelectorChecker::isCommonPseudoClassSelector(m_selector)); |
209 switch (m_selector->pseudoType()) { | 209 switch (m_selector.pseudoType()) { |
210 case CSSSelector::PseudoLink: | 210 case CSSSelector::PseudoLink: |
211 case CSSSelector::PseudoAnyLink: | 211 case CSSSelector::PseudoAnyLink: |
212 return m_element.isLink(); | 212 return m_element.isLink(); |
213 case CSSSelector::PseudoVisited: | 213 case CSSSelector::PseudoVisited: |
214 return m_element.isLink() && visitedMatchType == SelectorChecker::Visite
dMatchEnabled; | 214 return m_element.isLink() && visitedMatchType == SelectorChecker::Visite
dMatchEnabled; |
215 case CSSSelector::PseudoFocus: | 215 case CSSSelector::PseudoFocus: |
216 return SelectorChecker::matchesFocusPseudoClass(m_element); | 216 return SelectorChecker::matchesFocusPseudoClass(m_element); |
217 default: | 217 default: |
218 ASSERT_NOT_REACHED(); | 218 ASSERT_NOT_REACHED(); |
219 } | 219 } |
220 return true; | 220 return true; |
221 } | 221 } |
222 | 222 |
223 | 223 |
224 } | 224 } |
OLD | NEW |