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

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

Issue 210713002: Implement ::shadow pseudo element and replace /shadow/ with ::shadow. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixed patch conflict Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/css/SelectorChecker.h ('k') | Source/core/css/SelectorFilter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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. 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
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
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
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
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 }
OLDNEW
« no previous file with comments | « Source/core/css/SelectorChecker.h ('k') | Source/core/css/SelectorFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698