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

Side by Side Diff: Source/core/dom/Element.cpp

Issue 143873016: Implement style invalidation tree walk for targeted style recalc upon class change. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Merge. Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com) 4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * (C) 2007 David Smith (catfish.man@gmail.com) 6 * (C) 2007 David Smith (catfish.man@gmail.com)
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
8 * (C) 2007 Eric Seidel (eric@webkit.org) 8 * (C) 2007 Eric Seidel (eric@webkit.org)
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 unsigned length = newClassString.length(); 1038 unsigned length = newClassString.length();
1039 1039
1040 if (!length) 1040 if (!length)
1041 return false; 1041 return false;
1042 1042
1043 if (newClassString.is8Bit()) 1043 if (newClassString.is8Bit())
1044 return classStringHasClassName(newClassString.characters8(), length); 1044 return classStringHasClassName(newClassString.characters8(), length);
1045 return classStringHasClassName(newClassString.characters16(), length); 1045 return classStringHasClassName(newClassString.characters16(), length);
1046 } 1046 }
1047 1047
1048 template<typename Checker>
1049 static bool checkSelectorForClassChange(const SpaceSplitString& changedClasses, const Checker& checker)
1050 {
1051 unsigned changedSize = changedClasses.size();
1052 for (unsigned i = 0; i < changedSize; ++i) {
1053 if (checker.hasSelectorForClass(changedClasses[i]))
1054 return true;
1055 }
1056 return false;
1057 }
1058
1059 template<typename Checker>
1060 static bool checkSelectorForClassChange(const SpaceSplitString& oldClasses, cons t SpaceSplitString& newClasses, const Checker& checker)
1061 {
1062 if (!oldClasses.size())
1063 return checkSelectorForClassChange(newClasses, checker);
1064
1065 // Class vectors tend to be very short. This is faster than using a hash tab le.
1066 BitVector remainingClassBits;
1067 remainingClassBits.ensureSize(oldClasses.size());
1068
1069 for (unsigned i = 0; i < newClasses.size(); ++i) {
1070 bool found = false;
1071 for (unsigned j = 0; j < oldClasses.size(); ++j) {
1072 if (newClasses[i] == oldClasses[j]) {
1073 // Mark each class that is still in the newClasses so we can ski p doing
1074 // an n^2 search below when looking for removals. We can't break from
1075 // this loop early since a class can appear more than once.
1076 remainingClassBits.quickSet(j);
1077 found = true;
1078 }
1079 }
1080 // Class was added.
1081 if (!found && checker.hasSelectorForClass(newClasses[i]))
1082 return true;
1083 }
1084
1085 for (unsigned i = 0; i < oldClasses.size(); ++i) {
1086 if (remainingClassBits.quickGet(i))
1087 continue;
1088 // Class was removed.
1089 if (checker.hasSelectorForClass(oldClasses[i]))
1090 return true;
1091 }
1092
1093 return false;
1094 }
1095
1096 void Element::classAttributeChanged(const AtomicString& newClassString) 1048 void Element::classAttributeChanged(const AtomicString& newClassString)
1097 { 1049 {
1098 StyleResolver* styleResolver = document().styleResolver(); 1050 StyleResolver* styleResolver = document().styleResolver();
1099 bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styl eChangeType() < SubtreeStyleChange; 1051 bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styl eChangeType() < SubtreeStyleChange;
ojan 2014/01/30 19:08:39 Hmmm...as an aside, I think this code might be wro
chrishtr 2014/01/30 19:25:48 yikes.
1100 bool shouldInvalidateStyle = false;
1101 1052
1102 if (classStringHasClassName(newClassString)) { 1053 if (classStringHasClassName(newClassString)) {
1103 const bool shouldFoldCase = document().inQuirksMode(); 1054 const bool shouldFoldCase = document().inQuirksMode();
1104 const SpaceSplitString oldClasses = elementData()->classNames(); 1055 const SpaceSplitString oldClasses = elementData()->classNames();
1105 elementData()->setClass(newClassString, shouldFoldCase); 1056 elementData()->setClass(newClassString, shouldFoldCase);
1106 const SpaceSplitString& newClasses = elementData()->classNames(); 1057 const SpaceSplitString& newClasses = elementData()->classNames();
1107 shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForCla ssChange(oldClasses, newClasses, styleResolver->ensureRuleFeatureSet()); 1058 if (testShouldInvalidateStyle)
1059 styleResolver->ensureRuleFeatureSet().scheduleStyleInvalidationForCl assChange(oldClasses, newClasses, this);
1108 } else { 1060 } else {
1109 const SpaceSplitString& oldClasses = elementData()->classNames(); 1061 const SpaceSplitString& oldClasses = elementData()->classNames();
1110 shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForCla ssChange(oldClasses, styleResolver->ensureRuleFeatureSet()); 1062 if (testShouldInvalidateStyle)
1063 styleResolver->ensureRuleFeatureSet().scheduleStyleInvalidationForCl assChange(oldClasses, this);
1111 elementData()->clearClass(); 1064 elementData()->clearClass();
1112 } 1065 }
1113 1066
1114 if (hasRareData()) 1067 if (hasRareData())
1115 elementRareData()->clearClassListValueForQuirksMode(); 1068 elementRareData()->clearClassListValueForQuirksMode();
1116
1117 if (shouldInvalidateStyle)
1118 setNeedsStyleRecalc();
1119 } 1069 }
1120 1070
1121 bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* el ementShadow, const QualifiedName& name, const AtomicString& newValue) 1071 bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* el ementShadow, const QualifiedName& name, const AtomicString& newValue)
1122 { 1072 {
1123 ASSERT(elementShadow); 1073 ASSERT(elementShadow);
1124 const SelectRuleFeatureSet& featureSet = elementShadow->ensureSelectFeatureS et(); 1074 const SelectRuleFeatureSet& featureSet = elementShadow->ensureSelectFeatureS et();
1125 1075
1126 if (isIdAttributeName(name)) { 1076 if (isIdAttributeName(name)) {
1127 AtomicString oldId = elementData()->idForStyleResolution(); 1077 AtomicString oldId = elementData()->idForStyleResolution();
1128 AtomicString newId = makeIdForStyleResolution(newValue, document().inQui rksMode()); 1078 AtomicString newId = makeIdForStyleResolution(newValue, document().inQui rksMode());
1129 if (newId != oldId) { 1079 if (newId != oldId) {
1130 if (!oldId.isEmpty() && featureSet.hasSelectorForId(oldId)) 1080 if (!oldId.isEmpty() && featureSet.hasSelectorForId(oldId))
1131 return true; 1081 return true;
1132 if (!newId.isEmpty() && featureSet.hasSelectorForId(newId)) 1082 if (!newId.isEmpty() && featureSet.hasSelectorForId(newId))
1133 return true; 1083 return true;
1134 } 1084 }
1135 } 1085 }
1136 1086
1137 if (name == HTMLNames::classAttr) { 1087 if (name == HTMLNames::classAttr) {
1138 const AtomicString& newClassString = newValue; 1088 const AtomicString& newClassString = newValue;
1139 if (classStringHasClassName(newClassString)) { 1089 if (classStringHasClassName(newClassString)) {
1140 const bool shouldFoldCase = document().inQuirksMode(); 1090 const bool shouldFoldCase = document().inQuirksMode();
1141 const SpaceSplitString& oldClasses = elementData()->classNames(); 1091 const SpaceSplitString& oldClasses = elementData()->classNames();
1142 const SpaceSplitString newClasses(newClassString, shouldFoldCase); 1092 const SpaceSplitString newClasses(newClassString, shouldFoldCase);
1143 if (checkSelectorForClassChange(oldClasses, newClasses, featureSet)) 1093 if (featureSet.checkSelectorsForClassChange(oldClasses, newClasses))
1144 return true; 1094 return true;
1145 } else { 1095 } else {
1146 const SpaceSplitString& oldClasses = elementData()->classNames(); 1096 const SpaceSplitString& oldClasses = elementData()->classNames();
1147 if (checkSelectorForClassChange(oldClasses, featureSet)) 1097 if (featureSet.checkSelectorsForClassChange(oldClasses))
1148 return true; 1098 return true;
1149 } 1099 }
1150 } 1100 }
1151 1101
1152 return featureSet.hasSelectorForAttribute(name.localName()); 1102 return featureSet.hasSelectorForAttribute(name.localName());
1153 } 1103 }
1154 1104
1155 // Returns true is the given attribute is an event handler. 1105 // Returns true is the given attribute is an event handler.
1156 // We consider an event handler any attribute that begins with "on". 1106 // We consider an event handler any attribute that begins with "on".
1157 // It is a simple solution that has the advantage of not requiring any 1107 // It is a simple solution that has the advantage of not requiring any
(...skipping 2468 matching lines...) Expand 10 before | Expand all | Expand 10 after
3626 // Before doing so, we need to resolve issues in HTMLSelectElement::recalcLi stItems 3576 // Before doing so, we need to resolve issues in HTMLSelectElement::recalcLi stItems
3627 // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cg i?id=88405 3577 // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cg i?id=88405
3628 if (hasTagName(optionTag) || hasTagName(optgroupTag)) 3578 if (hasTagName(optionTag) || hasTagName(optgroupTag))
3629 return false; 3579 return false;
3630 if (FullscreenElementStack::isActiveFullScreenElement(this)) 3580 if (FullscreenElementStack::isActiveFullScreenElement(this))
3631 return false; 3581 return false;
3632 return true; 3582 return true;
3633 } 3583 }
3634 3584
3635 } // namespace WebCore 3585 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698