Changeset 228285 in webkit
- Timestamp:
- Feb 8, 2018 11:48:30 AM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r228284 r228285 1 2018-02-08 Antti Koivisto <antti@apple.com> 2 3 Use invalidation rulesets for attribute selectors 4 https://bugs.webkit.org/show_bug.cgi?id=182569 5 6 Reviewed by Zalan Bujtas. 7 8 Attribute change style invalidation should use invalidation rulesets, similarly how class change invalidation already does. 9 We'll invalidate fewer unnecessary elements immediately and enable more significant future gains. 10 11 * css/DocumentRuleSets.cpp: 12 (WebCore::DocumentRuleSets::collectFeatures const): 13 (WebCore::DocumentRuleSets::classInvalidationRuleSets const): 14 (WebCore::DocumentRuleSets::attributeInvalidationRuleSets const): 15 16 Make and cache invalidation RuleSets for an attribute. 17 18 (WebCore::DocumentRuleSets::ancestorAttributeRulesForHTML const): Deleted. 19 * css/DocumentRuleSets.h: 20 * css/RuleFeature.cpp: 21 (WebCore::RuleFeatureSet::recursivelyCollectFeaturesFromSelector): 22 23 Collect attribute selectors along with match elements. 24 25 (WebCore::RuleFeatureSet::collectFeatures): 26 (WebCore::RuleFeatureSet::add): 27 (WebCore::RuleFeatureSet::registerContentAttribute): 28 29 Separate hash to deal with invalidation of content:attr(foo) special case. 30 31 (WebCore::RuleFeatureSet::clear): 32 (WebCore::RuleFeatureSet::shrinkToFit): 33 (WebCore::makeAttributeSelectorKey): Deleted. 34 * css/RuleFeature.h: 35 (WebCore::RuleFeature::RuleFeature): 36 * css/StyleBuilderCustom.h: 37 (WebCore::StyleBuilderCustom::applyValueContent): 38 (WebCore::StyleBuilderCustom::applyValueAlt): 39 40 Use registerContentAttribute() 41 42 * html/HTMLEmbedElement.cpp: 43 (WebCore::hasTypeOrSrc): 44 (WebCore::HTMLEmbedElement::parseAttribute): 45 46 Invalidate style if both type and src attributes go missing as this changes result of rendererIsNeeded(). 47 This was previously relying on any attribute change invalidating style. 48 49 (WebCore::HTMLEmbedElement::rendererIsNeeded): 50 * style/AttributeChangeInvalidation.cpp: 51 (WebCore::Style::AttributeChangeInvalidation::invalidateStyle): 52 53 Collect the invalidation rulesets for this attribute change. 54 Also check if any attribute selector actually changes state, unlike with classes attribute changes may 55 often not lead to a selector becoming non-matching. 56 57 (WebCore::Style::AttributeChangeInvalidation::invalidateStyleWithRuleSets): 58 (WebCore::Style::AttributeChangeInvalidation::invalidateDescendants): Deleted. 59 * style/AttributeChangeInvalidation.h: 60 (WebCore::Style::AttributeChangeInvalidation::AttributeChangeInvalidation): 61 (WebCore::Style::AttributeChangeInvalidation::~AttributeChangeInvalidation): 62 * style/ClassChangeInvalidation.cpp: 63 (WebCore::Style::ClassChangeInvalidation::computeInvalidation): 64 65 Should not bail on shadow tree invalidation as we may also need to invalidate siblings. 66 1 67 2018-02-08 Zalan Bujtas <zalan@apple.com> 2 68 -
trunk/Source/WebCore/css/DocumentRuleSets.cpp
r227787 r228285 169 169 170 170 m_classInvalidationRuleSets.clear(); 171 m_a ncestorAttributeRuleSetsForHTML.clear();171 m_attributeInvalidationRuleSets.clear(); 172 172 173 173 m_features.shrinkToFit(); 174 174 } 175 175 176 const Vector<InvalidationRuleSet>* DocumentRuleSets::classInvalidationRuleSets(const AtomicString& className) const 177 { 178 return m_classInvalidationRuleSets.ensure(className, [&] () -> std::unique_ptr<Vector<InvalidationRuleSet>> {179 auto* features = m_features.classRules.get(className);176 static Vector<InvalidationRuleSet>* ensureInvalidationRuleSets(const AtomicString& key, HashMap<AtomicString, std::unique_ptr<Vector<InvalidationRuleSet>>>& ruleSetMap, const HashMap<AtomicString, std::unique_ptr<Vector<RuleFeature>>>& ruleFeatures) 177 { 178 return ruleSetMap.ensure(key, [&] () -> std::unique_ptr<Vector<InvalidationRuleSet>> { 179 auto* features = ruleFeatures.get(key); 180 180 if (!features) 181 181 return nullptr; 182 182 183 std::array<std::unique_ptr<RuleSet>, matchElementCount> matchElementArray; 184 std::array<Vector<const CSSSelector*>, matchElementCount> invalidationSelectorArray; 183 185 for (auto& feature : *features) { 184 auto& ruleSet = matchElementArray[static_cast<unsigned>(*feature.matchElement)]; 186 auto arrayIndex = static_cast<unsigned>(*feature.matchElement); 187 auto& ruleSet = matchElementArray[arrayIndex]; 185 188 if (!ruleSet) 186 189 ruleSet = std::make_unique<RuleSet>(); 187 190 ruleSet->addRule(feature.rule, feature.selectorIndex); 191 if (feature.invalidationSelector) 192 invalidationSelectorArray[arrayIndex].append(feature.invalidationSelector); 188 193 } 189 194 auto invalidationRuleSets = std::make_unique<Vector<InvalidationRuleSet>>(); 190 195 for (unsigned i = 0; i < matchElementArray.size(); ++i) { 191 196 if (matchElementArray[i]) 192 invalidationRuleSets->append({ static_cast<MatchElement>(i), WTFMove(matchElementArray[i]) });197 invalidationRuleSets->append({ static_cast<MatchElement>(i), WTFMove(matchElementArray[i]), WTFMove(invalidationSelectorArray[i]) }); 193 198 } 194 199 return invalidationRuleSets; … … 196 201 } 197 202 198 const DocumentRuleSets::AttributeRules* DocumentRuleSets::ancestorAttributeRulesForHTML(const AtomicString& attributeName) const 199 { 200 auto addResult = m_ancestorAttributeRuleSetsForHTML.add(attributeName, nullptr); 201 auto& value = addResult.iterator->value; 202 if (addResult.isNewEntry) { 203 if (auto* rules = m_features.ancestorAttributeRulesForHTML.get(attributeName)) { 204 value = std::make_unique<AttributeRules>(); 205 value->attributeSelectors.reserveCapacity(rules->selectors.size()); 206 for (auto* selector : rules->selectors.values()) 207 value->attributeSelectors.uncheckedAppend(selector); 208 value->ruleSet = makeRuleSet(rules->features); 209 } 210 } 211 return value.get(); 203 const Vector<InvalidationRuleSet>* DocumentRuleSets::classInvalidationRuleSets(const AtomicString& className) const 204 { 205 return ensureInvalidationRuleSets(className, m_classInvalidationRuleSets, m_features.classRules); 206 } 207 208 const Vector<InvalidationRuleSet>* DocumentRuleSets::attributeInvalidationRuleSets(const AtomicString& attributeName) const 209 { 210 return ensureInvalidationRuleSets(attributeName, m_attributeInvalidationRuleSets, m_features.attributeRules); 212 211 } 213 212 -
trunk/Source/WebCore/css/DocumentRuleSets.h
r227787 r228285 42 42 MatchElement matchElement; 43 43 std::unique_ptr<RuleSet> ruleSet; 44 Vector<const CSSSelector*> invalidationSelectors; 44 45 45 46 WTF_MAKE_FAST_ALLOCATED; … … 60 61 61 62 const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomicString& className) const; 62 63 struct AttributeRules { 64 WTF_MAKE_FAST_ALLOCATED; 65 public: 66 Vector<const CSSSelector*> attributeSelectors; 67 std::unique_ptr<RuleSet> ruleSet; 68 }; 69 const AttributeRules* ancestorAttributeRulesForHTML(const AtomicString&) const; 63 const Vector<InvalidationRuleSet>* attributeInvalidationRuleSets(const AtomicString& attributeName) const; 70 64 71 65 void setIsForShadowScope() { m_isForShadowScope = true; } … … 100 94 mutable std::unique_ptr<RuleSet> m_uncommonAttributeRuleSet; 101 95 mutable HashMap<AtomicString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets; 102 mutable HashMap<AtomicString, std::unique_ptr< AttributeRules>> m_ancestorAttributeRuleSetsForHTML;96 mutable HashMap<AtomicString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_attributeInvalidationRuleSets; 103 97 }; 104 98 -
trunk/Source/WebCore/css/RuleFeature.cpp
r227956 r228285 131 131 attributeCanonicalLocalNamesInRules.add(canonicalLocalName); 132 132 attributeLocalNamesInRules.add(localName); 133 if (matchElement == MatchElement::Parent || matchElement == MatchElement::Ancestor) 134 selectorFeatures.attributeSelectorsMatchingAncestors.append(selector); 133 selectorFeatures.attributes.append(std::make_pair(selector, matchElement)); 135 134 } else if (selector->match() == CSSSelector::PseudoElement) { 136 135 switch (selector->pseudoElementType()) { … … 165 164 } 166 165 167 static RuleFeatureSet::AttributeRules::SelectorKey makeAttributeSelectorKey(const CSSSelector& selector)168 {169 bool caseInsensitive = selector.attributeValueMatchingIsCaseInsensitive();170 unsigned matchAndCase = static_cast<unsigned>(selector.match()) << 1 | (caseInsensitive ? 1 : 0);171 return std::make_pair(selector.attributeCanonicalLocalName().impl(), std::make_pair(selector.value().impl(), matchAndCase));172 }173 174 166 void RuleFeatureSet::collectFeatures(const RuleData& ruleData) 175 167 { … … 180 172 if (ruleData.containsUncommonAttributeSelector()) 181 173 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex())); 174 182 175 for (auto& nameAndMatch : selectorFeatures.classes) { 183 176 classRules.ensure(nameAndMatch.first, [] { … … 187 180 classesAffectingHost.add(nameAndMatch.first); 188 181 } 189 for (auto* selector : selectorFeatures.attributeSelectorsMatchingAncestors) { 190 // Hashing by attributeCanonicalLocalName makes this HTML specific.191 auto addResult = ancestorAttributeRulesForHTML.ensure(selector->attributeCanonicalLocalName(), [] {192 return std::make_unique<AttributeRules>();193 });194 auto& rules = *addResult.iterator->value;195 rules.features.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex()));196 // Deduplicate selectors.197 rules.selectors.add(makeAttributeSelectorKey(*selector), selector);182 183 for (auto& selectorAndMatch : selectorFeatures.attributes) { 184 auto* selector = selectorAndMatch.first; 185 auto matchElement = selectorAndMatch.second; 186 attributeRules.ensure(selector->attribute().localName().convertToASCIILowercase(), [] { 187 return std::make_unique<Vector<RuleFeature>>(); 188 }).iterator->value->append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), matchElement, selector)); 189 if (matchElement == MatchElement::Host) 190 attributesAffectingHost.add(selector->attribute().localName().convertToASCIILowercase()); 198 191 } 199 192 } … … 205 198 attributeCanonicalLocalNamesInRules.add(other.attributeCanonicalLocalNamesInRules.begin(), other.attributeCanonicalLocalNamesInRules.end()); 206 199 attributeLocalNamesInRules.add(other.attributeLocalNamesInRules.begin(), other.attributeLocalNamesInRules.end()); 200 contentAttributeNamesInRules.add(other.contentAttributeNamesInRules.begin(), other.contentAttributeNamesInRules.end()); 207 201 siblingRules.appendVector(other.siblingRules); 208 202 uncommonAttributeRules.appendVector(other.uncommonAttributeRules); … … 214 208 classesAffectingHost.add(other.classesAffectingHost.begin(), other.classesAffectingHost.end()); 215 209 216 for (auto& keyValuePair : other.ancestorAttributeRulesForHTML) { 217 auto addResult = ancestorAttributeRulesForHTML.ensure(keyValuePair.key, [] { 218 return std::make_unique<AttributeRules>(); 219 }); 220 auto& rules = *addResult.iterator->value; 221 rules.features.appendVector(keyValuePair.value->features); 222 for (auto& selectorPair : keyValuePair.value->selectors) 223 rules.selectors.add(selectorPair.key, selectorPair.value); 224 } 210 for (auto& keyValuePair : other.attributeRules) { 211 attributeRules.ensure(keyValuePair.key, [] { 212 return std::make_unique<Vector<RuleFeature>>(); 213 }).iterator->value->appendVector(*keyValuePair.value); 214 } 215 attributesAffectingHost.add(other.attributesAffectingHost.begin(), other.attributesAffectingHost.end()); 216 225 217 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; 226 218 usesFirstLetterRules = usesFirstLetterRules || other.usesFirstLetterRules; 219 } 220 221 void RuleFeatureSet::registerContentAttribute(const AtomicString& attributeName) 222 { 223 contentAttributeNamesInRules.add(attributeName.convertToASCIILowercase()); 224 attributeCanonicalLocalNamesInRules.add(attributeName); 225 attributeLocalNamesInRules.add(attributeName); 227 226 } 228 227 … … 233 232 attributeCanonicalLocalNamesInRules.clear(); 234 233 attributeLocalNamesInRules.clear(); 234 contentAttributeNamesInRules.clear(); 235 235 siblingRules.clear(); 236 236 uncommonAttributeRules.clear(); 237 237 classRules.clear(); 238 238 classesAffectingHost.clear(); 239 ancestorAttributeRulesForHTML.clear(); 239 attributeRules.clear(); 240 attributesAffectingHost.clear(); 240 241 usesFirstLineRules = false; 241 242 usesFirstLetterRules = false; … … 248 249 for (auto& rules : classRules.values()) 249 250 rules->shrinkToFit(); 250 for (auto& rules : a ncestorAttributeRulesForHTML.values())251 rules-> features.shrinkToFit();251 for (auto& rules : attributeRules.values()) 252 rules->shrinkToFit(); 252 253 } 253 254 -
trunk/Source/WebCore/css/RuleFeature.h
r227956 r228285 38 38 39 39 struct RuleFeature { 40 RuleFeature(StyleRule* rule, unsigned selectorIndex, std::optional<MatchElement> matchElement = std::nullopt )40 RuleFeature(StyleRule* rule, unsigned selectorIndex, std::optional<MatchElement> matchElement = std::nullopt, const CSSSelector* invalidationSelector = nullptr) 41 41 : rule(rule) 42 42 , selectorIndex(selectorIndex) 43 43 , matchElement(matchElement) 44 , invalidationSelector(invalidationSelector) 44 45 { 45 46 } … … 47 48 unsigned selectorIndex; 48 49 std::optional<MatchElement> matchElement; 50 const CSSSelector* invalidationSelector; 49 51 }; 50 52 … … 54 56 void shrinkToFit(); 55 57 void collectFeatures(const RuleData&); 58 void registerContentAttribute(const AtomicString&); 56 59 57 60 HashSet<AtomicString> idsInRules; … … 59 62 HashSet<AtomicString> attributeCanonicalLocalNamesInRules; 60 63 HashSet<AtomicString> attributeLocalNamesInRules; 64 HashSet<AtomicString> contentAttributeNamesInRules; 61 65 Vector<RuleFeature> siblingRules; 62 66 Vector<RuleFeature> uncommonAttributeRules; 63 67 64 68 HashMap<AtomicString, std::unique_ptr<Vector<RuleFeature>>> classRules; 69 HashMap<AtomicString, std::unique_ptr<Vector<RuleFeature>>> attributeRules; 65 70 HashSet<AtomicString> classesAffectingHost; 71 HashSet<AtomicString> attributesAffectingHost; 66 72 67 struct AttributeRules {68 WTF_MAKE_FAST_ALLOCATED;69 public:70 using SelectorKey = std::pair<AtomicStringImpl*, std::pair<AtomicStringImpl*, unsigned>>;71 HashMap<SelectorKey, const CSSSelector*> selectors;72 Vector<RuleFeature> features;73 };74 HashMap<AtomicString, std::unique_ptr<AttributeRules>> ancestorAttributeRulesForHTML;75 73 bool usesFirstLineRules { false }; 76 74 bool usesFirstLetterRules { false }; … … 84 82 85 83 Vector<std::pair<AtomicString, MatchElement>, 32> classes; 86 Vector< const CSSSelector*> attributeSelectorsMatchingAncestors;84 Vector<std::pair<const CSSSelector*, MatchElement>, 32> attributes; 87 85 }; 88 86 void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, MatchElement = MatchElement::Subject); -
trunk/Source/WebCore/css/StyleBuilderCustom.h
r227676 r228285 1424 1424 didSet = true; 1425 1425 // Register the fact that the attribute value affects the style. 1426 styleResolver.ruleSets().mutableFeatures().attributeCanonicalLocalNamesInRules.add(attr.localName().impl()); 1427 styleResolver.ruleSets().mutableFeatures().attributeLocalNamesInRules.add(attr.localName().impl()); 1426 styleResolver.ruleSets().mutableFeatures().registerContentAttribute(attr.localName()); 1428 1427 } else if (contentValue.isCounter()) { 1429 1428 auto* counterValue = contentValue.counterValue(); … … 1822 1821 1823 1822 // Register the fact that the attribute value affects the style. 1824 styleResolver.ruleSets().mutableFeatures().attributeCanonicalLocalNamesInRules.add(attr.localName().impl()); 1825 styleResolver.ruleSets().mutableFeatures().attributeLocalNamesInRules.add(attr.localName().impl()); 1823 styleResolver.ruleSets().mutableFeatures().registerContentAttribute(attr.localName()); 1826 1824 } else 1827 1825 styleResolver.style()->setContentAltText(emptyAtom()); -
trunk/Source/WebCore/html/HTMLEmbedElement.cpp
r224320 r228285 106 106 } 107 107 108 static bool hasTypeOrSrc(const HTMLEmbedElement& embed) 109 { 110 return embed.hasAttributeWithoutSynchronization(typeAttr) || embed.hasAttributeWithoutSynchronization(srcAttr); 111 } 112 108 113 void HTMLEmbedElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 109 114 { … … 113 118 // code is that HTMLObjectElement does setNeedsWidgetUpdate(true). Consider moving 114 119 // this up to the HTMLPlugInImageElement to be shared. 120 if (renderer() && !hasTypeOrSrc(*this)) 121 invalidateStyle(); 115 122 } else if (name == codeAttr) { 116 123 m_url = stripLeadingAndTrailingHTMLSpaces(value); … … 120 127 m_url = stripLeadingAndTrailingHTMLSpaces(value); 121 128 updateImageLoaderWithNewURLSoon(); 129 if (renderer() && !hasTypeOrSrc(*this)) 130 invalidateStyle(); 122 131 // FIXME: If both code and src attributes are specified, last one parsed/changed wins. That can't be right! 123 132 } else … … 192 201 bool HTMLEmbedElement::rendererIsNeeded(const RenderStyle& style) 193 202 { 194 if (!has AttributeWithoutSynchronization(typeAttr) && !hasAttributeWithoutSynchronization(srcAttr))203 if (!hasTypeOrSrc(*this)) 195 204 return false; 196 205 -
trunk/Source/WebCore/style/AttributeChangeInvalidation.cpp
r220204 r228285 47 47 bool isHTML = m_element.isHTMLElement(); 48 48 49 bool mayAffectStyle= false;49 bool shouldInvalidateCurrent = false; 50 50 bool mayAffectStyleInShadowTree = false; 51 51 52 auto attributeNameForLookups = attributeName.localName().convertToASCIILowercase(); 53 52 54 traverseRuleFeatures(m_element, [&] (const RuleFeatureSet& features, bool mayAffectShadowTree) { 53 if (!mayBeAffectedByAttributeChange(features, isHTML, attributeName)) 54 return; 55 mayAffectStyle = true; 56 if (mayAffectShadowTree) 55 if (mayAffectShadowTree && mayBeAffectedByAttributeChange(features, isHTML, attributeName)) 57 56 mayAffectStyleInShadowTree = true; 57 if (features.attributesAffectingHost.contains(attributeNameForLookups)) 58 shouldInvalidateCurrent = true; 59 else if (features.contentAttributeNamesInRules.contains(attributeNameForLookups)) 60 shouldInvalidateCurrent = true; 58 61 }); 59 60 if (!mayAffectStyle)61 return;62 63 if (!isHTML) {64 m_element.invalidateStyleForSubtree();65 return;66 }67 62 68 63 if (mayAffectStyleInShadowTree) { 69 64 // FIXME: More fine-grained invalidation. 70 65 m_element.invalidateStyleForSubtree(); 71 return;72 66 } 73 67 74 m_element.invalidateStyle(); 68 if (shouldInvalidateCurrent) 69 m_element.invalidateStyle(); 75 70 76 if (!childrenOfType<Element>(m_element).first()) 71 auto& ruleSets = m_element.styleResolver().ruleSets(); 72 73 auto* invalidationRuleSets = ruleSets.attributeInvalidationRuleSets(attributeNameForLookups); 74 if (!invalidationRuleSets) 77 75 return; 78 76 79 auto& ruleSets = m_element.styleResolver().ruleSets(); 80 auto* attributeRules = ruleSets.ancestorAttributeRulesForHTML(attributeName.localName()); 81 if (!attributeRules) 82 return; 83 84 // Check if descendants may be affected by this attribute change. 85 for (auto* selector : attributeRules->attributeSelectors) { 86 bool oldMatches = oldValue.isNull() ? false : SelectorChecker::attributeSelectorMatches(m_element, attributeName, oldValue, *selector); 87 bool newMatches = newValue.isNull() ? false : SelectorChecker::attributeSelectorMatches(m_element, attributeName, newValue, *selector); 88 89 if (oldMatches != newMatches) { 90 m_descendantInvalidationRuleSet = attributeRules->ruleSet.get(); 91 return; 77 for (auto& invalidationRuleSet : *invalidationRuleSets) { 78 for (auto* selector : invalidationRuleSet.invalidationSelectors) { 79 bool oldMatches = !oldValue.isNull() && SelectorChecker::attributeSelectorMatches(m_element, attributeName, oldValue, *selector); 80 bool newMatches = !newValue.isNull() && SelectorChecker::attributeSelectorMatches(m_element, attributeName, newValue, *selector); 81 if (oldMatches != newMatches) { 82 m_invalidationRuleSets.append(&invalidationRuleSet); 83 break; 84 } 92 85 } 93 86 } 94 87 } 95 88 96 void AttributeChangeInvalidation::invalidate Descendants()89 void AttributeChangeInvalidation::invalidateStyleWithRuleSets() 97 90 { 98 if (!m_descendantInvalidationRuleSet)99 return;100 Invalidator invalidator(*m_descendantInvalidationRuleSet);101 invalidator.invalidateStyle(m_element);91 for (auto* invalidationRuleSet : m_invalidationRuleSets) { 92 Invalidator invalidator(*invalidationRuleSet->ruleSet); 93 invalidator.invalidateStyleWithMatchElement(m_element, invalidationRuleSet->matchElement); 94 } 102 95 } 96 103 97 104 98 } -
trunk/Source/WebCore/style/AttributeChangeInvalidation.h
r208668 r228285 30 30 namespace WebCore { 31 31 32 classRuleSet;32 struct InvalidationRuleSet; 33 33 34 34 namespace Style { … … 41 41 private: 42 42 void invalidateStyle(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue); 43 void invalidate Descendants();43 void invalidateStyleWithRuleSets(); 44 44 45 45 const bool m_isEnabled; 46 46 Element& m_element; 47 47 48 const RuleSet* m_descendantInvalidationRuleSet { nullptr };48 Vector<const InvalidationRuleSet*, 4> m_invalidationRuleSets; 49 49 }; 50 50 … … 56 56 return; 57 57 invalidateStyle(attributeName, oldValue, newValue); 58 invalidate Descendants();58 invalidateStyleWithRuleSets(); 59 59 } 60 60 … … 63 63 if (!m_isEnabled) 64 64 return; 65 invalidate Descendants();65 invalidateStyleWithRuleSets(); 66 66 } 67 67 -
trunk/Source/WebCore/style/ClassChangeInvalidation.cpp
r227787 r228285 103 103 // FIXME: We should do fine-grained invalidation for shadow tree. 104 104 m_element.invalidateStyleForSubtree(); 105 return;106 105 } 107 106
Note: See TracChangeset
for help on using the changeset viewer.