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 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All r
ights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All r
ights reserved. |
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
8 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. |
9 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 9 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
10 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. | 10 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "core/dom/StyleEngine.h" | 28 #include "core/dom/StyleEngine.h" |
29 | 29 |
30 #include "core/HTMLNames.h" | 30 #include "core/HTMLNames.h" |
31 #include "core/css/CSSDefaultStyleSheets.h" | 31 #include "core/css/CSSDefaultStyleSheets.h" |
32 #include "core/css/CSSFontSelector.h" | 32 #include "core/css/CSSFontSelector.h" |
33 #include "core/css/CSSStyleSheet.h" | 33 #include "core/css/CSSStyleSheet.h" |
34 #include "core/css/FontFaceCache.h" | 34 #include "core/css/FontFaceCache.h" |
35 #include "core/css/StyleSheetContents.h" | 35 #include "core/css/StyleSheetContents.h" |
36 #include "core/css/invalidation/InvalidationSet.h" | 36 #include "core/css/invalidation/InvalidationSet.h" |
37 #include "core/css/resolver/ScopedStyleResolver.h" | 37 #include "core/css/resolver/ScopedStyleResolver.h" |
| 38 #include "core/css/resolver/SharedStyleFinder.h" |
| 39 #include "core/css/resolver/ViewportStyleResolver.h" |
38 #include "core/dom/DocumentStyleSheetCollector.h" | 40 #include "core/dom/DocumentStyleSheetCollector.h" |
39 #include "core/dom/Element.h" | 41 #include "core/dom/Element.h" |
| 42 #include "core/dom/ElementTraversal.h" |
40 #include "core/dom/ProcessingInstruction.h" | 43 #include "core/dom/ProcessingInstruction.h" |
41 #include "core/dom/ShadowTreeStyleSheetCollection.h" | 44 #include "core/dom/ShadowTreeStyleSheetCollection.h" |
42 #include "core/dom/StyleChangeReason.h" | 45 #include "core/dom/StyleChangeReason.h" |
43 #include "core/dom/shadow/ShadowRoot.h" | 46 #include "core/dom/shadow/ShadowRoot.h" |
44 #include "core/frame/Settings.h" | 47 #include "core/frame/Settings.h" |
45 #include "core/html/HTMLIFrameElement.h" | 48 #include "core/html/HTMLIFrameElement.h" |
46 #include "core/html/HTMLLinkElement.h" | 49 #include "core/html/HTMLLinkElement.h" |
| 50 #include "core/html/HTMLSlotElement.h" |
47 #include "core/html/imports/HTMLImportsController.h" | 51 #include "core/html/imports/HTMLImportsController.h" |
48 #include "core/inspector/InspectorInstrumentation.h" | 52 #include "core/inspector/InspectorInstrumentation.h" |
49 #include "core/page/Page.h" | 53 #include "core/page/Page.h" |
50 #include "core/svg/SVGStyleElement.h" | 54 #include "core/svg/SVGStyleElement.h" |
51 #include "platform/TraceEvent.h" | 55 #include "platform/TraceEvent.h" |
52 #include "platform/fonts/FontCache.h" | 56 #include "platform/fonts/FontCache.h" |
53 | 57 |
54 namespace blink { | 58 namespace blink { |
55 | 59 |
56 using namespace HTMLNames; | 60 using namespace HTMLNames; |
57 | 61 |
58 StyleEngine::StyleEngine(Document& document) | 62 StyleEngine::StyleEngine(Document& document) |
59 : m_document(&document) | 63 : m_document(&document) |
60 , m_isMaster(!document.importsController() || document.importsController()->
master() == &document) | 64 , m_isMaster(!document.importsController() || document.importsController()->
master() == &document) |
61 , m_documentStyleSheetCollection(DocumentStyleSheetCollection::create(docume
nt)) | 65 , m_documentStyleSheetCollection(DocumentStyleSheetCollection::create(docume
nt)) |
62 // We don't need to create CSSFontSelector for imported document or | |
63 // HTMLTemplateElement's document, because those documents have no frame. | |
64 , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : nul
lptr) | |
65 { | 66 { |
66 if (m_fontSelector) | 67 if (document.frame()) { |
| 68 // We don't need to create CSSFontSelector for imported document or |
| 69 // HTMLTemplateElement's document, because those documents have no frame
. |
| 70 m_fontSelector = CSSFontSelector::create(&document); |
67 m_fontSelector->registerForInvalidationCallbacks(this); | 71 m_fontSelector->registerForInvalidationCallbacks(this); |
| 72 } |
68 } | 73 } |
69 | 74 |
70 StyleEngine::~StyleEngine() | 75 StyleEngine::~StyleEngine() |
71 { | 76 { |
72 } | 77 } |
73 | 78 |
74 static bool isStyleElement(Node& node) | 79 static bool isStyleElement(Node& node) |
75 { | 80 { |
76 return isHTMLStyleElement(node) || isSVGStyleElement(node); | 81 return isHTMLStyleElement(node) || isSVGStyleElement(node); |
77 } | 82 } |
(...skipping 25 matching lines...) Expand all Loading... |
103 return documentStyleSheetCollection(); | 108 return documentStyleSheetCollection(); |
104 | 109 |
105 StyleSheetCollectionMap::iterator it = m_styleSheetCollectionMap.find(&treeS
cope); | 110 StyleSheetCollectionMap::iterator it = m_styleSheetCollectionMap.find(&treeS
cope); |
106 if (it == m_styleSheetCollectionMap.end()) | 111 if (it == m_styleSheetCollectionMap.end()) |
107 return 0; | 112 return 0; |
108 return it->value.get(); | 113 return it->value.get(); |
109 } | 114 } |
110 | 115 |
111 const HeapVector<Member<StyleSheet>>& StyleEngine::styleSheetsForStyleSheetList(
TreeScope& treeScope) | 116 const HeapVector<Member<StyleSheet>>& StyleEngine::styleSheetsForStyleSheetList(
TreeScope& treeScope) |
112 { | 117 { |
| 118 // TODO(rune@opera.com): we could split styleSheets and active stylesheet |
| 119 // update to have a lighter update while accessing the styleSheets list. |
| 120 DCHECK(master()); |
| 121 if (master()->isActive()) { |
| 122 if (isMaster()) |
| 123 updateActiveStyle(); |
| 124 else |
| 125 master()->styleEngine().updateActiveStyle(); |
| 126 } |
| 127 |
113 if (treeScope == m_document) | 128 if (treeScope == m_document) |
114 return documentStyleSheetCollection()->styleSheetsForStyleSheetList(); | 129 return documentStyleSheetCollection()->styleSheetsForStyleSheetList(); |
115 | 130 |
116 return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetLis
t(); | 131 return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetLis
t(); |
117 } | 132 } |
118 | 133 |
119 void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features) | |
120 { | |
121 m_usesSiblingRules = features.usesSiblingRules(); | |
122 m_usesFirstLineRules = features.usesFirstLineRules(); | |
123 m_usesWindowInactiveSelector = features.usesWindowInactiveSelector(); | |
124 m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors(); | |
125 } | |
126 | |
127 void StyleEngine::injectAuthorSheet(StyleSheetContents* authorSheet) | 134 void StyleEngine::injectAuthorSheet(StyleSheetContents* authorSheet) |
128 { | 135 { |
129 m_injectedAuthorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_docu
ment)); | 136 m_injectedAuthorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_docu
ment)); |
130 markDocumentDirty(); | 137 markDocumentDirty(); |
131 resolverChanged(AnalyzedStyleUpdate); | |
132 } | 138 } |
133 | 139 |
134 void StyleEngine::addPendingSheet(StyleEngineContext &context) | 140 void StyleEngine::addPendingSheet(StyleEngineContext &context) |
135 { | 141 { |
136 m_pendingScriptBlockingStylesheets++; | 142 m_pendingScriptBlockingStylesheets++; |
137 | 143 |
138 context.addingPendingSheet(document()); | 144 context.addingPendingSheet(document()); |
139 if (context.addedPendingSheetBeforeBody()) | 145 if (context.addedPendingSheetBeforeBody()) |
140 m_pendingRenderBlockingStylesheets++; | 146 m_pendingRenderBlockingStylesheets++; |
141 } | 147 } |
142 | 148 |
143 // This method is called whenever a top-level stylesheet has finished loading. | 149 // This method is called whenever a top-level stylesheet has finished loading. |
144 void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, const StyleE
ngineContext &context) | 150 void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, const StyleE
ngineContext &context) |
145 { | 151 { |
146 DCHECK(styleSheetCandidateNode); | 152 DCHECK(styleSheetCandidateNode); |
147 TreeScope* treeScope = isStyleElement(*styleSheetCandidateNode) ? &styleShee
tCandidateNode->treeScope() : m_document.get(); | 153 TreeScope* treeScope = isStyleElement(*styleSheetCandidateNode) ? &styleShee
tCandidateNode->treeScope() : m_document.get(); |
148 if (styleSheetCandidateNode->inShadowIncludingDocument()) | 154 if (styleSheetCandidateNode->inShadowIncludingDocument()) |
149 markTreeScopeDirty(*treeScope); | 155 markTreeScopeDirty(*treeScope); |
150 | 156 |
151 if (context.addedPendingSheetBeforeBody()) { | 157 if (context.addedPendingSheetBeforeBody()) { |
152 DCHECK_GT(m_pendingRenderBlockingStylesheets, 0); | 158 DCHECK(m_pendingRenderBlockingStylesheets); |
153 m_pendingRenderBlockingStylesheets--; | 159 m_pendingRenderBlockingStylesheets--; |
154 } | 160 } |
155 | 161 |
156 // Make sure we knew this sheet was pending, and that our count isn't out of
sync. | 162 // Make sure we knew this sheet was pending, and that our count isn't out of
sync. |
157 DCHECK_GT(m_pendingScriptBlockingStylesheets, 0); | 163 DCHECK(m_pendingScriptBlockingStylesheets); |
158 | 164 |
159 m_pendingScriptBlockingStylesheets--; | 165 m_pendingScriptBlockingStylesheets--; |
160 if (m_pendingScriptBlockingStylesheets) | 166 if (m_pendingScriptBlockingStylesheets) |
161 return; | 167 return; |
162 | 168 |
163 document().didRemoveAllPendingStylesheet(); | 169 document().didRemoveAllPendingStylesheet(); |
164 } | 170 } |
165 | 171 |
166 void StyleEngine::setNeedsActiveStyleUpdate(StyleSheet* sheet, StyleResolverUpda
teMode updateMode) | 172 void StyleEngine::setNeedsActiveStyleUpdate(TreeScope& treeScope) |
167 { | 173 { |
168 // resolverChanged() is called for inactive non-master documents because | |
169 // import documents are inactive documents. resolverChanged() for imports | |
170 // will call resolverChanged() for the master document and update the active | |
171 // stylesheets including the ones from the import. | |
172 if (!document().isActive() && isMaster()) | 174 if (!document().isActive() && isMaster()) |
173 return; | 175 return; |
| 176 markTreeScopeDirty(treeScope); |
| 177 } |
174 | 178 |
175 if (sheet && document().isActive()) { | 179 void StyleEngine::updateActiveStyle() |
176 Node* node = sheet->ownerNode(); | 180 { |
177 if (node && node->inShadowIncludingDocument()) { | 181 DCHECK(document().isActive()); |
178 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *
m_document; | |
179 DCHECK(isStyleElement(*node) || node->treeScope() == m_document); | |
180 markTreeScopeDirty(treeScope); | |
181 } | |
182 } | |
183 | 182 |
184 resolverChanged(updateMode); | 183 if (!needsActiveStyleUpdate()) |
| 184 return; |
| 185 |
| 186 updateActiveStyleSheets(); |
| 187 updateGlobalRuleSet(); |
| 188 |
| 189 DCHECK(!needsActiveStyleUpdate()); |
185 } | 190 } |
186 | 191 |
187 void StyleEngine::addStyleSheetCandidateNode(Node* node) | 192 void StyleEngine::addStyleSheetCandidateNode(Node* node) |
188 { | 193 { |
189 if (!node->inShadowIncludingDocument() || document().isDetached()) | 194 if (!node->inShadowIncludingDocument() || document().isDetached()) |
190 return; | 195 return; |
191 | 196 |
192 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_docume
nt; | 197 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_docume
nt; |
193 DCHECK(isStyleElement(*node) || treeScope == m_document); | 198 DCHECK(isStyleElement(*node) || treeScope == m_document); |
194 DCHECK(!isXSLStyleSheet(*node)); | 199 DCHECK(!isXSLStyleSheet(*node)); |
(...skipping 27 matching lines...) Expand all Loading... |
222 } | 227 } |
223 | 228 |
224 void StyleEngine::modifiedStyleSheetCandidateNode(Node* node) | 229 void StyleEngine::modifiedStyleSheetCandidateNode(Node* node) |
225 { | 230 { |
226 if (!node->inShadowIncludingDocument()) | 231 if (!node->inShadowIncludingDocument()) |
227 return; | 232 return; |
228 | 233 |
229 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_docume
nt; | 234 TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_docume
nt; |
230 DCHECK(isStyleElement(*node) || treeScope == m_document); | 235 DCHECK(isStyleElement(*node) || treeScope == m_document); |
231 markTreeScopeDirty(treeScope); | 236 markTreeScopeDirty(treeScope); |
232 resolverChanged(FullStyleUpdate); | |
233 } | 237 } |
234 | 238 |
235 void StyleEngine::watchedSelectorsChanged() | 239 void StyleEngine::watchedSelectorsChanged() |
236 { | 240 { |
237 if (m_resolver) { | 241 m_globalRuleSet.initWatchedSelectorsRuleSet(document()); |
238 m_resolver->initWatchedSelectorRules(); | 242 m_needsGlobalRuleSetUpdate = true; |
239 m_resolver->resetRuleFeatures(); | |
240 } | |
241 document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTraci
ng::create(StyleChangeReason::DeclarativeContent)); | 243 document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTraci
ng::create(StyleChangeReason::DeclarativeContent)); |
242 } | 244 } |
243 | 245 |
244 bool StyleEngine::shouldUpdateDocumentStyleSheetCollection(StyleResolverUpdateMo
de updateMode) const | 246 bool StyleEngine::shouldUpdateDocumentStyleSheetCollection() const |
245 { | 247 { |
246 return m_documentScopeDirty || updateMode == FullStyleUpdate; | 248 return m_allTreeScopesDirty || m_documentScopeDirty; |
247 } | 249 } |
248 | 250 |
249 bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdate
Mode updateMode) const | 251 bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection() const |
250 { | 252 { |
251 return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate; | 253 return m_allTreeScopesDirty || !m_dirtyTreeScopes.isEmpty(); |
252 } | 254 } |
253 | 255 |
254 void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(UnorderedTreeScop
eSet& treeScopes) | 256 void StyleEngine::mediaQueryAffectingValueChanged(UnorderedTreeScopeSet& treeSco
pes) |
255 { | 257 { |
256 for (TreeScope* treeScope : treeScopes) { | 258 for (TreeScope* treeScope : treeScopes) { |
257 DCHECK(treeScope != m_document); | 259 DCHECK(treeScope != m_document); |
258 ShadowTreeStyleSheetCollection* collection = toShadowTreeStyleSheetColle
ction(styleSheetCollectionFor(*treeScope)); | 260 ShadowTreeStyleSheetCollection* collection = toShadowTreeStyleSheetColle
ction(styleSheetCollectionFor(*treeScope)); |
259 DCHECK(collection); | 261 DCHECK(collection); |
260 collection->clearMediaQueryRuleSetStyleSheets(); | 262 if (collection->mediaQueryAffectingValueChanged()) |
| 263 setNeedsActiveStyleUpdate(*treeScope); |
261 } | 264 } |
262 } | 265 } |
263 | 266 |
264 void StyleEngine::clearMediaQueryRuleSetStyleSheets() | 267 void StyleEngine::mediaQueryAffectingValueChanged() |
265 { | 268 { |
266 resolverChanged(FullStyleUpdate); | 269 if (documentStyleSheetCollection()->mediaQueryAffectingValueChanged()) |
267 documentStyleSheetCollection()->clearMediaQueryRuleSetStyleSheets(); | 270 setNeedsActiveStyleUpdate(document()); |
268 clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes); | 271 mediaQueryAffectingValueChanged(m_activeTreeScopes); |
| 272 |
| 273 if (!document().frame()) |
| 274 return; |
| 275 |
| 276 if (document().wasPrinting() != document().printing() && document().frame()-
>pageZoomFactor() != 1) |
| 277 document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForT
racing::create(StyleChangeReason::StyleSheetChange)); |
269 } | 278 } |
270 | 279 |
271 void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentC
ollector) | 280 void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentC
ollector) |
272 { | 281 { |
273 DCHECK(!isMaster()); | 282 DCHECK(!isMaster()); |
274 HeapVector<Member<StyleSheet>> sheetsForList; | 283 HeapVector<Member<StyleSheet>> sheetsForList; |
275 ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForL
ist); | 284 ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForL
ist); |
276 documentStyleSheetCollection()->collectStyleSheets(*this, subcollector); | 285 documentStyleSheetCollection()->collectStyleSheets(subcollector); |
277 documentStyleSheetCollection()->swapSheetsForSheetList(sheetsForList); | 286 documentStyleSheetCollection()->swapSheetsForSheetList(sheetsForList); |
278 } | 287 } |
279 | 288 |
280 void StyleEngine::updateActiveStyleSheetsInShadow(StyleResolverUpdateMode update
Mode, TreeScope* treeScope, UnorderedTreeScopeSet& treeScopesRemoved) | 289 void StyleEngine::updateActiveStyleSheetsInShadow(TreeScope* treeScope, Unordere
dTreeScopeSet& treeScopesRemoved) |
281 { | 290 { |
282 DCHECK_NE(treeScope, m_document); | 291 DCHECK_NE(treeScope, m_document); |
283 ShadowTreeStyleSheetCollection* collection = toShadowTreeStyleSheetCollectio
n(styleSheetCollectionFor(*treeScope)); | 292 ShadowTreeStyleSheetCollection* collection = toShadowTreeStyleSheetCollectio
n(styleSheetCollectionFor(*treeScope)); |
284 DCHECK(collection); | 293 DCHECK(collection); |
285 collection->updateActiveStyleSheets(*this, updateMode); | 294 collection->updateActiveStyleSheets(); |
286 if (!collection->hasStyleSheetCandidateNodes()) { | 295 if (!collection->hasStyleSheetCandidateNodes()) { |
287 treeScopesRemoved.add(treeScope); | 296 treeScopesRemoved.add(treeScope); |
288 // When removing TreeScope from ActiveTreeScopes, | 297 // When removing TreeScope from ActiveTreeScopes, |
289 // its resolver should be destroyed by invoking resetAuthorStyle. | 298 // its resolver should be destroyed by invoking resetAuthorStyle. |
290 DCHECK(!treeScope->scopedStyleResolver()); | 299 DCHECK(!treeScope->scopedStyleResolver()); |
291 } | 300 } |
292 } | 301 } |
293 | 302 |
294 void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode) | 303 void StyleEngine::updateActiveStyleSheets() |
295 { | 304 { |
| 305 if (!needsActiveStyleSheetUpdate()) |
| 306 return; |
| 307 |
296 DCHECK(isMaster()); | 308 DCHECK(isMaster()); |
297 DCHECK(!document().inStyleRecalc()); | 309 DCHECK(!document().inStyleRecalc()); |
298 | 310 DCHECK(document().isActive()); |
299 if (!document().isActive()) | |
300 return; | |
301 | 311 |
302 TRACE_EVENT0("blink,blink_style", "StyleEngine::updateActiveStyleSheets"); | 312 TRACE_EVENT0("blink,blink_style", "StyleEngine::updateActiveStyleSheets"); |
303 | 313 |
304 if (shouldUpdateDocumentStyleSheetCollection(updateMode)) | 314 if (shouldUpdateDocumentStyleSheetCollection()) { |
305 documentStyleSheetCollection()->updateActiveStyleSheets(*this, updateMod
e); | 315 documentStyleSheetCollection()->updateViewport(); |
| 316 documentStyleSheetCollection()->updateActiveStyleSheets(); |
| 317 } |
306 | 318 |
307 if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) { | 319 if (shouldUpdateShadowTreeStyleSheetCollection()) { |
308 UnorderedTreeScopeSet treeScopesRemoved; | 320 UnorderedTreeScopeSet treeScopesRemoved; |
309 | 321 |
310 if (updateMode == FullStyleUpdate) { | 322 for (TreeScope* treeScope : m_dirtyTreeScopes) |
311 for (TreeScope* treeScope : m_activeTreeScopes) | 323 updateActiveStyleSheetsInShadow(treeScope, treeScopesRemoved); |
312 updateActiveStyleSheetsInShadow(updateMode, treeScope, treeScope
sRemoved); | |
313 } else { | |
314 for (TreeScope* treeScope : m_dirtyTreeScopes) | |
315 updateActiveStyleSheetsInShadow(updateMode, treeScope, treeScope
sRemoved); | |
316 } | |
317 for (TreeScope* treeScope : treeScopesRemoved) | 324 for (TreeScope* treeScope : treeScopesRemoved) |
318 m_activeTreeScopes.remove(treeScope); | 325 m_activeTreeScopes.remove(treeScope); |
319 } | 326 } |
320 | 327 |
321 InspectorInstrumentation::activeStyleSheetsUpdated(m_document); | 328 InspectorInstrumentation::activeStyleSheetsUpdated(m_document); |
322 | 329 |
323 m_dirtyTreeScopes.clear(); | 330 m_dirtyTreeScopes.clear(); |
324 m_documentScopeDirty = false; | 331 m_documentScopeDirty = false; |
| 332 m_allTreeScopesDirty = false; |
325 } | 333 } |
326 | 334 |
327 const HeapVector<Member<CSSStyleSheet>> StyleEngine::activeStyleSheetsForInspect
or() const | 335 const ActiveStyleSheetVector StyleEngine::activeStyleSheetsForInspector() |
328 { | 336 { |
| 337 if (document().isActive()) |
| 338 updateActiveStyle(); |
| 339 |
329 if (m_activeTreeScopes.isEmpty()) | 340 if (m_activeTreeScopes.isEmpty()) |
330 return documentStyleSheetCollection()->activeAuthorStyleSheets(); | 341 return documentStyleSheetCollection()->activeAuthorStyleSheets(); |
331 | 342 |
332 HeapVector<Member<CSSStyleSheet>> activeStyleSheets; | 343 ActiveStyleSheetVector activeStyleSheets; |
333 | 344 |
334 activeStyleSheets.appendVector(documentStyleSheetCollection()->activeAuthorS
tyleSheets()); | 345 activeStyleSheets.appendVector(documentStyleSheetCollection()->activeAuthorS
tyleSheets()); |
335 for (TreeScope* treeScope : m_activeTreeScopes) { | 346 for (TreeScope* treeScope : m_activeTreeScopes) { |
336 if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMa
p.get(treeScope)) | 347 if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMa
p.get(treeScope)) |
337 activeStyleSheets.appendVector(collection->activeAuthorStyleSheets()
); | 348 activeStyleSheets.appendVector(collection->activeAuthorStyleSheets()
); |
338 } | 349 } |
339 | 350 |
340 // FIXME: Inspector needs a vector which has all active stylesheets. | 351 // FIXME: Inspector needs a vector which has all active stylesheets. |
341 // However, creating such a large vector might cause performance regression. | 352 // However, creating such a large vector might cause performance regression. |
342 // Need to implement some smarter solution. | 353 // Need to implement some smarter solution. |
343 return activeStyleSheets; | 354 return activeStyleSheets; |
344 } | 355 } |
345 | 356 |
346 void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot) | 357 void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot) |
347 { | 358 { |
348 m_styleSheetCollectionMap.remove(shadowRoot); | 359 m_styleSheetCollectionMap.remove(shadowRoot); |
349 m_activeTreeScopes.remove(shadowRoot); | 360 m_activeTreeScopes.remove(shadowRoot); |
350 m_dirtyTreeScopes.remove(shadowRoot); | 361 m_dirtyTreeScopes.remove(shadowRoot); |
351 } | 362 } |
352 | 363 |
353 void StyleEngine::shadowRootRemovedFromDocument(ShadowRoot* shadowRoot) | 364 void StyleEngine::shadowRootRemovedFromDocument(ShadowRoot* shadowRoot) |
354 { | 365 { |
355 if (StyleResolver* styleResolver = resolver()) { | 366 m_needsGlobalRuleSetUpdate = true; |
356 styleResolver->resetAuthorStyle(*shadowRoot); | 367 shadowRoot->clearScopedStyleResolver(); |
357 | |
358 if (TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(
*shadowRoot)) | |
359 styleResolver->removePendingAuthorStyleSheets(collection->activeAuth
orStyleSheets()); | |
360 } | |
361 m_styleSheetCollectionMap.remove(shadowRoot); | 368 m_styleSheetCollectionMap.remove(shadowRoot); |
362 m_activeTreeScopes.remove(shadowRoot); | 369 m_activeTreeScopes.remove(shadowRoot); |
363 m_dirtyTreeScopes.remove(shadowRoot); | 370 m_dirtyTreeScopes.remove(shadowRoot); |
| 371 m_treeBoundaryCrossingScopes.remove(&shadowRoot->rootNode()); |
364 } | 372 } |
365 | 373 |
366 void StyleEngine::appendActiveAuthorStyleSheets() | 374 void StyleEngine::addTreeBoundaryCrossingScope(ContainerNode& scope) |
367 { | 375 { |
368 DCHECK(isMaster()); | 376 m_treeBoundaryCrossingScopes.add(&scope); |
| 377 } |
369 | 378 |
370 m_resolver->appendAuthorStyleSheets(documentStyleSheetCollection()->activeAu
thorStyleSheets()); | 379 RuleSet& StyleEngine::ensureRuleSetForSheet(CSSStyleSheet& sheet) |
371 for (TreeScope* treeScope : m_activeTreeScopes) { | 380 { |
372 if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMa
p.get(treeScope)) | 381 if (!sheet.matchesMediaQueries(ensureMediaQueryEvaluator())) |
373 m_resolver->appendAuthorStyleSheets(collection->activeAuthorStyleShe
ets()); | 382 return *RuleSet::emptyRuleSet(); |
374 } | 383 |
375 m_resolver->finishAppendAuthorStyleSheets(); | 384 AddRuleFlags addRuleFlags = RuleHasNoSpecialState; |
| 385 if (m_document->getSecurityOrigin()->canRequest(sheet.baseURL())) |
| 386 addRuleFlags = RuleHasDocumentSecurityOrigin; |
| 387 return sheet.contents()->ensureRuleSet(*m_medium, addRuleFlags); |
376 } | 388 } |
377 | 389 |
378 void StyleEngine::createResolver() | 390 void StyleEngine::createResolver() |
379 { | 391 { |
380 TRACE_EVENT1("blink", "StyleEngine::createResolver", "frame", document().fra
me()); | 392 TRACE_EVENT1("blink", "StyleEngine::createResolver", "frame", document().fra
me()); |
381 // It is a programming error to attempt to resolve style on a Document | 393 // It is a programming error to attempt to resolve style on a Document |
382 // which is not in a frame. Code which hits this should have checked | 394 // which is not in a frame. Code which hits this should have checked |
383 // Document::isActive() before calling into code which could get here. | 395 // Document::isActive() before calling into code which could get here. |
384 | 396 |
385 DCHECK(document().frame()); | 397 DCHECK(document().frame()); |
386 | 398 |
387 m_resolver = StyleResolver::create(*m_document); | 399 m_resolver = StyleResolver::create(*m_document); |
388 | |
389 // A scoped style resolver for document will be created during | |
390 // appendActiveAuthorStyleSheets if needed. | |
391 appendActiveAuthorStyleSheets(); | |
392 } | 400 } |
393 | 401 |
394 void StyleEngine::clearResolver() | 402 void StyleEngine::clearResolver() |
395 { | 403 { |
396 DCHECK(!document().inStyleRecalc()); | 404 DCHECK(!document().inStyleRecalc()); |
397 DCHECK(isMaster() || !m_resolver); | 405 DCHECK(isMaster() || !m_resolver); |
398 | 406 |
399 document().clearScopedStyleResolver(); | 407 document().clearScopedStyleResolver(); |
400 // StyleEngine::shadowRootRemovedFromDocument removes not-in-document | 408 // StyleEngine::shadowRootRemovedFromDocument removes not-in-document |
401 // treescopes from activeTreeScopes. StyleEngine::didRemoveShadowRoot | 409 // treescopes from activeTreeScopes. StyleEngine::didRemoveShadowRoot |
402 // removes treescopes which are being destroyed from activeTreeScopes. | 410 // removes treescopes which are being destroyed from activeTreeScopes. |
403 // So we need to clearScopedStyleResolver for treescopes which have been | 411 // So we need to clearScopedStyleResolver for treescopes which have been |
404 // just removed from document. If document is destroyed before invoking | 412 // just removed from document. If document is destroyed before invoking |
405 // updateActiveStyleSheets, the treescope has a scopedStyleResolver which | 413 // updateActiveStyleSheets, the treescope has a scopedStyleResolver which |
406 // has destroyed StyleSheetContents. | 414 // has destroyed StyleSheetContents. |
407 for (TreeScope* treeScope : m_activeTreeScopes) | 415 for (TreeScope* treeScope : m_activeTreeScopes) |
408 treeScope->clearScopedStyleResolver(); | 416 treeScope->clearScopedStyleResolver(); |
409 | 417 |
410 if (m_resolver) { | 418 if (m_resolver) { |
411 TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame", document().
frame()); | 419 TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame", document().
frame()); |
412 m_resolver->dispose(); | 420 m_resolver->dispose(); |
413 m_resolver.clear(); | 421 m_resolver.clear(); |
414 } | 422 } |
415 } | 423 } |
416 | 424 |
417 void StyleEngine::clearMasterResolver() | |
418 { | |
419 if (Document* master = this->master()) | |
420 master->styleEngine().clearResolver(); | |
421 } | |
422 | |
423 void StyleEngine::didDetach() | 425 void StyleEngine::didDetach() |
424 { | 426 { |
425 clearResolver(); | 427 clearResolver(); |
| 428 m_viewportResolver.clear(); |
| 429 m_medium = nullptr; |
426 } | 430 } |
427 | 431 |
428 bool StyleEngine::shouldClearResolver() const | 432 bool StyleEngine::shouldClearResolver() const |
429 { | 433 { |
430 return !m_didCalculateResolver && !haveScriptBlockingStylesheetsLoaded(); | 434 return !m_didCalculateResolver && !haveScriptBlockingStylesheetsLoaded(); |
431 } | 435 } |
432 | 436 |
433 void StyleEngine::resolverChanged(StyleResolverUpdateMode mode) | |
434 { | |
435 if (!isMaster()) { | |
436 if (Document* master = this->master()) | |
437 master->styleEngine().resolverChanged(mode); | |
438 return; | |
439 } | |
440 | |
441 // Don't bother updating, since we haven't loaded all our style info yet | |
442 // and haven't calculated the style selector for the first time. | |
443 if (!document().isActive() || shouldClearResolver()) { | |
444 clearResolver(); | |
445 return; | |
446 } | |
447 | |
448 m_didCalculateResolver = true; | |
449 updateActiveStyleSheets(mode); | |
450 } | |
451 | |
452 void StyleEngine::clearFontCache() | 437 void StyleEngine::clearFontCache() |
453 { | 438 { |
454 if (m_fontSelector) | 439 if (m_fontSelector) |
455 m_fontSelector->fontFaceCache()->clearCSSConnected(); | 440 m_fontSelector->fontFaceCache()->clearCSSConnected(); |
456 if (m_resolver) | 441 if (m_resolver) |
457 m_resolver->invalidateMatchedPropertiesCache(); | 442 m_resolver->invalidateMatchedPropertiesCache(); |
458 } | 443 } |
459 | 444 |
460 void StyleEngine::updateGenericFontFamilySettings() | 445 void StyleEngine::updateGenericFontFamilySettings() |
461 { | 446 { |
(...skipping 15 matching lines...) Expand all Loading... |
477 if (!m_fontSelector) | 462 if (!m_fontSelector) |
478 return; | 463 return; |
479 | 464 |
480 FontFaceCache* cache = m_fontSelector->fontFaceCache(); | 465 FontFaceCache* cache = m_fontSelector->fontFaceCache(); |
481 for (unsigned i = 0; i < fontFaceRules.size(); ++i) | 466 for (unsigned i = 0; i < fontFaceRules.size(); ++i) |
482 cache->remove(fontFaceRules[i]); | 467 cache->remove(fontFaceRules[i]); |
483 if (m_resolver) | 468 if (m_resolver) |
484 m_resolver->invalidateMatchedPropertiesCache(); | 469 m_resolver->invalidateMatchedPropertiesCache(); |
485 } | 470 } |
486 | 471 |
| 472 void StyleEngine::removeFontFaceRules(const HeapVector<Member<StyleRuleFontFace>
>& fontFaceRules) |
| 473 { |
| 474 if (!m_fontSelector) |
| 475 return; |
| 476 |
| 477 FontFaceCache* cache = m_fontSelector->fontFaceCache(); |
| 478 for (unsigned i = 0; i < fontFaceRules.size(); ++i) |
| 479 cache->remove(fontFaceRules[i]); |
| 480 if (m_resolver) |
| 481 m_resolver->invalidateMatchedPropertiesCache(); |
| 482 } |
| 483 |
| 484 ViewportStyleResolver& StyleEngine::ensureViewportStyleResolver() |
| 485 { |
| 486 if (!m_viewportResolver) |
| 487 m_viewportResolver = ViewportStyleResolver::create(m_document); |
| 488 return *m_viewportResolver.get(); |
| 489 } |
| 490 |
487 void StyleEngine::markTreeScopeDirty(TreeScope& scope) | 491 void StyleEngine::markTreeScopeDirty(TreeScope& scope) |
488 { | 492 { |
489 if (scope == m_document) { | 493 if (scope == m_document) { |
490 markDocumentDirty(); | 494 markDocumentDirty(); |
491 return; | 495 return; |
492 } | 496 } |
493 | 497 |
494 DCHECK(m_styleSheetCollectionMap.contains(&scope)); | 498 DCHECK(m_styleSheetCollectionMap.contains(&scope)); |
495 m_dirtyTreeScopes.add(&scope); | 499 m_dirtyTreeScopes.add(&scope); |
| 500 document().scheduleLayoutTreeUpdateIfNeeded(); |
496 } | 501 } |
497 | 502 |
498 void StyleEngine::markDocumentDirty() | 503 void StyleEngine::markDocumentDirty() |
499 { | 504 { |
500 m_documentScopeDirty = true; | 505 m_documentScopeDirty = true; |
501 if (document().importLoader()) | 506 if (document().importLoader()) |
502 document().importsController()->master()->styleEngine().markDocumentDirt
y(); | 507 document().importsController()->master()->styleEngine().markDocumentDirt
y(); |
| 508 else |
| 509 document().scheduleLayoutTreeUpdateIfNeeded(); |
503 } | 510 } |
504 | 511 |
505 CSSStyleSheet* StyleEngine::createSheet(Element* e, const String& text, TextPosi
tion startPosition, StyleEngineContext &context) | 512 CSSStyleSheet* StyleEngine::createSheet(Element* e, const String& text, TextPosi
tion startPosition, StyleEngineContext &context) |
506 { | 513 { |
507 CSSStyleSheet* styleSheet = nullptr; | 514 CSSStyleSheet* styleSheet = nullptr; |
508 | 515 |
509 e->document().styleEngine().addPendingSheet(context); | 516 addPendingSheet(context); |
510 | 517 |
511 AtomicString textContent(text); | 518 AtomicString textContent(text); |
512 | 519 |
513 HeapHashMap<AtomicString, Member<StyleSheetContents>>::AddResult result = m_
textToSheetCache.add(textContent, nullptr); | 520 HeapHashMap<AtomicString, Member<StyleSheetContents>>::AddResult result = m_
textToSheetCache.add(textContent, nullptr); |
514 if (result.isNewEntry || !result.storedValue->value) { | 521 if (result.isNewEntry || !result.storedValue->value) { |
515 styleSheet = StyleEngine::parseSheet(e, text, startPosition); | 522 styleSheet = parseSheet(e, text, startPosition); |
516 if (result.isNewEntry && styleSheet->contents()->isCacheableForStyleElem
ent()) { | 523 if (result.isNewEntry && styleSheet->contents()->isCacheableForStyleElem
ent()) { |
517 result.storedValue->value = styleSheet->contents(); | 524 result.storedValue->value = styleSheet->contents(); |
518 m_sheetToTextCache.add(styleSheet->contents(), textContent); | 525 m_sheetToTextCache.add(styleSheet->contents(), textContent); |
519 } | 526 } |
520 } else { | 527 } else { |
521 StyleSheetContents* contents = result.storedValue->value; | 528 StyleSheetContents* contents = result.storedValue->value; |
522 DCHECK(contents); | 529 DCHECK(contents); |
523 DCHECK(contents->isCacheableForStyleElement()); | 530 DCHECK(contents->isCacheableForStyleElement()); |
524 DCHECK_EQ(contents->singleOwnerDocument(), e->document()); | 531 DCHECK_EQ(contents->singleOwnerDocument(), document()); |
525 styleSheet = CSSStyleSheet::createInline(contents, e, startPosition); | 532 styleSheet = CSSStyleSheet::createInline(contents, e, startPosition); |
526 } | 533 } |
527 | 534 |
528 DCHECK(styleSheet); | 535 DCHECK(styleSheet); |
529 styleSheet->setTitle(e->title()); | 536 styleSheet->setTitle(e->title()); |
| 537 if (!e->isInShadowTree()) |
| 538 setPreferredStylesheetSetNameIfNotSet(e->title()); |
530 return styleSheet; | 539 return styleSheet; |
531 } | 540 } |
532 | 541 |
533 CSSStyleSheet* StyleEngine::parseSheet(Element* e, const String& text, TextPosit
ion startPosition) | 542 CSSStyleSheet* StyleEngine::parseSheet(Element* e, const String& text, TextPosit
ion startPosition) |
534 { | 543 { |
535 CSSStyleSheet* styleSheet = nullptr; | 544 CSSStyleSheet* styleSheet = nullptr; |
536 styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, e->docume
nt().characterSet()); | 545 styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, document(
).characterSet()); |
537 styleSheet->contents()->parseStringAtPosition(text, startPosition); | 546 styleSheet->contents()->parseStringAtPosition(text, startPosition); |
538 return styleSheet; | 547 return styleSheet; |
539 } | 548 } |
540 | 549 |
541 void StyleEngine::removeSheet(StyleSheetContents* contents) | 550 void StyleEngine::removeSheet(StyleSheetContents* contents) |
542 { | 551 { |
543 HeapHashMap<Member<StyleSheetContents>, AtomicString>::iterator it = m_sheet
ToTextCache.find(contents); | 552 HeapHashMap<Member<StyleSheetContents>, AtomicString>::iterator it = m_sheet
ToTextCache.find(contents); |
544 if (it == m_sheetToTextCache.end()) | 553 if (it == m_sheetToTextCache.end()) |
545 return; | 554 return; |
546 | 555 |
547 m_textToSheetCache.remove(it->value); | 556 m_textToSheetCache.remove(it->value); |
548 m_sheetToTextCache.remove(contents); | 557 m_sheetToTextCache.remove(contents); |
549 } | 558 } |
550 | 559 |
| 560 bool StyleEngine::hasRulesForId(const AtomicString& id) const |
| 561 { |
| 562 return m_globalRuleSet.m_features.hasSelectorForId(id); |
| 563 } |
| 564 |
| 565 void StyleEngine::updateGlobalRuleSet() |
| 566 { |
| 567 if (!m_needsGlobalRuleSetUpdate) |
| 568 return; |
| 569 |
| 570 m_globalRuleSet.update(document()); |
| 571 m_needsGlobalRuleSetUpdate = false; |
| 572 } |
| 573 |
551 void StyleEngine::collectScopedStyleFeaturesTo(RuleFeatureSet& features) const | 574 void StyleEngine::collectScopedStyleFeaturesTo(RuleFeatureSet& features) const |
552 { | 575 { |
553 HeapHashSet<Member<const StyleSheetContents>> visitedSharedStyleSheetContent
s; | 576 HeapHashSet<Member<const StyleSheetContents>> visitedSharedStyleSheetContent
s; |
554 if (document().scopedStyleResolver()) | 577 if (document().scopedStyleResolver()) |
555 document().scopedStyleResolver()->collectFeaturesTo(features, visitedSha
redStyleSheetContents); | 578 document().scopedStyleResolver()->collectFeaturesTo(features, visitedSha
redStyleSheetContents); |
556 for (TreeScope* treeScope : m_activeTreeScopes) { | 579 for (TreeScope* treeScope : m_activeTreeScopes) { |
557 // When creating StyleResolver, dirty treescopes might not be processed. | 580 // When creating StyleResolver, dirty treescopes might not be processed. |
558 // So some active treescopes might not have a scoped style resolver. | 581 // So some active treescopes might not have a scoped style resolver. |
559 // In this case, we should skip collectFeatures for the treescopes witho
ut | 582 // In this case, we should skip collectFeatures for the treescopes witho
ut |
560 // scoped style resolvers. When invoking updateActiveStyleSheets, | 583 // scoped style resolvers. When invoking updateActiveStyleSheets, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 return true; | 623 return true; |
601 return element.parentNode()->getStyleChangeType() >= SubtreeStyleChange; | 624 return element.parentNode()->getStyleChangeType() >= SubtreeStyleChange; |
602 } | 625 } |
603 | 626 |
604 void StyleEngine::classChangedForElement(const SpaceSplitString& changedClasses,
Element& element) | 627 void StyleEngine::classChangedForElement(const SpaceSplitString& changedClasses,
Element& element) |
605 { | 628 { |
606 if (shouldSkipInvalidationFor(element)) | 629 if (shouldSkipInvalidationFor(element)) |
607 return; | 630 return; |
608 InvalidationLists invalidationLists; | 631 InvalidationLists invalidationLists; |
609 unsigned changedSize = changedClasses.size(); | 632 unsigned changedSize = changedClasses.size(); |
610 RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSe
t(); | 633 const RuleFeatureSet& ruleFeatures = ruleFeatureSet(); |
611 for (unsigned i = 0; i < changedSize; ++i) | 634 for (unsigned i = 0; i < changedSize; ++i) |
612 ruleFeatureSet.collectInvalidationSetsForClass(invalidationLists, elemen
t, changedClasses[i]); | 635 ruleFeatures.collectInvalidationSetsForClass(invalidationLists, element,
changedClasses[i]); |
613 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); | 636 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); |
614 } | 637 } |
615 | 638 |
616 void StyleEngine::classChangedForElement(const SpaceSplitString& oldClasses, con
st SpaceSplitString& newClasses, Element& element) | 639 void StyleEngine::classChangedForElement(const SpaceSplitString& oldClasses, con
st SpaceSplitString& newClasses, Element& element) |
617 { | 640 { |
618 if (shouldSkipInvalidationFor(element)) | 641 if (shouldSkipInvalidationFor(element)) |
619 return; | 642 return; |
620 | 643 |
621 if (!oldClasses.size()) { | 644 if (!oldClasses.size()) { |
622 classChangedForElement(newClasses, element); | 645 classChangedForElement(newClasses, element); |
623 return; | 646 return; |
624 } | 647 } |
625 | 648 |
626 // Class vectors tend to be very short. This is faster than using a hash tab
le. | 649 // Class vectors tend to be very short. This is faster than using a hash tab
le. |
627 BitVector remainingClassBits; | 650 BitVector remainingClassBits; |
628 remainingClassBits.ensureSize(oldClasses.size()); | 651 remainingClassBits.ensureSize(oldClasses.size()); |
629 | 652 |
630 InvalidationLists invalidationLists; | 653 InvalidationLists invalidationLists; |
631 RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSe
t(); | 654 const RuleFeatureSet& ruleFeatures = ruleFeatureSet(); |
632 | 655 |
633 for (unsigned i = 0; i < newClasses.size(); ++i) { | 656 for (unsigned i = 0; i < newClasses.size(); ++i) { |
634 bool found = false; | 657 bool found = false; |
635 for (unsigned j = 0; j < oldClasses.size(); ++j) { | 658 for (unsigned j = 0; j < oldClasses.size(); ++j) { |
636 if (newClasses[i] == oldClasses[j]) { | 659 if (newClasses[i] == oldClasses[j]) { |
637 // Mark each class that is still in the newClasses so we can ski
p doing | 660 // Mark each class that is still in the newClasses so we can ski
p doing |
638 // an n^2 search below when looking for removals. We can't break
from | 661 // an n^2 search below when looking for removals. We can't break
from |
639 // this loop early since a class can appear more than once. | 662 // this loop early since a class can appear more than once. |
640 remainingClassBits.quickSet(j); | 663 remainingClassBits.quickSet(j); |
641 found = true; | 664 found = true; |
642 } | 665 } |
643 } | 666 } |
644 // Class was added. | 667 // Class was added. |
645 if (!found) | 668 if (!found) |
646 ruleFeatureSet.collectInvalidationSetsForClass(invalidationLists, el
ement, newClasses[i]); | 669 ruleFeatures.collectInvalidationSetsForClass(invalidationLists, elem
ent, newClasses[i]); |
647 } | 670 } |
648 | 671 |
649 for (unsigned i = 0; i < oldClasses.size(); ++i) { | 672 for (unsigned i = 0; i < oldClasses.size(); ++i) { |
650 if (remainingClassBits.quickGet(i)) | 673 if (remainingClassBits.quickGet(i)) |
651 continue; | 674 continue; |
652 // Class was removed. | 675 // Class was removed. |
653 ruleFeatureSet.collectInvalidationSetsForClass(invalidationLists, elemen
t, oldClasses[i]); | 676 ruleFeatures.collectInvalidationSetsForClass(invalidationLists, element,
oldClasses[i]); |
654 } | 677 } |
655 | 678 |
656 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); | 679 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); |
657 } | 680 } |
658 | 681 |
659 void StyleEngine::attributeChangedForElement(const QualifiedName& attributeName,
Element& element) | 682 void StyleEngine::attributeChangedForElement(const QualifiedName& attributeName,
Element& element) |
660 { | 683 { |
661 if (shouldSkipInvalidationFor(element)) | 684 if (shouldSkipInvalidationFor(element)) |
662 return; | 685 return; |
663 | 686 |
664 InvalidationLists invalidationLists; | 687 InvalidationLists invalidationLists; |
665 ensureResolver().ensureUpdatedRuleFeatureSet().collectInvalidationSetsForAtt
ribute(invalidationLists, element, attributeName); | 688 ruleFeatureSet().collectInvalidationSetsForAttribute(invalidationLists, elem
ent, attributeName); |
666 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); | 689 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); |
667 } | 690 } |
668 | 691 |
669 void StyleEngine::idChangedForElement(const AtomicString& oldId, const AtomicStr
ing& newId, Element& element) | 692 void StyleEngine::idChangedForElement(const AtomicString& oldId, const AtomicStr
ing& newId, Element& element) |
670 { | 693 { |
671 if (shouldSkipInvalidationFor(element)) | 694 if (shouldSkipInvalidationFor(element)) |
672 return; | 695 return; |
673 | 696 |
674 InvalidationLists invalidationLists; | 697 InvalidationLists invalidationLists; |
675 RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSe
t(); | 698 const RuleFeatureSet& ruleFeatures = ruleFeatureSet(); |
676 if (!oldId.isEmpty()) | 699 if (!oldId.isEmpty()) |
677 ruleFeatureSet.collectInvalidationSetsForId(invalidationLists, element,
oldId); | 700 ruleFeatures.collectInvalidationSetsForId(invalidationLists, element, ol
dId); |
678 if (!newId.isEmpty()) | 701 if (!newId.isEmpty()) |
679 ruleFeatureSet.collectInvalidationSetsForId(invalidationLists, element,
newId); | 702 ruleFeatures.collectInvalidationSetsForId(invalidationLists, element, ne
wId); |
680 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); | 703 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); |
681 } | 704 } |
682 | 705 |
683 void StyleEngine::pseudoStateChangedForElement(CSSSelector::PseudoType pseudoTyp
e, Element& element) | 706 void StyleEngine::pseudoStateChangedForElement(CSSSelector::PseudoType pseudoTyp
e, Element& element) |
684 { | 707 { |
685 if (shouldSkipInvalidationFor(element)) | 708 if (shouldSkipInvalidationFor(element)) |
686 return; | 709 return; |
687 | 710 |
688 InvalidationLists invalidationLists; | 711 InvalidationLists invalidationLists; |
689 ensureResolver().ensureUpdatedRuleFeatureSet().collectInvalidationSetsForPse
udoClass(invalidationLists, element, pseudoType); | 712 ruleFeatureSet().collectInvalidationSetsForPseudoClass(invalidationLists, el
ement, pseudoType); |
690 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); | 713 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); |
691 } | 714 } |
692 | 715 |
693 void StyleEngine::setStatsEnabled(bool enabled) | 716 void StyleEngine::setStatsEnabled(bool enabled) |
694 { | 717 { |
695 if (!enabled) { | 718 if (!enabled) { |
696 m_styleResolverStats = nullptr; | 719 m_styleResolverStats = nullptr; |
697 return; | 720 return; |
698 } | 721 } |
699 if (!m_styleResolverStats) | 722 if (!m_styleResolverStats) |
700 m_styleResolverStats = StyleResolverStats::create(); | 723 m_styleResolverStats = StyleResolverStats::create(); |
701 else | 724 else |
702 m_styleResolverStats->reset(); | 725 m_styleResolverStats->reset(); |
703 } | 726 } |
704 | 727 |
| 728 void StyleEngine::scheduleRuleSetInvalidationsForElement(Element& element, const
HeapVector<Member<RuleSet>>& ruleSets) |
| 729 { |
| 730 AtomicString id; |
| 731 const SpaceSplitString* classNames = nullptr; |
| 732 bool typeSelectorMatch = false; |
| 733 const AtomicString& shadowPseudoId = element.shadowPseudoId(); |
| 734 bool customPseudoMatch = shadowPseudoId.isEmpty(); |
| 735 |
| 736 if (element.hasID()) |
| 737 id = element.idForStyleResolution(); |
| 738 if (element.hasClass()) |
| 739 classNames = &element.classNames(); |
| 740 |
| 741 InvalidationLists invalidationLists; |
| 742 for (const auto& ruleSet : ruleSets) { |
| 743 |
| 744 if (!id.isNull()) |
| 745 ruleSet->features().collectInvalidationSetsForId(invalidationLists,
element, id); |
| 746 |
| 747 if (classNames) { |
| 748 unsigned classNameCount = classNames->size(); |
| 749 for (size_t i = 0; i < classNameCount; i++) |
| 750 ruleSet->features().collectInvalidationSetsForClass(invalidation
Lists, element, (*classNames)[i]); |
| 751 } |
| 752 |
| 753 for (const Attribute& attribute : element.attributes()) |
| 754 ruleSet->features().collectInvalidationSetsForAttribute(invalidation
Lists, element, attribute.name()); |
| 755 |
| 756 if (element.needsStyleRecalc()) |
| 757 continue; |
| 758 |
| 759 if (!typeSelectorMatch && ruleSet->tagRules(element.localNameForSelector
Matching())) { |
| 760 typeSelectorMatch = true; |
| 761 element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTr
acing::create(StyleChangeReason::StyleSheetChange)); |
| 762 } |
| 763 |
| 764 if (!customPseudoMatch && ruleSet->shadowPseudoElementRules(shadowPseudo
Id)) { |
| 765 customPseudoMatch = true; |
| 766 element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTr
acing::create(StyleChangeReason::StyleSheetChange)); |
| 767 } |
| 768 } |
| 769 m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, ele
ment); |
| 770 } |
| 771 |
| 772 void StyleEngine::scheduleInvalidationsForRuleSets(TreeScope& treeScope, const H
eapVector<Member<RuleSet>>& ruleSets) |
| 773 { |
| 774 if (treeScope.rootNode().isShadowRoot()) { |
| 775 Element& host = toShadowRoot(treeScope.rootNode()).host(); |
| 776 scheduleRuleSetInvalidationsForElement(host, ruleSets); |
| 777 if (host.getStyleChangeType() >= SubtreeStyleChange) |
| 778 return; |
| 779 } |
| 780 |
| 781 Node* stayWithin = &treeScope.rootNode(); |
| 782 Element* element = ElementTraversal::firstChild(*stayWithin); |
| 783 while (element) { |
| 784 scheduleRuleSetInvalidationsForElement(*element, ruleSets); |
| 785 if (isHTMLSlotElement(element)) { |
| 786 for (auto& node : toHTMLSlotElement(element)->getDistributedNodes())
{ |
| 787 if (node->isElementNode()) |
| 788 scheduleRuleSetInvalidationsForElement(*toElement(node), rul
eSets); |
| 789 } |
| 790 } |
| 791 if (element->getStyleChangeType() < SubtreeStyleChange) |
| 792 element = ElementTraversal::next(*element, stayWithin); |
| 793 else |
| 794 element = ElementTraversal::nextSkippingChildren(*element, stayWithi
n); |
| 795 } |
| 796 } |
| 797 |
705 void StyleEngine::setPreferredStylesheetSetNameIfNotSet(const String& name) | 798 void StyleEngine::setPreferredStylesheetSetNameIfNotSet(const String& name) |
706 { | 799 { |
707 if (!m_preferredStylesheetSetName.isEmpty()) | 800 if (!m_preferredStylesheetSetName.isEmpty()) |
708 return; | 801 return; |
709 m_preferredStylesheetSetName = name; | 802 m_preferredStylesheetSetName = name; |
710 // TODO(rune@opera.com): Setting the selected set here is wrong if the set | 803 // TODO(rune@opera.com): Setting the selected set here is wrong if the set |
711 // has been previously set by through Document.selectedStylesheetSet. Our | 804 // has been previously set by through Document.selectedStylesheetSet. Our |
712 // current implementation ignores the effect of Document.selectedStylesheetS
et | 805 // current implementation ignores the effect of Document.selectedStylesheetS
et |
713 // and either only collects persistent style, or additionally preferred | 806 // and either only collects persistent style, or additionally preferred |
714 // style when present. We are currently not marking the document scope dirty | 807 // style when present. We are currently not marking the document scope dirty |
715 // because preferred style is updated during active stylesheet update which | 808 // because preferred style is updated during active stylesheet update which |
716 // would make this method re-entrant. Will need to change for async update. | 809 // would make this method re-entrant. Will need to change for async update. |
717 m_selectedStylesheetSetName = name; | 810 m_selectedStylesheetSetName = name; |
718 } | 811 } |
719 | 812 |
720 void StyleEngine::setSelectedStylesheetSetName(const String& name) | 813 void StyleEngine::setSelectedStylesheetSetName(const String& name) |
721 { | 814 { |
722 m_selectedStylesheetSetName = name; | 815 m_selectedStylesheetSetName = name; |
723 // TODO(rune@opera.com): Setting Document.selectedStylesheetSet currently | 816 // TODO(rune@opera.com): Setting Document.selectedStylesheetSet currently |
724 // has no other effect than the ability to read back the set value using | 817 // has no other effect than the ability to read back the set value using |
725 // the same api. If it did have an effect, we should have marked the | 818 // the same api. If it did have an effect, we should have marked the |
726 // document scope dirty and triggered an update of the active stylesheets | 819 // document scope dirty and triggered an update of the active stylesheets |
727 // from here. | 820 // from here. |
728 } | 821 } |
729 | 822 |
730 void StyleEngine::setHttpDefaultStyle(const String& content) | 823 void StyleEngine::setHttpDefaultStyle(const String& content) |
731 { | 824 { |
732 setPreferredStylesheetSetNameIfNotSet(content); | 825 setPreferredStylesheetSetNameIfNotSet(content); |
733 markDocumentDirty(); | 826 markDocumentDirty(); |
734 resolverChanged(FullStyleUpdate); | |
735 } | 827 } |
736 | 828 |
737 void StyleEngine::ensureFullscreenUAStyle() | 829 void StyleEngine::ensureUAStyleForFullscreen() |
738 { | 830 { |
739 CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetForFullscreen(); | 831 if (CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetForFullscreen()
) { |
740 if (!m_resolver) | 832 m_needsGlobalRuleSetUpdate = true; |
741 return; | 833 updateGlobalRuleSet(); |
742 if (!m_resolver->hasFullscreenUAStyle()) | 834 } |
743 m_resolver->resetRuleFeatures(); | 835 } |
| 836 |
| 837 void StyleEngine::ensureUAStyleForElement(const Element& element) |
| 838 { |
| 839 if (CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(ele
ment)) { |
| 840 m_needsGlobalRuleSetUpdate = true; |
| 841 updateGlobalRuleSet(); |
| 842 } |
| 843 } |
| 844 |
| 845 PassRefPtr<ComputedStyle> StyleEngine::findSharedStyle(const ElementResolveConte
xt& elementResolveContext) |
| 846 { |
| 847 return SharedStyleFinder(elementResolveContext, |
| 848 m_globalRuleSet.m_features, |
| 849 m_globalRuleSet.m_siblingRuleSet.get(), |
| 850 m_globalRuleSet.m_uncommonAttributeRuleSet.get(), |
| 851 *m_resolver).findSharedStyle(); |
| 852 } |
| 853 |
| 854 MediaQueryEvaluator& StyleEngine::ensureMediaQueryEvaluator() |
| 855 { |
| 856 if (!m_medium) { |
| 857 if (document().frame()) |
| 858 m_medium = new MediaQueryEvaluator(document().frame()); |
| 859 else |
| 860 m_medium = new MediaQueryEvaluator("all"); |
| 861 } |
| 862 return *m_medium; |
| 863 } |
| 864 |
| 865 bool StyleEngine::mediaQueryAffectedByViewportChange() |
| 866 { |
| 867 const MediaQueryEvaluator& evaluator = ensureMediaQueryEvaluator(); |
| 868 const auto& results = m_globalRuleSet.m_features.viewportDependentMediaQuery
Results; |
| 869 for (unsigned i = 0; i < results.size(); ++i) { |
| 870 if (evaluator.eval(results[i]->expression()) != results[i]->result()) |
| 871 return true; |
| 872 } |
| 873 return false; |
| 874 } |
| 875 |
| 876 bool StyleEngine::mediaQueryAffectedByDeviceChange() |
| 877 { |
| 878 const MediaQueryEvaluator& evaluator = ensureMediaQueryEvaluator(); |
| 879 const auto& results = m_globalRuleSet.m_features.deviceDependentMediaQueryRe
sults; |
| 880 for (unsigned i = 0; i < results.size(); ++i) { |
| 881 if (evaluator.eval(results[i]->expression()) != results[i]->result()) |
| 882 return true; |
| 883 } |
| 884 return false; |
744 } | 885 } |
745 | 886 |
746 DEFINE_TRACE(StyleEngine) | 887 DEFINE_TRACE(StyleEngine) |
747 { | 888 { |
748 visitor->trace(m_document); | 889 visitor->trace(m_document); |
749 visitor->trace(m_injectedAuthorStyleSheets); | 890 visitor->trace(m_injectedAuthorStyleSheets); |
750 visitor->trace(m_documentStyleSheetCollection); | 891 visitor->trace(m_documentStyleSheetCollection); |
751 visitor->trace(m_styleSheetCollectionMap); | 892 visitor->trace(m_styleSheetCollectionMap); |
752 visitor->trace(m_resolver); | 893 visitor->trace(m_resolver); |
| 894 visitor->trace(m_viewportResolver); |
| 895 visitor->trace(m_medium); |
753 visitor->trace(m_styleInvalidator); | 896 visitor->trace(m_styleInvalidator); |
754 visitor->trace(m_dirtyTreeScopes); | 897 visitor->trace(m_dirtyTreeScopes); |
755 visitor->trace(m_activeTreeScopes); | 898 visitor->trace(m_activeTreeScopes); |
| 899 visitor->trace(m_treeBoundaryCrossingScopes); |
| 900 visitor->trace(m_globalRuleSet); |
756 visitor->trace(m_fontSelector); | 901 visitor->trace(m_fontSelector); |
757 visitor->trace(m_textToSheetCache); | 902 visitor->trace(m_textToSheetCache); |
758 visitor->trace(m_sheetToTextCache); | 903 visitor->trace(m_sheetToTextCache); |
759 CSSFontSelectorClient::trace(visitor); | 904 CSSFontSelectorClient::trace(visitor); |
760 } | 905 } |
761 | 906 |
762 DEFINE_TRACE_WRAPPERS(StyleEngine) | 907 DEFINE_TRACE_WRAPPERS(StyleEngine) |
763 { | 908 { |
764 for (auto sheet : m_injectedAuthorStyleSheets) { | 909 for (auto sheet : m_injectedAuthorStyleSheets) { |
765 visitor->traceWrappers(sheet); | 910 visitor->traceWrappers(sheet); |
766 } | 911 } |
767 visitor->traceWrappers(m_documentStyleSheetCollection); | 912 visitor->traceWrappers(m_documentStyleSheetCollection); |
768 } | 913 } |
769 | 914 |
770 } // namespace blink | 915 } // namespace blink |
OLD | NEW |