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

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

Issue 1129673002: Remove support for pseudo classes in <content select>. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix more tests. Created 5 years, 7 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
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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 return true; 153 return true;
154 return context.element->isLink(); 154 return context.element->isLink();
155 } 155 }
156 156
157 // Recursive check of selectors and combinators 157 // Recursive check of selectors and combinators
158 // It can return 4 different values: 158 // It can return 4 different values:
159 // * SelectorMatches - the selector matches the element e 159 // * SelectorMatches - the selector matches the element e
160 // * SelectorFailsLocally - the selector fails for the element e 160 // * SelectorFailsLocally - the selector fails for the element e
161 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e 161 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
162 // * SelectorFailsCompletely - the selector fails for e and any sibling or ance stor of e 162 // * SelectorFailsCompletely - the selector fails for e and any sibling or ance stor of e
163 template<typename SiblingTraversalStrategy> 163 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con text, MatchResult* result) const
164 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con text, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* res ult) const
165 { 164 {
166 // first selector has to match 165 // first selector has to match
167 unsigned specificity = 0; 166 unsigned specificity = 0;
168 if (!checkOne(context, siblingTraversalStrategy, &specificity)) 167 if (!checkOne(context, &specificity))
169 return SelectorFailsLocally; 168 return SelectorFailsLocally;
170 169
171 if (context.selector->match() == CSSSelector::PseudoElement) { 170 if (context.selector->match() == CSSSelector::PseudoElement) {
172 if (context.selector->isCustomPseudoElement()) { 171 if (context.selector->isCustomPseudoElement()) {
173 if (!matchesCustomPseudoElement(context.element, *context.selector)) 172 if (!matchesCustomPseudoElement(context.element, *context.selector))
174 return SelectorFailsLocally; 173 return SelectorFailsLocally;
175 } else if (context.selector->isContentPseudoElement()) { 174 } else if (context.selector->isContentPseudoElement()) {
176 if (!context.element->isInShadowTree() || !context.element->isInsert ionPoint()) 175 if (!context.element->isInShadowTree() || !context.element->isInsert ionPoint())
177 return SelectorFailsLocally; 176 return SelectorFailsLocally;
178 } else if (context.selector->isShadowPseudoElement()) { 177 } else if (context.selector->isShadowPseudoElement()) {
(...skipping 26 matching lines...) Expand all
205 // Abort if the next selector would exceed the scope. 204 // Abort if the next selector would exceed the scope.
206 if (nextSelectorExceedsScope(context)) 205 if (nextSelectorExceedsScope(context))
207 return SelectorFailsCompletely; 206 return SelectorFailsCompletely;
208 207
209 // Bail-out if this selector is irrelevant for the pseudoId 208 // Bail-out if this selector is irrelevant for the pseudoId
210 if (context.pseudoId != NOPSEUDO && (!result || context.pseudoId != resu lt->dynamicPseudo)) 209 if (context.pseudoId != NOPSEUDO && (!result || context.pseudoId != resu lt->dynamicPseudo))
211 return SelectorFailsCompletely; 210 return SelectorFailsCompletely;
212 211
213 if (result) { 212 if (result) {
214 TemporaryChange<PseudoId> dynamicPseudoScope(result->dynamicPseudo, NOPSEUDO); 213 TemporaryChange<PseudoId> dynamicPseudoScope(result->dynamicPseudo, NOPSEUDO);
215 match = matchForRelation(context, siblingTraversalStrategy, result); 214 match = matchForRelation(context, result);
216 } else { 215 } else {
217 return matchForRelation(context, siblingTraversalStrategy, 0); 216 return matchForRelation(context, 0);
218 } 217 }
219 } else { 218 } else {
220 match = matchForSubSelector(context, siblingTraversalStrategy, result); 219 match = matchForSubSelector(context, result);
221 } 220 }
222 if (match != SelectorMatches || !result) 221 if (match != SelectorMatches || !result)
223 return match; 222 return match;
224 223
225 result->specificity += specificity; 224 result->specificity += specificity;
226 return SelectorMatches; 225 return SelectorMatches;
227 } 226 }
228 227
229 static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRela tion(const SelectorChecker::SelectorCheckingContext& context) 228 static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRela tion(const SelectorChecker::SelectorCheckingContext& context)
230 { 229 {
231 SelectorChecker::SelectorCheckingContext nextContext(context); 230 SelectorChecker::SelectorCheckingContext nextContext(context);
232 ASSERT(context.selector->tagHistory()); 231 ASSERT(context.selector->tagHistory());
233 nextContext.selector = context.selector->tagHistory(); 232 nextContext.selector = context.selector->tagHistory();
234 return nextContext; 233 return nextContext;
235 } 234 }
236 235
237 static inline bool isOpenShadowRoot(const Node* node) 236 static inline bool isOpenShadowRoot(const Node* node)
238 { 237 {
239 return node && node->isShadowRoot() && toShadowRoot(node)->type() == ShadowR oot::OpenShadowRoot; 238 return node && node->isShadowRoot() && toShadowRoot(node)->type() == ShadowR oot::OpenShadowRoot;
240 } 239 }
241 240
242 template<typename SiblingTraversalStrategy> 241 SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorChecki ngContext& context, MatchResult* result) const
243 SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorChecki ngContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, Ma tchResult* result) const
244 { 242 {
245 SelectorCheckingContext nextContext = prepareNextContextForRelation(context) ; 243 SelectorCheckingContext nextContext = prepareNextContextForRelation(context) ;
246 244
247 PseudoId dynamicPseudo = result ? result->dynamicPseudo : NOPSEUDO; 245 PseudoId dynamicPseudo = result ? result->dynamicPseudo : NOPSEUDO;
248 // a selector is invalid if something follows a pseudo-element 246 // a selector is invalid if something follows a pseudo-element
249 // We make an exception for scrollbar pseudo elements and allow a set of pse udo classes (but nothing else) 247 // We make an exception for scrollbar pseudo elements and allow a set of pse udo classes (but nothing else)
250 // to follow the pseudo elements. 248 // to follow the pseudo elements.
251 nextContext.hasScrollbarPseudo = dynamicPseudo != NOPSEUDO && (context.scrol lbar || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER); 249 nextContext.hasScrollbarPseudo = dynamicPseudo != NOPSEUDO && (context.scrol lbar || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER);
252 nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION; 250 nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION;
253 if ((context.elementStyle || m_mode == CollectingCSSRules || m_mode == Colle ctingStyleRules || m_mode == QueryingRules) && dynamicPseudo != NOPSEUDO 251 if ((context.elementStyle || m_mode == CollectingCSSRules || m_mode == Colle ctingStyleRules || m_mode == QueryingRules) && dynamicPseudo != NOPSEUDO
254 && !nextContext.hasSelectionPseudo 252 && !nextContext.hasSelectionPseudo
255 && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass)) 253 && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass))
256 return SelectorFailsCompletely; 254 return SelectorFailsCompletely;
257 255
258 nextContext.isSubSelector = true; 256 nextContext.isSubSelector = true;
259 return match(nextContext, siblingTraversalStrategy, result); 257 return match(nextContext, result);
260 } 258 }
261 259
262 static bool selectorMatchesShadowRoot(const CSSSelector* selector) 260 static bool selectorMatchesShadowRoot(const CSSSelector* selector)
263 { 261 {
264 return selector && selector->isShadowPseudoElement(); 262 return selector && selector->isShadowPseudoElement();
265 } 263 }
266 264
267 static inline Element* parentOrShadowHostButDisallowEscapingUserAgentShadowTree( const Element& element) 265 static inline Element* parentOrShadowHostButDisallowEscapingUserAgentShadowTree( const Element& element)
268 { 266 {
269 ContainerNode* parent = element.parentOrShadowHostNode(); 267 ContainerNode* parent = element.parentOrShadowHostNode();
270 if (!parent) 268 if (!parent)
271 return nullptr; 269 return nullptr;
272 if (parent->isShadowRoot()) 270 if (parent->isShadowRoot())
273 return (toShadowRoot(parent)->type() == ShadowRoot::UserAgentShadowRoot) ? nullptr : toShadowRoot(parent)->host(); 271 return (toShadowRoot(parent)->type() == ShadowRoot::UserAgentShadowRoot) ? nullptr : toShadowRoot(parent)->host();
274 if (!parent->isElementNode()) 272 if (!parent->isElementNode())
275 return nullptr; 273 return nullptr;
276 return toElement(parent); 274 return toElement(parent);
277 } 275 }
278 276
279 template<typename SiblingTraversalStrategy> 277 SelectorChecker::Match SelectorChecker::matchForPseudoShadow(const ContainerNode * node, const SelectorCheckingContext& context, MatchResult* result) const
280 SelectorChecker::Match SelectorChecker::matchForPseudoShadow(const ContainerNode * node, const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const
281 { 278 {
282 if (!isOpenShadowRoot(node)) 279 if (!isOpenShadowRoot(node))
283 return SelectorFailsCompletely; 280 return SelectorFailsCompletely;
284 return match(context, siblingTraversalStrategy, result); 281 return match(context, result);
285 } 282 }
286 283
287 template<typename SiblingTraversalStrategy> 284 SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC ontext& context, MatchResult* result) const
288 SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC ontext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, Match Result* result) const
289 { 285 {
290 SelectorCheckingContext nextContext = prepareNextContextForRelation(context) ; 286 SelectorCheckingContext nextContext = prepareNextContextForRelation(context) ;
291 nextContext.previousElement = context.element; 287 nextContext.previousElement = context.element;
292 288
293 CSSSelector::Relation relation = context.selector->relation(); 289 CSSSelector::Relation relation = context.selector->relation();
294 290
295 // Disable :visited matching when we see the first link or try to match anyt hing else than an ancestors. 291 // Disable :visited matching when we see the first link or try to match anyt hing else than an ancestors.
296 if (!context.isSubSelector && (context.element->isLink() || (relation != CSS Selector::Descendant && relation != CSSSelector::Child))) 292 if (!context.isSubSelector && (context.element->isLink() || (relation != CSS Selector::Descendant && relation != CSSSelector::Child)))
297 nextContext.visitedMatchType = VisitedMatchDisabled; 293 nextContext.visitedMatchType = VisitedMatchDisabled;
298 294
299 nextContext.pseudoId = NOPSEUDO; 295 nextContext.pseudoId = NOPSEUDO;
300 296
301 switch (relation) { 297 switch (relation) {
302 case CSSSelector::Descendant: 298 case CSSSelector::Descendant:
303 if (context.selector->relationIsAffectedByPseudoContent()) { 299 if (context.selector->relationIsAffectedByPseudoContent()) {
304 for (Element* element = context.element; element; element = element- >parentElement()) { 300 for (Element* element = context.element; element; element = element- >parentElement()) {
305 if (matchForShadowDistributed(element, siblingTraversalStrategy, nextContext, result) == SelectorMatches) 301 if (matchForShadowDistributed(element, nextContext, result) == S electorMatches)
306 return SelectorMatches; 302 return SelectorMatches;
307 } 303 }
308 return SelectorFailsCompletely; 304 return SelectorFailsCompletely;
309 } 305 }
310 nextContext.isSubSelector = false; 306 nextContext.isSubSelector = false;
311 nextContext.elementStyle = 0; 307 nextContext.elementStyle = 0;
312 308
313 if (selectorMatchesShadowRoot(nextContext.selector)) 309 if (selectorMatchesShadowRoot(nextContext.selector))
314 return matchForPseudoShadow(context.element->containingShadowRoot(), nextContext, siblingTraversalStrategy, result); 310 return matchForPseudoShadow(context.element->containingShadowRoot(), nextContext, result);
315 311
316 for (nextContext.element = parentElement(context); nextContext.element; nextContext.element = parentElement(nextContext)) { 312 for (nextContext.element = parentElement(context); nextContext.element; nextContext.element = parentElement(nextContext)) {
317 Match match = this->match(nextContext, siblingTraversalStrategy, res ult); 313 Match match = this->match(nextContext, result);
318 if (match == SelectorMatches || match == SelectorFailsCompletely) 314 if (match == SelectorMatches || match == SelectorFailsCompletely)
319 return match; 315 return match;
320 if (nextSelectorExceedsScope(nextContext)) 316 if (nextSelectorExceedsScope(nextContext))
321 return SelectorFailsCompletely; 317 return SelectorFailsCompletely;
322 } 318 }
323 return SelectorFailsCompletely; 319 return SelectorFailsCompletely;
324 case CSSSelector::Child: 320 case CSSSelector::Child:
325 { 321 {
326 if (context.selector->relationIsAffectedByPseudoContent()) 322 if (context.selector->relationIsAffectedByPseudoContent())
327 return matchForShadowDistributed(context.element, siblingTravers alStrategy, nextContext, result); 323 return matchForShadowDistributed(context.element, nextContext, r esult);
328 324
329 nextContext.isSubSelector = false; 325 nextContext.isSubSelector = false;
330 nextContext.elementStyle = 0; 326 nextContext.elementStyle = 0;
331 327
332 if (selectorMatchesShadowRoot(nextContext.selector)) 328 if (selectorMatchesShadowRoot(nextContext.selector))
333 return matchForPseudoShadow(context.element->parentNode(), nextC ontext, siblingTraversalStrategy, result); 329 return matchForPseudoShadow(context.element->parentNode(), nextC ontext, result);
334 330
335 nextContext.element = parentElement(context); 331 nextContext.element = parentElement(context);
336 if (!nextContext.element) 332 if (!nextContext.element)
337 return SelectorFailsCompletely; 333 return SelectorFailsCompletely;
338 return match(nextContext, siblingTraversalStrategy, result); 334 return match(nextContext, result);
339 } 335 }
340 case CSSSelector::DirectAdjacent: 336 case CSSSelector::DirectAdjacent:
341 // Shadow roots can't have sibling elements 337 // Shadow roots can't have sibling elements
342 if (selectorMatchesShadowRoot(nextContext.selector)) 338 if (selectorMatchesShadowRoot(nextContext.selector))
343 return SelectorFailsCompletely; 339 return SelectorFailsCompletely;
344 340
345 if (m_mode == ResolvingStyle) { 341 if (m_mode == ResolvingStyle) {
346 if (ContainerNode* parent = context.element->parentElementOrShadowRo ot()) 342 if (ContainerNode* parent = context.element->parentElementOrShadowRo ot())
347 parent->setChildrenAffectedByDirectAdjacentRules(); 343 parent->setChildrenAffectedByDirectAdjacentRules();
348 } 344 }
349 nextContext.element = ElementTraversal::previousSibling(*context.element ); 345 nextContext.element = ElementTraversal::previousSibling(*context.element );
350 if (!nextContext.element) 346 if (!nextContext.element)
351 return SelectorFailsAllSiblings; 347 return SelectorFailsAllSiblings;
352 nextContext.isSubSelector = false; 348 nextContext.isSubSelector = false;
353 nextContext.elementStyle = 0; 349 nextContext.elementStyle = 0;
354 return match(nextContext, siblingTraversalStrategy, result); 350 return match(nextContext, result);
355 351
356 case CSSSelector::IndirectAdjacent: 352 case CSSSelector::IndirectAdjacent:
357 // Shadow roots can't have sibling elements 353 // Shadow roots can't have sibling elements
358 if (selectorMatchesShadowRoot(nextContext.selector)) 354 if (selectorMatchesShadowRoot(nextContext.selector))
359 return SelectorFailsCompletely; 355 return SelectorFailsCompletely;
360 356
361 if (m_mode == ResolvingStyle) { 357 if (m_mode == ResolvingStyle) {
362 if (ContainerNode* parent = context.element->parentElementOrShadowRo ot()) 358 if (ContainerNode* parent = context.element->parentElementOrShadowRo ot())
363 parent->setChildrenAffectedByIndirectAdjacentRules(); 359 parent->setChildrenAffectedByIndirectAdjacentRules();
364 } 360 }
365 nextContext.element = ElementTraversal::previousSibling(*context.element ); 361 nextContext.element = ElementTraversal::previousSibling(*context.element );
366 nextContext.isSubSelector = false; 362 nextContext.isSubSelector = false;
367 nextContext.elementStyle = 0; 363 nextContext.elementStyle = 0;
368 for (; nextContext.element; nextContext.element = ElementTraversal::prev iousSibling(*nextContext.element)) { 364 for (; nextContext.element; nextContext.element = ElementTraversal::prev iousSibling(*nextContext.element)) {
369 Match match = this->match(nextContext, siblingTraversalStrategy, res ult); 365 Match match = this->match(nextContext, result);
370 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) 366 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely)
371 return match; 367 return match;
372 }; 368 };
373 return SelectorFailsAllSiblings; 369 return SelectorFailsAllSiblings;
374 370
375 case CSSSelector::ShadowPseudo: 371 case CSSSelector::ShadowPseudo:
376 { 372 {
377 // 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. 373 // 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.
378 if (context.scope && context.scope->shadowHost() && context.scope->s hadowHost()->treeScope() == context.element->treeScope()) 374 if (context.scope && context.scope->shadowHost() && context.scope->s hadowHost()->treeScope() == context.element->treeScope())
379 return SelectorFailsCompletely; 375 return SelectorFailsCompletely;
380 376
381 Element* shadowHost = context.element->shadowHost(); 377 Element* shadowHost = context.element->shadowHost();
382 if (!shadowHost) 378 if (!shadowHost)
383 return SelectorFailsCompletely; 379 return SelectorFailsCompletely;
384 nextContext.element = shadowHost; 380 nextContext.element = shadowHost;
385 nextContext.isSubSelector = false; 381 nextContext.isSubSelector = false;
386 nextContext.elementStyle = 0; 382 nextContext.elementStyle = 0;
387 return this->match(nextContext, siblingTraversalStrategy, result); 383 return this->match(nextContext, result);
388 } 384 }
389 385
390 case CSSSelector::ShadowDeep: 386 case CSSSelector::ShadowDeep:
391 { 387 {
392 if (context.selector->relationIsAffectedByPseudoContent()) { 388 if (context.selector->relationIsAffectedByPseudoContent()) {
393 for (Element* element = context.element; element; element = pare ntOrShadowHostButDisallowEscapingUserAgentShadowTree(*element)) { 389 for (Element* element = context.element; element; element = pare ntOrShadowHostButDisallowEscapingUserAgentShadowTree(*element)) {
394 if (matchForShadowDistributed(element, siblingTraversalStrat egy, nextContext, result) == SelectorMatches) 390 if (matchForShadowDistributed(element, nextContext, result) == SelectorMatches)
395 return SelectorMatches; 391 return SelectorMatches;
396 } 392 }
397 return SelectorFailsCompletely; 393 return SelectorFailsCompletely;
398 } 394 }
399 395
400 nextContext.isSubSelector = false; 396 nextContext.isSubSelector = false;
401 nextContext.elementStyle = 0; 397 nextContext.elementStyle = 0;
402 for (nextContext.element = parentOrShadowHostButDisallowEscapingUser AgentShadowTree(*context.element); nextContext.element; nextContext.element = pa rentOrShadowHostButDisallowEscapingUserAgentShadowTree(*nextContext.element)) { 398 for (nextContext.element = parentOrShadowHostButDisallowEscapingUser AgentShadowTree(*context.element); nextContext.element; nextContext.element = pa rentOrShadowHostButDisallowEscapingUserAgentShadowTree(*nextContext.element)) {
403 Match match = this->match(nextContext, siblingTraversalStrategy, result); 399 Match match = this->match(nextContext, result);
404 if (match == SelectorMatches || match == SelectorFailsCompletely ) 400 if (match == SelectorMatches || match == SelectorFailsCompletely )
405 return match; 401 return match;
406 if (nextSelectorExceedsScope(nextContext)) 402 if (nextSelectorExceedsScope(nextContext))
407 return SelectorFailsCompletely; 403 return SelectorFailsCompletely;
408 } 404 }
409 return SelectorFailsCompletely; 405 return SelectorFailsCompletely;
410 } 406 }
411 407
412 case CSSSelector::SubSelector: 408 case CSSSelector::SubSelector:
413 ASSERT_NOT_REACHED(); 409 ASSERT_NOT_REACHED();
414 } 410 }
415 411
416 ASSERT_NOT_REACHED(); 412 ASSERT_NOT_REACHED();
417 return SelectorFailsCompletely; 413 return SelectorFailsCompletely;
418 } 414 }
419 415
420 template<typename SiblingTraversalStrategy> 416 SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* element, SelectorCheckingContext& nextContext, MatchResult* result) const
421 SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* element, const SiblingTraversalStrategy& siblingTraversalStrategy, SelectorChec kingContext& nextContext, MatchResult* result) const
422 { 417 {
423 ASSERT(element); 418 ASSERT(element);
424 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; 419 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
425 collectDestinationInsertionPoints(*element, insertionPoints); 420 collectDestinationInsertionPoints(*element, insertionPoints);
426 for (size_t i = 0; i < insertionPoints.size(); ++i) { 421 for (size_t i = 0; i < insertionPoints.size(); ++i) {
427 nextContext.element = insertionPoints[i]; 422 nextContext.element = insertionPoints[i];
428 if (m_mode == SharingRules) 423 if (m_mode == SharingRules)
429 nextContext.scope = insertionPoints[i]->containingShadowRoot(); 424 nextContext.scope = insertionPoints[i]->containingShadowRoot();
430 nextContext.isSubSelector = false; 425 nextContext.isSubSelector = false;
431 nextContext.elementStyle = 0; 426 nextContext.elementStyle = 0;
432 if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatc hes) 427 if (match(nextContext, result) == SelectorMatches)
433 return SelectorMatches; 428 return SelectorMatches;
434 } 429 }
435 return SelectorFailsLocally; 430 return SelectorFailsLocally;
436 } 431 }
437 432
438 template<typename CharType> 433 template<typename CharType>
439 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned le ngth) 434 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned le ngth)
440 { 435 {
441 for (unsigned i = 0; i < length; ++i) 436 for (unsigned i = 0; i < length; ++i)
442 if (isHTMLSpace<CharType>(string[i])) 437 if (isHTMLSpace<CharType>(string[i]))
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 UseCounter::count(element.document(), UseCounter::CaseInsensitiveAtt rSelectorMatch); 546 UseCounter::count(element.document(), UseCounter::CaseInsensitiveAtt rSelectorMatch);
552 return true; 547 return true;
553 } 548 }
554 if (selectorAttr.namespaceURI() != starAtom) 549 if (selectorAttr.namespaceURI() != starAtom)
555 return false; 550 return false;
556 } 551 }
557 552
558 return false; 553 return false;
559 } 554 }
560 555
561 template<typename SiblingTraversalStrategy> 556 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, unsigned* specificity) const
562 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib lingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const
563 { 557 {
564 ASSERT(context.element); 558 ASSERT(context.element);
565 Element& element = *context.element; 559 Element& element = *context.element;
566 ASSERT(context.selector); 560 ASSERT(context.selector);
567 const CSSSelector& selector = *context.selector; 561 const CSSSelector& selector = *context.selector;
568 562
569 // Only :host and :host-context() should match the host: http://drafts.csswg .org/css-scoping/#host-element 563 // Only :host and :host-context() should match the host: http://drafts.csswg .org/css-scoping/#host-element
570 if (context.scope && context.scope->shadowHost() == element && (!selector.is HostPseudoClass() 564 if (context.scope && context.scope->shadowHost() == element && (!selector.is HostPseudoClass()
571 && !context.treatShadowHostAsNormalScope 565 && !context.treatShadowHostAsNormalScope
572 && selector.match() != CSSSelector::PseudoElement)) 566 && selector.match() != CSSSelector::PseudoElement))
(...skipping 11 matching lines...) Expand all
584 case CSSSelector::AttributeExact: 578 case CSSSelector::AttributeExact:
585 case CSSSelector::AttributeSet: 579 case CSSSelector::AttributeSet:
586 case CSSSelector::AttributeHyphen: 580 case CSSSelector::AttributeHyphen:
587 case CSSSelector::AttributeList: 581 case CSSSelector::AttributeList:
588 case CSSSelector::AttributeContain: 582 case CSSSelector::AttributeContain:
589 case CSSSelector::AttributeBegin: 583 case CSSSelector::AttributeBegin:
590 case CSSSelector::AttributeEnd: 584 case CSSSelector::AttributeEnd:
591 return anyAttributeMatches(element, selector.match(), selector); 585 return anyAttributeMatches(element, selector.match(), selector);
592 586
593 case CSSSelector::PseudoClass: 587 case CSSSelector::PseudoClass:
594 return checkPseudoClass(context, siblingTraversalStrategy, specificity); 588 return checkPseudoClass(context, specificity);
595 case CSSSelector::PseudoElement: 589 case CSSSelector::PseudoElement:
596 return checkPseudoElement(context, siblingTraversalStrategy); 590 return checkPseudoElement(context);
597 591
598 case CSSSelector::PagePseudoClass: 592 case CSSSelector::PagePseudoClass:
599 // FIXME: what? 593 // FIXME: what?
600 return true; 594 return true;
601 case CSSSelector::Unknown: 595 case CSSSelector::Unknown:
602 // FIXME: what? 596 // FIXME: what?
603 return true; 597 return true;
604 } 598 }
605 ASSERT_NOT_REACHED(); 599 ASSERT_NOT_REACHED();
606 return true; 600 return true;
607 } 601 }
608 602
609 template<typename SiblingTraversalStrategy> 603 bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context, u nsigned* specificity) const
610 bool SelectorChecker::checkPseudoClass(const SelectorCheckingContext& context, c onst SiblingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const
611 { 604 {
612 Element& element = *context.element; 605 Element& element = *context.element;
613 const CSSSelector& selector = *context.selector; 606 const CSSSelector& selector = *context.selector;
614 607
615 // Handle :not up front. 608 // Handle :not up front.
616 if (selector.pseudoType() == CSSSelector::PseudoNot) { 609 if (selector.pseudoType() == CSSSelector::PseudoNot) {
617 SelectorCheckingContext subContext(context); 610 SelectorCheckingContext subContext(context);
618 subContext.isSubSelector = true; 611 subContext.isSubSelector = true;
619 ASSERT(selector.selectorList()); 612 ASSERT(selector.selectorList());
620 for (subContext.selector = selector.selectorList()->first(); subContext. selector; subContext.selector = subContext.selector->tagHistory()) { 613 for (subContext.selector = selector.selectorList()->first(); subContext. selector; subContext.selector = subContext.selector->tagHistory()) {
621 // :not cannot nest. I don't really know why this is a 614 // :not cannot nest. I don't really know why this is a
622 // restriction in CSS3, but it is, so let's honor it. 615 // restriction in CSS3, but it is, so let's honor it.
623 // the parser enforces that this never occurs 616 // the parser enforces that this never occurs
624 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoNot); 617 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoNot);
625 // We select between :visited and :link when applying. We don't know which one applied (or not) yet. 618 // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
626 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.v isitedMatchType == VisitedMatchEnabled)) 619 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.v isitedMatchType == VisitedMatchEnabled))
627 return true; 620 return true;
628 // context.scope is not available if m_mode == SharingRules. 621 // context.scope is not available if m_mode == SharingRules.
629 // We cannot determine whether :host or :scope matches a given eleme nt or not. 622 // We cannot determine whether :host or :scope matches a given eleme nt or not.
630 if (m_mode == SharingRules && (subContext.selector->isHostPseudoClas s() || subContext.selector->pseudoType() == CSSSelector::PseudoScope)) 623 if (m_mode == SharingRules && (subContext.selector->isHostPseudoClas s() || subContext.selector->pseudoType() == CSSSelector::PseudoScope))
631 return true; 624 return true;
632 if (!checkOne(subContext, siblingTraversalStrategy)) 625 if (!checkOne(subContext))
633 return true; 626 return true;
634 } 627 }
635 return false; 628 return false;
636 } 629 }
637 630
638 if (context.hasScrollbarPseudo) { 631 if (context.hasScrollbarPseudo) {
639 // CSS scrollbars match a specific subset of pseudo classes, and they ha ve specialized rules for each 632 // CSS scrollbars match a specific subset of pseudo classes, and they ha ve specialized rules for each
640 // (since there are no elements involved). 633 // (since there are no elements involved).
641 return checkScrollbarPseudoClass(context, &element.document(), selector) ; 634 return checkScrollbarPseudoClass(context, &element.document(), selector) ;
642 } 635 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 element.mutableComputedStyle()->setEmptyState(result); 667 element.mutableComputedStyle()->setEmptyState(result);
675 } 668 }
676 return result; 669 return result;
677 } 670 }
678 case CSSSelector::PseudoFirstChild: 671 case CSSSelector::PseudoFirstChild:
679 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 672 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
680 if (m_mode == ResolvingStyle) { 673 if (m_mode == ResolvingStyle) {
681 parent->setChildrenAffectedByFirstChildRules(); 674 parent->setChildrenAffectedByFirstChildRules();
682 element.setAffectedByFirstChildRules(); 675 element.setAffectedByFirstChildRules();
683 } 676 }
684 return siblingTraversalStrategy.isFirstChild(element); 677 return DOMSiblingTraversalStrategy::isFirstChild(element);
685 } 678 }
686 break; 679 break;
687 case CSSSelector::PseudoFirstOfType: 680 case CSSSelector::PseudoFirstOfType:
688 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 681 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
689 if (m_mode == ResolvingStyle) 682 if (m_mode == ResolvingStyle)
690 parent->setChildrenAffectedByForwardPositionalRules(); 683 parent->setChildrenAffectedByForwardPositionalRules();
691 return siblingTraversalStrategy.isFirstOfType(element, element.tagQN ame()); 684 return DOMSiblingTraversalStrategy::isFirstOfType(element, element.t agQName());
692 } 685 }
693 break; 686 break;
694 case CSSSelector::PseudoLastChild: 687 case CSSSelector::PseudoLastChild:
695 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 688 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
696 if (m_mode == ResolvingStyle) { 689 if (m_mode == ResolvingStyle) {
697 parent->setChildrenAffectedByLastChildRules(); 690 parent->setChildrenAffectedByLastChildRules();
698 element.setAffectedByLastChildRules(); 691 element.setAffectedByLastChildRules();
699 } 692 }
700 if (!parent->isFinishedParsingChildren()) 693 if (!parent->isFinishedParsingChildren())
701 return false; 694 return false;
702 return siblingTraversalStrategy.isLastChild(element); 695 return DOMSiblingTraversalStrategy::isLastChild(element);
703 } 696 }
704 break; 697 break;
705 case CSSSelector::PseudoLastOfType: 698 case CSSSelector::PseudoLastOfType:
706 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 699 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
707 if (m_mode == ResolvingStyle) 700 if (m_mode == ResolvingStyle)
708 parent->setChildrenAffectedByBackwardPositionalRules(); 701 parent->setChildrenAffectedByBackwardPositionalRules();
709 if (!parent->isFinishedParsingChildren()) 702 if (!parent->isFinishedParsingChildren())
710 return false; 703 return false;
711 return siblingTraversalStrategy.isLastOfType(element, element.tagQNa me()); 704 return DOMSiblingTraversalStrategy::isLastOfType(element, element.ta gQName());
712 } 705 }
713 break; 706 break;
714 case CSSSelector::PseudoOnlyChild: 707 case CSSSelector::PseudoOnlyChild:
715 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 708 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
716 if (m_mode == ResolvingStyle) { 709 if (m_mode == ResolvingStyle) {
717 parent->setChildrenAffectedByFirstChildRules(); 710 parent->setChildrenAffectedByFirstChildRules();
718 parent->setChildrenAffectedByLastChildRules(); 711 parent->setChildrenAffectedByLastChildRules();
719 element.setAffectedByFirstChildRules(); 712 element.setAffectedByFirstChildRules();
720 element.setAffectedByLastChildRules(); 713 element.setAffectedByLastChildRules();
721 } 714 }
722 if (!parent->isFinishedParsingChildren()) 715 if (!parent->isFinishedParsingChildren())
723 return false; 716 return false;
724 return siblingTraversalStrategy.isFirstChild(element) && siblingTrav ersalStrategy.isLastChild(element); 717 return DOMSiblingTraversalStrategy::isFirstChild(element) && DOMSibl ingTraversalStrategy::isLastChild(element);
725 } 718 }
726 break; 719 break;
727 case CSSSelector::PseudoOnlyOfType: 720 case CSSSelector::PseudoOnlyOfType:
728 // FIXME: This selector is very slow. 721 // FIXME: This selector is very slow.
729 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 722 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
730 if (m_mode == ResolvingStyle) { 723 if (m_mode == ResolvingStyle) {
731 parent->setChildrenAffectedByForwardPositionalRules(); 724 parent->setChildrenAffectedByForwardPositionalRules();
732 parent->setChildrenAffectedByBackwardPositionalRules(); 725 parent->setChildrenAffectedByBackwardPositionalRules();
733 } 726 }
734 if (!parent->isFinishedParsingChildren()) 727 if (!parent->isFinishedParsingChildren())
735 return false; 728 return false;
736 return siblingTraversalStrategy.isFirstOfType(element, element.tagQN ame()) && siblingTraversalStrategy.isLastOfType(element, element.tagQName()); 729 return DOMSiblingTraversalStrategy::isFirstOfType(element, element.t agQName()) && DOMSiblingTraversalStrategy::isLastOfType(element, element.tagQNam e());
737 } 730 }
738 break; 731 break;
739 case CSSSelector::PseudoNthChild: 732 case CSSSelector::PseudoNthChild:
740 if (!selector.parseNth()) 733 if (!selector.parseNth())
741 break; 734 break;
742 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 735 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
743 if (m_mode == ResolvingStyle) 736 if (m_mode == ResolvingStyle)
744 parent->setChildrenAffectedByForwardPositionalRules(); 737 parent->setChildrenAffectedByForwardPositionalRules();
745 return selector.matchNth(1 + siblingTraversalStrategy.countElementsB efore(element)); 738 return selector.matchNth(1 + DOMSiblingTraversalStrategy::countEleme ntsBefore(element));
746 } 739 }
747 break; 740 break;
748 case CSSSelector::PseudoNthOfType: 741 case CSSSelector::PseudoNthOfType:
749 if (!selector.parseNth()) 742 if (!selector.parseNth())
750 break; 743 break;
751 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 744 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
752 if (m_mode == ResolvingStyle) 745 if (m_mode == ResolvingStyle)
753 parent->setChildrenAffectedByForwardPositionalRules(); 746 parent->setChildrenAffectedByForwardPositionalRules();
754 return selector.matchNth(1 + siblingTraversalStrategy.countElementsO fTypeBefore(element, element.tagQName())); 747 return selector.matchNth(1 + DOMSiblingTraversalStrategy::countEleme ntsOfTypeBefore(element, element.tagQName()));
755 } 748 }
756 break; 749 break;
757 case CSSSelector::PseudoNthLastChild: 750 case CSSSelector::PseudoNthLastChild:
758 if (!selector.parseNth()) 751 if (!selector.parseNth())
759 break; 752 break;
760 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 753 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
761 if (m_mode == ResolvingStyle) 754 if (m_mode == ResolvingStyle)
762 parent->setChildrenAffectedByBackwardPositionalRules(); 755 parent->setChildrenAffectedByBackwardPositionalRules();
763 if (!parent->isFinishedParsingChildren()) 756 if (!parent->isFinishedParsingChildren())
764 return false; 757 return false;
765 return selector.matchNth(1 + siblingTraversalStrategy.countElementsA fter(element)); 758 return selector.matchNth(1 + DOMSiblingTraversalStrategy::countEleme ntsAfter(element));
766 } 759 }
767 break; 760 break;
768 case CSSSelector::PseudoNthLastOfType: 761 case CSSSelector::PseudoNthLastOfType:
769 if (!selector.parseNth()) 762 if (!selector.parseNth())
770 break; 763 break;
771 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { 764 if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
772 if (m_mode == ResolvingStyle) 765 if (m_mode == ResolvingStyle)
773 parent->setChildrenAffectedByBackwardPositionalRules(); 766 parent->setChildrenAffectedByBackwardPositionalRules();
774 if (!parent->isFinishedParsingChildren()) 767 if (!parent->isFinishedParsingChildren())
775 return false; 768 return false;
776 return selector.matchNth(1 + siblingTraversalStrategy.countElementsO fTypeAfter(element, element.tagQName())); 769 return selector.matchNth(1 + DOMSiblingTraversalStrategy::countEleme ntsOfTypeAfter(element, element.tagQName()));
777 } 770 }
778 break; 771 break;
779 case CSSSelector::PseudoTarget: 772 case CSSSelector::PseudoTarget:
780 return element == element.document().cssTarget(); 773 return element == element.document().cssTarget();
781 case CSSSelector::PseudoAny: 774 case CSSSelector::PseudoAny:
782 { 775 {
783 SelectorCheckingContext subContext(context); 776 SelectorCheckingContext subContext(context);
784 subContext.isSubSelector = true; 777 subContext.isSubSelector = true;
785 ASSERT(selector.selectorList()); 778 ASSERT(selector.selectorList());
786 for (subContext.selector = selector.selectorList()->first(); subCont ext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { 779 for (subContext.selector = selector.selectorList()->first(); subCont ext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) {
787 if (match(subContext, siblingTraversalStrategy) == SelectorMatch es) 780 if (match(subContext) == SelectorMatches)
788 return true; 781 return true;
789 } 782 }
790 } 783 }
791 break; 784 break;
792 case CSSSelector::PseudoAutofill: 785 case CSSSelector::PseudoAutofill:
793 return element.isFormControlElement() && toHTMLFormControlElement(elemen t).isAutofilled(); 786 return element.isFormControlElement() && toHTMLFormControlElement(elemen t).isAutofilled();
794 case CSSSelector::PseudoAnyLink: 787 case CSSSelector::PseudoAnyLink:
795 case CSSSelector::PseudoLink: 788 case CSSSelector::PseudoLink:
796 return element.isLink(); 789 return element.isLink();
797 case CSSSelector::PseudoVisited: 790 case CSSSelector::PseudoVisited:
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 case CSSSelector::PseudoScope: 923 case CSSSelector::PseudoScope:
931 if (m_mode == SharingRules) 924 if (m_mode == SharingRules)
932 return true; 925 return true;
933 if (context.scope) 926 if (context.scope)
934 return context.scope == element; 927 return context.scope == element;
935 return element == element.document().documentElement(); 928 return element == element.document().documentElement();
936 case CSSSelector::PseudoUnresolved: 929 case CSSSelector::PseudoUnresolved:
937 return element.isUnresolvedCustomElement(); 930 return element.isUnresolvedCustomElement();
938 case CSSSelector::PseudoHost: 931 case CSSSelector::PseudoHost:
939 case CSSSelector::PseudoHostContext: 932 case CSSSelector::PseudoHostContext:
940 return checkPseudoHost(context, siblingTraversalStrategy, specificity); 933 return checkPseudoHost(context, specificity);
941 case CSSSelector::PseudoSpatialNavigationFocus: 934 case CSSSelector::PseudoSpatialNavigationFocus:
942 return context.isUARule && matchesSpatialNavigationFocusPseudoClass(elem ent); 935 return context.isUARule && matchesSpatialNavigationFocusPseudoClass(elem ent);
943 case CSSSelector::PseudoListBox: 936 case CSSSelector::PseudoListBox:
944 return context.isUARule && matchesListBoxPseudoClass(element); 937 return context.isUARule && matchesListBoxPseudoClass(element);
945 case CSSSelector::PseudoHorizontal: 938 case CSSSelector::PseudoHorizontal:
946 case CSSSelector::PseudoVertical: 939 case CSSSelector::PseudoVertical:
947 case CSSSelector::PseudoDecrement: 940 case CSSSelector::PseudoDecrement:
948 case CSSSelector::PseudoIncrement: 941 case CSSSelector::PseudoIncrement:
949 case CSSSelector::PseudoStart: 942 case CSSSelector::PseudoStart:
950 case CSSSelector::PseudoEnd: 943 case CSSSelector::PseudoEnd:
951 case CSSSelector::PseudoDoubleButton: 944 case CSSSelector::PseudoDoubleButton:
952 case CSSSelector::PseudoSingleButton: 945 case CSSSelector::PseudoSingleButton:
953 case CSSSelector::PseudoNoButton: 946 case CSSSelector::PseudoNoButton:
954 case CSSSelector::PseudoCornerPresent: 947 case CSSSelector::PseudoCornerPresent:
955 case CSSSelector::PseudoWindowInactive: 948 case CSSSelector::PseudoWindowInactive:
956 return false; 949 return false;
957 case CSSSelector::PseudoUnknown: 950 case CSSSelector::PseudoUnknown:
958 case CSSSelector::PseudoNotParsed: 951 case CSSSelector::PseudoNotParsed:
959 default: 952 default:
960 ASSERT_NOT_REACHED(); 953 ASSERT_NOT_REACHED();
961 break; 954 break;
962 } 955 }
963 return false; 956 return false;
964 } 957 }
965 958
966 template<typename SiblingTraversalStrategy> 959 bool SelectorChecker::checkPseudoElement(const SelectorCheckingContext& context) const
967 bool SelectorChecker::checkPseudoElement(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy) const
968 { 960 {
969 const CSSSelector& selector = *context.selector; 961 const CSSSelector& selector = *context.selector;
970 962
971 if (selector.pseudoType() == CSSSelector::PseudoCue) { 963 if (selector.pseudoType() == CSSSelector::PseudoCue) {
972 SelectorCheckingContext subContext(context); 964 SelectorCheckingContext subContext(context);
973 subContext.isSubSelector = true; 965 subContext.isSubSelector = true;
974 subContext.scopeContainsLastMatchedElement = false; 966 subContext.scopeContainsLastMatchedElement = false;
975 subContext.treatShadowHostAsNormalScope = false; 967 subContext.treatShadowHostAsNormalScope = false;
976 968
977 const CSSSelector* contextSelector = context.selector; 969 const CSSSelector* contextSelector = context.selector;
978 ASSERT(contextSelector); 970 ASSERT(contextSelector);
979 for (subContext.selector = contextSelector->selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) { 971 for (subContext.selector = contextSelector->selectorList()->first(); sub Context.selector; subContext.selector = CSSSelectorList::next(*subContext.select or)) {
980 if (match(subContext, siblingTraversalStrategy) == SelectorMatches) 972 if (match(subContext) == SelectorMatches)
981 return true; 973 return true;
982 } 974 }
983 return false; 975 return false;
984 } 976 }
985 977
986 // FIXME: this used to be a fallthrough condition. 978 // FIXME: this used to be a fallthrough condition.
987 return true; 979 return true;
988 } 980 }
989 981
990 template<typename SiblingTraversalStrategy> 982 bool SelectorChecker::checkPseudoHost(const SelectorCheckingContext& context, un signed* specificity) const
991 bool SelectorChecker::checkPseudoHost(const SelectorCheckingContext& context, co nst SiblingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) c onst
992 { 983 {
993 const CSSSelector& selector = *context.selector; 984 const CSSSelector& selector = *context.selector;
994 Element& element = *context.element; 985 Element& element = *context.element;
995 986
996 if (m_mode == SharingRules) 987 if (m_mode == SharingRules)
997 return true; 988 return true;
998 // :host only matches a shadow host when :host is in a shadow tree of the sh adow host. 989 // :host only matches a shadow host when :host is in a shadow tree of the sh adow host.
999 if (!context.scope) 990 if (!context.scope)
1000 return false; 991 return false;
1001 const ContainerNode* shadowHost = context.scope->shadowHost(); 992 const ContainerNode* shadowHost = context.scope->shadowHost();
(...skipping 14 matching lines...) Expand all
1016 // If one of simple selectors matches an element, returns SelectorMatches. J ust "OR". 1007 // If one of simple selectors matches an element, returns SelectorMatches. J ust "OR".
1017 for (subContext.selector = selector.selectorList()->first(); subContext.sele ctor; subContext.selector = CSSSelectorList::next(*subContext.selector)) { 1008 for (subContext.selector = selector.selectorList()->first(); subContext.sele ctor; subContext.selector = CSSSelectorList::next(*subContext.selector)) {
1018 subContext.treatShadowHostAsNormalScope = true; 1009 subContext.treatShadowHostAsNormalScope = true;
1019 subContext.scope = context.scope; 1010 subContext.scope = context.scope;
1020 // Use ComposedTreeTraversal to traverse a composed ancestor list of a g iven element. 1011 // Use ComposedTreeTraversal to traverse a composed ancestor list of a g iven element.
1021 Element* nextElement = &element; 1012 Element* nextElement = &element;
1022 SelectorCheckingContext hostContext(subContext); 1013 SelectorCheckingContext hostContext(subContext);
1023 do { 1014 do {
1024 MatchResult subResult; 1015 MatchResult subResult;
1025 hostContext.element = nextElement; 1016 hostContext.element = nextElement;
1026 if (match(hostContext, siblingTraversalStrategy, &subResult) == Sele ctorMatches) { 1017 if (match(hostContext, &subResult) == SelectorMatches) {
1027 matched = true; 1018 matched = true;
1028 // Consider div:host(div:host(div:host(div:host...))). 1019 // Consider div:host(div:host(div:host(div:host...))).
1029 maxSpecificity = std::max(maxSpecificity, hostContext.selector-> specificity() + subResult.specificity); 1020 maxSpecificity = std::max(maxSpecificity, hostContext.selector-> specificity() + subResult.specificity);
1030 break; 1021 break;
1031 } 1022 }
1032 hostContext.scopeContainsLastMatchedElement = false; 1023 hostContext.scopeContainsLastMatchedElement = false;
1033 hostContext.treatShadowHostAsNormalScope = false; 1024 hostContext.treatShadowHostAsNormalScope = false;
1034 hostContext.scope = nullptr; 1025 hostContext.scope = nullptr;
1035 1026
1036 if (selector.pseudoType() == CSSSelector::PseudoHost) 1027 if (selector.pseudoType() == CSSSelector::PseudoHost)
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 } 1122 }
1132 } 1123 }
1133 1124
1134 bool SelectorChecker::matchesFocusPseudoClass(const Element& element) 1125 bool SelectorChecker::matchesFocusPseudoClass(const Element& element)
1135 { 1126 {
1136 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element ), CSSSelector::PseudoFocus)) 1127 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element ), CSSSelector::PseudoFocus))
1137 return true; 1128 return true;
1138 return element.focused() && isFrameFocused(element); 1129 return element.focused() && isFrameFocused(element);
1139 } 1130 }
1140 1131
1141 template
1142 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst DOMSiblingTraversalStrategy&, MatchResult*) const;
1143
1144 template
1145 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, co nst ShadowDOMSiblingTraversalStrategy&, MatchResult*) const;
1146
1147 } 1132 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698