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, 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 m_cssRuleList = StaticCSSRuleList::create(); | 97 m_cssRuleList = StaticCSSRuleList::create(); |
98 return m_cssRuleList.get(); | 98 return m_cssRuleList.get(); |
99 } | 99 } |
100 | 100 |
101 void ElementRuleCollector::addElementStyleProperties(const StylePropertySet* pro
pertySet, bool isCacheable) | 101 void ElementRuleCollector::addElementStyleProperties(const StylePropertySet* pro
pertySet, bool isCacheable) |
102 { | 102 { |
103 if (!propertySet) | 103 if (!propertySet) |
104 return; | 104 return; |
105 m_result.addMatchedProperties(propertySet); | 105 m_result.addMatchedProperties(propertySet); |
106 if (!isCacheable) | 106 if (!isCacheable) |
107 m_result.isCacheable = false; | 107 m_result.setIsCacheable(false); |
108 } | 108 } |
109 | 109 |
110 static bool rulesApplicableInCurrentTreeScope(const Element* element, const Cont
ainerNode* scopingNode, bool matchingTreeBoundaryRules) | 110 static bool rulesApplicableInCurrentTreeScope(const Element* element, const Cont
ainerNode* scopingNode, bool matchingTreeBoundaryRules) |
111 { | 111 { |
112 // [skipped, because already checked] a) it's a UA rule | 112 // [skipped, because already checked] a) it's a UA rule |
113 // b) We're mathcing tree boundary rules. | 113 // b) We're mathcing tree boundary rules. |
114 if (matchingTreeBoundaryRules) | 114 if (matchingTreeBoundaryRules) |
115 return true; | 115 return true; |
116 // c) the rules comes from a scoped style sheet within the same tree scope | 116 // c) the rules comes from a scoped style sheet within the same tree scope |
117 if (!scopingNode || element->treeScope() == scopingNode->treeScope()) | 117 if (!scopingNode || element->treeScope() == scopingNode->treeScope()) |
118 return true; | 118 return true; |
119 // d) the rules comes from a scoped style sheet within an active shadow root
whose host is the given element | 119 // d) the rules comes from a scoped style sheet within an active shadow root
whose host is the given element |
120 if (element == scopingNode->shadowHost()) | 120 if (element == scopingNode->shadowHost()) |
121 return true; | 121 return true; |
122 return false; | 122 return false; |
123 } | 123 } |
124 | 124 |
125 template<typename RuleDataListType> | 125 template<typename RuleDataListType> |
126 void ElementRuleCollector::collectMatchingRulesForList(const RuleDataListType* r
ules, CascadeOrder cascadeOrder, const MatchRequest& matchRequest) | 126 void ElementRuleCollector::collectMatchingRulesForList(const RuleDataListType* r
ules, const MatchRequest& matchRequest) |
127 { | 127 { |
128 if (!rules) | 128 if (!rules) |
129 return; | 129 return; |
130 | 130 |
131 SelectorChecker checker(m_mode); | 131 SelectorChecker checker(m_mode); |
132 SelectorChecker::SelectorCheckingContext checkerContext(m_context.element(),
SelectorChecker::VisitedMatchEnabled); | 132 SelectorChecker::SelectorCheckingContext checkerContext(m_context.element(),
SelectorChecker::VisitedMatchEnabled); |
133 checkerContext.elementStyle = m_style.get(); | 133 checkerContext.elementStyle = m_style.get(); |
134 checkerContext.scope = matchRequest.scope; | 134 checkerContext.scope = matchRequest.scope; |
135 checkerContext.pseudoId = m_pseudoStyleRequest.pseudoId; | 135 checkerContext.pseudoId = m_pseudoStyleRequest.pseudoId; |
136 checkerContext.scrollbar = m_pseudoStyleRequest.scrollbar; | 136 checkerContext.scrollbar = m_pseudoStyleRequest.scrollbar; |
(...skipping 27 matching lines...) Expand all Loading... |
164 if (!checker.match(checkerContext, result)) { | 164 if (!checker.match(checkerContext, result)) { |
165 rejected++; | 165 rejected++; |
166 continue; | 166 continue; |
167 } | 167 } |
168 if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.ps
eudoId != result.dynamicPseudo) { | 168 if (m_pseudoStyleRequest.pseudoId != NOPSEUDO && m_pseudoStyleRequest.ps
eudoId != result.dynamicPseudo) { |
169 rejected++; | 169 rejected++; |
170 continue; | 170 continue; |
171 } | 171 } |
172 | 172 |
173 matched++; | 173 matched++; |
174 didMatchRule(ruleData, result, cascadeOrder, matchRequest); | 174 didMatchRule(ruleData, result, matchRequest); |
175 } | 175 } |
176 | 176 |
177 if (StyleResolver* resolver = m_context.element()->document().styleResolver(
)) { | 177 if (StyleResolver* resolver = m_context.element()->document().styleResolver(
)) { |
178 INCREMENT_STYLE_STATS_COUNTER(*resolver, rulesRejected, rejected); | 178 INCREMENT_STYLE_STATS_COUNTER(*resolver, rulesRejected, rejected); |
179 INCREMENT_STYLE_STATS_COUNTER(*resolver, rulesFastRejected, fastRejected
); | 179 INCREMENT_STYLE_STATS_COUNTER(*resolver, rulesFastRejected, fastRejected
); |
180 INCREMENT_STYLE_STATS_COUNTER(*resolver, rulesMatched, matched); | 180 INCREMENT_STYLE_STATS_COUNTER(*resolver, rulesMatched, matched); |
181 } | 181 } |
182 } | 182 } |
183 | 183 |
184 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest
, CascadeOrder cascadeOrder, bool matchingTreeBoundaryRules) | 184 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest
, bool matchingTreeBoundaryRules) |
185 { | 185 { |
186 ASSERT(matchRequest.ruleSet); | 186 ASSERT(matchRequest.ruleSet); |
187 ASSERT(m_context.element()); | 187 ASSERT(m_context.element()); |
188 | 188 |
189 Element& element = *m_context.element(); | 189 Element& element = *m_context.element(); |
190 const AtomicString& pseudoId = element.shadowPseudoId(); | 190 const AtomicString& pseudoId = element.shadowPseudoId(); |
191 if (!pseudoId.isEmpty()) { | 191 if (!pseudoId.isEmpty()) { |
192 ASSERT(element.isStyledElement()); | 192 ASSERT(element.isStyledElement()); |
193 collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRul
es(pseudoId), cascadeOrder, matchRequest); | 193 collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRul
es(pseudoId), matchRequest); |
194 } | 194 } |
195 | 195 |
196 if (element.isVTTElement()) | 196 if (element.isVTTElement()) |
197 collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), casc
adeOrder, matchRequest); | 197 collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matc
hRequest); |
198 // Check whether other types of rules are applicable in the current tree sco
pe. Criteria for this: | 198 // Check whether other types of rules are applicable in the current tree sco
pe. Criteria for this: |
199 // a) it's a UA rule | 199 // a) it's a UA rule |
200 // b) the rules comes from a scoped style sheet within the same tree scope | 200 // b) the rules comes from a scoped style sheet within the same tree scope |
201 // c) the rules comes from a scoped style sheet within an active shadow root
whose host is the given element | 201 // c) the rules comes from a scoped style sheet within an active shadow root
whose host is the given element |
202 // d) the rules can cross boundaries | 202 // d) the rules can cross boundaries |
203 // b)-e) is checked in rulesApplicableInCurrentTreeScope. | 203 // b)-e) is checked in rulesApplicableInCurrentTreeScope. |
204 if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, match
Request.scope, matchingTreeBoundaryRules)) | 204 if (!m_matchingUARules && !rulesApplicableInCurrentTreeScope(&element, match
Request.scope, matchingTreeBoundaryRules)) |
205 return; | 205 return; |
206 | 206 |
207 // We need to collect the rules for id, class, tag, and everything else into
a buffer and | 207 // We need to collect the rules for id, class, tag, and everything else into
a buffer and |
208 // then sort the buffer. | 208 // then sort the buffer. |
209 if (element.hasID()) | 209 if (element.hasID()) |
210 collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForS
tyleResolution()), cascadeOrder, matchRequest); | 210 collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForS
tyleResolution()), matchRequest); |
211 if (element.isStyledElement() && element.hasClass()) { | 211 if (element.isStyledElement() && element.hasClass()) { |
212 for (size_t i = 0; i < element.classNames().size(); ++i) | 212 for (size_t i = 0; i < element.classNames().size(); ++i) |
213 collectMatchingRulesForList(matchRequest.ruleSet->classRules(element
.classNames()[i]), cascadeOrder, matchRequest); | 213 collectMatchingRulesForList(matchRequest.ruleSet->classRules(element
.classNames()[i]), matchRequest); |
214 } | 214 } |
215 | 215 |
216 if (element.isLink()) | 216 if (element.isLink()) |
217 collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules()
, cascadeOrder, matchRequest); | 217 collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules()
, matchRequest); |
218 if (SelectorChecker::matchesFocusPseudoClass(element)) | 218 if (SelectorChecker::matchesFocusPseudoClass(element)) |
219 collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(
), cascadeOrder, matchRequest); | 219 collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(
), matchRequest); |
220 collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName
ForSelectorMatching()), cascadeOrder, matchRequest); | 220 collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName
ForSelectorMatching()), matchRequest); |
221 collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), cascadeO
rder, matchRequest); | 221 collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchReq
uest); |
222 } | 222 } |
223 | 223 |
224 void ElementRuleCollector::collectMatchingShadowHostRules(const MatchRequest& ma
tchRequest, CascadeOrder cascadeOrder, bool matchingTreeBoundaryRules) | 224 void ElementRuleCollector::collectMatchingShadowHostRules(const MatchRequest& ma
tchRequest, bool matchingTreeBoundaryRules) |
225 { | 225 { |
226 collectMatchingRulesForList(matchRequest.ruleSet->shadowHostRules(), cascade
Order, matchRequest); | 226 collectMatchingRulesForList(matchRequest.ruleSet->shadowHostRules(), matchRe
quest); |
227 } | 227 } |
228 | 228 |
229 template<class CSSRuleCollection> | 229 template<class CSSRuleCollection> |
230 CSSRule* ElementRuleCollector::findStyleRule(CSSRuleCollection* cssRules, StyleR
ule* styleRule) | 230 CSSRule* ElementRuleCollector::findStyleRule(CSSRuleCollection* cssRules, StyleR
ule* styleRule) |
231 { | 231 { |
232 if (!cssRules) | 232 if (!cssRules) |
233 return 0; | 233 return 0; |
234 CSSRule* result = 0; | 234 CSSRule* result = 0; |
235 for (unsigned i = 0; i < cssRules->length() && !result; ++i) { | 235 for (unsigned i = 0; i < cssRules->length() && !result; ++i) { |
236 CSSRule* cssRule = cssRules->item(i); | 236 CSSRule* cssRule = cssRules->item(i); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 appendCSSOMWrapperForRule(const_cast<CSSStyleSheet*>(m_matchedRules[
i].parentStyleSheet()), m_matchedRules[i].ruleData()->rule()); | 281 appendCSSOMWrapperForRule(const_cast<CSSStyleSheet*>(m_matchedRules[
i].parentStyleSheet()), m_matchedRules[i].ruleData()->rule()); |
282 return; | 282 return; |
283 } | 283 } |
284 | 284 |
285 // Now transfer the set of matched rules over to our list of declarations. | 285 // Now transfer the set of matched rules over to our list of declarations. |
286 for (unsigned i = 0; i < m_matchedRules.size(); i++) { | 286 for (unsigned i = 0; i < m_matchedRules.size(); i++) { |
287 const RuleData* ruleData = m_matchedRules[i].ruleData(); | 287 const RuleData* ruleData = m_matchedRules[i].ruleData(); |
288 m_result.addMatchedProperties(&ruleData->rule()->properties(), ruleData-
>linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules)); | 288 m_result.addMatchedProperties(&ruleData->rule()->properties(), ruleData-
>linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules)); |
289 } | 289 } |
290 | 290 |
291 if (m_matchingUARules) | 291 m_result.closeOriginOrScope(m_matchingUARules); |
292 m_result.uaEnd = m_result.matchedProperties.size(); | |
293 } | 292 } |
294 | 293 |
295 void ElementRuleCollector::didMatchRule(const RuleData& ruleData, const Selector
Checker::MatchResult& result, CascadeOrder cascadeOrder, const MatchRequest& mat
chRequest) | 294 void ElementRuleCollector::didMatchRule(const RuleData& ruleData, const Selector
Checker::MatchResult& result, const MatchRequest& matchRequest) |
296 { | 295 { |
297 PseudoId dynamicPseudo = result.dynamicPseudo; | 296 PseudoId dynamicPseudo = result.dynamicPseudo; |
298 // If we're matching normal rules, set a pseudo bit if | 297 // If we're matching normal rules, set a pseudo bit if |
299 // we really just matched a pseudo-element. | 298 // we really just matched a pseudo-element. |
300 if (dynamicPseudo != NOPSEUDO && m_pseudoStyleRequest.pseudoId == NOPSEUDO)
{ | 299 if (dynamicPseudo != NOPSEUDO && m_pseudoStyleRequest.pseudoId == NOPSEUDO)
{ |
301 if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorC
hecker::CollectingStyleRules) | 300 if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorC
hecker::CollectingStyleRules) |
302 return; | 301 return; |
303 // FIXME: Matching should not modify the style directly. | 302 // FIXME: Matching should not modify the style directly. |
304 if (!m_style || dynamicPseudo >= FIRST_INTERNAL_PSEUDOID) | 303 if (!m_style || dynamicPseudo >= FIRST_INTERNAL_PSEUDOID) |
305 return; | 304 return; |
306 if ((dynamicPseudo == BEFORE || dynamicPseudo == AFTER) && !ruleData.rul
e()->properties().hasProperty(CSSPropertyContent)) | 305 if ((dynamicPseudo == BEFORE || dynamicPseudo == AFTER) && !ruleData.rul
e()->properties().hasProperty(CSSPropertyContent)) |
307 return; | 306 return; |
308 m_style->setHasPseudoStyle(dynamicPseudo); | 307 m_style->setHasPseudoStyle(dynamicPseudo); |
309 } else { | 308 } else { |
310 if (m_style && ruleData.containsUncommonAttributeSelector()) | 309 if (m_style && ruleData.containsUncommonAttributeSelector()) |
311 m_style->setUnique(); | 310 m_style->setUnique(); |
312 | 311 |
313 m_matchedRules.append(MatchedRule(&ruleData, result.specificity, cascade
Order, matchRequest.styleSheetIndex, matchRequest.styleSheet)); | 312 m_matchedRules.append(MatchedRule(&ruleData, result.specificity, matchRe
quest.styleSheetIndex, matchRequest.styleSheet)); |
314 } | 313 } |
315 } | 314 } |
316 | 315 |
317 static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRu
le& matchedRule2) | 316 static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRu
le& matchedRule2) |
318 { | 317 { |
319 unsigned specificity1 = matchedRule1.specificity(); | 318 unsigned specificity1 = matchedRule1.specificity(); |
320 unsigned specificity2 = matchedRule2.specificity(); | 319 unsigned specificity2 = matchedRule2.specificity(); |
321 if (specificity1 != specificity2) | 320 if (specificity1 != specificity2) |
322 return specificity1 < specificity2; | 321 return specificity1 < specificity2; |
323 | 322 |
(...skipping 14 matching lines...) Expand all Loading... |
338 // should not see the element's treescope. Because RuleSet has no | 337 // should not see the element's treescope. Because RuleSet has no |
339 // information about "scope". | 338 // information about "scope". |
340 MatchRequest matchRequest(ruleSet); | 339 MatchRequest matchRequest(ruleSet); |
341 collectMatchingRules(matchRequest); | 340 collectMatchingRules(matchRequest); |
342 collectMatchingShadowHostRules(matchRequest); | 341 collectMatchingShadowHostRules(matchRequest); |
343 | 342 |
344 return !m_matchedRules.isEmpty(); | 343 return !m_matchedRules.isEmpty(); |
345 } | 344 } |
346 | 345 |
347 } // namespace blink | 346 } // namespace blink |
OLD | NEW |