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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 if (!checkOne(context, siblingTraversalStrategy, &specificity)) | 147 if (!checkOne(context, siblingTraversalStrategy, &specificity)) |
148 return SelectorFailsLocally; | 148 return SelectorFailsLocally; |
149 | 149 |
150 if (context.selector->m_match == CSSSelector::PseudoElement) { | 150 if (context.selector->m_match == CSSSelector::PseudoElement) { |
151 if (context.selector->isCustomPseudoElement()) { | 151 if (context.selector->isCustomPseudoElement()) { |
152 if (!matchesCustomPseudoElement(context.element, *context.selector)) | 152 if (!matchesCustomPseudoElement(context.element, *context.selector)) |
153 return SelectorFailsLocally; | 153 return SelectorFailsLocally; |
154 } else if (context.selector->isContentPseudoElement()) { | 154 } else if (context.selector->isContentPseudoElement()) { |
155 if (!context.element->isInShadowTree() || !context.element->isInsert
ionPoint()) | 155 if (!context.element->isInShadowTree() || !context.element->isInsert
ionPoint()) |
156 return SelectorFailsLocally; | 156 return SelectorFailsLocally; |
| 157 } else if (context.selector->isShadowPseudoElement()) { |
| 158 if (!context.element->isInShadowTree()) |
| 159 return SelectorFailsLocally; |
157 } else { | 160 } else { |
158 if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode ==
QueryingRules) | 161 if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode ==
QueryingRules) |
159 return SelectorFailsLocally; | 162 return SelectorFailsLocally; |
160 | 163 |
161 PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoTy
pe()); | 164 PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoTy
pe()); |
162 if (pseudoId == FIRST_LETTER) | 165 if (pseudoId == FIRST_LETTER) |
163 context.element->document().styleEngine()->setUsesFirstLetterRul
es(true); | 166 context.element->document().styleEngine()->setUsesFirstLetterRul
es(true); |
164 if (pseudoId != NOPSEUDO && m_mode != SharingRules && result) | 167 if (pseudoId != NOPSEUDO && m_mode != SharingRules && result) |
165 result->dynamicPseudo = pseudoId; | 168 result->dynamicPseudo = pseudoId; |
166 } | 169 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } | 207 } |
205 | 208 |
206 static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRela
tion(const SelectorChecker::SelectorCheckingContext& context) | 209 static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRela
tion(const SelectorChecker::SelectorCheckingContext& context) |
207 { | 210 { |
208 SelectorChecker::SelectorCheckingContext nextContext(context); | 211 SelectorChecker::SelectorCheckingContext nextContext(context); |
209 ASSERT(context.selector->tagHistory()); | 212 ASSERT(context.selector->tagHistory()); |
210 nextContext.selector = context.selector->tagHistory(); | 213 nextContext.selector = context.selector->tagHistory(); |
211 return nextContext; | 214 return nextContext; |
212 } | 215 } |
213 | 216 |
| 217 static inline bool isAuthorShadowRoot(const Node* node) |
| 218 { |
| 219 return node && node->isShadowRoot() && toShadowRoot(node)->type() == ShadowR
oot::AuthorShadowRoot; |
| 220 } |
| 221 |
214 template<typename SiblingTraversalStrategy> | 222 template<typename SiblingTraversalStrategy> |
215 SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorChecki
ngContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, Ma
tchResult* result) const | 223 SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorChecki
ngContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, Ma
tchResult* result) const |
216 { | 224 { |
217 SelectorCheckingContext nextContext = prepareNextContextForRelation(context)
; | 225 SelectorCheckingContext nextContext = prepareNextContextForRelation(context)
; |
218 | 226 |
219 PseudoId dynamicPseudo = result ? result->dynamicPseudo : NOPSEUDO; | 227 PseudoId dynamicPseudo = result ? result->dynamicPseudo : NOPSEUDO; |
220 // a selector is invalid if something follows a pseudo-element | 228 // a selector is invalid if something follows a pseudo-element |
221 // We make an exception for scrollbar pseudo elements and allow a set of pse
udo classes (but nothing else) | 229 // We make an exception for scrollbar pseudo elements and allow a set of pse
udo classes (but nothing else) |
222 // to follow the pseudo elements. | 230 // to follow the pseudo elements. |
223 nextContext.hasScrollbarPseudo = dynamicPseudo != NOPSEUDO && (context.scrol
lbar || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER); | 231 nextContext.hasScrollbarPseudo = dynamicPseudo != NOPSEUDO && (context.scrol
lbar || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER); |
224 nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION; | 232 nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION; |
225 if ((context.elementStyle || m_mode == CollectingCSSRules || m_mode == Colle
ctingStyleRules || m_mode == QueryingRules) && dynamicPseudo != NOPSEUDO | 233 if ((context.elementStyle || m_mode == CollectingCSSRules || m_mode == Colle
ctingStyleRules || m_mode == QueryingRules) && dynamicPseudo != NOPSEUDO |
226 && !nextContext.hasSelectionPseudo | 234 && !nextContext.hasSelectionPseudo |
227 && !(nextContext.hasScrollbarPseudo && nextContext.selector->m_match ==
CSSSelector::PseudoClass)) | 235 && !(nextContext.hasScrollbarPseudo && nextContext.selector->m_match ==
CSSSelector::PseudoClass)) |
228 return SelectorFailsCompletely; | 236 return SelectorFailsCompletely; |
229 | 237 |
230 nextContext.isSubSelector = true; | 238 nextContext.isSubSelector = true; |
231 return match(nextContext, siblingTraversalStrategy, result); | 239 return match(nextContext, siblingTraversalStrategy, result); |
232 } | 240 } |
233 | 241 |
| 242 static bool selectorMatchesShadowRoot(const CSSSelector* selector) |
| 243 { |
| 244 return selector && selector->isShadowPseudoElement(); |
| 245 } |
| 246 |
| 247 template<typename SiblingTraversalStrategy> |
| 248 SelectorChecker::Match SelectorChecker::matchForPseudoShadow(const ContainerNode
* node, const SelectorCheckingContext& context, const SiblingTraversalStrategy&
siblingTraversalStrategy, MatchResult* result) const |
| 249 { |
| 250 if (!isAuthorShadowRoot(node)) |
| 251 return SelectorFailsCompletely; |
| 252 return match(context, siblingTraversalStrategy, result); |
| 253 } |
| 254 |
234 template<typename SiblingTraversalStrategy> | 255 template<typename SiblingTraversalStrategy> |
235 SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC
ontext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, Match
Result* result) const | 256 SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC
ontext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, Match
Result* result) const |
236 { | 257 { |
237 SelectorCheckingContext nextContext = prepareNextContextForRelation(context)
; | 258 SelectorCheckingContext nextContext = prepareNextContextForRelation(context)
; |
238 | 259 |
239 CSSSelector::Relation relation = context.selector->relation(); | 260 CSSSelector::Relation relation = context.selector->relation(); |
240 | 261 |
241 // Disable :visited matching when we see the first link or try to match anyt
hing else than an ancestors. | 262 // Disable :visited matching when we see the first link or try to match anyt
hing else than an ancestors. |
242 if (!context.isSubSelector && (context.element->isLink() || (relation != CSS
Selector::Descendant && relation != CSSSelector::Child))) | 263 if (!context.isSubSelector && (context.element->isLink() || (relation != CSS
Selector::Descendant && relation != CSSSelector::Child))) |
243 nextContext.visitedMatchType = VisitedMatchDisabled; | 264 nextContext.visitedMatchType = VisitedMatchDisabled; |
244 | 265 |
245 nextContext.pseudoId = NOPSEUDO; | 266 nextContext.pseudoId = NOPSEUDO; |
246 | 267 |
247 switch (relation) { | 268 switch (relation) { |
248 case CSSSelector::Descendant: | 269 case CSSSelector::Descendant: |
249 if (context.selector->relationIsAffectedByPseudoContent()) { | 270 if (context.selector->relationIsAffectedByPseudoContent()) { |
250 for (Element* element = context.element; element; element = element-
>parentElement()) { | 271 for (Element* element = context.element; element; element = element-
>parentElement()) { |
251 if (matchForShadowDistributed(element, siblingTraversalStrategy,
nextContext, result) == SelectorMatches) | 272 if (matchForShadowDistributed(element, siblingTraversalStrategy,
nextContext, result) == SelectorMatches) |
252 return SelectorMatches; | 273 return SelectorMatches; |
253 } | 274 } |
254 return SelectorFailsCompletely; | 275 return SelectorFailsCompletely; |
255 } | 276 } |
256 nextContext.isSubSelector = false; | 277 nextContext.isSubSelector = false; |
257 nextContext.elementStyle = 0; | 278 nextContext.elementStyle = 0; |
| 279 |
| 280 if (selectorMatchesShadowRoot(nextContext.selector)) |
| 281 return matchForPseudoShadow(context.element->containingShadowRoot(),
nextContext, siblingTraversalStrategy, result); |
| 282 |
258 for (nextContext.element = parentElement(context); nextContext.element;
nextContext.element = parentElement(nextContext)) { | 283 for (nextContext.element = parentElement(context); nextContext.element;
nextContext.element = parentElement(nextContext)) { |
259 Match match = this->match(nextContext, siblingTraversalStrategy, res
ult); | 284 Match match = this->match(nextContext, siblingTraversalStrategy, res
ult); |
260 if (match == SelectorMatches || match == SelectorFailsCompletely) | 285 if (match == SelectorMatches || match == SelectorFailsCompletely) |
261 return match; | 286 return match; |
262 if (nextSelectorExceedsScope(nextContext)) | 287 if (nextSelectorExceedsScope(nextContext)) |
263 return SelectorFailsCompletely; | 288 return SelectorFailsCompletely; |
264 } | 289 } |
265 return SelectorFailsCompletely; | 290 return SelectorFailsCompletely; |
266 case CSSSelector::Child: | 291 case CSSSelector::Child: |
267 { | 292 { |
268 if (context.selector->relationIsAffectedByPseudoContent()) | 293 if (context.selector->relationIsAffectedByPseudoContent()) |
269 return matchForShadowDistributed(context.element, siblingTravers
alStrategy, nextContext, result); | 294 return matchForShadowDistributed(context.element, siblingTravers
alStrategy, nextContext, result); |
270 | 295 |
| 296 nextContext.isSubSelector = false; |
| 297 nextContext.elementStyle = 0; |
| 298 |
| 299 if (selectorMatchesShadowRoot(nextContext.selector)) |
| 300 return matchForPseudoShadow(context.element->parentNode(), nextC
ontext, siblingTraversalStrategy, result); |
| 301 |
271 nextContext.element = parentElement(context); | 302 nextContext.element = parentElement(context); |
272 if (!nextContext.element) | 303 if (!nextContext.element) |
273 return SelectorFailsCompletely; | 304 return SelectorFailsCompletely; |
274 | |
275 nextContext.isSubSelector = false; | |
276 nextContext.elementStyle = 0; | |
277 return match(nextContext, siblingTraversalStrategy, result); | 305 return match(nextContext, siblingTraversalStrategy, result); |
278 } | 306 } |
279 case CSSSelector::DirectAdjacent: | 307 case CSSSelector::DirectAdjacent: |
280 if (m_mode == ResolvingStyle) { | 308 if (m_mode == ResolvingStyle) { |
281 if (ContainerNode* parent = context.element->parentElementOrShadowRo
ot()) | 309 if (ContainerNode* parent = context.element->parentElementOrShadowRo
ot()) |
282 parent->setChildrenAffectedByDirectAdjacentRules(); | 310 parent->setChildrenAffectedByDirectAdjacentRules(); |
283 } | 311 } |
284 nextContext.element = ElementTraversal::previousSibling(*context.element
); | 312 nextContext.element = ElementTraversal::previousSibling(*context.element
); |
285 if (!nextContext.element) | 313 if (!nextContext.element) |
286 return SelectorFailsAllSiblings; | 314 return SelectorFailsAllSiblings; |
(...skipping 10 matching lines...) Expand all Loading... |
297 nextContext.isSubSelector = false; | 325 nextContext.isSubSelector = false; |
298 nextContext.elementStyle = 0; | 326 nextContext.elementStyle = 0; |
299 for (; nextContext.element; nextContext.element = ElementTraversal::prev
iousSibling(*nextContext.element)) { | 327 for (; nextContext.element; nextContext.element = ElementTraversal::prev
iousSibling(*nextContext.element)) { |
300 Match match = this->match(nextContext, siblingTraversalStrategy, res
ult); | 328 Match match = this->match(nextContext, siblingTraversalStrategy, res
ult); |
301 if (match == SelectorMatches || match == SelectorFailsAllSiblings ||
match == SelectorFailsCompletely) | 329 if (match == SelectorMatches || match == SelectorFailsAllSiblings ||
match == SelectorFailsCompletely) |
302 return match; | 330 return match; |
303 }; | 331 }; |
304 return SelectorFailsAllSiblings; | 332 return SelectorFailsAllSiblings; |
305 | 333 |
306 case CSSSelector::ShadowPseudo: | 334 case CSSSelector::ShadowPseudo: |
307 case CSSSelector::Shadow: | |
308 { | 335 { |
309 // If we're in the same tree-scope as the scoping element, then foll
owing a shadow descendant combinator would escape that and thus the scope. | 336 // If we're in the same tree-scope as the scoping element, then foll
owing a shadow descendant combinator would escape that and thus the scope. |
310 if (context.scope && context.scope->treeScope() == context.element->
treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithi
nTreeScope) | 337 if (context.scope && context.scope->treeScope() == context.element->
treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithi
nTreeScope) |
311 return SelectorFailsCompletely; | 338 return SelectorFailsCompletely; |
312 | 339 |
313 Element* shadowHost = context.element->shadowHost(); | 340 Element* shadowHost = context.element->shadowHost(); |
314 if (!shadowHost) | 341 if (!shadowHost) |
315 return SelectorFailsCompletely; | 342 return SelectorFailsCompletely; |
316 nextContext.element = shadowHost; | 343 nextContext.element = shadowHost; |
317 nextContext.isSubSelector = false; | 344 nextContext.isSubSelector = false; |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 return element.focused() && isFrameFocused(element); | 1124 return element.focused() && isFrameFocused(element); |
1098 } | 1125 } |
1099 | 1126 |
1100 template | 1127 template |
1101 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst DOMSiblingTraversalStrategy&, MatchResult*) const; | 1128 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst DOMSiblingTraversalStrategy&, MatchResult*) const; |
1102 | 1129 |
1103 template | 1130 template |
1104 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; | 1131 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co
nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const; |
1105 | 1132 |
1106 } | 1133 } |
OLD | NEW |