OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 14 matching lines...) Expand all Loading... | |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/css/invalidation/StyleSheetInvalidationAnalysis.h" | 27 #include "core/css/invalidation/StyleSheetInvalidationAnalysis.h" |
28 | 28 |
29 #include "core/css/CSSSelectorList.h" | 29 #include "core/css/CSSSelectorList.h" |
30 #include "core/css/StyleRuleImport.h" | 30 #include "core/css/StyleRuleImport.h" |
31 #include "core/css/StyleSheetContents.h" | 31 #include "core/css/StyleSheetContents.h" |
32 #include "core/dom/ContainerNode.h" | 32 #include "core/dom/ContainerNode.h" |
33 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
34 #include "core/dom/ElementTraversal.h" | 34 #include "core/dom/ElementTraversal.h" |
35 #include "core/dom/TreeScope.h" | |
35 #include "core/dom/shadow/ShadowRoot.h" | 36 #include "core/dom/shadow/ShadowRoot.h" |
36 #include "core/html/HTMLStyleElement.h" | 37 #include "core/html/HTMLStyleElement.h" |
37 | 38 |
38 namespace blink { | 39 namespace blink { |
39 | 40 |
40 StyleSheetInvalidationAnalysis::StyleSheetInvalidationAnalysis(const WillBeHeapV ector<RawPtrWillBeMember<StyleSheetContents>>& sheets) | 41 StyleSheetInvalidationAnalysis::StyleSheetInvalidationAnalysis(const TreeScope& treeScope, const WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents>>& sheet s) |
41 : m_dirtiesAllStyle(false) | 42 : m_treeScope(treeScope) |
42 { | 43 { |
43 for (unsigned i = 0; i < sheets.size() && !m_dirtiesAllStyle; ++i) | 44 for (unsigned i = 0; i < sheets.size() && !m_dirtiesAllStyle; ++i) |
44 analyzeStyleSheet(sheets[i]); | 45 analyzeStyleSheet(sheets[i]); |
45 } | 46 } |
46 | 47 |
47 static bool determineSelectorScopes(const CSSSelectorList& selectorList, HashSet <StringImpl*>& idScopes, HashSet<StringImpl*>& classScopes) | 48 static bool determineSelectorScopes(const CSSSelectorList& selectorList, HashSet <StringImpl*>& idScopes, HashSet<StringImpl*>& classScopes) |
48 { | 49 { |
49 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) { | 50 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) { |
50 const CSSSelector* scopeSelector = 0; | 51 const CSSSelector* scopeSelector = 0; |
51 // This picks the widest scope, not the narrowest, to minimize the numbe r of found scopes. | 52 // This picks the widest scope, not the narrowest, to minimize the numbe r of found scopes. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 const StyleRule* styleRule = toStyleRule(rule); | 86 const StyleRule* styleRule = toStyleRule(rule); |
86 const CSSSelectorList& selectorList = styleRule->selectorList(); | 87 const CSSSelectorList& selectorList = styleRule->selectorList(); |
87 for (size_t selectorIndex = 0; selectorIndex != kNotFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex)) { | 88 for (size_t selectorIndex = 0; selectorIndex != kNotFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex)) { |
88 if (selectorList.hasShadowDistributedAt(selectorIndex)) | 89 if (selectorList.hasShadowDistributedAt(selectorIndex)) |
89 return true; | 90 return true; |
90 } | 91 } |
91 } | 92 } |
92 return false; | 93 return false; |
93 } | 94 } |
94 | 95 |
95 static Node* determineScopingNodeForStyleInShadow(HTMLStyleElement* ownerElement , StyleSheetContents* styleSheetContents) | |
96 { | |
97 ASSERT(ownerElement && ownerElement->isInShadowTree()); | |
98 | |
99 if (hasDistributedRule(styleSheetContents)) { | |
100 ContainerNode* scope = ownerElement; | |
101 do { | |
102 scope = scope->containingShadowRoot()->shadowHost(); | |
103 } while (scope->isInShadowTree()); | |
104 return scope; | |
105 } | |
106 | |
107 return ownerElement->containingShadowRoot()->shadowHost(); | |
108 } | |
109 | |
110 static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule) | 96 static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule) |
111 { | 97 { |
112 // This funciton is conservative. We only return false when we know that | 98 // This funciton is conservative. We only return false when we know that |
113 // the added @rule can't require style recalcs. | 99 // the added @rule can't require style recalcs. |
114 switch (rule->type()) { | 100 switch (rule->type()) { |
115 case StyleRule::Import: // Whatever we import should do its own analysis, we don't need to invalidate the document here! | 101 case StyleRule::Import: // Whatever we import should do its own analysis, we don't need to invalidate the document here! |
116 case StyleRule::Page: // Page rules apply only during printing, we force a f ull-recalc before printing. | 102 case StyleRule::Page: // Page rules apply only during printing, we force a f ull-recalc before printing. |
117 return false; | 103 return false; |
118 | 104 |
119 case StyleRule::Media: // If the media rule doesn't apply, we could avoid re calc. | 105 case StyleRule::Media: // If the media rule doesn't apply, we could avoid re calc. |
(...skipping 25 matching lines...) Expand all Loading... | |
145 // See if all rules on the sheet are scoped to some specific ids or classes. | 131 // See if all rules on the sheet are scoped to some specific ids or classes. |
146 // Then test if we actually have any of those in the tree at the moment. | 132 // Then test if we actually have any of those in the tree at the moment. |
147 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport>>& importRules = s tyleSheetContents->importRules(); | 133 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport>>& importRules = s tyleSheetContents->importRules(); |
148 for (unsigned i = 0; i < importRules.size(); ++i) { | 134 for (unsigned i = 0; i < importRules.size(); ++i) { |
149 if (!importRules[i]->styleSheet()) | 135 if (!importRules[i]->styleSheet()) |
150 continue; | 136 continue; |
151 analyzeStyleSheet(importRules[i]->styleSheet()); | 137 analyzeStyleSheet(importRules[i]->styleSheet()); |
152 if (m_dirtiesAllStyle) | 138 if (m_dirtiesAllStyle) |
153 return; | 139 return; |
154 } | 140 } |
155 if (styleSheetContents->hasSingleOwnerNode()) { | 141 |
156 Node* ownerNode = styleSheetContents->singleOwnerNode(); | 142 if (m_treeScope.rootNode().isShadowRoot()) { |
157 if (isHTMLStyleElement(ownerNode) && toHTMLStyleElement(*ownerNode).isIn ShadowTree()) { | 143 if (hasDistributedRule(styleSheetContents)) |
158 m_scopingNodes.append(determineScopingNodeForStyleInShadow(toHTMLSty leElement(ownerNode), styleSheetContents)); | 144 m_hasDistributedRules = true; |
159 return; | 145 return; |
160 } | |
161 } | 146 } |
162 | 147 |
163 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase>>& rules = styleShee tContents->childRules(); | 148 const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase>>& rules = styleShee tContents->childRules(); |
164 for (unsigned i = 0; i < rules.size(); i++) { | 149 for (unsigned i = 0; i < rules.size(); i++) { |
165 StyleRuleBase* rule = rules[i].get(); | 150 StyleRuleBase* rule = rules[i].get(); |
166 if (!rule->isStyleRule()) { | 151 if (!rule->isStyleRule()) { |
167 if (ruleAdditionMightRequireDocumentStyleRecalc(rule)) { | 152 if (ruleAdditionMightRequireDocumentStyleRecalc(rule)) { |
168 m_dirtiesAllStyle = true; | 153 m_dirtiesAllStyle = true; |
169 return; | 154 return; |
170 } | 155 } |
(...skipping 14 matching lines...) Expand all Loading... | |
185 if (classScopes.isEmpty() || !element->hasClass()) | 170 if (classScopes.isEmpty() || !element->hasClass()) |
186 return false; | 171 return false; |
187 const SpaceSplitString& classNames = element->classNames(); | 172 const SpaceSplitString& classNames = element->classNames(); |
188 for (unsigned i = 0; i < classNames.size(); ++i) { | 173 for (unsigned i = 0; i < classNames.size(); ++i) { |
189 if (classScopes.contains(classNames[i].impl())) | 174 if (classScopes.contains(classNames[i].impl())) |
190 return true; | 175 return true; |
191 } | 176 } |
192 return false; | 177 return false; |
193 } | 178 } |
194 | 179 |
195 void StyleSheetInvalidationAnalysis::invalidateStyle(Document& document) | 180 static ContainerNode* outermostShadowHost(const ShadowRoot& root) |
esprehn
2015/08/23 15:34:51
Do you actually want the outer most host or the ro
rune
2015/08/23 20:21:46
rootInTreeOfTrees is document() as long as the nod
| |
181 { | |
182 ContainerNode* host = root.shadowHost(); | |
esprehn
2015/08/23 15:34:52
.host()
rune
2015/08/23 20:21:47
Done.
| |
183 while (host->isInShadowTree()) | |
184 host = host->containingShadowRoot()->shadowHost(); | |
esprehn
2015/08/23 15:34:51
->host(), that's all the shadowHost() call here is
rune
2015/08/23 20:21:47
Done.
| |
185 return host; | |
186 } | |
187 | |
188 void StyleSheetInvalidationAnalysis::invalidateStyle() | |
196 { | 189 { |
197 ASSERT(!m_dirtiesAllStyle); | 190 ASSERT(!m_dirtiesAllStyle); |
198 | 191 |
199 if (!m_scopingNodes.isEmpty()) { | 192 if (m_treeScope.rootNode().isShadowRoot()) { |
200 for (unsigned i = 0; i < m_scopingNodes.size(); ++i) | 193 ContainerNode* invalidationRoot = &m_treeScope.rootNode(); |
201 m_scopingNodes.at(i)->setNeedsStyleRecalc(SubtreeStyleChange, StyleC hangeReasonForTracing::create(StyleChangeReason::StyleSheetChange)); | 194 if (m_hasDistributedRules) |
195 invalidationRoot = outermostShadowHost(*toShadowRoot(invalidationRoo t)); | |
196 invalidationRoot->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeRea sonForTracing::create(StyleChangeReason::StyleSheetChange)); | |
197 return; | |
202 } | 198 } |
203 | 199 |
204 if (m_idScopes.isEmpty() && m_classScopes.isEmpty()) | 200 if (m_idScopes.isEmpty() && m_classScopes.isEmpty()) |
205 return; | 201 return; |
206 Element* element = ElementTraversal::firstWithin(document); | 202 Element* element = ElementTraversal::firstWithin(m_treeScope.document()); |
207 while (element) { | 203 while (element) { |
208 if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) { | 204 if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) { |
209 element->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonFo rTracing::create(StyleChangeReason::StyleSheetChange)); | 205 element->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonFo rTracing::create(StyleChangeReason::StyleSheetChange)); |
210 // The whole subtree is now invalidated, we can skip to the next sib ling. | 206 // The whole subtree is now invalidated, we can skip to the next sib ling. |
211 element = ElementTraversal::nextSkippingChildren(*element); | 207 element = ElementTraversal::nextSkippingChildren(*element); |
212 continue; | 208 continue; |
213 } | 209 } |
214 element = ElementTraversal::next(*element); | 210 element = ElementTraversal::next(*element); |
215 } | 211 } |
216 } | 212 } |
217 | 213 |
218 } | 214 } |
OLD | NEW |