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

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

Issue 1155393002: Refactor matched rule ranges. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 7 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
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, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 , m_canUseFastReject(m_selectorFilter.parentStackIsConsistent(context.parent Node())) 54 , m_canUseFastReject(m_selectorFilter.parentStackIsConsistent(context.parent Node()))
55 , m_sameOriginOnly(false) 55 , m_sameOriginOnly(false)
56 , m_matchingUARules(false) 56 , m_matchingUARules(false)
57 , m_scopeContainsLastMatchedElement(false) 57 , m_scopeContainsLastMatchedElement(false)
58 { } 58 { }
59 59
60 ElementRuleCollector::~ElementRuleCollector() 60 ElementRuleCollector::~ElementRuleCollector()
61 { 61 {
62 } 62 }
63 63
64 MatchResult& ElementRuleCollector::matchedResult() 64 const MatchResult& ElementRuleCollector::matchedResult()
65 { 65 {
66 return m_result; 66 return m_result;
67 } 67 }
68 68
69 PassRefPtrWillBeRawPtr<StyleRuleList> ElementRuleCollector::matchedStyleRuleList () 69 PassRefPtrWillBeRawPtr<StyleRuleList> ElementRuleCollector::matchedStyleRuleList ()
70 { 70 {
71 ASSERT(m_mode == SelectorChecker::CollectingStyleRules); 71 ASSERT(m_mode == SelectorChecker::CollectingStyleRules);
72 return m_styleRuleList.release(); 72 return m_styleRuleList.release();
73 } 73 }
74 74
(...skipping 19 matching lines...) Expand all
94 { 94 {
95 if (!m_cssRuleList) 95 if (!m_cssRuleList)
96 m_cssRuleList = StaticCSSRuleList::create(); 96 m_cssRuleList = StaticCSSRuleList::create();
97 return m_cssRuleList.get(); 97 return m_cssRuleList.get();
98 } 98 }
99 99
100 void ElementRuleCollector::addElementStyleProperties(const StylePropertySet* pro pertySet, bool isCacheable) 100 void ElementRuleCollector::addElementStyleProperties(const StylePropertySet* pro pertySet, bool isCacheable)
101 { 101 {
102 if (!propertySet) 102 if (!propertySet)
103 return; 103 return;
104 m_result.ranges.lastAuthorRule = m_result.matchedProperties.size();
105 if (m_result.ranges.firstAuthorRule == -1)
106 m_result.ranges.firstAuthorRule = m_result.ranges.lastAuthorRule;
107 m_result.addMatchedProperties(propertySet); 104 m_result.addMatchedProperties(propertySet);
108 if (!isCacheable) 105 if (!isCacheable)
109 m_result.isCacheable = false; 106 m_result.isCacheable = false;
110 } 107 }
111 108
112 static bool rulesApplicableInCurrentTreeScope(const Element* element, const Cont ainerNode* scopingNode, bool matchingTreeBoundaryRules) 109 static bool rulesApplicableInCurrentTreeScope(const Element* element, const Cont ainerNode* scopingNode, bool matchingTreeBoundaryRules)
113 { 110 {
114 // [skipped, because already checked] a) it's a UA rule 111 // [skipped, because already checked] a) it's a UA rule
115 // b) We're mathcing tree boundary rules. 112 // b) We're mathcing tree boundary rules.
116 if (matchingTreeBoundaryRules) 113 if (matchingTreeBoundaryRules)
117 return true; 114 return true;
118 // c) the rules comes from a scoped style sheet within the same tree scope 115 // c) the rules comes from a scoped style sheet within the same tree scope
119 if (!scopingNode || element->treeScope() == scopingNode->treeScope()) 116 if (!scopingNode || element->treeScope() == scopingNode->treeScope())
120 return true; 117 return true;
121 // d) the rules comes from a scoped style sheet within an active shadow root whose host is the given element 118 // d) the rules comes from a scoped style sheet within an active shadow root whose host is the given element
122 if (element == scopingNode->shadowHost()) 119 if (element == scopingNode->shadowHost())
123 return true; 120 return true;
124 return false; 121 return false;
125 } 122 }
126 123
127 template<typename RuleDataListType> 124 template<typename RuleDataListType>
128 void ElementRuleCollector::collectMatchingRulesForList(const RuleDataListType* r ules, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ru leRange) 125 void ElementRuleCollector::collectMatchingRulesForList(const RuleDataListType* r ules, CascadeOrder cascadeOrder, const MatchRequest& matchRequest)
129 { 126 {
130 if (!rules) 127 if (!rules)
131 return; 128 return;
132 129
133 SelectorChecker checker(m_mode); 130 SelectorChecker checker(m_mode);
134 SelectorChecker::SelectorCheckingContext checkerContext(m_context.element(), SelectorChecker::VisitedMatchEnabled); 131 SelectorChecker::SelectorCheckingContext checkerContext(m_context.element(), SelectorChecker::VisitedMatchEnabled);
135 checkerContext.elementStyle = m_style.get(); 132 checkerContext.elementStyle = m_style.get();
136 checkerContext.scope = matchRequest.scope; 133 checkerContext.scope = matchRequest.scope;
137 checkerContext.pseudoId = m_pseudoStyleRequest.pseudoId; 134 checkerContext.pseudoId = m_pseudoStyleRequest.pseudoId;
138 checkerContext.scrollbar = m_pseudoStyleRequest.scrollbar; 135 checkerContext.scrollbar = m_pseudoStyleRequest.scrollbar;
(...skipping 16 matching lines...) Expand all
155 if (properties.isEmpty() && !matchRequest.includeEmptyRules) 152 if (properties.isEmpty() && !matchRequest.includeEmptyRules)
156 continue; 153 continue;
157 154
158 SelectorChecker::MatchResult result; 155 SelectorChecker::MatchResult result;
159 checkerContext.selector = &ruleData.selector(); 156 checkerContext.selector = &ruleData.selector();
160 if (!checker.match(checkerContext, result)) 157 if (!checker.match(checkerContext, result))
161 continue; 158 continue;
162 if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.ps eudoId != result.dynamicPseudo) 159 if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.ps eudoId != result.dynamicPseudo)
163 continue; 160 continue;
164 161
165 didMatchRule(ruleData, result, cascadeOrder, matchRequest, ruleRange); 162 didMatchRule(ruleData, result, cascadeOrder, matchRequest);
166 } 163 }
167 } 164 }
168 165
169 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest , RuleRange& ruleRange, CascadeOrder cascadeOrder, bool matchingTreeBoundaryRule s) 166 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest , CascadeOrder cascadeOrder, bool matchingTreeBoundaryRules)
170 { 167 {
171 ASSERT(matchRequest.ruleSet); 168 ASSERT(matchRequest.ruleSet);
172 ASSERT(m_context.element()); 169 ASSERT(m_context.element());
173 170
174 Element& element = *m_context.element(); 171 Element& element = *m_context.element();
175 const AtomicString& pseudoId = element.shadowPseudoId(); 172 const AtomicString& pseudoId = element.shadowPseudoId();
176 if (!pseudoId.isEmpty()) { 173 if (!pseudoId.isEmpty()) {
177 ASSERT(element.isStyledElement()); 174 ASSERT(element.isStyledElement());
178 collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRul es(pseudoId), cascadeOrder, matchRequest, ruleRange); 175 collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRul es(pseudoId), cascadeOrder, matchRequest);
179 } 176 }
180 177
181 if (element.isVTTElement()) 178 if (element.isVTTElement())
182 collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), casc adeOrder, matchRequest, ruleRange); 179 collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), casc adeOrder, matchRequest);
183 // Check whether other types of rules are applicable in the current tree sco pe. Criteria for this: 180 // Check whether other types of rules are applicable in the current tree sco pe. Criteria for this:
184 // a) it's a UA rule 181 // a) it's a UA rule
185 // b) the rules comes from a scoped style sheet within the same tree scope 182 // b) the rules comes from a scoped style sheet within the same tree scope
186 // c) the rules comes from a scoped style sheet within an active shadow root whose host is the given element 183 // c) the rules comes from a scoped style sheet within an active shadow root whose host is the given element
187 // d) the rules can cross boundaries 184 // d) the rules can cross boundaries
188 // b)-e) is checked in rulesApplicableInCurrentTreeScope. 185 // b)-e) is checked in rulesApplicableInCurrentTreeScope.
189 if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, match Request.scope, matchingTreeBoundaryRules)) 186 if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, match Request.scope, matchingTreeBoundaryRules))
190 return; 187 return;
191 188
192 // We need to collect the rules for id, class, tag, and everything else into a buffer and 189 // We need to collect the rules for id, class, tag, and everything else into a buffer and
193 // then sort the buffer. 190 // then sort the buffer.
194 if (element.hasID()) 191 if (element.hasID())
195 collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForS tyleResolution()), cascadeOrder, matchRequest, ruleRange); 192 collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForS tyleResolution()), cascadeOrder, matchRequest);
196 if (element.isStyledElement() && element.hasClass()) { 193 if (element.isStyledElement() && element.hasClass()) {
197 for (size_t i = 0; i < element.classNames().size(); ++i) 194 for (size_t i = 0; i < element.classNames().size(); ++i)
198 collectMatchingRulesForList(matchRequest.ruleSet->classRules(element .classNames()[i]), cascadeOrder, matchRequest, ruleRange); 195 collectMatchingRulesForList(matchRequest.ruleSet->classRules(element .classNames()[i]), cascadeOrder, matchRequest);
199 } 196 }
200 197
201 if (element.isLink()) 198 if (element.isLink())
202 collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules() , cascadeOrder, matchRequest, ruleRange); 199 collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules() , cascadeOrder, matchRequest);
203 if (SelectorChecker::matchesFocusPseudoClass(element)) 200 if (SelectorChecker::matchesFocusPseudoClass(element))
204 collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules( ), cascadeOrder, matchRequest, ruleRange); 201 collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules( ), cascadeOrder, matchRequest);
205 collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName ForSelectorMatching()), cascadeOrder, matchRequest, ruleRange); 202 collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName ForSelectorMatching()), cascadeOrder, matchRequest);
206 collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), cascadeO rder, matchRequest, ruleRange); 203 collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), cascadeO rder, matchRequest);
207 } 204 }
208 205
209 void ElementRuleCollector::collectMatchingShadowHostRules(const MatchRequest& ma tchRequest, RuleRange& ruleRange, CascadeOrder cascadeOrder, bool matchingTreeBo undaryRules) 206 void ElementRuleCollector::collectMatchingShadowHostRules(const MatchRequest& ma tchRequest, CascadeOrder cascadeOrder, bool matchingTreeBoundaryRules)
210 { 207 {
211 collectMatchingRulesForList(matchRequest.ruleSet->shadowHostRules(), cascade Order, matchRequest, ruleRange); 208 collectMatchingRulesForList(matchRequest.ruleSet->shadowHostRules(), cascade Order, matchRequest);
212 } 209 }
213 210
214 template<class CSSRuleCollection> 211 template<class CSSRuleCollection>
215 CSSRule* ElementRuleCollector::findStyleRule(CSSRuleCollection* cssRules, StyleR ule* styleRule) 212 CSSRule* ElementRuleCollector::findStyleRule(CSSRuleCollection* cssRules, StyleR ule* styleRule)
216 { 213 {
217 if (!cssRules) 214 if (!cssRules)
218 return 0; 215 return 0;
219 CSSRule* result = 0; 216 CSSRule* result = 0;
220 for (unsigned i = 0; i < cssRules->length() && !result; ++i) { 217 for (unsigned i = 0; i < cssRules->length() && !result; ++i) {
221 CSSRule* cssRule = cssRules->item(i); 218 CSSRule* cssRule = cssRules->item(i);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 for (unsigned i = 0; i < m_matchedRules.size(); ++i) 262 for (unsigned i = 0; i < m_matchedRules.size(); ++i)
266 appendCSSOMWrapperForRule(const_cast<CSSStyleSheet*>(m_matchedRules[ i].parentStyleSheet()), m_matchedRules[i].ruleData()->rule()); 263 appendCSSOMWrapperForRule(const_cast<CSSStyleSheet*>(m_matchedRules[ i].parentStyleSheet()), m_matchedRules[i].ruleData()->rule());
267 return; 264 return;
268 } 265 }
269 266
270 // Now transfer the set of matched rules over to our list of declarations. 267 // Now transfer the set of matched rules over to our list of declarations.
271 for (unsigned i = 0; i < m_matchedRules.size(); i++) { 268 for (unsigned i = 0; i < m_matchedRules.size(); i++) {
272 const RuleData* ruleData = m_matchedRules[i].ruleData(); 269 const RuleData* ruleData = m_matchedRules[i].ruleData();
273 m_result.addMatchedProperties(&ruleData->rule()->properties(), ruleData- >linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules)); 270 m_result.addMatchedProperties(&ruleData->rule()->properties(), ruleData- >linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules));
274 } 271 }
272
273 if (m_matchingUARules)
274 m_result.lastUARuleIndex = m_result.matchedProperties.size() - 1;
275 } 275 }
276 276
277 void ElementRuleCollector::didMatchRule(const RuleData& ruleData, const Selector Checker::MatchResult& result, CascadeOrder cascadeOrder, const MatchRequest& mat chRequest, RuleRange& ruleRange) 277 void ElementRuleCollector::didMatchRule(const RuleData& ruleData, const Selector Checker::MatchResult& result, CascadeOrder cascadeOrder, const MatchRequest& mat chRequest)
278 { 278 {
279 PseudoId dynamicPseudo = result.dynamicPseudo; 279 PseudoId dynamicPseudo = result.dynamicPseudo;
280 // If we're matching normal rules, set a pseudo bit if 280 // If we're matching normal rules, set a pseudo bit if
281 // we really just matched a pseudo-element. 281 // we really just matched a pseudo-element.
282 if (dynamicPseudo != NOPSEUDO && m_pseudoStyleRequest.pseudoId == NOPSEUDO) { 282 if (dynamicPseudo != NOPSEUDO && m_pseudoStyleRequest.pseudoId == NOPSEUDO) {
283 if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorC hecker::CollectingStyleRules) 283 if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorC hecker::CollectingStyleRules)
284 return; 284 return;
285 // FIXME: Matching should not modify the style directly. 285 // FIXME: Matching should not modify the style directly.
286 if (!m_style || dynamicPseudo >= FIRST_INTERNAL_PSEUDOID) 286 if (!m_style || dynamicPseudo >= FIRST_INTERNAL_PSEUDOID)
287 return; 287 return;
288 if ((dynamicPseudo == BEFORE || dynamicPseudo == AFTER) && !ruleData.rul e()->properties().hasProperty(CSSPropertyContent)) 288 if ((dynamicPseudo == BEFORE || dynamicPseudo == AFTER) && !ruleData.rul e()->properties().hasProperty(CSSPropertyContent))
289 return; 289 return;
290 m_style->setHasPseudoStyle(dynamicPseudo); 290 m_style->setHasPseudoStyle(dynamicPseudo);
291 } else { 291 } else {
292 // Update our first/last rule indices in the matched rules array.
293 ++ruleRange.lastRuleIndex;
294 if (ruleRange.firstRuleIndex == -1)
295 ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
296
297 if (m_style && ruleData.containsUncommonAttributeSelector()) 292 if (m_style && ruleData.containsUncommonAttributeSelector())
298 m_style->setUnique(); 293 m_style->setUnique();
299 294
300 m_matchedRules.append(MatchedRule(&ruleData, result.specificity, cascade Order, matchRequest.styleSheetIndex, matchRequest.styleSheet)); 295 m_matchedRules.append(MatchedRule(&ruleData, result.specificity, cascade Order, matchRequest.styleSheetIndex, matchRequest.styleSheet));
301 } 296 }
302 } 297 }
303 298
304 static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRu le& matchedRule2) 299 static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRu le& matchedRule2)
305 { 300 {
306 unsigned specificity1 = matchedRule1.specificity(); 301 unsigned specificity1 = matchedRule1.specificity();
(...skipping 10 matching lines...) Expand all
317 } 312 }
318 313
319 bool ElementRuleCollector::hasAnyMatchingRules(RuleSet* ruleSet) 314 bool ElementRuleCollector::hasAnyMatchingRules(RuleSet* ruleSet)
320 { 315 {
321 clearMatchedRules(); 316 clearMatchedRules();
322 317
323 m_mode = SelectorChecker::SharingRules; 318 m_mode = SelectorChecker::SharingRules;
324 // To check whether a given RuleSet has any rule matching a given element, 319 // To check whether a given RuleSet has any rule matching a given element,
325 // should not see the element's treescope. Because RuleSet has no 320 // should not see the element's treescope. Because RuleSet has no
326 // information about "scope". 321 // information about "scope".
327 int firstRuleIndex = -1, lastRuleIndex = -1;
328 RuleRange ruleRange(firstRuleIndex, lastRuleIndex);
329 MatchRequest matchRequest(ruleSet); 322 MatchRequest matchRequest(ruleSet);
330 collectMatchingRules(matchRequest, ruleRange); 323 collectMatchingRules(matchRequest);
331 collectMatchingShadowHostRules(matchRequest, ruleRange); 324 collectMatchingShadowHostRules(matchRequest);
332 325
333 return !m_matchedRules.isEmpty(); 326 return !m_matchedRules.isEmpty();
334 } 327 }
335 328
336 } // namespace blink 329 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698