Changeset 201073 in webkit
- Timestamp:
- May 18, 2016, 1:41:50 AM (9 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r200697 r201073 1 2016-05-18 Antti Koivisto <antti@apple.com> 2 3 Cascading order for !important properties in ::slotted and ::host rules is incorrect 4 https://bugs.webkit.org/show_bug.cgi?id=157789 5 <rdar://problem/26318781> 6 7 Reviewed by Andreas Kling. 8 9 * csswg-test/css-scoping-1/shadow-cascade-order-001-expected.txt: This now passes. 10 1 11 2016-05-11 Brady Eidson <beidson@apple.com> 2 12 -
trunk/LayoutTests/imported/w3c/csswg-test/css-scoping-1/shadow-cascade-order-001-expected.txt
r200234 r201073 18 18 PASS C5. ::slotted with !important vs inline, ::slotted rule should win for open mode. 19 19 PASS C6. :host with !important vs inline, :host rule should win for open mode. 20 FAIL D1. document vs ::slotted both with !important, ::slotted rule should win for open mode. assert_equals: D1. document vs ::slotted both with !important, ::slotted rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 21 FAIL D2. document vs :host both with !important, :host rule should win for open mode. assert_equals: D2. document vs :host both with !important, :host rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 20 PASS D1. document vs ::slotted both with !important, ::slotted rule should win for open mode. 21 PASS D2. document vs :host both with !important, :host rule should win for open mode. 22 22 PASS D3. document vs inline both with !important, inline rule should win for open mode. 23 FAIL D4. ::slotted vs :host both with !important, later in tree-of-trees rule should win for open mode. assert_equals: D4. ::slotted vs :host both with !important, later in tree-of-trees rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 24 FAIL D5. ::slotted vs inline both with !important, ::slotted rule should win for open mode. assert_equals: D5. ::slotted vs inline both with !important, ::slotted rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 25 FAIL D6. :host vs inline both with !important, :host rule should win for open mode. assert_equals: D6. :host vs inline both with !important, :host rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 23 PASS D4. ::slotted vs :host both with !important, later in tree-of-trees rule should win for open mode. 24 PASS D5. ::slotted vs inline both with !important, ::slotted rule should win for open mode. 25 PASS D6. :host vs inline both with !important, :host rule should win for open mode. 26 26 PASS E1. all style applied, inline rule should win for open mode. 27 FAIL E2. all styles with !important applied, rule in the last tree-of-trees should win for open mode. assert_equals: E2. all styles with !important applied, rule in the last tree-of-trees should win expected "rgb(0, 128, 0)" but got "rgb(255, 255, 0)" 27 PASS E2. all styles with !important applied, rule in the last tree-of-trees should win for open mode. 28 28 PASS A1. document vs ::slotted, document rule should win for closed mode. 29 29 PASS A2. document vs :host, document rule should win for closed mode. … … 44 44 PASS C5. ::slotted with !important vs inline, ::slotted rule should win for closed mode. 45 45 PASS C6. :host with !important vs inline, :host rule should win for closed mode. 46 FAIL D1. document vs ::slotted both with !important, ::slotted rule should win for closed mode. assert_equals: D1. document vs ::slotted both with !important, ::slotted rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 47 FAIL D2. document vs :host both with !important, :host rule should win for closed mode. assert_equals: D2. document vs :host both with !important, :host rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 46 PASS D1. document vs ::slotted both with !important, ::slotted rule should win for closed mode. 47 PASS D2. document vs :host both with !important, :host rule should win for closed mode. 48 48 PASS D3. document vs inline both with !important, inline rule should win for closed mode. 49 FAIL D4. ::slotted vs :host both with !important, later in tree-of-trees rule should win for closed mode. assert_equals: D4. ::slotted vs :host both with !important, later in tree-of-trees rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 50 FAIL D5. ::slotted vs inline both with !important, ::slotted rule should win for closed mode. assert_equals: D5. ::slotted vs inline both with !important, ::slotted rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 51 FAIL D6. :host vs inline both with !important, :host rule should win for closed mode. assert_equals: D6. :host vs inline both with !important, :host rule should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 49 PASS D4. ::slotted vs :host both with !important, later in tree-of-trees rule should win for closed mode. 50 PASS D5. ::slotted vs inline both with !important, ::slotted rule should win for closed mode. 51 PASS D6. :host vs inline both with !important, :host rule should win for closed mode. 52 52 PASS E1. all style applied, inline rule should win for closed mode. 53 FAIL E2. all styles with !important applied, rule in the last tree-of-trees should win for closed mode. assert_equals: E2. all styles with !important applied, rule in the last tree-of-trees should win expected "rgb(0, 128, 0)" but got "rgb(255, 255, 0)" 53 PASS E2. all styles with !important applied, rule in the last tree-of-trees should win for closed mode. 54 54 PASS F1. document vs others, document (the first rule in tree-of-trees order) rule should win for open mode. 55 55 PASS F2. document with !important vs others, document rule should win for open mode. … … 57 57 PASS F4. document vs ::slotted with !important, important rule should win for open mode. 58 58 PASS F5. document vs :host with !important, important rule should win for open mode. 59 FAIL F6. all rules with !important, the last rule in tree-of-trees should win for open mode. assert_equals: F6. all rules with !important, the last rule in tree-of-trees should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 59 PASS F6. all rules with !important, the last rule in tree-of-trees should win for open mode. 60 60 PASS F1. document vs others, document (the first rule in tree-of-trees order) rule should win for closed mode. 61 61 PASS F2. document with !important vs others, document rule should win for closed mode. … … 63 63 PASS F4. document vs ::slotted with !important, important rule should win for closed mode. 64 64 PASS F5. document vs :host with !important, important rule should win for closed mode. 65 FAIL F6. all rules with !important, the last rule in tree-of-trees should win for closed mode. assert_equals: F6. all rules with !important, the last rule in tree-of-trees should win expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" 65 PASS F6. all rules with !important, the last rule in tree-of-trees should win for closed mode. 66 66 -
trunk/Source/WebCore/ChangeLog
r201072 r201073 1 2016-05-17 Antti Koivisto <antti@apple.com> 2 3 Cascading order for !important properties in ::slotted and ::host rules is incorrect 4 https://bugs.webkit.org/show_bug.cgi?id=157789 5 <rdar://problem/26318781> 6 7 Reviewed by Andreas Kling. 8 9 https://drafts.csswg.org/css-scoping-1/#shadow-cascading 10 11 "When comparing two declarations that have different tree contexts, then for normal rules the declaration earlier 12 in the shadow-including tree order wins, and for important rules the declaration coming later in the shadow-including 13 tree order wins." 14 15 * css/ElementRuleCollector.cpp: 16 (WebCore::MatchRequest::MatchRequest): 17 (WebCore::ElementRuleCollector::ElementRuleCollector): 18 (WebCore::ElementRuleCollector::matchedRuleList): 19 (WebCore::ElementRuleCollector::addMatchedRule): 20 (WebCore::ElementRuleCollector::clearMatchedRules): 21 (WebCore::ElementRuleCollector::addElementStyleProperties): 22 (WebCore::ElementRuleCollector::sortAndTransferMatchedRules): 23 24 Pass the tree context ordinal onwards so we can implement the order reversal semantics for !important properties. 25 26 (WebCore::ElementRuleCollector::matchAuthorRules): 27 (WebCore::ElementRuleCollector::matchHostPseudoClassRules): 28 (WebCore::ElementRuleCollector::matchSlottedPseudoElementRules): 29 30 Don't flush the matched rules immediately to get the right ordering. Instead compute tree context ordinal 31 that is then used as a sorting criteria. 32 33 (WebCore::ElementRuleCollector::collectSlottedPseudoElementRulesForSlot): 34 (WebCore::ElementRuleCollector::collectMatchingRulesForList): 35 (WebCore::compareRules): 36 37 Sort regular rules so that earlier shadow trees win. 38 39 (WebCore::ElementRuleCollector::sortMatchedRules): 40 * css/ElementRuleCollector.h: 41 * css/StyleResolver.cpp: 42 (WebCore::StyleResolver::State::clear): 43 (WebCore::StyleResolver::MatchResult::addMatchedProperties): 44 (WebCore::StyleResolver::CascadedProperties::addMatch): Added. 45 46 Add a helper. 47 48 (WebCore::StyleResolver::CascadedProperties::addNormalMatches): 49 50 Split normal and important to different functions for clarity. 51 52 (WebCore::StyleResolver::CascadedProperties::addImportantMatches): 53 54 For !important properties a later shadow tree wins. Do multiple passes to apply in correct order if needed. 55 56 * css/StyleResolver.h: 57 (WebCore::StyleResolver::MatchResult::matchedProperties): 58 1 59 2016-05-18 Joanmarie Diggs <jdiggs@igalia.com> 2 60 -
trunk/Source/WebCore/css/ElementRuleCollector.cpp
r199844 r201073 70 70 class MatchRequest { 71 71 public: 72 MatchRequest(const RuleSet* ruleSet, bool includeEmptyRules = false )72 MatchRequest(const RuleSet* ruleSet, bool includeEmptyRules = false, unsigned treeContextOrdinal = 0) 73 73 : ruleSet(ruleSet) 74 74 , includeEmptyRules(includeEmptyRules) 75 , treeContextOrdinal(treeContextOrdinal) 75 76 { 76 77 } 77 78 const RuleSet* ruleSet; 78 79 const bool includeEmptyRules; 80 unsigned treeContextOrdinal; 79 81 }; 80 82 … … 108 110 } 109 111 110 inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, StyleResolver::RuleRange& ruleRange)112 inline void ElementRuleCollector::addMatchedRule(const RuleData& ruleData, unsigned specificity, unsigned treeContextOrdinal, StyleResolver::RuleRange& ruleRange) 111 113 { 112 114 // Update our first/last rule indices in the matched rules array. … … 115 117 ruleRange.firstRuleIndex = ruleRange.lastRuleIndex; 116 118 117 m_matchedRules.append({ &ruleData, specificity });119 m_matchedRules.append({ &ruleData, specificity, treeContextOrdinal }); 118 120 } 119 121 … … 121 123 { 122 124 m_matchedRules.clear(); 125 #if ENABLE(SHADOW_DOM) 126 m_keepAliveSlottedPseudoElementRules.clear(); 127 #endif 128 123 129 } 124 130 … … 200 206 201 207 for (const MatchedRule& matchedRule : m_matchedRules) { 202 m_result.addMatchedProperties(matchedRule.ruleData->rule()->properties(), matchedRule.ruleData->rule(), matchedRule.ruleData->linkMatchType(), matchedRule.ruleData->propertyWhitelistType() );208 m_result.addMatchedProperties(matchedRule.ruleData->rule()->properties(), matchedRule.ruleData->rule(), matchedRule.ruleData->linkMatchType(), matchedRule.ruleData->propertyWhitelistType(), matchedRule.treeContextOrdinal); 203 209 } 204 210 } … … 206 212 void ElementRuleCollector::matchAuthorRules(bool includeEmptyRules) 207 213 { 208 #if ENABLE(SHADOW_DOM)209 if (m_element.shadowRoot())210 matchHostPseudoClassRules(includeEmptyRules);211 212 auto* parent = m_element.parentNode();213 if (parent && parent->shadowRoot())214 matchSlottedPseudoElementRules(includeEmptyRules);215 #endif216 217 214 clearMatchedRules(); 215 218 216 m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1; 217 StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange(); 219 218 220 219 // Match global author rules. 221 220 MatchRequest matchRequest(&m_authorStyle, includeEmptyRules); 222 StyleResolver::RuleRange ruleRange = m_result.ranges.authorRuleRange();223 221 collectMatchingRules(matchRequest, ruleRange); 224 222 collectMatchingRulesForRegion(matchRequest, ruleRange); 225 223 224 #if ENABLE(SHADOW_DOM) 225 auto* parent = m_element.parentElement(); 226 if (parent && parent->shadowRoot()) 227 matchSlottedPseudoElementRules(matchRequest, ruleRange); 228 229 if (m_element.shadowRoot()) 230 matchHostPseudoClassRules(matchRequest, ruleRange); 231 #endif 232 226 233 sortAndTransferMatchedRules(); 227 234 } 228 235 229 236 #if ENABLE(SHADOW_DOM) 230 void ElementRuleCollector::matchHostPseudoClassRules( bool includeEmptyRules)237 void ElementRuleCollector::matchHostPseudoClassRules(MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange) 231 238 { 232 239 ASSERT(m_element.shadowRoot()); 240 241 matchRequest.treeContextOrdinal++; 242 233 243 auto& shadowAuthorStyle = *m_element.shadowRoot()->styleResolver().ruleSets().authorStyle(); 234 244 auto& shadowHostRules = shadowAuthorStyle.hostPseudoClassRules(); … … 236 246 return; 237 247 238 clearMatchedRules();239 m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1;240 241 248 SelectorChecker::CheckingContext context(m_mode); 242 249 SelectorChecker selectorChecker(m_element.document()); 243 250 244 auto ruleRange = m_result.ranges.authorRuleRange();245 251 for (auto& ruleData : shadowHostRules) { 246 if (ruleData.rule()->properties().isEmpty() && ! includeEmptyRules)252 if (ruleData.rule()->properties().isEmpty() && !matchRequest.includeEmptyRules) 247 253 continue; 248 254 auto& selector = *ruleData.selector(); … … 250 256 if (!selectorChecker.matchHostPseudoClass(selector, m_element, context, specificity)) 251 257 continue; 252 addMatchedRule(ruleData, specificity, ruleRange); 253 } 254 255 // We just sort the host rules before other author rules. This matches the current vague spec language 256 // but is not necessarily exactly what is needed. 257 // FIXME: Match the spec when it is finalized. 258 sortAndTransferMatchedRules(); 259 } 260 261 void ElementRuleCollector::matchSlottedPseudoElementRules(bool includeEmptyRules) 262 { 263 RuleSet::RuleDataVector slottedPseudoElementRules; 264 258 addMatchedRule(ruleData, specificity, matchRequest.treeContextOrdinal, ruleRange); 259 } 260 } 261 262 void ElementRuleCollector::matchSlottedPseudoElementRules(MatchRequest& matchRequest, StyleResolver::RuleRange& ruleRange) 263 { 265 264 auto* maybeSlotted = &m_element; 266 265 for (auto* hostShadowRoot = m_element.parentNode()->shadowRoot(); hostShadowRoot; hostShadowRoot = maybeSlotted->parentNode()->shadowRoot()) { 267 266 auto* slot = hostShadowRoot->findAssignedSlot(*maybeSlotted); 268 267 if (!slot) 269 break; 268 return; 269 270 matchRequest.treeContextOrdinal++; 271 270 272 // In nested case the slot may itself be assigned to a slot. Collect ::slotted rules from all the nested trees. 271 273 maybeSlotted = slot; … … 276 278 // FIXME: This is really part of the slot style and could be cached when resolving it. 277 279 ElementRuleCollector collector(*slot, *shadowAuthorStyle, nullptr); 278 slottedPseudoElementRules.appendVector(collector.collectSlottedPseudoElementRulesForSlot(includeEmptyRules)); 279 } 280 281 if (slottedPseudoElementRules.isEmpty()) 282 return; 283 284 clearMatchedRules(); 285 m_result.ranges.lastAuthorRule = m_result.matchedProperties().size() - 1; 286 287 { 280 auto slottedPseudoElementRules = collector.collectSlottedPseudoElementRulesForSlot(matchRequest.includeEmptyRules); 281 if (!slottedPseudoElementRules) 282 continue; 288 283 // Match in the current scope. 289 284 TemporaryChange<bool> change(m_isMatchingSlottedPseudoElements, true); 290 285 291 MatchRequest matchRequest(nullptr, includeEmptyRules); 292 auto ruleRange = m_result.ranges.authorRuleRange(); 293 collectMatchingRulesForList(&slottedPseudoElementRules, matchRequest, ruleRange); 294 } 295 296 // FIXME: What is the correct order? 297 sortAndTransferMatchedRules(); 298 } 299 300 RuleSet::RuleDataVector ElementRuleCollector::collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules) 286 MatchRequest scopeMatchRequest(nullptr, matchRequest.includeEmptyRules, matchRequest.treeContextOrdinal); 287 collectMatchingRulesForList(slottedPseudoElementRules.get(), scopeMatchRequest, ruleRange); 288 289 m_keepAliveSlottedPseudoElementRules.append(WTFMove(slottedPseudoElementRules)); 290 } 291 } 292 293 std::unique_ptr<RuleSet::RuleDataVector> ElementRuleCollector::collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules) 301 294 { 302 295 ASSERT(is<HTMLSlotElement>(m_element)); … … 314 307 return { }; 315 308 316 RuleSet::RuleDataVector ruleDataVector;317 ruleDataVector .reserveInitialCapacity(m_matchedRules.size());309 auto ruleDataVector = std::make_unique<RuleSet::RuleDataVector>(); 310 ruleDataVector->reserveInitialCapacity(m_matchedRules.size()); 318 311 for (auto& matchedRule : m_matchedRules) 319 ruleDataVector.uncheckedAppend(*matchedRule.ruleData); 312 ruleDataVector->uncheckedAppend(*matchedRule.ruleData); 313 320 314 return ruleDataVector; 321 315 } … … 504 498 unsigned specificity; 505 499 if (ruleMatches(ruleData, specificity)) 506 addMatchedRule(ruleData, specificity, ruleRange);500 addMatchedRule(ruleData, specificity, matchRequest.treeContextOrdinal, ruleRange); 507 501 } 508 502 } … … 510 504 static inline bool compareRules(MatchedRule r1, MatchedRule r2) 511 505 { 512 unsigned specificity1 = r1.specificity; 513 unsigned specificity2 = r2.specificity; 514 return (specificity1 == specificity2) ? r1.ruleData->position() < r2.ruleData->position() : specificity1 < specificity2; 506 // For normal properties the earlier tree wins. This may be reversed by !important which is handled when resolving cascade. 507 if (r1.treeContextOrdinal != r2.treeContextOrdinal) 508 return r1.treeContextOrdinal > r2.treeContextOrdinal; 509 510 if (r1.specificity != r2.specificity) 511 return r1.specificity < r2.specificity; 512 513 return r1.ruleData->position() < r2.ruleData->position(); 515 514 } 516 515 -
trunk/Source/WebCore/css/ElementRuleCollector.h
r199291 r201073 41 41 struct MatchedRule { 42 42 const RuleData* ruleData; 43 unsigned specificity; 43 unsigned specificity; 44 unsigned treeContextOrdinal; 44 45 }; 45 46 … … 77 78 void matchUARules(RuleSet*); 78 79 #if ENABLE(SHADOW_DOM) 79 void matchHostPseudoClassRules( bool includeEmptyRules);80 void matchSlottedPseudoElementRules( bool includeEmptyRules);81 RuleSet::RuleDataVectorcollectSlottedPseudoElementRulesForSlot(bool includeEmptyRules);80 void matchHostPseudoClassRules(MatchRequest&, StyleResolver::RuleRange&); 81 void matchSlottedPseudoElementRules(MatchRequest&, StyleResolver::RuleRange&); 82 std::unique_ptr<RuleSet::RuleDataVector> collectSlottedPseudoElementRulesForSlot(bool includeEmptyRules); 82 83 #endif 83 84 … … 90 91 void sortAndTransferMatchedRules(); 91 92 92 void addMatchedRule(const RuleData&, unsigned specificity, StyleResolver::RuleRange&);93 void addMatchedRule(const RuleData&, unsigned specificity, unsigned treeContextOrdinal, StyleResolver::RuleRange&); 93 94 94 95 const Element& m_element; … … 104 105 #if ENABLE(SHADOW_DOM) 105 106 bool m_isMatchingSlottedPseudoElements { false }; 107 Vector<std::unique_ptr<RuleSet::RuleDataVector>> m_keepAliveSlottedPseudoElementRules; 106 108 #endif 107 109 -
trunk/Source/WebCore/css/StyleResolver.cpp
r200626 r201073 198 198 } 199 199 200 void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType )200 void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType, unsigned treeContextOrdinal) 201 201 { 202 202 m_matchedProperties.grow(m_matchedProperties.size() + 1); … … 205 205 newProperties.linkMatchType = linkMatchType; 206 206 newProperties.whitelistType = propertyWhitelistType; 207 newProperties.treeContextOrdinal = treeContextOrdinal; 207 208 matchedRules.append(rule); 209 210 // Ordinal is relative to the currently matched element 211 if (treeContextOrdinal) 212 isCacheable = false; 208 213 209 214 if (isCacheable) { … … 464 469 // decl, there's nothing to override. So just add the first properties. 465 470 CascadedProperties cascade(direction, writingMode); 466 cascade.add Matches(result, false, 0, result.matchedProperties().size() - 1);471 cascade.addNormalMatches(result, 0, result.matchedProperties().size() - 1); 467 472 468 473 // Resolve custom properties first. … … 632 637 633 638 CascadedProperties cascade(direction, writingMode); 634 cascade.add Matches(result, false, 0, result.matchedProperties().size() - 1);639 cascade.addNormalMatches(result, 0, result.matchedProperties().size() - 1); 635 640 636 641 // Resolve custom properties first. … … 1325 1330 // can look at them later to figure out if this is a styled form control or not. 1326 1331 CascadedProperties cascade(direction, writingMode); 1327 cascade.add Matches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);1328 cascade.add Matches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);1332 cascade.addNormalMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); 1333 cascade.addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); 1329 1334 1330 1335 applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult); … … 1344 1349 1345 1350 CascadedProperties cascade(direction, writingMode); 1346 cascade.add Matches(matchResult, false, 0, matchResult.matchedProperties().size() - 1, applyInheritedOnly);1347 cascade.add Matches(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);1348 cascade.add Matches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);1349 cascade.add Matches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);1351 cascade.addNormalMatches(matchResult, 0, matchResult.matchedProperties().size() - 1, applyInheritedOnly); 1352 cascade.addImportantMatches(matchResult, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); 1353 cascade.addImportantMatches(matchResult, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); 1354 cascade.addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); 1350 1355 1351 1356 // Resolve custom properties first. … … 1523 1528 1524 1529 // This special rollback cascade contains UA rules and user rules but no author rules. 1525 newAuthorRollback->add Matches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);1526 newAuthorRollback->add Matches(matchResult, false, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);1527 newAuthorRollback->add Matches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);1528 newAuthorRollback->add Matches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);1530 newAuthorRollback->addNormalMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false); 1531 newAuthorRollback->addNormalMatches(matchResult, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false); 1532 newAuthorRollback->addImportantMatches(matchResult, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false); 1533 newAuthorRollback->addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false); 1529 1534 1530 1535 state().setAuthorRollback(newAuthorRollback); … … 1540 1545 1541 1546 // This special rollback cascade contains only UA rules. 1542 newUserRollback->add Matches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);1543 newUserRollback->add Matches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);1547 newUserRollback->addNormalMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false); 1548 newUserRollback->addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false); 1544 1549 1545 1550 state().setUserRollback(newUserRollback); … … 2381 2386 } 2382 2387 2383 void StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly) 2388 void StyleResolver::CascadedProperties::addMatch(const MatchResult& matchResult, unsigned index, bool isImportant, bool inheritedOnly) 2389 { 2390 const MatchedProperties& matchedProperties = matchResult.matchedProperties()[index]; 2391 2392 auto propertyWhitelistType = static_cast<PropertyWhitelistType>(matchedProperties.whitelistType); 2393 auto cascadeLevel = cascadeLevelForIndex(matchResult, index); 2394 2395 addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[index], isImportant, inheritedOnly, propertyWhitelistType, matchedProperties.linkMatchType, cascadeLevel); 2396 } 2397 2398 void StyleResolver::CascadedProperties::addNormalMatches(const MatchResult& matchResult, int startIndex, int endIndex, bool inheritedOnly) 2384 2399 { 2385 2400 if (startIndex == -1) 2386 2401 return; 2387 2402 2388 for (int i = startIndex; i <= endIndex; ++i) { 2389 const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i]; 2390 addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType, 2391 cascadeLevelForIndex(matchResult, i)); 2403 for (int i = startIndex; i <= endIndex; ++i) 2404 addMatch(matchResult, i, false, inheritedOnly); 2405 } 2406 2407 static bool hasImportantProperties(const StyleProperties& properties) 2408 { 2409 for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) { 2410 if (properties.propertyAt(i).isImportant()) 2411 return true; 2412 } 2413 return false; 2414 } 2415 2416 void StyleResolver::CascadedProperties::addImportantMatches(const MatchResult& matchResult, int startIndex, int endIndex, bool inheritedOnly) 2417 { 2418 if (startIndex == -1) 2419 return; 2420 2421 unsigned highestTreeContextOrdinal = 0; 2422 for (unsigned treeContextPass = 0; treeContextPass <= highestTreeContextOrdinal; ++treeContextPass) { 2423 for (int i = startIndex; i <= endIndex; ++i) { 2424 const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i]; 2425 2426 if (!hasImportantProperties(*matchedProperties.properties)) 2427 continue; 2428 2429 // For !important properties a later shadow tree wins. Do multiple passes to apply in correct order if needed. 2430 // Matched properties are sorted in reverse tree context order so this is not needed for normal properties. 2431 if (matchedProperties.treeContextOrdinal != treeContextPass) { 2432 highestTreeContextOrdinal = std::max(matchedProperties.treeContextOrdinal, highestTreeContextOrdinal); 2433 continue; 2434 } 2435 2436 addMatch(matchResult, i, true, inheritedOnly); 2437 } 2392 2438 } 2393 2439 } -
trunk/Source/WebCore/css/StyleResolver.h
r200977 r201073 258 258 unsigned linkMatchType : 2; 259 259 unsigned whitelistType : 2; 260 unsigned treeContextOrdinal : 28; 260 261 }; 261 262 // Used to make sure all memory is zero-initialized since we compute the hash over the bytes of this object. … … 272 273 const Vector<MatchedProperties, 64>& matchedProperties() const { return m_matchedProperties; } 273 274 274 void addMatchedProperties(const StyleProperties&, StyleRule* = nullptr, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone );275 void addMatchedProperties(const StyleProperties&, StyleRule* = nullptr, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone, unsigned treeContextOrdinal = 0); 275 276 private: 276 277 Vector<MatchedProperties, 64> m_matchedProperties; … … 292 293 bool hasProperty(CSSPropertyID) const; 293 294 Property& property(CSSPropertyID); 294 void addMatches(const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly = false); 295 296 void addNormalMatches(const MatchResult&, int startIndex, int endIndex, bool inheritedOnly = false); 297 void addImportantMatches(const MatchResult&, int startIndex, int endIndex, bool inheritedOnly = false); 295 298 296 299 void set(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel); … … 304 307 305 308 private: 309 void addMatch(const MatchResult&, unsigned index, bool isImportant, bool inheritedOnly); 306 310 void addStyleProperties(const StyleProperties&, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType, unsigned linkMatchType, CascadeLevel); 307 311 static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel);
Note:
See TracChangeset
for help on using the changeset viewer.