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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 // These should not appear in StyleRule selectors. | 156 // These should not appear in StyleRule selectors. |
157 ASSERT_NOT_REACHED(); | 157 ASSERT_NOT_REACHED(); |
158 return false; | 158 return false; |
159 default: | 159 default: |
160 // New pseudo type added. Figure out if it needs a subtree invalidation or not. | 160 // New pseudo type added. Figure out if it needs a subtree invalidation or not. |
161 ASSERT_NOT_REACHED(); | 161 ASSERT_NOT_REACHED(); |
162 return false; | 162 return false; |
163 } | 163 } |
164 } | 164 } |
165 | 165 |
166 static bool supportsInvalidationWithSelectorList(CSSSelector::PseudoType pseudo) | |
167 { | |
168 return pseudo == CSSSelector::PseudoAny | |
169 || pseudo == CSSSelector::PseudoCue | |
170 || pseudo == CSSSelector::PseudoHost | |
171 || pseudo == CSSSelector::PseudoHostContext | |
chrishtr
2014/11/13 23:01:11
This one is sort of unrelated to the main thrust o
rune
2014/11/14 00:04:53
This is what's described in the last section of th
| |
172 || pseudo == CSSSelector::PseudoNot; | |
173 } | |
174 | |
166 #endif // ENABLE(ASSERT) | 175 #endif // ENABLE(ASSERT) |
167 | 176 |
168 static bool requiresSubtreeInvalidation(const CSSSelector& selector) | 177 static bool requiresSubtreeInvalidation(const CSSSelector& selector) |
169 { | 178 { |
170 if (!selector.matchesPseudoElement() && selector.match() != CSSSelector::Pse udoClass) { | 179 if (!selector.matchesPseudoElement() && selector.match() != CSSSelector::Pse udoClass) { |
171 ASSERT(supportsInvalidation(selector.match())); | 180 ASSERT(supportsInvalidation(selector.match())); |
172 return false; | 181 return false; |
173 } | 182 } |
174 | 183 |
175 switch (selector.pseudoType()) { | 184 switch (selector.pseudoType()) { |
(...skipping 17 matching lines...) Expand all Loading... | |
193 , selectorIndex(selectorIndex) | 202 , selectorIndex(selectorIndex) |
194 , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) | 203 , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) |
195 { | 204 { |
196 } | 205 } |
197 | 206 |
198 void RuleFeature::trace(Visitor* visitor) | 207 void RuleFeature::trace(Visitor* visitor) |
199 { | 208 { |
200 visitor->trace(rule); | 209 visitor->trace(rule); |
201 } | 210 } |
202 | 211 |
203 static bool supportsInvalidationWithSelectorList(CSSSelector::PseudoType pseudo) | 212 bool RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features) |
204 { | 213 { |
205 return pseudo == CSSSelector::PseudoAny | 214 if (selector.match() == CSSSelector::Tag && selector.tagQName().localName() != starAtom) |
chrishtr
2014/11/13 23:01:11
Why this change?
rune
2014/11/14 00:04:53
It's to get the return value correct, and avoid us
| |
206 || pseudo == CSSSelector::PseudoCue | |
207 || pseudo == CSSSelector::PseudoHost | |
208 || pseudo == CSSSelector::PseudoNot; | |
209 } | |
210 | |
211 // This method is somewhat conservative in what it accepts. | |
212 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::invalidationSetModeForSelect or(const CSSSelector& selector) | |
213 { | |
214 bool foundCombinator = false; | |
215 bool foundIdent = false; | |
216 for (const CSSSelector* component = &selector; component; component = compon ent->tagHistory()) { | |
217 | |
218 if (component->match() == CSSSelector::Class || component->match() == CS SSelector::Id | |
219 || (component->match() == CSSSelector::Tag && component->tagQName(). localName() != starAtom) | |
220 || component->isAttributeSelector() || component->isCustomPseudoElem ent()) { | |
221 if (!foundCombinator) { | |
222 // We have found an invalidation set feature in the rightmost co mpound selector. | |
223 foundIdent = true; | |
224 } | |
225 } else if (supportsInvalidationWithSelectorList(component->pseudoType()) ) { | |
226 if (const CSSSelectorList* selectorList = component->selectorList()) { | |
227 // Features inside :not() are not added to the feature set, so c onsider it a universal selector. | |
228 bool foundUniversal = component->pseudoType() == CSSSelector::Ps eudoNot; | |
229 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector)) { | |
230 // Find the invalidation set mode for each of the selectors in the selector list | |
231 // of a :not(), :host(), etc. For instance, ".x :-webkit-any (.a, .b)" yields an | |
232 // AddFeatures mode for both ".a" and ".b". ":-webkit-any(.a , *)" yields AddFeatures | |
233 // for ".a", but UseSubtreeStyleChange for "*". One sub-sele ctor without invalidation | |
234 // set features is sufficient to cause the selector to be a universal selector as far | |
235 // the invalidation set is concerned. | |
236 InvalidationSetMode subSelectorMode = invalidationSetModeFor Selector(*selector); | |
237 | |
238 // The sub-selector contained something unskippable, fall ba ck to whole subtree | |
239 // recalcs in collectFeaturesFromSelector. subSelectorMode w ill return | |
240 // UseSubtreeStyleChange since there are no combinators insi de the selector list, | |
241 // so translate it to UseLocalStyleChange if a combinator ha s been seen in the | |
242 // outer context. | |
243 // | |
244 // FIXME: Is UseSubtreeStyleChange ever needed as input to c ollectFeaturesFromSelector? | |
245 // That is, are there any selectors for which we need to use SubtreeStyleChange for | |
246 // changing features when present in the rightmost compound selector? | |
247 if (subSelectorMode == UseSubtreeStyleChange) | |
248 return foundCombinator ? UseLocalStyleChange : UseSubtre eStyleChange; | |
249 | |
250 // We found no features in the sub-selector, only skippable ones (foundIdent was | |
251 // false at the end of this method). That is a universal sel ector as far as the | |
252 // invalidation set is concerned. | |
253 if (subSelectorMode == UseLocalStyleChange) | |
254 foundUniversal = true; | |
255 } | |
256 if (!foundUniversal && !foundCombinator) { | |
257 // All sub-selectors contained invalidation set features and | |
258 // we are in the rightmost compound selector. | |
259 foundIdent = true; | |
260 } | |
261 } | |
262 } else if (requiresSubtreeInvalidation(*component)) { | |
263 return foundCombinator ? UseLocalStyleChange : UseSubtreeStyleChange ; | |
264 } | |
265 if (component->relation() != CSSSelector::SubSelector) | |
266 foundCombinator = true; | |
267 } | |
268 return foundIdent ? AddFeatures : UseLocalStyleChange; | |
269 } | |
270 | |
271 void RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features) | |
272 { | |
273 if (selector.match() == CSSSelector::Tag) | |
274 features.tagName = selector.tagQName().localName(); | 215 features.tagName = selector.tagQName().localName(); |
275 else if (selector.match() == CSSSelector::Id) | 216 else if (selector.match() == CSSSelector::Id) |
276 features.id = selector.value(); | 217 features.id = selector.value(); |
277 else if (selector.match() == CSSSelector::Class) | 218 else if (selector.match() == CSSSelector::Class) |
278 features.classes.append(selector.value()); | 219 features.classes.append(selector.value()); |
279 else if (selector.isAttributeSelector()) | 220 else if (selector.isAttributeSelector()) |
280 features.attributes.append(selector.attribute().localName()); | 221 features.attributes.append(selector.attribute().localName()); |
281 else if (selector.isCustomPseudoElement()) | 222 else if (selector.isCustomPseudoElement()) |
282 features.customPseudoElement = true; | 223 features.customPseudoElement = true; |
224 else | |
225 return false; | |
226 return true; | |
chrishtr
2014/11/13 23:01:11
Is this code reachable?
rune
2014/11/14 00:04:53
Yes, it's the return value for all but the last el
| |
283 } | 227 } |
284 | 228 |
285 RuleFeatureSet::RuleFeatureSet() | 229 RuleFeatureSet::RuleFeatureSet() |
286 { | 230 { |
287 } | 231 } |
288 | 232 |
289 RuleFeatureSet::~RuleFeatureSet() | 233 RuleFeatureSet::~RuleFeatureSet() |
290 { | 234 { |
291 } | 235 } |
292 | 236 |
(...skipping 21 matching lines...) Expand all Loading... | |
314 case CSSSelector::PseudoRequired: | 258 case CSSSelector::PseudoRequired: |
315 case CSSSelector::PseudoValid: | 259 case CSSSelector::PseudoValid: |
316 case CSSSelector::PseudoInvalid: | 260 case CSSSelector::PseudoInvalid: |
317 case CSSSelector::PseudoIndeterminate: | 261 case CSSSelector::PseudoIndeterminate: |
318 case CSSSelector::PseudoTarget: | 262 case CSSSelector::PseudoTarget: |
319 return &ensurePseudoInvalidationSet(selector.pseudoType()); | 263 return &ensurePseudoInvalidationSet(selector.pseudoType()); |
320 default: | 264 default: |
321 break; | 265 break; |
322 } | 266 } |
323 } | 267 } |
324 return 0; | 268 return nullptr; |
325 } | 269 } |
326 | 270 |
327 // Given a selector, update the descendant invalidation sets for the features fo und | 271 // Given a selector, update the descendant invalidation sets for the features fo und |
328 // in the selector. The first step is to extract the features from the rightmost | 272 // in the selector. The first step is to extract the features from the rightmost |
329 // compound selector (extractInvalidationSetFeatures). Secondly, those features will be | 273 // compound selector (extractInvalidationSetFeatures). Secondly, add those featu res |
330 // added to the invalidation sets for the features found in the other compound s electors | 274 // to the invalidation sets for the features found in the other compound selecto rs |
331 // (addFeaturesToInvalidationSets). | 275 // (addFeaturesToInvalidationSets). If we find a feature in the right-most compo und |
276 // selector that requires a subtree recalc, we addFeaturesToInvalidationSets for the | |
277 // rightmost compound selector as well. | |
332 | 278 |
333 RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector) | 279 void RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector) |
334 { | 280 { |
335 InvalidationSetMode mode = invalidationSetModeForSelector(selector); | |
336 if (mode != AddFeatures) | |
337 return mode; | |
338 | |
339 InvalidationSetFeatures features; | 281 InvalidationSetFeatures features; |
340 if (const CSSSelector* current = extractInvalidationSetFeatures(selector, fe atures, false)) | 282 auto result = extractInvalidationSetFeatures(selector, features, false); |
341 addFeaturesToInvalidationSets(*current, features); | 283 if (result.first) { |
342 return AddFeatures; | 284 features.forceSubtree = result.second == ForceSubtree; |
285 addFeaturesToInvalidationSets(*result.first, features); | |
286 } | |
343 } | 287 } |
344 | 288 |
345 const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelec tor& selector, InvalidationSetFeatures& features, bool negated) | 289 std::pair<const CSSSelector*, RuleFeatureSet::UseFeaturesType> |
290 RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, Inva lidationSetFeatures& features, bool negated) | |
346 { | 291 { |
292 bool foundFeatures = false; | |
347 for (const CSSSelector* current = &selector; current; current = current->tag History()) { | 293 for (const CSSSelector* current = &selector; current; current = current->tag History()) { |
348 if (!negated) | 294 if (!negated) |
349 extractInvalidationSetFeature(*current, features); | 295 foundFeatures |= extractInvalidationSetFeature(*current, features); |
350 // Initialize the entry in the invalidation set map, if supported. | 296 // Initialize the entry in the invalidation set map, if supported. |
351 invalidationSetForSelector(*current); | 297 if (!invalidationSetForSelector(*current)) { |
352 if (supportsInvalidationWithSelectorList(current->pseudoType())) { | 298 if (requiresSubtreeInvalidation(*current)) { |
299 // Fall back to use subtree invalidations, even for features in the | |
300 // rightmost compound selector. Returning the start &selector he re | |
301 // will make addFeaturesToInvalidationSets start marking invalid ation | |
302 // sets for subtree recalc for features in the rightmost compoun d | |
303 // selector. | |
304 return std::make_pair(&selector, ForceSubtree); | |
305 } | |
353 if (const CSSSelectorList* selectorList = current->selectorList()) { | 306 if (const CSSSelectorList* selectorList = current->selectorList()) { |
354 for (const CSSSelector* selector = selectorList->first(); select or; selector = CSSSelectorList::next(*selector)) | 307 ASSERT(supportsInvalidationWithSelectorList(current->pseudoType( ))); |
355 extractInvalidationSetFeatures(*selector, features, current- >pseudoType() == CSSSelector::PseudoNot); | 308 const CSSSelector* subSelector = selectorList->first(); |
309 bool allSubSelectorsHaveFeatures = !!subSelector; | |
310 for (; subSelector; subSelector = CSSSelectorList::next(*subSele ctor)) { | |
311 auto result = extractInvalidationSetFeatures(*subSelector, f eatures, current->pseudoType() == CSSSelector::PseudoNot); | |
312 if (result.first) { | |
313 // A non-null selector return means the sub-selector con tained a | |
314 // selector which requiresSubtreeInvalidation(). Return the rightmost | |
315 // selector to mark for subtree recalcs like above. | |
316 return std::make_pair(&selector, ForceSubtree); | |
317 } | |
318 allSubSelectorsHaveFeatures &= result.second == UseFeatures; | |
319 } | |
320 foundFeatures |= allSubSelectorsHaveFeatures; | |
356 } | 321 } |
357 } | 322 } |
358 | 323 |
359 if (current->relation() == CSSSelector::SubSelector) | 324 if (current->relation() == CSSSelector::SubSelector) |
360 continue; | 325 continue; |
361 | 326 |
362 features.treeBoundaryCrossing = current->isShadowSelector(); | 327 features.treeBoundaryCrossing = current->isShadowSelector(); |
363 features.adjacent = current->isAdjacentSelector(); | 328 features.adjacent = current->isAdjacentSelector(); |
364 return current->tagHistory(); | 329 return std::make_pair(current->tagHistory(), foundFeatures ? UseFeatures : ForceSubtree); |
365 } | 330 } |
366 return 0; | 331 return std::make_pair(nullptr, ForceSubtree); |
367 } | 332 } |
368 | 333 |
369 // Add features extracted from the rightmost compound selector to descendant inv alidation | 334 // Add features extracted from the rightmost compound selector to descendant inv alidation |
370 // sets for features found in other compound selectors. | 335 // sets for features found in other compound selectors. |
371 // | 336 // |
372 // Style invalidation is currently supported for descendants only, not for sibli ng subtrees. | 337 // Style invalidation is currently supported for descendants only, not for sibli ng subtrees. |
373 // We use wholeSubtree invalidation for features found left of adjacent combinat ors as | 338 // We use wholeSubtree invalidation for features found left of adjacent combinat ors as |
374 // SubtreeStyleChange will force sibling subtree recalc in | 339 // SubtreeStyleChange will force sibling subtree recalc in |
375 // ContainerNode::checkForChildrenAdjacentRuleChanges. | 340 // ContainerNode::checkForChildrenAdjacentRuleChanges. |
376 // | 341 // |
377 // As we encounter a descendant type of combinator, the features only need to be checked | 342 // As we encounter a descendant type of combinator, the features only need to be checked |
378 // against descendants in the same subtree only. features.adjacent is set to fal se, and | 343 // against descendants in the same subtree only. features.adjacent is set to fal se, and |
379 // we start adding features instead of calling setWholeSubtreeInvalid. | 344 // we start adding features instead of calling setWholeSubtreeInvalid. |
380 | 345 |
381 void RuleFeatureSet::addFeaturesToInvalidationSet(DescendantInvalidationSet& inv alidationSet, const InvalidationSetFeatures& features) | 346 void RuleFeatureSet::addFeaturesToInvalidationSet(DescendantInvalidationSet& inv alidationSet, const InvalidationSetFeatures& features) |
382 { | 347 { |
383 if (features.treeBoundaryCrossing) | 348 if (features.treeBoundaryCrossing) |
384 invalidationSet.setTreeBoundaryCrossing(); | 349 invalidationSet.setTreeBoundaryCrossing(); |
385 if (features.insertionPointCrossing) | 350 if (features.insertionPointCrossing) |
386 invalidationSet.setInsertionPointCrossing(); | 351 invalidationSet.setInsertionPointCrossing(); |
387 if (features.adjacent) { | 352 if (features.useSubtreeInvalidation()) { |
388 invalidationSet.setWholeSubtreeInvalid(); | 353 invalidationSet.setWholeSubtreeInvalid(); |
389 return; | 354 return; |
390 } | 355 } |
391 if (!features.id.isEmpty()) | 356 if (!features.id.isEmpty()) |
392 invalidationSet.addId(features.id); | 357 invalidationSet.addId(features.id); |
393 if (!features.tagName.isEmpty()) | 358 if (!features.tagName.isEmpty()) |
394 invalidationSet.addTagName(features.tagName); | 359 invalidationSet.addTagName(features.tagName); |
395 for (const auto& className : features.classes) | 360 for (const auto& className : features.classes) |
396 invalidationSet.addClass(className); | 361 invalidationSet.addClass(className); |
397 for (const auto& attribute : features.attributes) | 362 for (const auto& attribute : features.attributes) |
(...skipping 29 matching lines...) Expand all Loading... | |
427 } | 392 } |
428 } | 393 } |
429 | 394 |
430 void RuleFeatureSet::addContentAttr(const AtomicString& attributeName) | 395 void RuleFeatureSet::addContentAttr(const AtomicString& attributeName) |
431 { | 396 { |
432 ensureAttributeInvalidationSet(attributeName); | 397 ensureAttributeInvalidationSet(attributeName); |
433 } | 398 } |
434 | 399 |
435 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) | 400 void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) |
436 { | 401 { |
402 updateInvalidationSets(ruleData.selector()); | |
403 | |
437 FeatureMetadata metadata; | 404 FeatureMetadata metadata; |
438 InvalidationSetMode mode = updateInvalidationSets(ruleData.selector()); | 405 collectFeaturesFromSelector(ruleData.selector(), metadata); |
439 | |
440 collectFeaturesFromSelector(ruleData.selector(), metadata, mode); | |
441 m_metadata.add(metadata); | 406 m_metadata.add(metadata); |
442 | 407 |
443 if (metadata.foundSiblingSelector) | 408 if (metadata.foundSiblingSelector) |
444 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex( ), ruleData.hasDocumentSecurityOrigin())); | 409 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex( ), ruleData.hasDocumentSecurityOrigin())); |
445 if (ruleData.containsUncommonAttributeSelector()) | 410 if (ruleData.containsUncommonAttributeSelector()) |
446 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele ctorIndex(), ruleData.hasDocumentSecurityOrigin())); | 411 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele ctorIndex(), ruleData.hasDocumentSecurityOrigin())); |
447 } | 412 } |
448 | 413 |
449 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom icString& className) | 414 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom icString& className) |
450 { | 415 { |
(...skipping 20 matching lines...) Expand all Loading... | |
471 } | 436 } |
472 | 437 |
473 DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelect or::PseudoType pseudoType) | 438 DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelect or::PseudoType pseudoType) |
474 { | 439 { |
475 PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets .add(pseudoType, nullptr); | 440 PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets .add(pseudoType, nullptr); |
476 if (addResult.isNewEntry) | 441 if (addResult.isNewEntry) |
477 addResult.storedValue->value = DescendantInvalidationSet::create(); | 442 addResult.storedValue->value = DescendantInvalidationSet::create(); |
478 return *addResult.storedValue->value; | 443 return *addResult.storedValue->value; |
479 } | 444 } |
480 | 445 |
481 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru leFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) | 446 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, Ru leFeatureSet::FeatureMetadata& metadata) |
482 { | 447 { |
483 unsigned maxDirectAdjacentSelectors = 0; | 448 unsigned maxDirectAdjacentSelectors = 0; |
484 | 449 |
485 for (const CSSSelector* current = &selector; current; current = current->tag History()) { | 450 for (const CSSSelector* current = &selector; current; current = current->tag History()) { |
486 if (mode != AddFeatures) { | |
487 if (DescendantInvalidationSet* invalidationSet = invalidationSetForS elector(*current)) { | |
488 if (mode == UseSubtreeStyleChange) | |
489 invalidationSet->setWholeSubtreeInvalid(); | |
490 } | |
491 } | |
492 if (current->pseudoType() == CSSSelector::PseudoFirstLine) | 451 if (current->pseudoType() == CSSSelector::PseudoFirstLine) |
493 metadata.usesFirstLineRules = true; | 452 metadata.usesFirstLineRules = true; |
494 if (current->isDirectAdjacentSelector()) { | 453 if (current->isDirectAdjacentSelector()) { |
495 maxDirectAdjacentSelectors++; | 454 maxDirectAdjacentSelectors++; |
496 } else if (maxDirectAdjacentSelectors) { | 455 } else if (maxDirectAdjacentSelectors) { |
497 if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors ) | 456 if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors ) |
498 metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors ; | 457 metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors ; |
499 maxDirectAdjacentSelectors = 0; | 458 maxDirectAdjacentSelectors = 0; |
500 } | 459 } |
501 if (current->isSiblingSelector()) | 460 if (current->isSiblingSelector()) |
502 metadata.foundSiblingSelector = true; | 461 metadata.foundSiblingSelector = true; |
503 | 462 |
504 collectFeaturesFromSelectorList(current->selectorList(), metadata, mode) ; | 463 const CSSSelectorList* selectorList = current->selectorList(); |
464 if (!selectorList) | |
465 continue; | |
505 | 466 |
506 if (mode == UseLocalStyleChange && current->relation() != CSSSelector::S ubSelector) | 467 for (const CSSSelector* selector = selectorList->first(); selector; sele ctor = CSSSelectorList::next(*selector)) |
507 mode = UseSubtreeStyleChange; | 468 collectFeaturesFromSelector(*selector, metadata); |
508 } | 469 } |
509 | 470 |
510 ASSERT(!maxDirectAdjacentSelectors); | 471 ASSERT(!maxDirectAdjacentSelectors); |
511 } | 472 } |
512 | 473 |
513 void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* sele ctorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) | |
514 { | |
515 if (!selectorList) | |
516 return; | |
517 | |
518 for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) | |
519 collectFeaturesFromSelector(*selector, metadata, mode); | |
520 } | |
521 | |
522 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) | 474 void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) |
523 { | 475 { |
524 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; | 476 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; |
525 maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxD irectAdjacentSelectors); | 477 maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxD irectAdjacentSelectors); |
526 } | 478 } |
527 | 479 |
528 void RuleFeatureSet::FeatureMetadata::clear() | 480 void RuleFeatureSet::FeatureMetadata::clear() |
529 { | 481 { |
530 usesFirstLineRules = false; | 482 usesFirstLineRules = false; |
531 foundSiblingSelector = false; | 483 foundSiblingSelector = false; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 visitor->trace(uncommonAttributeRules); | 610 visitor->trace(uncommonAttributeRules); |
659 visitor->trace(m_classInvalidationSets); | 611 visitor->trace(m_classInvalidationSets); |
660 visitor->trace(m_attributeInvalidationSets); | 612 visitor->trace(m_attributeInvalidationSets); |
661 visitor->trace(m_idInvalidationSets); | 613 visitor->trace(m_idInvalidationSets); |
662 visitor->trace(m_pseudoInvalidationSets); | 614 visitor->trace(m_pseudoInvalidationSets); |
663 visitor->trace(m_styleInvalidator); | 615 visitor->trace(m_styleInvalidator); |
664 #endif | 616 #endif |
665 } | 617 } |
666 | 618 |
667 } // namespace blink | 619 } // namespace blink |
OLD | NEW |