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 Apple Inc. All r
ights reserved. | 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All r
ights 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "core/dom/Node.h" | 42 #include "core/dom/Node.h" |
43 #include "core/inspector/InspectorTraceEvents.h" | 43 #include "core/inspector/InspectorTraceEvents.h" |
44 #include "wtf/BitVector.h" | 44 #include "wtf/BitVector.h" |
45 | 45 |
46 namespace blink { | 46 namespace blink { |
47 | 47 |
48 namespace { | 48 namespace { |
49 | 49 |
50 #if ENABLE(ASSERT) | 50 #if ENABLE(ASSERT) |
51 | 51 |
52 bool supportsInvalidation(CSSSelector::Match match) | 52 bool supportsInvalidation(CSSSelector::MatchType match) |
53 { | 53 { |
54 switch (match) { | 54 switch (match) { |
55 case CSSSelector::Tag: | 55 case CSSSelector::Tag: |
56 case CSSSelector::Id: | 56 case CSSSelector::Id: |
57 case CSSSelector::Class: | 57 case CSSSelector::Class: |
58 case CSSSelector::AttributeExact: | 58 case CSSSelector::AttributeExact: |
59 case CSSSelector::AttributeSet: | 59 case CSSSelector::AttributeSet: |
60 case CSSSelector::AttributeHyphen: | 60 case CSSSelector::AttributeHyphen: |
61 case CSSSelector::AttributeList: | 61 case CSSSelector::AttributeList: |
62 case CSSSelector::AttributeContain: | 62 case CSSSelector::AttributeContain: |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 | 180 |
181 #endif // ENABLE(ASSERT) | 181 #endif // ENABLE(ASSERT) |
182 | 182 |
183 bool requiresSubtreeInvalidation(const CSSSelector& selector) | 183 bool requiresSubtreeInvalidation(const CSSSelector& selector) |
184 { | 184 { |
185 if (selector.match() != CSSSelector::PseudoElement && selector.match() != CS
SSelector::PseudoClass) { | 185 if (selector.match() != CSSSelector::PseudoElement && selector.match() != CS
SSelector::PseudoClass) { |
186 ASSERT(supportsInvalidation(selector.match())); | 186 ASSERT(supportsInvalidation(selector.match())); |
187 return false; | 187 return false; |
188 } | 188 } |
189 | 189 |
190 switch (selector.pseudoType()) { | 190 switch (selector.getPseudoType()) { |
191 case CSSSelector::PseudoFirstLine: | 191 case CSSSelector::PseudoFirstLine: |
192 case CSSSelector::PseudoFirstLetter: | 192 case CSSSelector::PseudoFirstLetter: |
193 // FIXME: Most pseudo classes/elements above can be supported and moved | 193 // FIXME: Most pseudo classes/elements above can be supported and moved |
194 // to assertSupportedPseudo(). Move on a case-by-case basis. If they | 194 // to assertSupportedPseudo(). Move on a case-by-case basis. If they |
195 // require subtree invalidation, document why. | 195 // require subtree invalidation, document why. |
196 case CSSSelector::PseudoHostContext: | 196 case CSSSelector::PseudoHostContext: |
197 // :host-context matches a shadow host, yet the simple selectors inside | 197 // :host-context matches a shadow host, yet the simple selectors inside |
198 // :host-context matches an ancestor of the shadow host. | 198 // :host-context matches an ancestor of the shadow host. |
199 return true; | 199 return true; |
200 default: | 200 default: |
201 ASSERT(supportsInvalidation(selector.pseudoType())); | 201 ASSERT(supportsInvalidation(selector.getPseudoType())); |
202 return false; | 202 return false; |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 template<class Map> | 206 template<class Map> |
207 InvalidationSet& ensureInvalidationSet(Map& map, const typename Map::KeyType& ke
y, InvalidationType type) | 207 InvalidationSet& ensureInvalidationSet(Map& map, const typename Map::KeyType& ke
y, InvalidationType type) |
208 { | 208 { |
209 typename Map::AddResult addResult = map.add(key, nullptr); | 209 typename Map::AddResult addResult = map.add(key, nullptr); |
210 if (addResult.isNewEntry) { | 210 if (addResult.isNewEntry) { |
211 if (type == InvalidateDescendants) | 211 if (type == InvalidateDescendants) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 return true; | 289 return true; |
290 } | 290 } |
291 if (selector.match() == CSSSelector::Class) { | 291 if (selector.match() == CSSSelector::Class) { |
292 features.classes.append(selector.value()); | 292 features.classes.append(selector.value()); |
293 return true; | 293 return true; |
294 } | 294 } |
295 if (selector.isAttributeSelector()) { | 295 if (selector.isAttributeSelector()) { |
296 features.attributes.append(selector.attribute().localName()); | 296 features.attributes.append(selector.attribute().localName()); |
297 return true; | 297 return true; |
298 } | 298 } |
299 if (selector.pseudoType() == CSSSelector::PseudoWebKitCustomElement) { | 299 if (selector.getPseudoType() == CSSSelector::PseudoWebKitCustomElement) { |
300 features.customPseudoElement = true; | 300 features.customPseudoElement = true; |
301 return true; | 301 return true; |
302 } | 302 } |
303 if (selector.pseudoType() == CSSSelector::PseudoBefore || selector.pseudoTyp
e() == CSSSelector::PseudoAfter) | 303 if (selector.getPseudoType() == CSSSelector::PseudoBefore || selector.getPse
udoType() == CSSSelector::PseudoAfter) |
304 features.hasBeforeOrAfter = true; | 304 features.hasBeforeOrAfter = true; |
305 return false; | 305 return false; |
306 } | 306 } |
307 | 307 |
308 InvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& s
elector, InvalidationType type) | 308 InvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& s
elector, InvalidationType type) |
309 { | 309 { |
310 if (selector.match() == CSSSelector::Class) | 310 if (selector.match() == CSSSelector::Class) |
311 return &ensureClassInvalidationSet(selector.value(), type); | 311 return &ensureClassInvalidationSet(selector.value(), type); |
312 if (selector.isAttributeSelector()) | 312 if (selector.isAttributeSelector()) |
313 return &ensureAttributeInvalidationSet(selector.attribute().localName(),
type); | 313 return &ensureAttributeInvalidationSet(selector.attribute().localName(),
type); |
314 if (selector.match() == CSSSelector::Id) | 314 if (selector.match() == CSSSelector::Id) |
315 return &ensureIdInvalidationSet(selector.value(), type); | 315 return &ensureIdInvalidationSet(selector.value(), type); |
316 if (selector.match() == CSSSelector::PseudoClass) { | 316 if (selector.match() == CSSSelector::PseudoClass) { |
317 switch (selector.pseudoType()) { | 317 switch (selector.getPseudoType()) { |
318 case CSSSelector::PseudoEmpty: | 318 case CSSSelector::PseudoEmpty: |
319 case CSSSelector::PseudoLink: | 319 case CSSSelector::PseudoLink: |
320 case CSSSelector::PseudoVisited: | 320 case CSSSelector::PseudoVisited: |
321 case CSSSelector::PseudoAnyLink: | 321 case CSSSelector::PseudoAnyLink: |
322 case CSSSelector::PseudoAutofill: | 322 case CSSSelector::PseudoAutofill: |
323 case CSSSelector::PseudoHover: | 323 case CSSSelector::PseudoHover: |
324 case CSSSelector::PseudoDrag: | 324 case CSSSelector::PseudoDrag: |
325 case CSSSelector::PseudoFocus: | 325 case CSSSelector::PseudoFocus: |
326 case CSSSelector::PseudoActive: | 326 case CSSSelector::PseudoActive: |
327 case CSSSelector::PseudoChecked: | 327 case CSSSelector::PseudoChecked: |
328 case CSSSelector::PseudoEnabled: | 328 case CSSSelector::PseudoEnabled: |
329 // TODO(rune@opera.com): crbug.com/557683 :default is currently not upda
ted dynamically. | 329 // TODO(rune@opera.com): crbug.com/557683 :default is currently not upda
ted dynamically. |
330 // case CSSSelector::Default: | 330 // case CSSSelector::Default: |
331 case CSSSelector::PseudoDisabled: | 331 case CSSSelector::PseudoDisabled: |
332 case CSSSelector::PseudoOptional: | 332 case CSSSelector::PseudoOptional: |
333 case CSSSelector::PseudoPlaceholderShown: | 333 case CSSSelector::PseudoPlaceholderShown: |
334 case CSSSelector::PseudoRequired: | 334 case CSSSelector::PseudoRequired: |
335 case CSSSelector::PseudoReadOnly: | 335 case CSSSelector::PseudoReadOnly: |
336 case CSSSelector::PseudoReadWrite: | 336 case CSSSelector::PseudoReadWrite: |
337 case CSSSelector::PseudoValid: | 337 case CSSSelector::PseudoValid: |
338 case CSSSelector::PseudoInvalid: | 338 case CSSSelector::PseudoInvalid: |
339 case CSSSelector::PseudoIndeterminate: | 339 case CSSSelector::PseudoIndeterminate: |
340 case CSSSelector::PseudoTarget: | 340 case CSSSelector::PseudoTarget: |
341 case CSSSelector::PseudoLang: | 341 case CSSSelector::PseudoLang: |
342 case CSSSelector::PseudoInRange: | 342 case CSSSelector::PseudoInRange: |
343 case CSSSelector::PseudoOutOfRange: | 343 case CSSSelector::PseudoOutOfRange: |
344 case CSSSelector::PseudoUnresolved: | 344 case CSSSelector::PseudoUnresolved: |
345 return &ensurePseudoInvalidationSet(selector.pseudoType(), type); | 345 return &ensurePseudoInvalidationSet(selector.getPseudoType(), type); |
346 default: | 346 default: |
347 break; | 347 break; |
348 } | 348 } |
349 } | 349 } |
350 return nullptr; | 350 return nullptr; |
351 } | 351 } |
352 | 352 |
353 // Given a rule, update the descendant invalidation sets for the features found | 353 // Given a rule, update the descendant invalidation sets for the features found |
354 // in its selector. The first step is to extract the features from the rightmost | 354 // in its selector. The first step is to extract the features from the rightmost |
355 // compound selector (extractInvalidationSetFeatures). Secondly, add those featu
res | 355 // compound selector (extractInvalidationSetFeatures). Secondly, add those featu
res |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 } else { | 413 } else { |
414 if (requiresSubtreeInvalidation(*current)) { | 414 if (requiresSubtreeInvalidation(*current)) { |
415 // Fall back to use subtree invalidations, even for features in
the | 415 // Fall back to use subtree invalidations, even for features in
the |
416 // rightmost compound selector. Returning the start &selector he
re | 416 // rightmost compound selector. Returning the start &selector he
re |
417 // will make addFeaturesToInvalidationSets start marking invalid
ation | 417 // will make addFeaturesToInvalidationSets start marking invalid
ation |
418 // sets for subtree recalc for features in the rightmost compoun
d | 418 // sets for subtree recalc for features in the rightmost compoun
d |
419 // selector. | 419 // selector. |
420 return std::make_pair(&selector, ForceSubtree); | 420 return std::make_pair(&selector, ForceSubtree); |
421 } | 421 } |
422 if (const CSSSelectorList* selectorList = current->selectorList()) { | 422 if (const CSSSelectorList* selectorList = current->selectorList()) { |
423 if (current->pseudoType() == CSSSelector::PseudoSlotted) { | 423 if (current->getPseudoType() == CSSSelector::PseudoSlotted) { |
424 ASSERT(position == Subject); | 424 ASSERT(position == Subject); |
425 features.invalidatesSlotted = true; | 425 features.invalidatesSlotted = true; |
426 } | 426 } |
427 ASSERT(supportsInvalidationWithSelectorList(current->pseudoType(
))); | 427 ASSERT(supportsInvalidationWithSelectorList(current->getPseudoTy
pe())); |
428 const CSSSelector* subSelector = selectorList->first(); | 428 const CSSSelector* subSelector = selectorList->first(); |
429 bool allSubSelectorsHaveFeatures = !!subSelector; | 429 bool allSubSelectorsHaveFeatures = !!subSelector; |
430 for (; subSelector; subSelector = CSSSelectorList::next(*subSele
ctor)) { | 430 for (; subSelector; subSelector = CSSSelectorList::next(*subSele
ctor)) { |
431 auto result = extractInvalidationSetFeatures(*subSelector, f
eatures, position, current->pseudoType()); | 431 auto result = extractInvalidationSetFeatures(*subSelector, f
eatures, position, current->getPseudoType()); |
432 if (result.first) { | 432 if (result.first) { |
433 // A non-null selector return means the sub-selector con
tained a | 433 // A non-null selector return means the sub-selector con
tained a |
434 // selector which requiresSubtreeInvalidation(). Return
the rightmost | 434 // selector which requiresSubtreeInvalidation(). Return
the rightmost |
435 // selector to mark for subtree recalcs like above. | 435 // selector to mark for subtree recalcs like above. |
436 return std::make_pair(&selector, ForceSubtree); | 436 return std::make_pair(&selector, ForceSubtree); |
437 } | 437 } |
438 allSubSelectorsHaveFeatures &= result.second == UseFeatures; | 438 allSubSelectorsHaveFeatures &= result.second == UseFeatures; |
439 } | 439 } |
440 foundFeatures |= allSubSelectorsHaveFeatures; | 440 foundFeatures |= allSubSelectorsHaveFeatures; |
441 } | 441 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 addFeaturesToInvalidationSet(siblingInvalidationSet->ensureS
iblingDescendants(), descendantFeatures); | 515 addFeaturesToInvalidationSet(siblingInvalidationSet->ensureS
iblingDescendants(), descendantFeatures); |
516 } else { | 516 } else { |
517 addFeaturesToInvalidationSet(*invalidationSet, descendantFeature
s); | 517 addFeaturesToInvalidationSet(*invalidationSet, descendantFeature
s); |
518 } | 518 } |
519 } else { | 519 } else { |
520 if (current->isHostPseudoClass()) | 520 if (current->isHostPseudoClass()) |
521 descendantFeatures.treeBoundaryCrossing = true; | 521 descendantFeatures.treeBoundaryCrossing = true; |
522 if (current->isInsertionPointCrossing()) | 522 if (current->isInsertionPointCrossing()) |
523 descendantFeatures.insertionPointCrossing = true; | 523 descendantFeatures.insertionPointCrossing = true; |
524 if (const CSSSelectorList* selectorList = current->selectorList()) { | 524 if (const CSSSelectorList* selectorList = current->selectorList()) { |
525 ASSERT(supportsInvalidationWithSelectorList(current->pseudoType(
))); | 525 ASSERT(supportsInvalidationWithSelectorList(current->getPseudoTy
pe())); |
526 for (const CSSSelector* subSelector = selectorList->first(); sub
Selector; subSelector = CSSSelectorList::next(*subSelector)) | 526 for (const CSSSelector* subSelector = selectorList->first(); sub
Selector; subSelector = CSSSelectorList::next(*subSelector)) |
527 addFeaturesToInvalidationSets(subSelector, siblingFeatures,
descendantFeatures); | 527 addFeaturesToInvalidationSets(subSelector, siblingFeatures,
descendantFeatures); |
528 } | 528 } |
529 } | 529 } |
530 | 530 |
531 if (current->relation() == CSSSelector::SubSelector) | 531 if (current->relation() == CSSSelector::SubSelector) |
532 continue; | 532 continue; |
533 | 533 |
534 if (current->relationIsAffectedByPseudoContent() || current->relation()
== CSSSelector::ShadowSlot) { | 534 if (current->relationIsAffectedByPseudoContent() || current->relation()
== CSSSelector::ShadowSlot) { |
535 descendantFeatures.insertionPointCrossing = true; | 535 descendantFeatures.insertionPointCrossing = true; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 if (ruleData.containsUncommonAttributeSelector()) | 575 if (ruleData.containsUncommonAttributeSelector()) |
576 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele
ctorIndex(), ruleData.hasDocumentSecurityOrigin())); | 576 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele
ctorIndex(), ruleData.hasDocumentSecurityOrigin())); |
577 | 577 |
578 updateInvalidationSets(ruleData); | 578 updateInvalidationSets(ruleData); |
579 return SelectorMayMatch; | 579 return SelectorMayMatch; |
580 } | 580 } |
581 | 581 |
582 RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromSelector(con
st CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata) | 582 RuleFeatureSet::SelectorPreMatch RuleFeatureSet::collectFeaturesFromSelector(con
st CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata) |
583 { | 583 { |
584 unsigned maxDirectAdjacentSelectors = 0; | 584 unsigned maxDirectAdjacentSelectors = 0; |
585 CSSSelector::Relation relation = CSSSelector::Descendant; | 585 CSSSelector::RelationType relation = CSSSelector::Descendant; |
586 bool foundHostPseudo = false; | 586 bool foundHostPseudo = false; |
587 | 587 |
588 for (const CSSSelector* current = &selector; current; current = current->tag
History()) { | 588 for (const CSSSelector* current = &selector; current; current = current->tag
History()) { |
589 switch (current->pseudoType()) { | 589 switch (current->getPseudoType()) { |
590 case CSSSelector::PseudoFirstLine: | 590 case CSSSelector::PseudoFirstLine: |
591 metadata.usesFirstLineRules = true; | 591 metadata.usesFirstLineRules = true; |
592 break; | 592 break; |
593 case CSSSelector::PseudoWindowInactive: | 593 case CSSSelector::PseudoWindowInactive: |
594 metadata.usesWindowInactiveSelector = true; | 594 metadata.usesWindowInactiveSelector = true; |
595 break; | 595 break; |
596 case CSSSelector::PseudoEmpty: | 596 case CSSSelector::PseudoEmpty: |
597 case CSSSelector::PseudoFirstChild: | 597 case CSSSelector::PseudoFirstChild: |
598 case CSSSelector::PseudoFirstOfType: | 598 case CSSSelector::PseudoFirstOfType: |
599 case CSSSelector::PseudoLastChild: | 599 case CSSSelector::PseudoLastChild: |
(...skipping 16 matching lines...) Expand all Loading... |
616 foundHostPseudo = true; | 616 foundHostPseudo = true; |
617 // fall through. | 617 // fall through. |
618 default: | 618 default: |
619 if (const CSSSelectorList* selectorList = current->selectorList()) { | 619 if (const CSSSelectorList* selectorList = current->selectorList()) { |
620 for (const CSSSelector* subSelector = selectorList->first(); sub
Selector; subSelector = CSSSelectorList::next(*subSelector)) | 620 for (const CSSSelector* subSelector = selectorList->first(); sub
Selector; subSelector = CSSSelectorList::next(*subSelector)) |
621 collectFeaturesFromSelector(*subSelector, metadata); | 621 collectFeaturesFromSelector(*subSelector, metadata); |
622 } | 622 } |
623 break; | 623 break; |
624 } | 624 } |
625 | 625 |
626 if (current->relationIsAffectedByPseudoContent() || current->pseudoType(
) == CSSSelector::PseudoSlotted) | 626 if (current->relationIsAffectedByPseudoContent() || current->getPseudoTy
pe() == CSSSelector::PseudoSlotted) |
627 metadata.foundInsertionPointCrossing = true; | 627 metadata.foundInsertionPointCrossing = true; |
628 | 628 |
629 relation = current->relation(); | 629 relation = current->relation(); |
630 | 630 |
631 if (foundHostPseudo && relation != CSSSelector::SubSelector) | 631 if (foundHostPseudo && relation != CSSSelector::SubSelector) |
632 return SelectorNeverMatches; | 632 return SelectorNeverMatches; |
633 | 633 |
634 if (relation == CSSSelector::DirectAdjacent) { | 634 if (relation == CSSSelector::DirectAdjacent) { |
635 maxDirectAdjacentSelectors++; | 635 maxDirectAdjacentSelectors++; |
636 } else if (maxDirectAdjacentSelectors | 636 } else if (maxDirectAdjacentSelectors |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 | 778 |
779 DEFINE_TRACE(RuleFeatureSet) | 779 DEFINE_TRACE(RuleFeatureSet) |
780 { | 780 { |
781 #if ENABLE(OILPAN) | 781 #if ENABLE(OILPAN) |
782 visitor->trace(siblingRules); | 782 visitor->trace(siblingRules); |
783 visitor->trace(uncommonAttributeRules); | 783 visitor->trace(uncommonAttributeRules); |
784 #endif | 784 #endif |
785 } | 785 } |
786 | 786 |
787 } // namespace blink | 787 } // namespace blink |
OLD | NEW |