2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.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 rights reserved.
6 * Copyright (C) 2007 Alexey Proskuryakov <ap@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.torchmobile.com/)
9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11 * Copyright (C) 2012 Google Inc. All rights reserved.
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public License
24 * along with this library; see the file COPYING.LIB. If not, write to
25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
30 #include "core/css/RuleFeature.h"
32 #include "core/HTMLNames.h"
33 #include "core/css/CSSFunctionValue.h"
34 #include "core/css/CSSSelector.h"
35 #include "core/css/CSSSelectorList.h"
36 #include "core/css/CSSValueList.h"
37 #include "core/css/RuleSet.h"
38 #include "core/css/StylePropertySet.h"
39 #include "core/css/StyleRule.h"
40 #include "core/css/invalidation/InvalidationSet.h"
41 #include "core/dom/Element.h"
42 #include "core/dom/Node.h"
43 #include "core/inspector/InspectorTraceEvents.h"
44 #include "wtf/BitVector.h"
50 static bool supportsInvalidation(CSSSelector::Match match
)
53 case CSSSelector::Tag
:
55 case CSSSelector::Class
:
56 case CSSSelector::AttributeExact
:
57 case CSSSelector::AttributeSet
:
58 case CSSSelector::AttributeHyphen
:
59 case CSSSelector::AttributeList
:
60 case CSSSelector::AttributeContain
:
61 case CSSSelector::AttributeBegin
:
62 case CSSSelector::AttributeEnd
:
64 case CSSSelector::Unknown
:
65 case CSSSelector::PagePseudoClass
:
66 // These should not appear in StyleRule selectors.
70 // New match type added. Figure out if it needs a subtree invalidation or not.
76 static bool supportsInvalidation(CSSSelector::PseudoType type
)
79 case CSSSelector::PseudoEmpty
:
80 case CSSSelector::PseudoFirstChild
:
81 case CSSSelector::PseudoFirstOfType
:
82 case CSSSelector::PseudoLastChild
:
83 case CSSSelector::PseudoLastOfType
:
84 case CSSSelector::PseudoOnlyChild
:
85 case CSSSelector::PseudoOnlyOfType
:
86 case CSSSelector::PseudoNthChild
:
87 case CSSSelector::PseudoNthOfType
:
88 case CSSSelector::PseudoNthLastChild
:
89 case CSSSelector::PseudoNthLastOfType
:
90 case CSSSelector::PseudoLink
:
91 case CSSSelector::PseudoVisited
:
92 case CSSSelector::PseudoAny
:
93 case CSSSelector::PseudoAnyLink
:
94 case CSSSelector::PseudoAutofill
:
95 case CSSSelector::PseudoHover
:
96 case CSSSelector::PseudoDrag
:
97 case CSSSelector::PseudoFocus
:
98 case CSSSelector::PseudoActive
:
99 case CSSSelector::PseudoChecked
:
100 case CSSSelector::PseudoEnabled
:
101 case CSSSelector::PseudoFullPageMedia
:
102 case CSSSelector::PseudoDefault
:
103 case CSSSelector::PseudoDisabled
:
104 case CSSSelector::PseudoOptional
:
105 case CSSSelector::PseudoPlaceholderShown
:
106 case CSSSelector::PseudoRequired
:
107 case CSSSelector::PseudoReadOnly
:
108 case CSSSelector::PseudoReadWrite
:
109 case CSSSelector::PseudoValid
:
110 case CSSSelector::PseudoInvalid
:
111 case CSSSelector::PseudoIndeterminate
:
112 case CSSSelector::PseudoTarget
:
113 case CSSSelector::PseudoBefore
:
114 case CSSSelector::PseudoAfter
:
115 case CSSSelector::PseudoBackdrop
:
116 case CSSSelector::PseudoLang
:
117 case CSSSelector::PseudoNot
:
118 case CSSSelector::PseudoResizer
:
119 case CSSSelector::PseudoRoot
:
120 case CSSSelector::PseudoScope
:
121 case CSSSelector::PseudoScrollbar
:
122 case CSSSelector::PseudoScrollbarButton
:
123 case CSSSelector::PseudoScrollbarCorner
:
124 case CSSSelector::PseudoScrollbarThumb
:
125 case CSSSelector::PseudoScrollbarTrack
:
126 case CSSSelector::PseudoScrollbarTrackPiece
:
127 case CSSSelector::PseudoWindowInactive
:
128 case CSSSelector::PseudoSelection
:
129 case CSSSelector::PseudoCornerPresent
:
130 case CSSSelector::PseudoDecrement
:
131 case CSSSelector::PseudoIncrement
:
132 case CSSSelector::PseudoHorizontal
:
133 case CSSSelector::PseudoVertical
:
134 case CSSSelector::PseudoStart
:
135 case CSSSelector::PseudoEnd
:
136 case CSSSelector::PseudoDoubleButton
:
137 case CSSSelector::PseudoSingleButton
:
138 case CSSSelector::PseudoNoButton
:
139 case CSSSelector::PseudoFullScreen
:
140 case CSSSelector::PseudoFullScreenAncestor
:
141 case CSSSelector::PseudoInRange
:
142 case CSSSelector::PseudoOutOfRange
:
143 case CSSSelector::PseudoWebKitCustomElement
:
144 case CSSSelector::PseudoCue
:
145 case CSSSelector::PseudoFutureCue
:
146 case CSSSelector::PseudoPastCue
:
147 case CSSSelector::PseudoUnresolved
:
148 case CSSSelector::PseudoContent
:
149 case CSSSelector::PseudoHost
:
150 case CSSSelector::PseudoShadow
:
151 case CSSSelector::PseudoSpatialNavigationFocus
:
152 case CSSSelector::PseudoListBox
:
154 case CSSSelector::PseudoUnknown
:
155 case CSSSelector::PseudoLeftPage
:
156 case CSSSelector::PseudoRightPage
:
157 case CSSSelector::PseudoFirstPage
:
158 // These should not appear in StyleRule selectors.
159 ASSERT_NOT_REACHED();
162 // New pseudo type added. Figure out if it needs a subtree invalidation or not.
163 ASSERT_NOT_REACHED();
168 static bool supportsInvalidationWithSelectorList(CSSSelector::PseudoType pseudo
)
170 return pseudo
== CSSSelector::PseudoAny
171 || pseudo
== CSSSelector::PseudoCue
172 || pseudo
== CSSSelector::PseudoHost
173 || pseudo
== CSSSelector::PseudoHostContext
174 || pseudo
== CSSSelector::PseudoNot
;
177 #endif // ENABLE(ASSERT)
179 static bool requiresSubtreeInvalidation(const CSSSelector
& selector
)
181 if (selector
.match() != CSSSelector::PseudoElement
&& selector
.match() != CSSSelector::PseudoClass
) {
182 ASSERT(supportsInvalidation(selector
.match()));
186 switch (selector
.pseudoType()) {
187 case CSSSelector::PseudoFirstLine
:
188 case CSSSelector::PseudoFirstLetter
:
189 // FIXME: Most pseudo classes/elements above can be supported and moved
190 // to assertSupportedPseudo(). Move on a case-by-case basis. If they
191 // require subtree invalidation, document why.
192 case CSSSelector::PseudoHostContext
:
193 // :host-context matches a shadow host, yet the simple selectors inside
194 // :host-context matches an ancestor of the shadow host.
197 ASSERT(supportsInvalidation(selector
.pseudoType()));
202 RuleFeature::RuleFeature(StyleRule
* rule
, unsigned selectorIndex
, bool hasDocumentSecurityOrigin
)
204 , selectorIndex(selectorIndex
)
205 , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin
)
209 DEFINE_TRACE(RuleFeature
)
211 visitor
->trace(rule
);
214 bool RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector
& selector
, InvalidationSetFeatures
& features
)
216 if (selector
.match() == CSSSelector::Tag
&& selector
.tagQName().localName() != starAtom
)
217 features
.tagName
= selector
.tagQName().localName();
218 else if (selector
.match() == CSSSelector::Id
)
219 features
.id
= selector
.value();
220 else if (selector
.match() == CSSSelector::Class
)
221 features
.classes
.append(selector
.value());
222 else if (selector
.isAttributeSelector())
223 features
.attributes
.append(selector
.attribute().localName());
224 else if (selector
.pseudoType() == CSSSelector::PseudoWebKitCustomElement
)
225 features
.customPseudoElement
= true;
226 else if (selector
.pseudoType() == CSSSelector::PseudoBefore
|| selector
.pseudoType() == CSSSelector::PseudoAfter
)
227 features
.hasBeforeOrAfter
= true;
233 RuleFeatureSet::RuleFeatureSet()
237 RuleFeatureSet::~RuleFeatureSet()
241 InvalidationSet
* RuleFeatureSet::invalidationSetForSelector(const CSSSelector
& selector
)
243 if (selector
.match() == CSSSelector::Class
)
244 return &ensureClassInvalidationSet(selector
.value());
245 if (selector
.isAttributeSelector())
246 return &ensureAttributeInvalidationSet(selector
.attribute().localName());
247 if (selector
.match() == CSSSelector::Id
)
248 return &ensureIdInvalidationSet(selector
.value());
249 if (selector
.match() == CSSSelector::PseudoClass
) {
250 switch (selector
.pseudoType()) {
251 case CSSSelector::PseudoEmpty
:
252 case CSSSelector::PseudoLink
:
253 case CSSSelector::PseudoVisited
:
254 case CSSSelector::PseudoAnyLink
:
255 case CSSSelector::PseudoAutofill
:
256 case CSSSelector::PseudoHover
:
257 case CSSSelector::PseudoFocus
:
258 case CSSSelector::PseudoActive
:
259 case CSSSelector::PseudoChecked
:
260 case CSSSelector::PseudoEnabled
:
261 case CSSSelector::PseudoDisabled
:
262 case CSSSelector::PseudoOptional
:
263 case CSSSelector::PseudoPlaceholderShown
:
264 case CSSSelector::PseudoRequired
:
265 case CSSSelector::PseudoValid
:
266 case CSSSelector::PseudoInvalid
:
267 case CSSSelector::PseudoIndeterminate
:
268 case CSSSelector::PseudoTarget
:
269 return &ensurePseudoInvalidationSet(selector
.pseudoType());
277 // Given a rule, update the descendant invalidation sets for the features found
278 // in its selector. The first step is to extract the features from the rightmost
279 // compound selector (extractInvalidationSetFeatures). Secondly, add those features
280 // to the invalidation sets for the features found in the other compound selectors
281 // (addFeaturesToInvalidationSets). If we find a feature in the right-most compound
282 // selector that requires a subtree recalc, we addFeaturesToInvalidationSets for the
283 // rightmost compound selector as well.
285 void RuleFeatureSet::updateInvalidationSets(const RuleData
& ruleData
)
287 InvalidationSetFeatures features
;
288 auto result
= extractInvalidationSetFeatures(ruleData
.selector(), features
, false);
290 features
.forceSubtree
= result
.second
== ForceSubtree
;
291 addFeaturesToInvalidationSets(*result
.first
, features
);
294 // If any ::before and ::after rules specify 'content: attr(...)', we
295 // need to create invalidation sets for those attributes.
296 if (features
.hasBeforeOrAfter
)
297 updateInvalidationSetsForContentAttribute(ruleData
);
300 void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData
& ruleData
)
302 const StylePropertySet
& propertySet
= ruleData
.rule()->properties();
304 int propertyIndex
= propertySet
.findPropertyIndex(CSSPropertyContent
);
306 if (propertyIndex
== -1)
309 StylePropertySet::PropertyReference contentProperty
= propertySet
.propertyAt(propertyIndex
);
310 CSSValue
* contentValue
= contentProperty
.value();
312 if (!contentValue
->isValueList())
315 for (auto& item
: toCSSValueList(*contentValue
)) {
316 if (!item
->isFunctionValue())
318 CSSFunctionValue
* functionValue
= toCSSFunctionValue(item
.get());
319 if (functionValue
->functionType() != CSSValueAttr
)
321 ensureAttributeInvalidationSet(AtomicString(toCSSPrimitiveValue(functionValue
->item(0))->getStringValue())).setInvalidatesSelf();
325 std::pair
<const CSSSelector
*, RuleFeatureSet::UseFeaturesType
>
326 RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector
& selector
, InvalidationSetFeatures
& features
, bool negated
)
328 bool foundFeatures
= false;
329 for (const CSSSelector
* current
= &selector
; current
; current
= current
->tagHistory()) {
331 foundFeatures
|= extractInvalidationSetFeature(*current
, features
);
332 // Initialize the entry in the invalidation set map, if supported.
333 if (InvalidationSet
* invalidationSet
= invalidationSetForSelector(*current
)) {
334 invalidationSet
->setInvalidatesSelf();
336 if (requiresSubtreeInvalidation(*current
)) {
337 // Fall back to use subtree invalidations, even for features in the
338 // rightmost compound selector. Returning the start &selector here
339 // will make addFeaturesToInvalidationSets start marking invalidation
340 // sets for subtree recalc for features in the rightmost compound
342 return std::make_pair(&selector
, ForceSubtree
);
344 if (const CSSSelectorList
* selectorList
= current
->selectorList()) {
345 ASSERT(supportsInvalidationWithSelectorList(current
->pseudoType()));
346 const CSSSelector
* subSelector
= selectorList
->first();
347 bool allSubSelectorsHaveFeatures
= !!subSelector
;
348 for (; subSelector
; subSelector
= CSSSelectorList::next(*subSelector
)) {
349 auto result
= extractInvalidationSetFeatures(*subSelector
, features
, current
->pseudoType() == CSSSelector::PseudoNot
);
351 // A non-null selector return means the sub-selector contained a
352 // selector which requiresSubtreeInvalidation(). Return the rightmost
353 // selector to mark for subtree recalcs like above.
354 return std::make_pair(&selector
, ForceSubtree
);
356 allSubSelectorsHaveFeatures
&= result
.second
== UseFeatures
;
358 foundFeatures
|= allSubSelectorsHaveFeatures
;
362 if (current
->relation() == CSSSelector::SubSelector
)
365 features
.treeBoundaryCrossing
= current
->isShadowSelector();
366 features
.adjacent
= current
->isAdjacentSelector();
367 return std::make_pair(current
->tagHistory(), foundFeatures
? UseFeatures
: ForceSubtree
);
369 return std::make_pair(nullptr, foundFeatures
? UseFeatures
: ForceSubtree
);
372 // Add features extracted from the rightmost compound selector to descendant invalidation
373 // sets for features found in other compound selectors.
375 // Style invalidation is currently supported for descendants only, not for sibling subtrees.
376 // We use wholeSubtree invalidation for features found left of adjacent combinators as
377 // SubtreeStyleChange will force sibling subtree recalc in
378 // ContainerNode::checkForChildrenAdjacentRuleChanges.
380 // As we encounter a descendant type of combinator, the features only need to be checked
381 // against descendants in the same subtree only. features.adjacent is set to false, and
382 // we start adding features instead of calling setWholeSubtreeInvalid.
384 void RuleFeatureSet::addFeaturesToInvalidationSet(InvalidationSet
& invalidationSet
, const InvalidationSetFeatures
& features
)
386 if (features
.treeBoundaryCrossing
)
387 invalidationSet
.setTreeBoundaryCrossing();
388 if (features
.insertionPointCrossing
)
389 invalidationSet
.setInsertionPointCrossing();
390 if (features
.useSubtreeInvalidation()) {
391 invalidationSet
.setWholeSubtreeInvalid();
394 if (!features
.id
.isEmpty())
395 invalidationSet
.addId(features
.id
);
396 if (!features
.tagName
.isEmpty())
397 invalidationSet
.addTagName(features
.tagName
);
398 for (const auto& className
: features
.classes
)
399 invalidationSet
.addClass(className
);
400 for (const auto& attribute
: features
.attributes
)
401 invalidationSet
.addAttribute(attribute
);
402 if (features
.customPseudoElement
)
403 invalidationSet
.setCustomPseudoInvalid();
406 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector
& selector
, InvalidationSetFeatures
& features
)
408 for (const CSSSelector
* current
= &selector
; current
; current
= current
->tagHistory()) {
409 if (InvalidationSet
* invalidationSet
= invalidationSetForSelector(*current
)) {
410 addFeaturesToInvalidationSet(*invalidationSet
, features
);
412 if (current
->isTreeBoundaryCrossing())
413 features
.treeBoundaryCrossing
= true;
414 if (current
->isInsertionPointCrossing())
415 features
.insertionPointCrossing
= true;
416 if (const CSSSelectorList
* selectorList
= current
->selectorList()) {
417 ASSERT(supportsInvalidationWithSelectorList(current
->pseudoType()));
418 for (const CSSSelector
* subSelector
= selectorList
->first(); subSelector
; subSelector
= CSSSelectorList::next(*subSelector
))
419 addFeaturesToInvalidationSets(*subSelector
, features
);
423 if (current
->relation() == CSSSelector::SubSelector
)
426 if (current
->isShadowSelector())
427 features
.treeBoundaryCrossing
= true;
429 features
.adjacent
= current
->isAdjacentSelector();
433 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData
& ruleData
)
435 updateInvalidationSets(ruleData
);
437 FeatureMetadata metadata
;
438 collectFeaturesFromSelector(ruleData
.selector(), metadata
);
439 m_metadata
.add(metadata
);
441 if (metadata
.foundSiblingSelector
)
442 siblingRules
.append(RuleFeature(ruleData
.rule(), ruleData
.selectorIndex(), ruleData
.hasDocumentSecurityOrigin()));
443 if (ruleData
.containsUncommonAttributeSelector())
444 uncommonAttributeRules
.append(RuleFeature(ruleData
.rule(), ruleData
.selectorIndex(), ruleData
.hasDocumentSecurityOrigin()));
447 InvalidationSet
& RuleFeatureSet::ensureClassInvalidationSet(const AtomicString
& className
)
449 InvalidationSetMap::AddResult addResult
= m_classInvalidationSets
.add(className
, nullptr);
450 if (addResult
.isNewEntry
)
451 addResult
.storedValue
->value
= InvalidationSet::create();
452 return *addResult
.storedValue
->value
;
455 InvalidationSet
& RuleFeatureSet::ensureAttributeInvalidationSet(const AtomicString
& attributeName
)
457 InvalidationSetMap::AddResult addResult
= m_attributeInvalidationSets
.add(attributeName
, nullptr);
458 if (addResult
.isNewEntry
)
459 addResult
.storedValue
->value
= InvalidationSet::create();
460 return *addResult
.storedValue
->value
;
463 InvalidationSet
& RuleFeatureSet::ensureIdInvalidationSet(const AtomicString
& id
)
465 InvalidationSetMap::AddResult addResult
= m_idInvalidationSets
.add(id
, nullptr);
466 if (addResult
.isNewEntry
)
467 addResult
.storedValue
->value
= InvalidationSet::create();
468 return *addResult
.storedValue
->value
;
471 InvalidationSet
& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelector::PseudoType pseudoType
)
473 PseudoTypeInvalidationSetMap::AddResult addResult
= m_pseudoInvalidationSets
.add(pseudoType
, nullptr);
474 if (addResult
.isNewEntry
)
475 addResult
.storedValue
->value
= InvalidationSet::create();
476 return *addResult
.storedValue
->value
;
479 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector
& selector
, RuleFeatureSet::FeatureMetadata
& metadata
)
481 unsigned maxDirectAdjacentSelectors
= 0;
483 for (const CSSSelector
* current
= &selector
; current
; current
= current
->tagHistory()) {
484 if (current
->pseudoType() == CSSSelector::PseudoFirstLine
)
485 metadata
.usesFirstLineRules
= true;
486 if (current
->pseudoType() == CSSSelector::PseudoWindowInactive
)
487 metadata
.usesWindowInactiveSelector
= true;
488 if (current
->relation() == CSSSelector::DirectAdjacent
) {
489 maxDirectAdjacentSelectors
++;
490 } else if (maxDirectAdjacentSelectors
491 && ((current
->relation() != CSSSelector::SubSelector
) || current
->isLastInTagHistory())) {
492 if (maxDirectAdjacentSelectors
> metadata
.maxDirectAdjacentSelectors
)
493 metadata
.maxDirectAdjacentSelectors
= maxDirectAdjacentSelectors
;
494 maxDirectAdjacentSelectors
= 0;
496 if (current
->isSiblingSelector())
497 metadata
.foundSiblingSelector
= true;
499 const CSSSelectorList
* selectorList
= current
->selectorList();
503 for (const CSSSelector
* subSelector
= selectorList
->first(); subSelector
; subSelector
= CSSSelectorList::next(*subSelector
))
504 collectFeaturesFromSelector(*subSelector
, metadata
);
507 ASSERT(!maxDirectAdjacentSelectors
);
510 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata
& other
)
512 usesFirstLineRules
= usesFirstLineRules
|| other
.usesFirstLineRules
;
513 usesWindowInactiveSelector
= usesWindowInactiveSelector
|| other
.usesWindowInactiveSelector
;
514 maxDirectAdjacentSelectors
= std::max(maxDirectAdjacentSelectors
, other
.maxDirectAdjacentSelectors
);
517 void RuleFeatureSet::FeatureMetadata::clear()
519 usesFirstLineRules
= false;
520 usesWindowInactiveSelector
= false;
521 foundSiblingSelector
= false;
522 maxDirectAdjacentSelectors
= 0;
525 void RuleFeatureSet::add(const RuleFeatureSet
& other
)
527 for (const auto& invalidationSet
: other
.m_classInvalidationSets
)
528 ensureClassInvalidationSet(invalidationSet
.key
).combine(*invalidationSet
.value
);
529 for (const auto& invalidationSet
: other
.m_attributeInvalidationSets
)
530 ensureAttributeInvalidationSet(invalidationSet
.key
).combine(*invalidationSet
.value
);
531 for (const auto& invalidationSet
: other
.m_idInvalidationSets
)
532 ensureIdInvalidationSet(invalidationSet
.key
).combine(*invalidationSet
.value
);
533 for (const auto& invalidationSet
: other
.m_pseudoInvalidationSets
)
534 ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType
>(invalidationSet
.key
)).combine(*invalidationSet
.value
);
536 m_metadata
.add(other
.m_metadata
);
538 siblingRules
.appendVector(other
.siblingRules
);
539 uncommonAttributeRules
.appendVector(other
.uncommonAttributeRules
);
542 void RuleFeatureSet::clear()
544 siblingRules
.clear();
545 uncommonAttributeRules
.clear();
547 m_classInvalidationSets
.clear();
548 m_attributeInvalidationSets
.clear();
549 m_idInvalidationSets
.clear();
552 void RuleFeatureSet::collectInvalidationSetsForClass(InvalidationSetVector
& invalidationSets
, Element
& element
, const AtomicString
& className
) const
554 if (RefPtrWillBeRawPtr
<InvalidationSet
> invalidationSet
= m_classInvalidationSets
.get(className
)) {
555 TRACE_SCHEDULE_STYLE_INVALIDATION(element
, *invalidationSet
, classChange
, className
);
556 invalidationSets
.append(invalidationSet
);
560 void RuleFeatureSet::collectInvalidationSetsForId(InvalidationSetVector
& invalidationSets
, Element
& element
, const AtomicString
& id
) const
562 if (RefPtrWillBeRawPtr
<InvalidationSet
> invalidationSet
= m_idInvalidationSets
.get(id
)) {
563 TRACE_SCHEDULE_STYLE_INVALIDATION(element
, *invalidationSet
, idChange
, id
);
564 invalidationSets
.append(invalidationSet
);
568 void RuleFeatureSet::collectInvalidationSetsForAttribute(InvalidationSetVector
& invalidationSets
, Element
& element
, const QualifiedName
& attributeName
) const
570 if (RefPtrWillBeRawPtr
<InvalidationSet
> invalidationSet
= m_attributeInvalidationSets
.get(attributeName
.localName())) {
571 TRACE_SCHEDULE_STYLE_INVALIDATION(element
, *invalidationSet
, attributeChange
, attributeName
);
572 invalidationSets
.append(invalidationSet
);
576 void RuleFeatureSet::collectInvalidationSetsForPseudoClass(InvalidationSetVector
& invalidationSets
, Element
& element
, CSSSelector::PseudoType pseudo
) const
578 if (RefPtrWillBeRawPtr
<InvalidationSet
> invalidationSet
= m_pseudoInvalidationSets
.get(pseudo
)) {
579 TRACE_SCHEDULE_STYLE_INVALIDATION(element
, *invalidationSet
, pseudoChange
, pseudo
);
580 invalidationSets
.append(invalidationSet
);
584 DEFINE_TRACE(RuleFeatureSet
)
587 visitor
->trace(siblingRules
);
588 visitor
->trace(uncommonAttributeRules
);
589 visitor
->trace(m_classInvalidationSets
);
590 visitor
->trace(m_attributeInvalidationSets
);
591 visitor
->trace(m_idInvalidationSets
);
592 visitor
->trace(m_pseudoInvalidationSets
);