| 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. | 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. |
| 6 * All rights reserved. | 6 * All rights reserved. |
| 7 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 7 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| 8 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> | 8 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |
| 9 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 9 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| 10 * (http://www.torchmobile.com/) | 10 * (http://www.torchmobile.com/) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 return !ElementTraversal::nextSibling(element, HasTagName(type)); | 193 return !ElementTraversal::nextSibling(element, HasTagName(type)); |
| 194 } | 194 } |
| 195 | 195 |
| 196 // Recursive check of selectors and combinators | 196 // Recursive check of selectors and combinators |
| 197 // It can return 4 different values: | 197 // It can return 4 different values: |
| 198 // * SelectorMatches - the selector matches the element e | 198 // * SelectorMatches - the selector matches the element e |
| 199 // * SelectorFailsLocally - the selector fails for the element e | 199 // * SelectorFailsLocally - the selector fails for the element e |
| 200 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e | 200 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e |
| 201 // * SelectorFailsCompletely - the selector fails for e and any sibling or | 201 // * SelectorFailsCompletely - the selector fails for e and any sibling or |
| 202 // ancestor of e | 202 // ancestor of e |
| 203 SelectorChecker::Match SelectorChecker::matchSelector( | 203 SelectorChecker::MatchStatus SelectorChecker::matchSelector( |
| 204 const SelectorCheckingContext& context, | 204 const SelectorCheckingContext& context, |
| 205 MatchResult& result) const { | 205 MatchResult& result) const { |
| 206 MatchResult subResult; | 206 MatchResult subResult; |
| 207 if (!checkOne(context, subResult)) | 207 if (!checkOne(context, subResult)) |
| 208 return SelectorFailsLocally; | 208 return SelectorFailsLocally; |
| 209 | 209 |
| 210 if (subResult.dynamicPseudo != PseudoIdNone) | 210 if (subResult.dynamicPseudo != PseudoIdNone) |
| 211 result.dynamicPseudo = subResult.dynamicPseudo; | 211 result.dynamicPseudo = subResult.dynamicPseudo; |
| 212 | 212 |
| 213 if (context.selector->isLastInTagHistory()) { | 213 if (context.selector->isLastInTagHistory()) { |
| 214 if (scopeContainsLastMatchedElement(context)) { | 214 if (scopeContainsLastMatchedElement(context)) { |
| 215 result.specificity += subResult.specificity; | 215 result.specificity += subResult.specificity; |
| 216 return SelectorMatches; | 216 return SelectorMatches; |
| 217 } | 217 } |
| 218 return SelectorFailsLocally; | 218 return SelectorFailsLocally; |
| 219 } | 219 } |
| 220 | 220 |
| 221 Match match; | 221 MatchStatus match; |
| 222 if (context.selector->relation() != CSSSelector::SubSelector) { | 222 if (context.selector->relation() != CSSSelector::SubSelector) { |
| 223 if (nextSelectorExceedsScope(context)) | 223 if (nextSelectorExceedsScope(context)) |
| 224 return SelectorFailsCompletely; | 224 return SelectorFailsCompletely; |
| 225 | 225 |
| 226 if (context.pseudoId != PseudoIdNone && | 226 if (context.pseudoId != PseudoIdNone && |
| 227 context.pseudoId != result.dynamicPseudo) | 227 context.pseudoId != result.dynamicPseudo) |
| 228 return SelectorFailsCompletely; | 228 return SelectorFailsCompletely; |
| 229 | 229 |
| 230 AutoReset<PseudoId> dynamicPseudoScope(&result.dynamicPseudo, PseudoIdNone); | 230 AutoReset<PseudoId> dynamicPseudoScope(&result.dynamicPseudo, PseudoIdNone); |
| 231 match = matchForRelation(context, result); | 231 match = matchForRelation(context, result); |
| 232 } else { | 232 } else { |
| 233 match = matchForSubSelector(context, result); | 233 match = matchForSubSelector(context, result); |
| 234 } | 234 } |
| 235 if (match == SelectorMatches) | 235 if (match == SelectorMatches) |
| 236 result.specificity += subResult.specificity; | 236 result.specificity += subResult.specificity; |
| 237 return match; | 237 return match; |
| 238 } | 238 } |
| 239 | 239 |
| 240 static inline SelectorChecker::SelectorCheckingContext | 240 static inline SelectorChecker::SelectorCheckingContext |
| 241 prepareNextContextForRelation( | 241 prepareNextContextForRelation( |
| 242 const SelectorChecker::SelectorCheckingContext& context) { | 242 const SelectorChecker::SelectorCheckingContext& context) { |
| 243 SelectorChecker::SelectorCheckingContext nextContext(context); | 243 SelectorChecker::SelectorCheckingContext nextContext(context); |
| 244 DCHECK(context.selector->tagHistory()); | 244 DCHECK(context.selector->tagHistory()); |
| 245 nextContext.selector = context.selector->tagHistory(); | 245 nextContext.selector = context.selector->tagHistory(); |
| 246 return nextContext; | 246 return nextContext; |
| 247 } | 247 } |
| 248 | 248 |
| 249 SelectorChecker::Match SelectorChecker::matchForSubSelector( | 249 SelectorChecker::MatchStatus SelectorChecker::matchForSubSelector( |
| 250 const SelectorCheckingContext& context, | 250 const SelectorCheckingContext& context, |
| 251 MatchResult& result) const { | 251 MatchResult& result) const { |
| 252 SelectorCheckingContext nextContext = prepareNextContextForRelation(context); | 252 SelectorCheckingContext nextContext = prepareNextContextForRelation(context); |
| 253 | 253 |
| 254 PseudoId dynamicPseudo = result.dynamicPseudo; | 254 PseudoId dynamicPseudo = result.dynamicPseudo; |
| 255 nextContext.hasScrollbarPseudo = | 255 nextContext.hasScrollbarPseudo = |
| 256 dynamicPseudo != PseudoIdNone && | 256 dynamicPseudo != PseudoIdNone && |
| 257 (m_scrollbar || dynamicPseudo == PseudoIdScrollbarCorner || | 257 (m_scrollbar || dynamicPseudo == PseudoIdScrollbarCorner || |
| 258 dynamicPseudo == PseudoIdResizer); | 258 dynamicPseudo == PseudoIdResizer); |
| 259 nextContext.hasSelectionPseudo = dynamicPseudo == PseudoIdSelection; | 259 nextContext.hasSelectionPseudo = dynamicPseudo == PseudoIdSelection; |
| 260 nextContext.isSubSelector = true; | 260 nextContext.isSubSelector = true; |
| 261 return matchSelector(nextContext, result); | 261 return matchSelector(nextContext, result); |
| 262 } | 262 } |
| 263 | 263 |
| 264 static inline bool isV0ShadowRoot(const Node* node) { | 264 static inline bool isV0ShadowRoot(const Node* node) { |
| 265 return node && node->isShadowRoot() && | 265 return node && node->isShadowRoot() && |
| 266 toShadowRoot(node)->type() == ShadowRootType::V0; | 266 toShadowRoot(node)->type() == ShadowRootType::V0; |
| 267 } | 267 } |
| 268 | 268 |
| 269 SelectorChecker::Match SelectorChecker::matchForPseudoShadow( | 269 SelectorChecker::MatchStatus SelectorChecker::matchForPseudoShadow( |
| 270 const SelectorCheckingContext& context, | 270 const SelectorCheckingContext& context, |
| 271 const ContainerNode* node, | 271 const ContainerNode* node, |
| 272 MatchResult& result) const { | 272 MatchResult& result) const { |
| 273 if (!isV0ShadowRoot(node)) | 273 if (!isV0ShadowRoot(node)) |
| 274 return SelectorFailsCompletely; | 274 return SelectorFailsCompletely; |
| 275 if (!context.previousElement) | 275 if (!context.previousElement) |
| 276 return SelectorFailsCompletely; | 276 return SelectorFailsCompletely; |
| 277 return matchSelector(context, result); | 277 return matchSelector(context, result); |
| 278 } | 278 } |
| 279 | 279 |
| 280 static inline Element* parentOrV0ShadowHostElement(const Element& element) { | 280 static inline Element* parentOrV0ShadowHostElement(const Element& element) { |
| 281 if (element.parentNode() && element.parentNode()->isShadowRoot()) { | 281 if (element.parentNode() && element.parentNode()->isShadowRoot()) { |
| 282 if (toShadowRoot(element.parentNode())->type() != ShadowRootType::V0) | 282 if (toShadowRoot(element.parentNode())->type() != ShadowRootType::V0) |
| 283 return nullptr; | 283 return nullptr; |
| 284 } | 284 } |
| 285 return element.parentOrShadowHostElement(); | 285 return element.parentOrShadowHostElement(); |
| 286 } | 286 } |
| 287 | 287 |
| 288 static inline Element* parentOrOpenShadowHostElement(const Element& element) { | 288 static inline Element* parentOrOpenShadowHostElement(const Element& element) { |
| 289 if (element.parentNode() && element.parentNode()->isShadowRoot()) { | 289 if (element.parentNode() && element.parentNode()->isShadowRoot()) { |
| 290 if (toShadowRoot(element.parentNode())->type() != ShadowRootType::Open) | 290 if (toShadowRoot(element.parentNode())->type() != ShadowRootType::Open) |
| 291 return nullptr; | 291 return nullptr; |
| 292 } | 292 } |
| 293 return element.parentOrShadowHostElement(); | 293 return element.parentOrShadowHostElement(); |
| 294 } | 294 } |
| 295 | 295 |
| 296 SelectorChecker::Match SelectorChecker::matchForRelation( | 296 SelectorChecker::MatchStatus SelectorChecker::matchForRelation( |
| 297 const SelectorCheckingContext& context, | 297 const SelectorCheckingContext& context, |
| 298 MatchResult& result) const { | 298 MatchResult& result) const { |
| 299 SelectorCheckingContext nextContext = prepareNextContextForRelation(context); | 299 SelectorCheckingContext nextContext = prepareNextContextForRelation(context); |
| 300 | 300 |
| 301 CSSSelector::RelationType relation = context.selector->relation(); | 301 CSSSelector::RelationType relation = context.selector->relation(); |
| 302 | 302 |
| 303 // Disable :visited matching when we see the first link or try to match | 303 // Disable :visited matching when we see the first link or try to match |
| 304 // anything else than an ancestors. | 304 // anything else than an ancestors. |
| 305 if (!context.isSubSelector && | 305 if (!context.isSubSelector && |
| 306 (context.element->isLink() || | 306 (context.element->isLink() || |
| (...skipping 16 matching lines...) Expand all Loading... |
| 323 } | 323 } |
| 324 return SelectorFailsCompletely; | 324 return SelectorFailsCompletely; |
| 325 } | 325 } |
| 326 | 326 |
| 327 if (nextContext.selector->getPseudoType() == CSSSelector::PseudoShadow) | 327 if (nextContext.selector->getPseudoType() == CSSSelector::PseudoShadow) |
| 328 return matchForPseudoShadow( | 328 return matchForPseudoShadow( |
| 329 nextContext, context.element->containingShadowRoot(), result); | 329 nextContext, context.element->containingShadowRoot(), result); |
| 330 | 330 |
| 331 for (nextContext.element = parentElement(context); nextContext.element; | 331 for (nextContext.element = parentElement(context); nextContext.element; |
| 332 nextContext.element = parentElement(nextContext)) { | 332 nextContext.element = parentElement(nextContext)) { |
| 333 Match match = matchSelector(nextContext, result); | 333 MatchStatus match = matchSelector(nextContext, result); |
| 334 if (match == SelectorMatches || match == SelectorFailsCompletely) | 334 if (match == SelectorMatches || match == SelectorFailsCompletely) |
| 335 return match; | 335 return match; |
| 336 if (nextSelectorExceedsScope(nextContext)) | 336 if (nextSelectorExceedsScope(nextContext)) |
| 337 return SelectorFailsCompletely; | 337 return SelectorFailsCompletely; |
| 338 } | 338 } |
| 339 return SelectorFailsCompletely; | 339 return SelectorFailsCompletely; |
| 340 case CSSSelector::Child: { | 340 case CSSSelector::Child: { |
| 341 if (context.selector->relationIsAffectedByPseudoContent()) | 341 if (context.selector->relationIsAffectedByPseudoContent()) |
| 342 return matchForPseudoContent(nextContext, *context.element, result); | 342 return matchForPseudoContent(nextContext, *context.element, result); |
| 343 | 343 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 372 | 372 |
| 373 if (m_mode == ResolvingStyle) { | 373 if (m_mode == ResolvingStyle) { |
| 374 if (ContainerNode* parent = | 374 if (ContainerNode* parent = |
| 375 context.element->parentElementOrShadowRoot()) | 375 context.element->parentElementOrShadowRoot()) |
| 376 parent->setChildrenAffectedByIndirectAdjacentRules(); | 376 parent->setChildrenAffectedByIndirectAdjacentRules(); |
| 377 } | 377 } |
| 378 nextContext.element = ElementTraversal::previousSibling(*context.element); | 378 nextContext.element = ElementTraversal::previousSibling(*context.element); |
| 379 for (; nextContext.element; | 379 for (; nextContext.element; |
| 380 nextContext.element = | 380 nextContext.element = |
| 381 ElementTraversal::previousSibling(*nextContext.element)) { | 381 ElementTraversal::previousSibling(*nextContext.element)) { |
| 382 Match match = matchSelector(nextContext, result); | 382 MatchStatus match = matchSelector(nextContext, result); |
| 383 if (match == SelectorMatches || match == SelectorFailsAllSiblings || | 383 if (match == SelectorMatches || match == SelectorFailsAllSiblings || |
| 384 match == SelectorFailsCompletely) | 384 match == SelectorFailsCompletely) |
| 385 return match; | 385 return match; |
| 386 } | 386 } |
| 387 return SelectorFailsAllSiblings; | 387 return SelectorFailsAllSiblings; |
| 388 | 388 |
| 389 case CSSSelector::ShadowPseudo: { | 389 case CSSSelector::ShadowPseudo: { |
| 390 if (!m_isUARule && !m_isQuerySelector && | 390 if (!m_isUARule && !m_isQuerySelector && |
| 391 context.selector->getPseudoType() == CSSSelector::PseudoShadow) | 391 context.selector->getPseudoType() == CSSSelector::PseudoShadow) |
| 392 Deprecation::countDeprecation(context.element->document(), | 392 Deprecation::countDeprecation(context.element->document(), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 return SelectorMatches; | 427 return SelectorMatches; |
| 428 } | 428 } |
| 429 } | 429 } |
| 430 return SelectorFailsCompletely; | 430 return SelectorFailsCompletely; |
| 431 } | 431 } |
| 432 | 432 |
| 433 for (nextContext.element = parentOrV0ShadowHostElement(*context.element); | 433 for (nextContext.element = parentOrV0ShadowHostElement(*context.element); |
| 434 nextContext.element; | 434 nextContext.element; |
| 435 nextContext.element = | 435 nextContext.element = |
| 436 parentOrV0ShadowHostElement(*nextContext.element)) { | 436 parentOrV0ShadowHostElement(*nextContext.element)) { |
| 437 Match match = matchSelector(nextContext, result); | 437 MatchStatus match = matchSelector(nextContext, result); |
| 438 if (match == SelectorMatches && context.element->isInShadowTree()) | 438 if (match == SelectorMatches && context.element->isInShadowTree()) |
| 439 UseCounter::count(context.element->document(), | 439 UseCounter::count(context.element->document(), |
| 440 UseCounter::CSSDeepCombinatorAndShadow); | 440 UseCounter::CSSDeepCombinatorAndShadow); |
| 441 if (match == SelectorMatches || match == SelectorFailsCompletely) | 441 if (match == SelectorMatches || match == SelectorFailsCompletely) |
| 442 return match; | 442 return match; |
| 443 if (nextSelectorExceedsScope(nextContext)) | 443 if (nextSelectorExceedsScope(nextContext)) |
| 444 return SelectorFailsCompletely; | 444 return SelectorFailsCompletely; |
| 445 } | 445 } |
| 446 return SelectorFailsCompletely; | 446 return SelectorFailsCompletely; |
| 447 } | 447 } |
| 448 | 448 |
| 449 case CSSSelector::ShadowPiercingDescendant: { | 449 case CSSSelector::ShadowPiercingDescendant: { |
| 450 DCHECK(m_isQuerySelector); | 450 DCHECK(m_isQuerySelector); |
| 451 UseCounter::count(context.element->document(), | 451 UseCounter::count(context.element->document(), |
| 452 UseCounter::CSSShadowPiercingDescendantCombinator); | 452 UseCounter::CSSShadowPiercingDescendantCombinator); |
| 453 // TODO(kochi): parentOrOpenShadowHostElement() is necessary because | 453 // TODO(kochi): parentOrOpenShadowHostElement() is necessary because |
| 454 // SelectorQuery can pass V0 shadow roots. All closed shadow roots are | 454 // SelectorQuery can pass V0 shadow roots. All closed shadow roots are |
| 455 // already filtered out, thus once V0 is removed this logic can use | 455 // already filtered out, thus once V0 is removed this logic can use |
| 456 // parentOrShadowHostElement() instead. | 456 // parentOrShadowHostElement() instead. |
| 457 for (nextContext.element = | 457 for (nextContext.element = |
| 458 parentOrOpenShadowHostElement(*context.element); | 458 parentOrOpenShadowHostElement(*context.element); |
| 459 nextContext.element; | 459 nextContext.element; |
| 460 nextContext.element = | 460 nextContext.element = |
| 461 parentOrOpenShadowHostElement(*nextContext.element)) { | 461 parentOrOpenShadowHostElement(*nextContext.element)) { |
| 462 Match match = matchSelector(nextContext, result); | 462 MatchStatus match = matchSelector(nextContext, result); |
| 463 if (match == SelectorMatches || match == SelectorFailsCompletely) | 463 if (match == SelectorMatches || match == SelectorFailsCompletely) |
| 464 return match; | 464 return match; |
| 465 if (nextSelectorExceedsScope(nextContext)) | 465 if (nextSelectorExceedsScope(nextContext)) |
| 466 break; | 466 break; |
| 467 } | 467 } |
| 468 return SelectorFailsCompletely; | 468 return SelectorFailsCompletely; |
| 469 } | 469 } |
| 470 | 470 |
| 471 case CSSSelector::ShadowSlot: { | 471 case CSSSelector::ShadowSlot: { |
| 472 const HTMLSlotElement* slot = findSlotElementInScope(context); | 472 const HTMLSlotElement* slot = findSlotElementInScope(context); |
| 473 if (!slot) | 473 if (!slot) |
| 474 return SelectorFailsCompletely; | 474 return SelectorFailsCompletely; |
| 475 | 475 |
| 476 nextContext.element = const_cast<HTMLSlotElement*>(slot); | 476 nextContext.element = const_cast<HTMLSlotElement*>(slot); |
| 477 return matchSelector(nextContext, result); | 477 return matchSelector(nextContext, result); |
| 478 } | 478 } |
| 479 | 479 |
| 480 case CSSSelector::SubSelector: | 480 case CSSSelector::SubSelector: |
| 481 break; | 481 break; |
| 482 } | 482 } |
| 483 NOTREACHED(); | 483 NOTREACHED(); |
| 484 return SelectorFailsCompletely; | 484 return SelectorFailsCompletely; |
| 485 } | 485 } |
| 486 | 486 |
| 487 SelectorChecker::Match SelectorChecker::matchForPseudoContent( | 487 SelectorChecker::MatchStatus SelectorChecker::matchForPseudoContent( |
| 488 const SelectorCheckingContext& context, | 488 const SelectorCheckingContext& context, |
| 489 const Element& element, | 489 const Element& element, |
| 490 MatchResult& result) const { | 490 MatchResult& result) const { |
| 491 HeapVector<Member<InsertionPoint>, 8> insertionPoints; | 491 HeapVector<Member<InsertionPoint>, 8> insertionPoints; |
| 492 collectDestinationInsertionPoints(element, insertionPoints); | 492 collectDestinationInsertionPoints(element, insertionPoints); |
| 493 SelectorCheckingContext nextContext(context); | 493 SelectorCheckingContext nextContext(context); |
| 494 for (const auto& insertionPoint : insertionPoints) { | 494 for (const auto& insertionPoint : insertionPoints) { |
| 495 nextContext.element = insertionPoint; | 495 nextContext.element = insertionPoint; |
| 496 // TODO(esprehn): Why does SharingRules have a special case? | 496 // TODO(esprehn): Why does SharingRules have a special case? |
| 497 if (m_mode == SharingRules) | 497 if (m_mode == SharingRules) |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1313 } | 1313 } |
| 1314 | 1314 |
| 1315 bool SelectorChecker::matchesFocusPseudoClass(const Element& element) { | 1315 bool SelectorChecker::matchesFocusPseudoClass(const Element& element) { |
| 1316 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element), | 1316 if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element), |
| 1317 CSSSelector::PseudoFocus)) | 1317 CSSSelector::PseudoFocus)) |
| 1318 return true; | 1318 return true; |
| 1319 return element.isFocused() && isFrameFocused(element); | 1319 return element.isFocused() && isFrameFocused(element); |
| 1320 } | 1320 } |
| 1321 | 1321 |
| 1322 } // namespace blink | 1322 } // namespace blink |
| OLD | NEW |