Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 1038 | 1038 |
| 1039 if (!length) | 1039 if (!length) |
| 1040 return false; | 1040 return false; |
| 1041 | 1041 |
| 1042 if (newClassString.is8Bit()) | 1042 if (newClassString.is8Bit()) |
| 1043 return classStringHasClassName(newClassString.characters8(), length); | 1043 return classStringHasClassName(newClassString.characters8(), length); |
| 1044 return classStringHasClassName(newClassString.characters16(), length); | 1044 return classStringHasClassName(newClassString.characters16(), length); |
| 1045 } | 1045 } |
| 1046 | 1046 |
| 1047 template<typename Checker> | 1047 template<typename Checker> |
| 1048 static bool checkSelectorForClassChange(const SpaceSplitString& changedClasses, const Checker& checker) | 1048 static bool checkSelectorForClassChange(const SpaceSplitString& changedClasses, const Checker& checker, Element* element) |
| 1049 { | 1049 { |
| 1050 unsigned changedSize = changedClasses.size(); | 1050 unsigned changedSize = changedClasses.size(); |
| 1051 for (unsigned i = 0; i < changedSize; ++i) { | 1051 for (unsigned i = 0; i < changedSize; ++i) { |
| 1052 if (checker.hasSelectorForClass(changedClasses[i])) | 1052 const RuleSetAnalyzer* ruleSetAnalyzer = checker.getRuleSetAnalyzer(); |
| 1053 if (ruleSetAnalyzer) | |
| 1054 ruleSetAnalyzer->invalidateElementSubtreeForClassChange(changedClass es[i], element); | |
|
esprehn
2014/01/14 21:32:56
I had envisioned doing this in a single pass, not
esprehn
2014/01/14 21:32:56
You ignore the return value of invalidateElementSu
chrishtr
2014/01/14 23:33:00
Done.
chrishtr
2014/01/14 23:33:00
Done.
| |
| 1055 else if (checker.hasSelectorForClass(changedClasses[i])) | |
| 1053 return true; | 1056 return true; |
| 1054 } | 1057 } |
| 1055 return false; | 1058 return false; |
| 1056 } | 1059 } |
| 1057 | 1060 |
| 1058 template<typename Checker> | 1061 template<typename Checker> |
| 1059 static bool checkSelectorForClassChange(const SpaceSplitString& oldClasses, cons t SpaceSplitString& newClasses, const Checker& checker) | 1062 static bool checkSelectorForClassChange(const SpaceSplitString& oldClasses, cons t SpaceSplitString& newClasses, const Checker& checker, Element* element) |
| 1060 { | 1063 { |
| 1061 if (!oldClasses.size()) | 1064 if (!oldClasses.size()) |
| 1062 return checkSelectorForClassChange(newClasses, checker); | 1065 return checkSelectorForClassChange(newClasses, checker, element); |
| 1063 | 1066 |
| 1064 // Class vectors tend to be very short. This is faster than using a hash tab le. | 1067 // Class vectors tend to be very short. This is faster than using a hash tab le. |
| 1065 BitVector remainingClassBits; | 1068 BitVector remainingClassBits; |
| 1066 remainingClassBits.ensureSize(oldClasses.size()); | 1069 remainingClassBits.ensureSize(oldClasses.size()); |
| 1067 | 1070 |
| 1068 for (unsigned i = 0; i < newClasses.size(); ++i) { | 1071 for (unsigned i = 0; i < newClasses.size(); ++i) { |
| 1069 bool found = false; | 1072 bool found = false; |
| 1070 for (unsigned j = 0; j < oldClasses.size(); ++j) { | 1073 for (unsigned j = 0; j < oldClasses.size(); ++j) { |
| 1071 if (newClasses[i] == oldClasses[j]) { | 1074 if (newClasses[i] == oldClasses[j]) { |
| 1072 // Mark each class that is still in the newClasses so we can ski p doing | 1075 // Mark each class that is still in the newClasses so we can ski p doing |
| 1073 // an n^2 search below when looking for removals. We can't break from | 1076 // an n^2 search below when looking for removals. We can't break from |
| 1074 // this loop early since a class can appear more than once. | 1077 // this loop early since a class can appear more than once. |
| 1075 remainingClassBits.quickSet(j); | 1078 remainingClassBits.quickSet(j); |
| 1076 found = true; | 1079 found = true; |
| 1077 } | 1080 } |
| 1078 } | 1081 } |
| 1079 // Class was added. | 1082 // Class was added. |
| 1080 if (!found && checker.hasSelectorForClass(newClasses[i])) | 1083 |
| 1081 return true; | 1084 if (!found) { |
| 1085 const RuleSetAnalyzer* ruleSetAnalyzer = checker.getRuleSetAnalyzer( ); | |
| 1086 if (ruleSetAnalyzer) | |
|
esprehn
2014/01/14 21:32:56
Combing if and get, if (const RuleSet.... = checke
chrishtr
2014/01/14 23:33:00
Done.
| |
| 1087 ruleSetAnalyzer->invalidateElementSubtreeForClassChange(newClass es[i], element); | |
| 1088 else if (checker.hasSelectorForClass(newClasses[i])) | |
| 1089 return true; | |
| 1090 } | |
| 1082 } | 1091 } |
| 1083 | 1092 |
| 1084 for (unsigned i = 0; i < oldClasses.size(); ++i) { | 1093 for (unsigned i = 0; i < oldClasses.size(); ++i) { |
| 1085 if (remainingClassBits.quickGet(i)) | 1094 if (remainingClassBits.quickGet(i)) |
| 1086 continue; | 1095 continue; |
| 1096 | |
| 1087 // Class was removed. | 1097 // Class was removed. |
| 1088 if (checker.hasSelectorForClass(oldClasses[i])) | 1098 const RuleSetAnalyzer* ruleSetAnalyzer = checker.getRuleSetAnalyzer(); |
| 1099 if (ruleSetAnalyzer) | |
| 1100 ruleSetAnalyzer->invalidateElementSubtreeForClassChange(oldClasses[i ], element); | |
| 1101 else if (checker.hasSelectorForClass(oldClasses[i])) | |
| 1089 return true; | 1102 return true; |
| 1090 } | 1103 } |
| 1091 | 1104 |
| 1092 return false; | 1105 return false; |
| 1093 } | 1106 } |
| 1094 | 1107 |
| 1095 void Element::classAttributeChanged(const AtomicString& newClassString) | 1108 void Element::classAttributeChanged(const AtomicString& newClassString) |
| 1096 { | 1109 { |
| 1097 StyleResolver* styleResolver = document().styleResolver(); | 1110 StyleResolver* styleResolver = document().styleResolver(); |
| 1098 bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styl eChangeType() < SubtreeStyleChange; | 1111 bool testShouldInvalidateStyle = inActiveDocument() && styleResolver && styl eChangeType() < SubtreeStyleChange; |
| 1099 bool shouldInvalidateStyle = false; | 1112 bool shouldInvalidateStyle = false; |
| 1100 | 1113 |
| 1101 if (classStringHasClassName(newClassString)) { | 1114 if (classStringHasClassName(newClassString)) { |
| 1102 const bool shouldFoldCase = document().inQuirksMode(); | 1115 const bool shouldFoldCase = document().inQuirksMode(); |
| 1103 const SpaceSplitString oldClasses = ensureUniqueElementData()->className s(); | 1116 const SpaceSplitString oldClasses = ensureUniqueElementData()->className s(); |
| 1104 elementData()->setClass(newClassString, shouldFoldCase); | 1117 elementData()->setClass(newClassString, shouldFoldCase); |
| 1105 const SpaceSplitString& newClasses = elementData()->classNames(); | 1118 const SpaceSplitString& newClasses = elementData()->classNames(); |
| 1106 shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForCla ssChange(oldClasses, newClasses, styleResolver->ensureRuleFeatureSet()); | 1119 shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForCla ssChange(oldClasses, newClasses, styleResolver->ensureRuleFeatureSet(), this); |
| 1107 } else if (elementData()) { | 1120 } else if (elementData()) { |
| 1108 const SpaceSplitString& oldClasses = elementData()->classNames(); | 1121 const SpaceSplitString& oldClasses = elementData()->classNames(); |
| 1109 shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForCla ssChange(oldClasses, styleResolver->ensureRuleFeatureSet()); | 1122 shouldInvalidateStyle = testShouldInvalidateStyle && checkSelectorForCla ssChange(oldClasses, styleResolver->ensureRuleFeatureSet(), this); |
| 1110 elementData()->clearClass(); | 1123 elementData()->clearClass(); |
| 1111 } | 1124 } |
| 1112 | 1125 |
| 1113 if (hasRareData()) | 1126 if (hasRareData()) |
| 1114 elementRareData()->clearClassListValueForQuirksMode(); | 1127 elementRareData()->clearClassListValueForQuirksMode(); |
| 1115 | 1128 |
| 1116 if (shouldInvalidateStyle) | 1129 if (shouldInvalidateStyle) |
| 1117 setNeedsStyleRecalc(); | 1130 setNeedsStyleRecalc(); |
| 1118 } | 1131 } |
| 1119 | 1132 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1132 return true; | 1145 return true; |
| 1133 } | 1146 } |
| 1134 } | 1147 } |
| 1135 | 1148 |
| 1136 if (name == HTMLNames::classAttr) { | 1149 if (name == HTMLNames::classAttr) { |
| 1137 const AtomicString& newClassString = newValue; | 1150 const AtomicString& newClassString = newValue; |
| 1138 if (classStringHasClassName(newClassString)) { | 1151 if (classStringHasClassName(newClassString)) { |
| 1139 const bool shouldFoldCase = document().inQuirksMode(); | 1152 const bool shouldFoldCase = document().inQuirksMode(); |
| 1140 const SpaceSplitString& oldClasses = elementData()->classNames(); | 1153 const SpaceSplitString& oldClasses = elementData()->classNames(); |
| 1141 const SpaceSplitString newClasses(newClassString, shouldFoldCase); | 1154 const SpaceSplitString newClasses(newClassString, shouldFoldCase); |
| 1142 if (checkSelectorForClassChange(oldClasses, newClasses, featureSet)) | 1155 if (checkSelectorForClassChange(oldClasses, newClasses, featureSet, this)) |
| 1143 return true; | 1156 return true; |
| 1144 } else { | 1157 } else { |
| 1145 const SpaceSplitString& oldClasses = elementData()->classNames(); | 1158 const SpaceSplitString& oldClasses = elementData()->classNames(); |
| 1146 if (checkSelectorForClassChange(oldClasses, featureSet)) | 1159 if (checkSelectorForClassChange(oldClasses, featureSet, this)) |
|
esprehn
2014/01/14 21:32:56
These should be methods now, don't pass |this|, ju
chrishtr
2014/01/14 23:33:00
Done.
| |
| 1147 return true; | 1160 return true; |
| 1148 } | 1161 } |
| 1149 } | 1162 } |
| 1150 | 1163 |
| 1151 return featureSet.hasSelectorForAttribute(name.localName()); | 1164 return featureSet.hasSelectorForAttribute(name.localName()); |
| 1152 } | 1165 } |
| 1153 | 1166 |
| 1154 // Returns true is the given attribute is an event handler. | 1167 // Returns true is the given attribute is an event handler. |
| 1155 // We consider an event handler any attribute that begins with "on". | 1168 // We consider an event handler any attribute that begins with "on". |
| 1156 // It is a simple solution that has the advantage of not requiring any | 1169 // It is a simple solution that has the advantage of not requiring any |
| (...skipping 2480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3637 // Before doing so, we need to resolve issues in HTMLSelectElement::recalcLi stItems | 3650 // Before doing so, we need to resolve issues in HTMLSelectElement::recalcLi stItems |
| 3638 // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cg i?id=88405 | 3651 // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cg i?id=88405 |
| 3639 if (hasTagName(optionTag) || hasTagName(optgroupTag)) | 3652 if (hasTagName(optionTag) || hasTagName(optgroupTag)) |
| 3640 return false; | 3653 return false; |
| 3641 if (FullscreenElementStack::isActiveFullScreenElement(this)) | 3654 if (FullscreenElementStack::isActiveFullScreenElement(this)) |
| 3642 return false; | 3655 return false; |
| 3643 return true; | 3656 return true; |
| 3644 } | 3657 } |
| 3645 | 3658 |
| 3646 } // namespace WebCore | 3659 } // namespace WebCore |
| OLD | NEW |