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

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

Issue 639433002: Drop InvalidationSetMode. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 2 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
« no previous file with comments | « Source/core/css/RuleFeature.h ('k') | Source/core/css/invalidation/DescendantInvalidationSet.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 19 matching lines...) Expand all
30 #include "core/css/RuleFeature.h" 30 #include "core/css/RuleFeature.h"
31 31
32 #include "core/HTMLNames.h" 32 #include "core/HTMLNames.h"
33 #include "core/css/CSSSelector.h" 33 #include "core/css/CSSSelector.h"
34 #include "core/css/CSSSelectorList.h" 34 #include "core/css/CSSSelectorList.h"
35 #include "core/css/RuleSet.h" 35 #include "core/css/RuleSet.h"
36 #include "core/css/StyleRule.h" 36 #include "core/css/StyleRule.h"
37 #include "core/css/invalidation/DescendantInvalidationSet.h" 37 #include "core/css/invalidation/DescendantInvalidationSet.h"
38 #include "core/dom/Element.h" 38 #include "core/dom/Element.h"
39 #include "core/dom/Node.h" 39 #include "core/dom/Node.h"
40 #include "platform/RuntimeEnabledFeatures.h"
41 #include "wtf/BitVector.h" 40 #include "wtf/BitVector.h"
42 41
43 namespace blink { 42 namespace blink {
44 43
45 static bool isSkippableComponentForInvalidation(const CSSSelector& selector) 44 static void assertSupportedMatch(CSSSelector::Match match)
46 { 45 {
47 if (selector.match() == CSSSelector::Tag) { 46 switch (match) {
48 ASSERT(selector.tagQName().localName() == starAtom); 47 case CSSSelector::Tag:
49 return true; 48 case CSSSelector::Id:
49 case CSSSelector::Class:
50 case CSSSelector::AttributeExact:
51 case CSSSelector::AttributeSet:
52 case CSSSelector::AttributeHyphen:
53 case CSSSelector::AttributeList:
54 case CSSSelector::AttributeContain:
55 case CSSSelector::AttributeBegin:
56 case CSSSelector::AttributeEnd:
57 break;
58 case CSSSelector::Unknown:
59 case CSSSelector::PagePseudoClass:
60 // These should not appear in StyleRule selectors.
61 ASSERT_NOT_REACHED();
62 break;
63 default:
64 // New match type added. Figure out if it needs a subtree recalc or not.
65 ASSERT_NOT_REACHED();
66 break;
50 } 67 }
51 if (selector.match() == CSSSelector::PseudoElement) { 68 }
52 switch (selector.pseudoType()) { 69
53 case CSSSelector::PseudoBefore: 70 static void assertSupportedPseudo(CSSSelector::PseudoType type)
54 case CSSSelector::PseudoAfter: 71 {
55 case CSSSelector::PseudoBackdrop: 72 switch (type) {
56 case CSSSelector::PseudoShadow:
57 return true;
58 default:
59 ASSERT(!selector.isCustomPseudoElement());
60 return false;
61 }
62 }
63 if (selector.match() != CSSSelector::PseudoClass)
64 return false;
65 switch (selector.pseudoType()) {
66 case CSSSelector::PseudoEmpty: 73 case CSSSelector::PseudoEmpty:
67 case CSSSelector::PseudoFirstChild: 74 case CSSSelector::PseudoFirstChild:
68 case CSSSelector::PseudoFirstOfType: 75 case CSSSelector::PseudoFirstOfType:
69 case CSSSelector::PseudoLastChild: 76 case CSSSelector::PseudoLastChild:
70 case CSSSelector::PseudoLastOfType: 77 case CSSSelector::PseudoLastOfType:
71 case CSSSelector::PseudoOnlyChild: 78 case CSSSelector::PseudoOnlyChild:
72 case CSSSelector::PseudoOnlyOfType: 79 case CSSSelector::PseudoOnlyOfType:
73 case CSSSelector::PseudoNthChild: 80 case CSSSelector::PseudoNthChild:
74 case CSSSelector::PseudoNthOfType: 81 case CSSSelector::PseudoNthOfType:
75 case CSSSelector::PseudoNthLastChild: 82 case CSSSelector::PseudoNthLastChild:
76 case CSSSelector::PseudoNthLastOfType: 83 case CSSSelector::PseudoNthLastOfType:
77 case CSSSelector::PseudoLink: 84 case CSSSelector::PseudoLink:
78 case CSSSelector::PseudoVisited: 85 case CSSSelector::PseudoVisited:
86 case CSSSelector::PseudoAny:
79 case CSSSelector::PseudoAnyLink: 87 case CSSSelector::PseudoAnyLink:
80 case CSSSelector::PseudoHover: 88 case CSSSelector::PseudoHover:
81 case CSSSelector::PseudoDrag: 89 case CSSSelector::PseudoDrag:
82 case CSSSelector::PseudoFocus: 90 case CSSSelector::PseudoFocus:
83 case CSSSelector::PseudoActive: 91 case CSSSelector::PseudoActive:
84 case CSSSelector::PseudoChecked: 92 case CSSSelector::PseudoChecked:
85 case CSSSelector::PseudoEnabled: 93 case CSSSelector::PseudoEnabled:
86 case CSSSelector::PseudoDefault: 94 case CSSSelector::PseudoDefault:
87 case CSSSelector::PseudoDisabled: 95 case CSSSelector::PseudoDisabled:
88 case CSSSelector::PseudoOptional: 96 case CSSSelector::PseudoOptional:
89 case CSSSelector::PseudoRequired: 97 case CSSSelector::PseudoRequired:
90 case CSSSelector::PseudoReadOnly: 98 case CSSSelector::PseudoReadOnly:
91 case CSSSelector::PseudoReadWrite: 99 case CSSSelector::PseudoReadWrite:
92 case CSSSelector::PseudoValid: 100 case CSSSelector::PseudoValid:
93 case CSSSelector::PseudoInvalid: 101 case CSSSelector::PseudoInvalid:
94 case CSSSelector::PseudoIndeterminate: 102 case CSSSelector::PseudoIndeterminate:
95 case CSSSelector::PseudoTarget: 103 case CSSSelector::PseudoTarget:
104 case CSSSelector::PseudoBefore:
105 case CSSSelector::PseudoAfter:
106 case CSSSelector::PseudoBackdrop:
96 case CSSSelector::PseudoLang: 107 case CSSSelector::PseudoLang:
108 case CSSSelector::PseudoNot:
97 case CSSSelector::PseudoRoot: 109 case CSSSelector::PseudoRoot:
98 case CSSSelector::PseudoScope: 110 case CSSSelector::PseudoScope:
99 case CSSSelector::PseudoInRange: 111 case CSSSelector::PseudoInRange:
100 case CSSSelector::PseudoOutOfRange: 112 case CSSSelector::PseudoOutOfRange:
113 case CSSSelector::PseudoUserAgentCustomElement:
114 case CSSSelector::PseudoWebKitCustomElement:
101 case CSSSelector::PseudoUnresolved: 115 case CSSSelector::PseudoUnresolved:
116 case CSSSelector::PseudoHost:
117 case CSSSelector::PseudoShadow:
102 case CSSSelector::PseudoListBox: 118 case CSSSelector::PseudoListBox:
119 case CSSSelector::PseudoAutofill:
120 case CSSSelector::PseudoFullPageMedia:
121 case CSSSelector::PseudoResizer:
122 case CSSSelector::PseudoScrollbar:
123 case CSSSelector::PseudoScrollbarBack:
124 case CSSSelector::PseudoScrollbarButton:
125 case CSSSelector::PseudoScrollbarCorner:
126 case CSSSelector::PseudoScrollbarForward:
127 case CSSSelector::PseudoScrollbarThumb:
128 case CSSSelector::PseudoScrollbarTrack:
129 case CSSSelector::PseudoScrollbarTrackPiece:
130 case CSSSelector::PseudoWindowInactive:
131 case CSSSelector::PseudoCornerPresent:
132 case CSSSelector::PseudoDecrement:
133 case CSSSelector::PseudoIncrement:
134 case CSSSelector::PseudoHorizontal:
135 case CSSSelector::PseudoVertical:
136 case CSSSelector::PseudoStart:
137 case CSSSelector::PseudoEnd:
138 case CSSSelector::PseudoDoubleButton:
139 case CSSSelector::PseudoSingleButton:
140 case CSSSelector::PseudoNoButton:
141 case CSSSelector::PseudoSelection:
142 case CSSSelector::PseudoFullScreen:
143 case CSSSelector::PseudoFullScreenDocument:
144 case CSSSelector::PseudoFullScreenAncestor:
145 case CSSSelector::PseudoCue:
146 case CSSSelector::PseudoFutureCue:
147 case CSSSelector::PseudoPastCue:
148 case CSSSelector::PseudoContent:
149 case CSSSelector::PseudoSpatialNavigationFocus:
150 break;
151 case CSSSelector::PseudoNotParsed:
152 case CSSSelector::PseudoUnknown:
153 case CSSSelector::PseudoLeftPage:
154 case CSSSelector::PseudoRightPage:
155 case CSSSelector::PseudoFirstPage:
156 // These should not appear in StyleRule selectors.
157 ASSERT_NOT_REACHED();
158 break;
159 default:
160 // New pseudo type added. Figure out if it needs a subtree recalc or not .
161 ASSERT_NOT_REACHED();
162 break;
163 }
164 }
165
166 static bool requiresSubtreeRecalc(const CSSSelector& selector)
167 {
168 if (!selector.matchesPseudoElement() && selector.match() != CSSSelector::Pse udoClass) {
169 assertSupportedMatch(selector.match());
170 return false;
171 }
172
173 switch (selector.pseudoType()) {
174 case CSSSelector::PseudoFirstLine:
175 // :first-line pseudo can apply to elements arbitrarily deep down in the
176 // DOM from its container given an arbitrary number of block descendants
177 // with no inline flow content in between.
178 case CSSSelector::PseudoFirstLetter:
179 // :first-letter pseudo elements can be arbitrarily deep down in the
180 // DOM from its container given an arbitrary number of block descendants
181 // with no text content in between.
182 case CSSSelector::PseudoHostContext:
183 // :host-context matches a shadow host, yet the simple selectors inside
184 // :host-context matches an ancestor of the shadow host.
103 return true; 185 return true;
104 default: 186 default:
187 assertSupportedPseudo(selector.pseudoType());
105 return false; 188 return false;
106 } 189 }
107 } 190 }
108 191
109 RuleFeature::RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocume ntSecurityOrigin) 192 RuleFeature::RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocume ntSecurityOrigin)
110 : rule(rule) 193 : rule(rule)
111 , selectorIndex(selectorIndex) 194 , selectorIndex(selectorIndex)
112 , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) 195 , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin)
113 { 196 {
114 } 197 }
115 198
116 void RuleFeature::trace(Visitor* visitor) 199 void RuleFeature::trace(Visitor* visitor)
117 { 200 {
118 visitor->trace(rule); 201 visitor->trace(rule);
119 } 202 }
120 203
121 // This method is somewhat conservative in what it accepts.
122 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::invalidationSetModeForSelect or(const CSSSelector& selector)
123 {
124 bool foundCombinator = false;
125 bool foundIdent = false;
126 for (const CSSSelector* component = &selector; component; component = compon ent->tagHistory()) {
127
128 if (component->match() == CSSSelector::Class || component->match() == CS SSelector::Id
129 || (component->match() == CSSSelector::Tag && component->tagQName(). localName() != starAtom)
130 || component->isAttributeSelector() || component->isCustomPseudoElem ent()) {
131 if (!foundCombinator) {
132 // We have found an invalidation set feature in the rightmost co mpound selector.
133 foundIdent = true;
134 }
135 } else if (component->pseudoType() == CSSSelector::PseudoNot
136 || component->pseudoType() == CSSSelector::PseudoHost
137 || component->pseudoType() == CSSSelector::PseudoAny) {
138 if (const CSSSelectorList* selectorList = component->selectorList()) {
139 // Features inside :not() are not added to the feature set, so c onsider it a universal selector.
140 bool foundUniversal = component->pseudoType() == CSSSelector::Ps eudoNot;
141 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector)) {
142 // Find the invalidation set mode for each of the selectors in the selector list
143 // of a :not(), :host(), etc. For instance, ".x :-webkit-any (.a, .b)" yields an
144 // AddFeatures mode for both ".a" and ".b". ":-webkit-any(.a , *)" yields AddFeatures
145 // for ".a", but UseSubtreeStyleChange for "*". One sub-sele ctor without invalidation
146 // set features is sufficient to cause the selector to be a universal selector as far
147 // the invalidation set is concerned.
148 InvalidationSetMode subSelectorMode = invalidationSetModeFor Selector(*selector);
149
150 // The sub-selector contained something unskippable, fall ba ck to whole subtree
151 // recalcs in collectFeaturesFromSelector. subSelectorMode w ill return
152 // UseSubtreeStyleChange since there are no combinators insi de the selector list,
153 // so translate it to UseLocalStyleChange if a combinator ha s been seen in the
154 // outer context.
155 //
156 // FIXME: Is UseSubtreeStyleChange ever needed as input to c ollectFeaturesFromSelector?
157 // That is, are there any selectors for which we need to use SubtreeStyleChange for
158 // changing features when present in the rightmost compound selector?
159 if (subSelectorMode == UseSubtreeStyleChange)
160 return foundCombinator ? UseLocalStyleChange : UseSubtre eStyleChange;
161
162 // We found no features in the sub-selector, only skippable ones (foundIdent was
163 // false at the end of this method). That is a universal sel ector as far as the
164 // invalidation set is concerned.
165 if (subSelectorMode == UseLocalStyleChange)
166 foundUniversal = true;
167 }
168 if (!foundUniversal && !foundCombinator) {
169 // All sub-selectors contained invalidation set features and
170 // we are in the rightmost compound selector.
171 foundIdent = true;
172 }
173 }
174 } else if (!isSkippableComponentForInvalidation(*component)) {
175 return foundCombinator ? UseLocalStyleChange : UseSubtreeStyleChange ;
176 }
177 if (component->relation() != CSSSelector::SubSelector)
178 foundCombinator = true;
179 }
180 return foundIdent ? AddFeatures : UseLocalStyleChange;
181 }
182
183 void RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features) 204 void RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features)
184 { 205 {
185 if (selector.match() == CSSSelector::Tag) 206 if (selector.match() == CSSSelector::Tag && selector.tagQName().localName() != starAtom)
186 features.tagName = selector.tagQName().localName(); 207 features.setTagName(selector.tagQName().localName());
187 else if (selector.match() == CSSSelector::Id) 208 else if (selector.match() == CSSSelector::Id)
188 features.id = selector.value(); 209 features.setId(selector.value());
189 else if (selector.match() == CSSSelector::Class) 210 else if (selector.match() == CSSSelector::Class)
190 features.classes.append(selector.value()); 211 features.addClass(selector.value());
191 else if (selector.isAttributeSelector()) 212 else if (selector.isAttributeSelector())
192 features.attributes.append(selector.attribute().localName()); 213 features.addAttribute(selector.attribute().localName());
193 else if (selector.isCustomPseudoElement()) 214 else if (selector.isCustomPseudoElement())
194 features.customPseudoElement = true; 215 features.setHasCustomPseudo();
195 } 216 }
196 217
197 RuleFeatureSet::RuleFeatureSet() 218 RuleFeatureSet::RuleFeatureSet()
198 { 219 {
199 } 220 }
200 221
201 RuleFeatureSet::~RuleFeatureSet() 222 RuleFeatureSet::~RuleFeatureSet()
202 { 223 {
203 } 224 }
204 225
(...skipping 21 matching lines...) Expand all
226 return &ensurePseudoInvalidationSet(selector.pseudoType()); 247 return &ensurePseudoInvalidationSet(selector.pseudoType());
227 default: 248 default:
228 break; 249 break;
229 } 250 }
230 } 251 }
231 return 0; 252 return 0;
232 } 253 }
233 254
234 // Given a selector, update the descendant invalidation sets for the features fo und 255 // Given a selector, update the descendant invalidation sets for the features fo und
235 // in the selector. The first step is to extract the features from the rightmost 256 // in the selector. The first step is to extract the features from the rightmost
236 // compound selector (extractInvalidationSetFeatures). Secondly, those features will be 257 // compound selector (extractInvalidationSetFeatures). Secondly, add those featu res
237 // added to the invalidation sets for the features found in the other compound s electors 258 // to the invalidation sets for the features found in the other compound selecto rs
238 // (addFeaturesToInvalidationSets). 259 // (addFeaturesToInvalidationSets). If we find a feature in the right-most compo und
260 // selector that requires a subtree recalc, we addFeaturesToInvalidationSets for the
261 // rightmost compound selector as well.
239 262
240 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector) 263 void RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector)
241 { 264 {
242 InvalidationSetMode mode = invalidationSetModeForSelector(selector);
243 if (mode != AddFeatures)
244 return mode;
245
246 InvalidationSetFeatures features; 265 InvalidationSetFeatures features;
247 if (const CSSSelector* current = extractInvalidationSetFeatures(selector, fe atures, false)) 266 if (const CSSSelector* current = extractInvalidationSetFeatures(selector, fe atures, false))
248 addFeaturesToInvalidationSets(*current, features); 267 addFeaturesToInvalidationSets(*current, features);
249 return AddFeatures;
250 } 268 }
251 269
252 const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec tor& selector, InvalidationSetFeatures& features, bool negated) 270 const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec tor& selector, InvalidationSetFeatures& features, bool negated)
253 { 271 {
254 for (const CSSSelector* current = &selector; current; current = current->tag History()) { 272 for (const CSSSelector* current = &selector; current; current = current->tag History()) {
255 if (!negated) 273 if (!negated)
256 extractInvalidationSetFeature(*current, features); 274 extractInvalidationSetFeature(*current, features);
257 // Initialize the entry in the invalidation set map, if supported. 275 if (!invalidationSetForSelector(*current)) {
258 invalidationSetForSelector(*current); 276 if (requiresSubtreeRecalc(*current)) {
259 if (current->pseudoType() == CSSSelector::PseudoHost || current->pseudoT ype() == CSSSelector::PseudoAny || current->pseudoType() == CSSSelector::PseudoN ot) { 277 // Fall back to use subtree invalidations, even for features in the
278 // rightmost compound selector. Returning the start &selector he re
279 // will make addFeaturesToInvalidationSets start marking invalid ation
280 // sets for subtree recalc for features in the rightmost compoun d
281 // selector.
282 features.hasFeatures = false;
chrishtr 2014/10/10 16:45:06 It's a weird to trigger subtree by setting hasFeat
283 return &selector;
284 }
260 if (const CSSSelectorList* selectorList = current->selectorList()) { 285 if (const CSSSelectorList* selectorList = current->selectorList()) {
261 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector)) 286 const CSSSelector* subSelector = selectorList->first();
262 extractInvalidationSetFeatures(*selector, features, current- >pseudoType() == CSSSelector::PseudoNot); 287 bool hadFeatures = features.hasFeatures;
288 bool allSubSelectorsHaveFeatures = !!subSelector;
289 for (; subSelector; subSelector = CSSSelectorList::next(*subSele ctor)) {
290 features.hasFeatures = false;
291 if (extractInvalidationSetFeatures(*subSelector, features, c urrent->pseudoType() == CSSSelector::PseudoNot)) {
292 // A non-null return means the sub-selector contained a selector
293 // which requiresSubtreeRecalc(). Return the rightmost s elector
294 // to mark for subtree recalcs like above.
295 ASSERT(!features.hasFeatures);
296 return &selector;
297 }
298 allSubSelectorsHaveFeatures &= features.hasFeatures;
299 }
300 features.hasFeatures = hadFeatures || allSubSelectorsHaveFeature s;
263 } 301 }
264 } 302 }
265 303
266 switch (current->relation()) { 304 if (current->relation() == CSSSelector::SubSelector)
267 case CSSSelector::SubSelector: 305 continue;
268 break; 306
269 case CSSSelector::ShadowPseudo: 307 if (current->isShadowSelector())
270 case CSSSelector::ShadowDeep:
271 features.treeBoundaryCrossing = true; 308 features.treeBoundaryCrossing = true;
272 return current->tagHistory(); 309
273 case CSSSelector::DirectAdjacent: 310 features.adjacent = current->isAdjacentSelector();
274 case CSSSelector::IndirectAdjacent: 311
275 features.wholeSubtree = true; 312 return current->tagHistory();
276 return current->tagHistory();
277 case CSSSelector::Descendant:
278 case CSSSelector::Child:
279 return current->tagHistory();
280 }
281 } 313 }
282 return 0; 314 return 0;
283 } 315 }
284 316
285 // Add features extracted from the rightmost compound selector to descendant inv alidation 317 // Add features extracted from the rightmost compound selector to descendant inv alidation
286 // sets for features found in other compound selectors. 318 // sets for features found in other compound selectors.
287 // 319 //
288 // Style invalidation is currently supported for descendants only, not for sibli ng subtrees. 320 // Style invalidation is currently supported for descendants only, not for sibli ng subtrees.
289 // We use wholeSubtree invalidation for features found left of adjacent combinat ors as 321 // We use wholeSubtree invalidation for features found left of adjacent combinat ors as
290 // SubtreeStyleChange will force sibling subtree recalc in 322 // SubtreeStyleChange will force sibling subtree recalc in
291 // ContainerNode::checkForChildrenAdjacentRuleChanges. 323 // ContainerNode::checkForChildrenAdjacentRuleChanges.
292 // 324 //
293 // As we encounter a descendant type of combinator, the features only need to be checked 325 // As we encounter a descendant type of combinator, the features only need to be checked
294 // against descendants in the same subtree only. Hence wholeSubtree is reset to false. 326 // against descendants in the same subtree only. Hence wholeSubtree is reset to false.
295 327
328 void RuleFeatureSet::addFeaturesToInvalidationSet(DescendantInvalidationSet& inv alidationSet, const InvalidationSetFeatures& features)
329 {
330 if (features.treeBoundaryCrossing)
331 invalidationSet.setTreeBoundaryCrossing();
332 if (features.insertionPointCrossing)
333 invalidationSet.setInsertionPointCrossing();
334 if (features.useSubtreeInvalidation()) {
335 invalidationSet.setWholeSubtreeInvalid();
336 return;
337 }
338 if (!features.id.isEmpty())
339 invalidationSet.addId(features.id);
340 if (!features.tagName.isEmpty())
341 invalidationSet.addTagName(features.tagName);
342 for (const auto& className : features.classes)
343 invalidationSet.addClass(className);
344 for (const auto& attribute : features.attributes)
345 invalidationSet.addAttribute(attribute);
346 if (features.customPseudoElement)
347 invalidationSet.setCustomPseudoInvalid();
348 }
349
296 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& features) 350 void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& features)
297 { 351 {
298 for (const CSSSelector* current = &selector; current; current = current->tag History()) { 352 for (const CSSSelector* current = &selector; current; current = current->tag History()) {
299 if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelec tor(*current)) { 353 if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelec tor(*current)) {
300 if (features.treeBoundaryCrossing) 354 addFeaturesToInvalidationSet(*invalidationSet, features);
301 invalidationSet->setTreeBoundaryCrossing();
302 if (features.wholeSubtree) {
303 invalidationSet->setWholeSubtreeInvalid();
304 } else {
305 if (!features.id.isEmpty())
306 invalidationSet->addId(features.id);
307 if (!features.tagName.isEmpty())
308 invalidationSet->addTagName(features.tagName);
309 for (Vector<AtomicString>::const_iterator it = features.classes. begin(); it != features.classes.end(); ++it)
310 invalidationSet->addClass(*it);
311 for (Vector<AtomicString>::const_iterator it = features.attribut es.begin(); it != features.attributes.end(); ++it)
312 invalidationSet->addAttribute(*it);
313 if (features.customPseudoElement)
314 invalidationSet->setCustomPseudoInvalid();
315 }
316 } else { 355 } else {
317 if (current->pseudoType() == CSSSelector::PseudoHost) 356 if (current->isTreeBoundaryCrossing())
318 features.treeBoundaryCrossing = true; 357 features.treeBoundaryCrossing = true;
358 if (current->isInsertionPointCrossing())
359 features.insertionPointCrossing = true;
319 if (const CSSSelectorList* selectorList = current->selectorList()) { 360 if (const CSSSelectorList* selectorList = current->selectorList()) {
320 ASSERT(current->pseudoType() == CSSSelector::PseudoHost || curre nt->pseudoType() == CSSSelector::PseudoAny || current->pseudoType() == CSSSelect or::PseudoNot);
321 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector)) 361 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector))
322 addFeaturesToInvalidationSets(*selector, features); 362 addFeaturesToInvalidationSets(*selector, features);
323 } 363 }
324 } 364 }
325 switch (current->relation()) { 365
326 case CSSSelector::SubSelector: 366 if (current->relation() == CSSSelector::SubSelector)
327 break; 367 continue;
328 case CSSSelector::ShadowPseudo: 368
329 case CSSSelector::ShadowDeep: 369 if (current->isShadowSelector())
330 features.treeBoundaryCrossing = true; 370 features.treeBoundaryCrossing = true;
331 features.wholeSubtree = false; 371
332 break; 372 features.adjacent = current->isAdjacentSelector();
333 case CSSSelector::Descendant:
334 case CSSSelector::Child:
335 features.wholeSubtree = false;
336 break;
337 case CSSSelector::DirectAdjacent:
338 case CSSSelector::IndirectAdjacent:
339 features.wholeSubtree = true;
340 break;
341 }
342 } 373 }
343 } 374 }
344 375
345 void RuleFeatureSet::addContentAttr(const AtomicString& attributeName) 376 void RuleFeatureSet::addContentAttr(const AtomicString& attributeName)
346 { 377 {
347 ensureAttributeInvalidationSet(attributeName); 378 ensureAttributeInvalidationSet(attributeName);
348 } 379 }
349 380
350 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) 381 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData)
351 { 382 {
383 updateInvalidationSets(ruleData.selector());
384
352 FeatureMetadata metadata; 385 FeatureMetadata metadata;
353 InvalidationSetMode mode = updateInvalidationSets(ruleData.selector()); 386 collectFeaturesFromSelector(ruleData.selector(), metadata);
354
355 collectFeaturesFromSelector(ruleData.selector(), metadata, mode);
356 m_metadata.add(metadata); 387 m_metadata.add(metadata);
357 388
358 if (metadata.foundSiblingSelector) 389 if (metadata.foundSiblingSelector)
359 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex( ), ruleData.hasDocumentSecurityOrigin())); 390 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex( ), ruleData.hasDocumentSecurityOrigin()));
360 if (ruleData.containsUncommonAttributeSelector()) 391 if (ruleData.containsUncommonAttributeSelector())
361 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele ctorIndex(), ruleData.hasDocumentSecurityOrigin())); 392 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele ctorIndex(), ruleData.hasDocumentSecurityOrigin()));
362 } 393 }
363 394
364 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom icString& className) 395 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom icString& className)
365 { 396 {
(...skipping 20 matching lines...) Expand all
386 } 417 }
387 418
388 DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelect or::PseudoType pseudoType) 419 DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelect or::PseudoType pseudoType)
389 { 420 {
390 PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets .add(pseudoType, nullptr); 421 PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets .add(pseudoType, nullptr);
391 if (addResult.isNewEntry) 422 if (addResult.isNewEntry)
392 addResult.storedValue->value = DescendantInvalidationSet::create(); 423 addResult.storedValue->value = DescendantInvalidationSet::create();
393 return *addResult.storedValue->value; 424 return *addResult.storedValue->value;
394 } 425 }
395 426
396 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru leFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) 427 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru leFeatureSet::FeatureMetadata& metadata)
397 { 428 {
398 unsigned maxDirectAdjacentSelectors = 0; 429 unsigned maxDirectAdjacentSelectors = 0;
399 430
400 for (const CSSSelector* current = &selector; current; current = current->tag History()) { 431 for (const CSSSelector* current = &selector; current; current = current->tag History()) {
401 if (mode != AddFeatures) {
402 if (DescendantInvalidationSet* invalidationSet = invalidationSetForS elector(*current)) {
403 if (mode == UseSubtreeStyleChange)
404 invalidationSet->setWholeSubtreeInvalid();
405 }
406 }
407 if (current->pseudoType() == CSSSelector::PseudoFirstLine) 432 if (current->pseudoType() == CSSSelector::PseudoFirstLine)
408 metadata.usesFirstLineRules = true; 433 metadata.usesFirstLineRules = true;
409 if (current->isDirectAdjacentSelector()) { 434 if (current->isDirectAdjacentSelector()) {
410 maxDirectAdjacentSelectors++; 435 maxDirectAdjacentSelectors++;
411 } else if (maxDirectAdjacentSelectors) { 436 } else if (maxDirectAdjacentSelectors) {
412 if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors ) 437 if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors )
413 metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors ; 438 metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors ;
414 maxDirectAdjacentSelectors = 0; 439 maxDirectAdjacentSelectors = 0;
415 } 440 }
416 if (current->isSiblingSelector()) 441 if (current->isSiblingSelector())
417 metadata.foundSiblingSelector = true; 442 metadata.foundSiblingSelector = true;
418 443
419 collectFeaturesFromSelectorList(current->selectorList(), metadata, mode) ; 444 const CSSSelectorList* selectorList = current->selectorList();
445 if (!selectorList)
446 continue;
420 447
421 if (mode == UseLocalStyleChange && current->relation() != CSSSelector::S ubSelector) 448 for (const CSSSelector* selector = selectorList->first(); selector; sele ctor = CSSSelectorList::next(*selector))
422 mode = UseSubtreeStyleChange; 449 collectFeaturesFromSelector(*selector, metadata);
423 } 450 }
424 451
425 ASSERT(!maxDirectAdjacentSelectors); 452 ASSERT(!maxDirectAdjacentSelectors);
426 } 453 }
427 454
428 void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* sele ctorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode)
429 {
430 if (!selectorList)
431 return;
432
433 for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector))
434 collectFeaturesFromSelector(*selector, metadata, mode);
435 }
436
437 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) 455 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other)
438 { 456 {
439 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; 457 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
440 maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxD irectAdjacentSelectors); 458 maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxD irectAdjacentSelectors);
441 } 459 }
442 460
443 void RuleFeatureSet::FeatureMetadata::clear() 461 void RuleFeatureSet::FeatureMetadata::clear()
444 { 462 {
445 usesFirstLineRules = false; 463 usesFirstLineRules = false;
446 foundSiblingSelector = false; 464 foundSiblingSelector = false;
447 maxDirectAdjacentSelectors = 0; 465 maxDirectAdjacentSelectors = 0;
448 } 466 }
449 467
450 void RuleFeatureSet::add(const RuleFeatureSet& other) 468 void RuleFeatureSet::add(const RuleFeatureSet& other)
451 { 469 {
452 for (InvalidationSetMap::const_iterator it = other.m_classInvalidationSets.b egin(); it != other.m_classInvalidationSets.end(); ++it) 470 for (const auto& it : other.m_classInvalidationSets)
453 ensureClassInvalidationSet(it->key).combine(*it->value); 471 ensureClassInvalidationSet(it.key).combine(*it.value);
454 for (InvalidationSetMap::const_iterator it = other.m_attributeInvalidationSe ts.begin(); it != other.m_attributeInvalidationSets.end(); ++it) 472 for (const auto& it : other.m_attributeInvalidationSets)
455 ensureAttributeInvalidationSet(it->key).combine(*it->value); 473 ensureAttributeInvalidationSet(it.key).combine(*it.value);
456 for (InvalidationSetMap::const_iterator it = other.m_idInvalidationSets.begi n(); it != other.m_idInvalidationSets.end(); ++it) 474 for (const auto& it : other.m_idInvalidationSets)
457 ensureIdInvalidationSet(it->key).combine(*it->value); 475 ensureIdInvalidationSet(it.key).combine(*it.value);
458 for (PseudoTypeInvalidationSetMap::const_iterator it = other.m_pseudoInvalid ationSets.begin(); it != other.m_pseudoInvalidationSets.end(); ++it) 476 for (const auto& it : other.m_pseudoInvalidationSets)
459 ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType>(it->key )).combine(*it->value); 477 ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType>(it.key) ).combine(*it.value);
460 478
461 m_metadata.add(other.m_metadata); 479 m_metadata.add(other.m_metadata);
462 480
463 siblingRules.appendVector(other.siblingRules); 481 siblingRules.appendVector(other.siblingRules);
464 uncommonAttributeRules.appendVector(other.uncommonAttributeRules); 482 uncommonAttributeRules.appendVector(other.uncommonAttributeRules);
465 } 483 }
466 484
467 void RuleFeatureSet::clear() 485 void RuleFeatureSet::clear()
468 { 486 {
469 siblingRules.clear(); 487 siblingRules.clear();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 visitor->trace(uncommonAttributeRules); 582 visitor->trace(uncommonAttributeRules);
565 visitor->trace(m_classInvalidationSets); 583 visitor->trace(m_classInvalidationSets);
566 visitor->trace(m_attributeInvalidationSets); 584 visitor->trace(m_attributeInvalidationSets);
567 visitor->trace(m_idInvalidationSets); 585 visitor->trace(m_idInvalidationSets);
568 visitor->trace(m_pseudoInvalidationSets); 586 visitor->trace(m_pseudoInvalidationSets);
569 visitor->trace(m_styleInvalidator); 587 visitor->trace(m_styleInvalidator);
570 #endif 588 #endif
571 } 589 }
572 590
573 } // namespace blink 591 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/css/RuleFeature.h ('k') | Source/core/css/invalidation/DescendantInvalidationSet.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698