Index: third_party/WebKit/Source/core/dom/StyleEngine.cpp |
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp |
index b7cccd69a0808c85471a3698915ce9c4f613368e..0083e7efae37a2986db3e6871ef1f170faa83a41 100644 |
--- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp |
+++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp |
@@ -35,8 +35,11 @@ |
#include "core/css/StyleSheetContents.h" |
#include "core/css/invalidation/InvalidationSet.h" |
#include "core/css/resolver/ScopedStyleResolver.h" |
+#include "core/css/resolver/SharedStyleFinder.h" |
+#include "core/css/resolver/ViewportStyleResolver.h" |
#include "core/dom/DocumentStyleSheetCollector.h" |
#include "core/dom/Element.h" |
+#include "core/dom/ElementTraversal.h" |
#include "core/dom/ProcessingInstruction.h" |
#include "core/dom/ShadowTreeStyleSheetCollection.h" |
#include "core/dom/StyleChangeReason.h" |
@@ -44,6 +47,7 @@ |
#include "core/frame/Settings.h" |
#include "core/html/HTMLIFrameElement.h" |
#include "core/html/HTMLLinkElement.h" |
+#include "core/html/HTMLSlotElement.h" |
#include "core/html/imports/HTMLImportsController.h" |
#include "core/inspector/InspectorInstrumentation.h" |
#include "core/page/Page.h" |
@@ -59,12 +63,13 @@ StyleEngine::StyleEngine(Document& document) |
: m_document(&document) |
, m_isMaster(!document.importsController() || document.importsController()->master() == &document) |
, m_documentStyleSheetCollection(DocumentStyleSheetCollection::create(document)) |
- // We don't need to create CSSFontSelector for imported document or |
- // HTMLTemplateElement's document, because those documents have no frame. |
- , m_fontSelector(document.frame() ? CSSFontSelector::create(&document) : nullptr) |
{ |
- if (m_fontSelector) |
+ if (document.frame()) { |
+ // We don't need to create CSSFontSelector for imported document or |
+ // HTMLTemplateElement's document, because those documents have no frame. |
+ m_fontSelector = CSSFontSelector::create(&document); |
m_fontSelector->registerForInvalidationCallbacks(this); |
+ } |
} |
StyleEngine::~StyleEngine() |
@@ -110,25 +115,26 @@ TreeScopeStyleSheetCollection* StyleEngine::styleSheetCollectionFor(TreeScope& t |
const HeapVector<Member<StyleSheet>>& StyleEngine::styleSheetsForStyleSheetList(TreeScope& treeScope) |
{ |
+ // TODO(rune@opera.com): we could split styleSheets and active stylesheet |
+ // update to have a lighter update while accessing the styleSheets list. |
+ DCHECK(master()); |
+ if (master()->isActive()) { |
+ if (isMaster()) |
+ updateActiveStyle(); |
+ else |
+ master()->styleEngine().updateActiveStyle(); |
+ } |
+ |
if (treeScope == m_document) |
return documentStyleSheetCollection()->styleSheetsForStyleSheetList(); |
return ensureStyleSheetCollectionFor(treeScope)->styleSheetsForStyleSheetList(); |
} |
-void StyleEngine::resetCSSFeatureFlags(const RuleFeatureSet& features) |
-{ |
- m_usesSiblingRules = features.usesSiblingRules(); |
- m_usesFirstLineRules = features.usesFirstLineRules(); |
- m_usesWindowInactiveSelector = features.usesWindowInactiveSelector(); |
- m_maxDirectAdjacentSelectors = features.maxDirectAdjacentSelectors(); |
-} |
- |
void StyleEngine::injectAuthorSheet(StyleSheetContents* authorSheet) |
{ |
m_injectedAuthorStyleSheets.append(CSSStyleSheet::create(authorSheet, m_document)); |
markDocumentDirty(); |
- resolverChanged(AnalyzedStyleUpdate); |
} |
void StyleEngine::addPendingSheet(StyleEngineContext &context) |
@@ -149,12 +155,12 @@ void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, const StyleE |
markTreeScopeDirty(*treeScope); |
if (context.addedPendingSheetBeforeBody()) { |
- DCHECK_GT(m_pendingRenderBlockingStylesheets, 0); |
+ DCHECK(m_pendingRenderBlockingStylesheets); |
m_pendingRenderBlockingStylesheets--; |
} |
// Make sure we knew this sheet was pending, and that our count isn't out of sync. |
- DCHECK_GT(m_pendingScriptBlockingStylesheets, 0); |
+ DCHECK(m_pendingScriptBlockingStylesheets); |
m_pendingScriptBlockingStylesheets--; |
if (m_pendingScriptBlockingStylesheets) |
@@ -163,25 +169,24 @@ void StyleEngine::removePendingSheet(Node* styleSheetCandidateNode, const StyleE |
document().didRemoveAllPendingStylesheet(); |
} |
-void StyleEngine::setNeedsActiveStyleUpdate(StyleSheet* sheet, StyleResolverUpdateMode updateMode) |
+void StyleEngine::setNeedsActiveStyleUpdate(TreeScope& treeScope) |
{ |
- // resolverChanged() is called for inactive non-master documents because |
- // import documents are inactive documents. resolverChanged() for imports |
- // will call resolverChanged() for the master document and update the active |
- // stylesheets including the ones from the import. |
if (!document().isActive() && isMaster()) |
return; |
+ markTreeScopeDirty(treeScope); |
+} |
+ |
+void StyleEngine::updateActiveStyle() |
+{ |
+ DCHECK(document().isActive()); |
+ |
+ if (!needsActiveStyleUpdate()) |
+ return; |
- if (sheet && document().isActive()) { |
- Node* node = sheet->ownerNode(); |
- if (node && node->inShadowIncludingDocument()) { |
- TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document; |
- DCHECK(isStyleElement(*node) || node->treeScope() == m_document); |
- markTreeScopeDirty(treeScope); |
- } |
- } |
+ updateActiveStyleSheets(); |
+ updateGlobalRuleSet(); |
- resolverChanged(updateMode); |
+ DCHECK(!needsActiveStyleUpdate()); |
} |
void StyleEngine::addStyleSheetCandidateNode(Node* node) |
@@ -229,43 +234,47 @@ void StyleEngine::modifiedStyleSheetCandidateNode(Node* node) |
TreeScope& treeScope = isStyleElement(*node) ? node->treeScope() : *m_document; |
DCHECK(isStyleElement(*node) || treeScope == m_document); |
markTreeScopeDirty(treeScope); |
- resolverChanged(FullStyleUpdate); |
} |
void StyleEngine::watchedSelectorsChanged() |
{ |
- if (m_resolver) { |
- m_resolver->initWatchedSelectorRules(); |
- m_resolver->resetRuleFeatures(); |
- } |
+ m_globalRuleSet.initWatchedSelectorsRuleSet(document()); |
+ m_needsGlobalRuleSetUpdate = true; |
document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::DeclarativeContent)); |
} |
-bool StyleEngine::shouldUpdateDocumentStyleSheetCollection(StyleResolverUpdateMode updateMode) const |
+bool StyleEngine::shouldUpdateDocumentStyleSheetCollection() const |
{ |
- return m_documentScopeDirty || updateMode == FullStyleUpdate; |
+ return m_allTreeScopesDirty || m_documentScopeDirty; |
} |
-bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode updateMode) const |
+bool StyleEngine::shouldUpdateShadowTreeStyleSheetCollection() const |
{ |
- return !m_dirtyTreeScopes.isEmpty() || updateMode == FullStyleUpdate; |
+ return m_allTreeScopesDirty || !m_dirtyTreeScopes.isEmpty(); |
} |
-void StyleEngine::clearMediaQueryRuleSetOnTreeScopeStyleSheets(UnorderedTreeScopeSet& treeScopes) |
+void StyleEngine::mediaQueryAffectingValueChanged(UnorderedTreeScopeSet& treeScopes) |
{ |
for (TreeScope* treeScope : treeScopes) { |
DCHECK(treeScope != m_document); |
ShadowTreeStyleSheetCollection* collection = toShadowTreeStyleSheetCollection(styleSheetCollectionFor(*treeScope)); |
DCHECK(collection); |
- collection->clearMediaQueryRuleSetStyleSheets(); |
+ if (collection->mediaQueryAffectingValueChanged()) |
+ setNeedsActiveStyleUpdate(*treeScope); |
} |
} |
-void StyleEngine::clearMediaQueryRuleSetStyleSheets() |
+void StyleEngine::mediaQueryAffectingValueChanged() |
{ |
- resolverChanged(FullStyleUpdate); |
- documentStyleSheetCollection()->clearMediaQueryRuleSetStyleSheets(); |
- clearMediaQueryRuleSetOnTreeScopeStyleSheets(m_activeTreeScopes); |
+ if (documentStyleSheetCollection()->mediaQueryAffectingValueChanged()) |
+ setNeedsActiveStyleUpdate(document()); |
+ mediaQueryAffectingValueChanged(m_activeTreeScopes); |
+ |
+ if (!document().frame()) |
+ return; |
+ |
+ if (document().wasPrinting() != document().printing() && document().frame()->pageZoomFactor() != 1) |
+ document().setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleSheetChange)); |
} |
void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector) |
@@ -273,16 +282,16 @@ void StyleEngine::updateStyleSheetsInImport(DocumentStyleSheetCollector& parentC |
DCHECK(!isMaster()); |
HeapVector<Member<StyleSheet>> sheetsForList; |
ImportedDocumentStyleSheetCollector subcollector(parentCollector, sheetsForList); |
- documentStyleSheetCollection()->collectStyleSheets(*this, subcollector); |
+ documentStyleSheetCollection()->collectStyleSheets(subcollector); |
documentStyleSheetCollection()->swapSheetsForSheetList(sheetsForList); |
} |
-void StyleEngine::updateActiveStyleSheetsInShadow(StyleResolverUpdateMode updateMode, TreeScope* treeScope, UnorderedTreeScopeSet& treeScopesRemoved) |
+void StyleEngine::updateActiveStyleSheetsInShadow(TreeScope* treeScope, UnorderedTreeScopeSet& treeScopesRemoved) |
{ |
DCHECK_NE(treeScope, m_document); |
ShadowTreeStyleSheetCollection* collection = toShadowTreeStyleSheetCollection(styleSheetCollectionFor(*treeScope)); |
DCHECK(collection); |
- collection->updateActiveStyleSheets(*this, updateMode); |
+ collection->updateActiveStyleSheets(); |
if (!collection->hasStyleSheetCandidateNodes()) { |
treeScopesRemoved.add(treeScope); |
// When removing TreeScope from ActiveTreeScopes, |
@@ -291,29 +300,27 @@ void StyleEngine::updateActiveStyleSheetsInShadow(StyleResolverUpdateMode update |
} |
} |
-void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode) |
+void StyleEngine::updateActiveStyleSheets() |
{ |
+ if (!needsActiveStyleSheetUpdate()) |
+ return; |
+ |
DCHECK(isMaster()); |
DCHECK(!document().inStyleRecalc()); |
- |
- if (!document().isActive()) |
- return; |
+ DCHECK(document().isActive()); |
TRACE_EVENT0("blink,blink_style", "StyleEngine::updateActiveStyleSheets"); |
- if (shouldUpdateDocumentStyleSheetCollection(updateMode)) |
- documentStyleSheetCollection()->updateActiveStyleSheets(*this, updateMode); |
+ if (shouldUpdateDocumentStyleSheetCollection()) { |
+ documentStyleSheetCollection()->updateViewport(); |
+ documentStyleSheetCollection()->updateActiveStyleSheets(); |
+ } |
- if (shouldUpdateShadowTreeStyleSheetCollection(updateMode)) { |
+ if (shouldUpdateShadowTreeStyleSheetCollection()) { |
UnorderedTreeScopeSet treeScopesRemoved; |
- if (updateMode == FullStyleUpdate) { |
- for (TreeScope* treeScope : m_activeTreeScopes) |
- updateActiveStyleSheetsInShadow(updateMode, treeScope, treeScopesRemoved); |
- } else { |
- for (TreeScope* treeScope : m_dirtyTreeScopes) |
- updateActiveStyleSheetsInShadow(updateMode, treeScope, treeScopesRemoved); |
- } |
+ for (TreeScope* treeScope : m_dirtyTreeScopes) |
+ updateActiveStyleSheetsInShadow(treeScope, treeScopesRemoved); |
for (TreeScope* treeScope : treeScopesRemoved) |
m_activeTreeScopes.remove(treeScope); |
} |
@@ -322,14 +329,18 @@ void StyleEngine::updateActiveStyleSheets(StyleResolverUpdateMode updateMode) |
m_dirtyTreeScopes.clear(); |
m_documentScopeDirty = false; |
+ m_allTreeScopesDirty = false; |
} |
-const HeapVector<Member<CSSStyleSheet>> StyleEngine::activeStyleSheetsForInspector() const |
+const ActiveStyleSheetVector StyleEngine::activeStyleSheetsForInspector() |
{ |
+ if (document().isActive()) |
+ updateActiveStyle(); |
+ |
if (m_activeTreeScopes.isEmpty()) |
return documentStyleSheetCollection()->activeAuthorStyleSheets(); |
- HeapVector<Member<CSSStyleSheet>> activeStyleSheets; |
+ ActiveStyleSheetVector activeStyleSheets; |
activeStyleSheets.appendVector(documentStyleSheetCollection()->activeAuthorStyleSheets()); |
for (TreeScope* treeScope : m_activeTreeScopes) { |
@@ -352,27 +363,28 @@ void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot) |
void StyleEngine::shadowRootRemovedFromDocument(ShadowRoot* shadowRoot) |
{ |
- if (StyleResolver* styleResolver = resolver()) { |
- styleResolver->resetAuthorStyle(*shadowRoot); |
- |
- if (TreeScopeStyleSheetCollection* collection = styleSheetCollectionFor(*shadowRoot)) |
- styleResolver->removePendingAuthorStyleSheets(collection->activeAuthorStyleSheets()); |
- } |
+ m_needsGlobalRuleSetUpdate = true; |
+ shadowRoot->clearScopedStyleResolver(); |
m_styleSheetCollectionMap.remove(shadowRoot); |
m_activeTreeScopes.remove(shadowRoot); |
m_dirtyTreeScopes.remove(shadowRoot); |
+ m_treeBoundaryCrossingScopes.remove(&shadowRoot->rootNode()); |
} |
-void StyleEngine::appendActiveAuthorStyleSheets() |
+void StyleEngine::addTreeBoundaryCrossingScope(ContainerNode& scope) |
{ |
- DCHECK(isMaster()); |
+ m_treeBoundaryCrossingScopes.add(&scope); |
+} |
- m_resolver->appendAuthorStyleSheets(documentStyleSheetCollection()->activeAuthorStyleSheets()); |
- for (TreeScope* treeScope : m_activeTreeScopes) { |
- if (TreeScopeStyleSheetCollection* collection = m_styleSheetCollectionMap.get(treeScope)) |
- m_resolver->appendAuthorStyleSheets(collection->activeAuthorStyleSheets()); |
- } |
- m_resolver->finishAppendAuthorStyleSheets(); |
+RuleSet& StyleEngine::ensureRuleSetForSheet(CSSStyleSheet& sheet) |
+{ |
+ if (!sheet.matchesMediaQueries(ensureMediaQueryEvaluator())) |
+ return *RuleSet::emptyRuleSet(); |
+ |
+ AddRuleFlags addRuleFlags = RuleHasNoSpecialState; |
+ if (m_document->getSecurityOrigin()->canRequest(sheet.baseURL())) |
+ addRuleFlags = RuleHasDocumentSecurityOrigin; |
+ return sheet.contents()->ensureRuleSet(*m_medium, addRuleFlags); |
} |
void StyleEngine::createResolver() |
@@ -385,10 +397,6 @@ void StyleEngine::createResolver() |
DCHECK(document().frame()); |
m_resolver = StyleResolver::create(*m_document); |
- |
- // A scoped style resolver for document will be created during |
- // appendActiveAuthorStyleSheets if needed. |
- appendActiveAuthorStyleSheets(); |
} |
void StyleEngine::clearResolver() |
@@ -414,15 +422,11 @@ void StyleEngine::clearResolver() |
} |
} |
-void StyleEngine::clearMasterResolver() |
-{ |
- if (Document* master = this->master()) |
- master->styleEngine().clearResolver(); |
-} |
- |
void StyleEngine::didDetach() |
{ |
clearResolver(); |
+ m_viewportResolver.clear(); |
+ m_medium = nullptr; |
} |
bool StyleEngine::shouldClearResolver() const |
@@ -430,25 +434,6 @@ bool StyleEngine::shouldClearResolver() const |
return !m_didCalculateResolver && !haveScriptBlockingStylesheetsLoaded(); |
} |
-void StyleEngine::resolverChanged(StyleResolverUpdateMode mode) |
-{ |
- if (!isMaster()) { |
- if (Document* master = this->master()) |
- master->styleEngine().resolverChanged(mode); |
- return; |
- } |
- |
- // Don't bother updating, since we haven't loaded all our style info yet |
- // and haven't calculated the style selector for the first time. |
- if (!document().isActive() || shouldClearResolver()) { |
- clearResolver(); |
- return; |
- } |
- |
- m_didCalculateResolver = true; |
- updateActiveStyleSheets(mode); |
-} |
- |
void StyleEngine::clearFontCache() |
{ |
if (m_fontSelector) |
@@ -484,6 +469,25 @@ void StyleEngine::removeFontFaceRules(const HeapVector<Member<const StyleRuleFon |
m_resolver->invalidateMatchedPropertiesCache(); |
} |
+void StyleEngine::removeFontFaceRules(const HeapVector<Member<StyleRuleFontFace>>& fontFaceRules) |
+{ |
+ if (!m_fontSelector) |
+ return; |
+ |
+ FontFaceCache* cache = m_fontSelector->fontFaceCache(); |
+ for (unsigned i = 0; i < fontFaceRules.size(); ++i) |
+ cache->remove(fontFaceRules[i]); |
+ if (m_resolver) |
+ m_resolver->invalidateMatchedPropertiesCache(); |
+} |
+ |
+ViewportStyleResolver& StyleEngine::ensureViewportStyleResolver() |
+{ |
+ if (!m_viewportResolver) |
+ m_viewportResolver = ViewportStyleResolver::create(m_document); |
+ return *m_viewportResolver.get(); |
+} |
+ |
void StyleEngine::markTreeScopeDirty(TreeScope& scope) |
{ |
if (scope == m_document) { |
@@ -493,6 +497,7 @@ void StyleEngine::markTreeScopeDirty(TreeScope& scope) |
DCHECK(m_styleSheetCollectionMap.contains(&scope)); |
m_dirtyTreeScopes.add(&scope); |
+ document().scheduleLayoutTreeUpdateIfNeeded(); |
} |
void StyleEngine::markDocumentDirty() |
@@ -500,19 +505,21 @@ void StyleEngine::markDocumentDirty() |
m_documentScopeDirty = true; |
if (document().importLoader()) |
document().importsController()->master()->styleEngine().markDocumentDirty(); |
+ else |
+ document().scheduleLayoutTreeUpdateIfNeeded(); |
} |
CSSStyleSheet* StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition, StyleEngineContext &context) |
{ |
CSSStyleSheet* styleSheet = nullptr; |
- e->document().styleEngine().addPendingSheet(context); |
+ addPendingSheet(context); |
AtomicString textContent(text); |
HeapHashMap<AtomicString, Member<StyleSheetContents>>::AddResult result = m_textToSheetCache.add(textContent, nullptr); |
if (result.isNewEntry || !result.storedValue->value) { |
- styleSheet = StyleEngine::parseSheet(e, text, startPosition); |
+ styleSheet = parseSheet(e, text, startPosition); |
if (result.isNewEntry && styleSheet->contents()->isCacheableForStyleElement()) { |
result.storedValue->value = styleSheet->contents(); |
m_sheetToTextCache.add(styleSheet->contents(), textContent); |
@@ -521,19 +528,21 @@ CSSStyleSheet* StyleEngine::createSheet(Element* e, const String& text, TextPosi |
StyleSheetContents* contents = result.storedValue->value; |
DCHECK(contents); |
DCHECK(contents->isCacheableForStyleElement()); |
- DCHECK_EQ(contents->singleOwnerDocument(), e->document()); |
+ DCHECK_EQ(contents->singleOwnerDocument(), document()); |
styleSheet = CSSStyleSheet::createInline(contents, e, startPosition); |
} |
DCHECK(styleSheet); |
styleSheet->setTitle(e->title()); |
+ if (!e->isInShadowTree()) |
+ setPreferredStylesheetSetNameIfNotSet(e->title()); |
return styleSheet; |
} |
CSSStyleSheet* StyleEngine::parseSheet(Element* e, const String& text, TextPosition startPosition) |
{ |
CSSStyleSheet* styleSheet = nullptr; |
- styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, e->document().characterSet()); |
+ styleSheet = CSSStyleSheet::createInline(e, KURL(), startPosition, document().characterSet()); |
styleSheet->contents()->parseStringAtPosition(text, startPosition); |
return styleSheet; |
} |
@@ -548,6 +557,20 @@ void StyleEngine::removeSheet(StyleSheetContents* contents) |
m_sheetToTextCache.remove(contents); |
} |
+bool StyleEngine::hasRulesForId(const AtomicString& id) const |
+{ |
+ return m_globalRuleSet.m_features.hasSelectorForId(id); |
+} |
+ |
+void StyleEngine::updateGlobalRuleSet() |
+{ |
+ if (!m_needsGlobalRuleSetUpdate) |
+ return; |
+ |
+ m_globalRuleSet.update(document()); |
+ m_needsGlobalRuleSetUpdate = false; |
+} |
+ |
void StyleEngine::collectScopedStyleFeaturesTo(RuleFeatureSet& features) const |
{ |
HeapHashSet<Member<const StyleSheetContents>> visitedSharedStyleSheetContents; |
@@ -607,9 +630,9 @@ void StyleEngine::classChangedForElement(const SpaceSplitString& changedClasses, |
return; |
InvalidationLists invalidationLists; |
unsigned changedSize = changedClasses.size(); |
- RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSet(); |
+ const RuleFeatureSet& ruleFeatures = ruleFeatureSet(); |
for (unsigned i = 0; i < changedSize; ++i) |
- ruleFeatureSet.collectInvalidationSetsForClass(invalidationLists, element, changedClasses[i]); |
+ ruleFeatures.collectInvalidationSetsForClass(invalidationLists, element, changedClasses[i]); |
m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, element); |
} |
@@ -628,7 +651,7 @@ void StyleEngine::classChangedForElement(const SpaceSplitString& oldClasses, con |
remainingClassBits.ensureSize(oldClasses.size()); |
InvalidationLists invalidationLists; |
- RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSet(); |
+ const RuleFeatureSet& ruleFeatures = ruleFeatureSet(); |
for (unsigned i = 0; i < newClasses.size(); ++i) { |
bool found = false; |
@@ -643,14 +666,14 @@ void StyleEngine::classChangedForElement(const SpaceSplitString& oldClasses, con |
} |
// Class was added. |
if (!found) |
- ruleFeatureSet.collectInvalidationSetsForClass(invalidationLists, element, newClasses[i]); |
+ ruleFeatures.collectInvalidationSetsForClass(invalidationLists, element, newClasses[i]); |
} |
for (unsigned i = 0; i < oldClasses.size(); ++i) { |
if (remainingClassBits.quickGet(i)) |
continue; |
// Class was removed. |
- ruleFeatureSet.collectInvalidationSetsForClass(invalidationLists, element, oldClasses[i]); |
+ ruleFeatures.collectInvalidationSetsForClass(invalidationLists, element, oldClasses[i]); |
} |
m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, element); |
@@ -662,7 +685,7 @@ void StyleEngine::attributeChangedForElement(const QualifiedName& attributeName, |
return; |
InvalidationLists invalidationLists; |
- ensureResolver().ensureUpdatedRuleFeatureSet().collectInvalidationSetsForAttribute(invalidationLists, element, attributeName); |
+ ruleFeatureSet().collectInvalidationSetsForAttribute(invalidationLists, element, attributeName); |
m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, element); |
} |
@@ -672,11 +695,11 @@ void StyleEngine::idChangedForElement(const AtomicString& oldId, const AtomicStr |
return; |
InvalidationLists invalidationLists; |
- RuleFeatureSet& ruleFeatureSet = ensureResolver().ensureUpdatedRuleFeatureSet(); |
+ const RuleFeatureSet& ruleFeatures = ruleFeatureSet(); |
if (!oldId.isEmpty()) |
- ruleFeatureSet.collectInvalidationSetsForId(invalidationLists, element, oldId); |
+ ruleFeatures.collectInvalidationSetsForId(invalidationLists, element, oldId); |
if (!newId.isEmpty()) |
- ruleFeatureSet.collectInvalidationSetsForId(invalidationLists, element, newId); |
+ ruleFeatures.collectInvalidationSetsForId(invalidationLists, element, newId); |
m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, element); |
} |
@@ -686,7 +709,7 @@ void StyleEngine::pseudoStateChangedForElement(CSSSelector::PseudoType pseudoTyp |
return; |
InvalidationLists invalidationLists; |
- ensureResolver().ensureUpdatedRuleFeatureSet().collectInvalidationSetsForPseudoClass(invalidationLists, element, pseudoType); |
+ ruleFeatureSet().collectInvalidationSetsForPseudoClass(invalidationLists, element, pseudoType); |
m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, element); |
} |
@@ -702,6 +725,76 @@ void StyleEngine::setStatsEnabled(bool enabled) |
m_styleResolverStats->reset(); |
} |
+void StyleEngine::scheduleRuleSetInvalidationsForElement(Element& element, const HeapVector<Member<RuleSet>>& ruleSets) |
+{ |
+ AtomicString id; |
+ const SpaceSplitString* classNames = nullptr; |
+ bool typeSelectorMatch = false; |
+ const AtomicString& shadowPseudoId = element.shadowPseudoId(); |
+ bool customPseudoMatch = shadowPseudoId.isEmpty(); |
+ |
+ if (element.hasID()) |
+ id = element.idForStyleResolution(); |
+ if (element.hasClass()) |
+ classNames = &element.classNames(); |
+ |
+ InvalidationLists invalidationLists; |
+ for (const auto& ruleSet : ruleSets) { |
+ |
+ if (!id.isNull()) |
+ ruleSet->features().collectInvalidationSetsForId(invalidationLists, element, id); |
+ |
+ if (classNames) { |
+ unsigned classNameCount = classNames->size(); |
+ for (size_t i = 0; i < classNameCount; i++) |
+ ruleSet->features().collectInvalidationSetsForClass(invalidationLists, element, (*classNames)[i]); |
+ } |
+ |
+ for (const Attribute& attribute : element.attributes()) |
+ ruleSet->features().collectInvalidationSetsForAttribute(invalidationLists, element, attribute.name()); |
+ |
+ if (element.needsStyleRecalc()) |
+ continue; |
+ |
+ if (!typeSelectorMatch && ruleSet->tagRules(element.localNameForSelectorMatching())) { |
+ typeSelectorMatch = true; |
+ element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleSheetChange)); |
+ } |
+ |
+ if (!customPseudoMatch && ruleSet->shadowPseudoElementRules(shadowPseudoId)) { |
+ customPseudoMatch = true; |
+ element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleSheetChange)); |
+ } |
+ } |
+ m_styleInvalidator.scheduleInvalidationSetsForElement(invalidationLists, element); |
+} |
+ |
+void StyleEngine::scheduleInvalidationsForRuleSets(TreeScope& treeScope, const HeapVector<Member<RuleSet>>& ruleSets) |
+{ |
+ if (treeScope.rootNode().isShadowRoot()) { |
+ Element& host = toShadowRoot(treeScope.rootNode()).host(); |
+ scheduleRuleSetInvalidationsForElement(host, ruleSets); |
+ if (host.getStyleChangeType() >= SubtreeStyleChange) |
+ return; |
+ } |
+ |
+ Node* stayWithin = &treeScope.rootNode(); |
+ Element* element = ElementTraversal::firstChild(*stayWithin); |
+ while (element) { |
+ scheduleRuleSetInvalidationsForElement(*element, ruleSets); |
+ if (isHTMLSlotElement(element)) { |
+ for (auto& node : toHTMLSlotElement(element)->getDistributedNodes()) { |
+ if (node->isElementNode()) |
+ scheduleRuleSetInvalidationsForElement(*toElement(node), ruleSets); |
+ } |
+ } |
+ if (element->getStyleChangeType() < SubtreeStyleChange) |
+ element = ElementTraversal::next(*element, stayWithin); |
+ else |
+ element = ElementTraversal::nextSkippingChildren(*element, stayWithin); |
+ } |
+} |
+ |
void StyleEngine::setPreferredStylesheetSetNameIfNotSet(const String& name) |
{ |
if (!m_preferredStylesheetSetName.isEmpty()) |
@@ -731,16 +824,64 @@ void StyleEngine::setHttpDefaultStyle(const String& content) |
{ |
setPreferredStylesheetSetNameIfNotSet(content); |
markDocumentDirty(); |
- resolverChanged(FullStyleUpdate); |
} |
-void StyleEngine::ensureFullscreenUAStyle() |
+void StyleEngine::ensureUAStyleForFullscreen() |
{ |
- CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetForFullscreen(); |
- if (!m_resolver) |
- return; |
- if (!m_resolver->hasFullscreenUAStyle()) |
- m_resolver->resetRuleFeatures(); |
+ if (CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetForFullscreen()) { |
+ m_needsGlobalRuleSetUpdate = true; |
+ updateGlobalRuleSet(); |
+ } |
+} |
+ |
+void StyleEngine::ensureUAStyleForElement(const Element& element) |
+{ |
+ if (CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(element)) { |
+ m_needsGlobalRuleSetUpdate = true; |
+ updateGlobalRuleSet(); |
+ } |
+} |
+ |
+PassRefPtr<ComputedStyle> StyleEngine::findSharedStyle(const ElementResolveContext& elementResolveContext) |
+{ |
+ return SharedStyleFinder(elementResolveContext, |
+ m_globalRuleSet.m_features, |
+ m_globalRuleSet.m_siblingRuleSet.get(), |
+ m_globalRuleSet.m_uncommonAttributeRuleSet.get(), |
+ *m_resolver).findSharedStyle(); |
+} |
+ |
+MediaQueryEvaluator& StyleEngine::ensureMediaQueryEvaluator() |
+{ |
+ if (!m_medium) { |
+ if (document().frame()) |
+ m_medium = new MediaQueryEvaluator(document().frame()); |
+ else |
+ m_medium = new MediaQueryEvaluator("all"); |
+ } |
+ return *m_medium; |
+} |
+ |
+bool StyleEngine::mediaQueryAffectedByViewportChange() |
+{ |
+ const MediaQueryEvaluator& evaluator = ensureMediaQueryEvaluator(); |
+ const auto& results = m_globalRuleSet.m_features.viewportDependentMediaQueryResults; |
+ for (unsigned i = 0; i < results.size(); ++i) { |
+ if (evaluator.eval(results[i]->expression()) != results[i]->result()) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+bool StyleEngine::mediaQueryAffectedByDeviceChange() |
+{ |
+ const MediaQueryEvaluator& evaluator = ensureMediaQueryEvaluator(); |
+ const auto& results = m_globalRuleSet.m_features.deviceDependentMediaQueryResults; |
+ for (unsigned i = 0; i < results.size(); ++i) { |
+ if (evaluator.eval(results[i]->expression()) != results[i]->result()) |
+ return true; |
+ } |
+ return false; |
} |
DEFINE_TRACE(StyleEngine) |
@@ -750,9 +891,13 @@ DEFINE_TRACE(StyleEngine) |
visitor->trace(m_documentStyleSheetCollection); |
visitor->trace(m_styleSheetCollectionMap); |
visitor->trace(m_resolver); |
+ visitor->trace(m_viewportResolver); |
+ visitor->trace(m_medium); |
visitor->trace(m_styleInvalidator); |
visitor->trace(m_dirtyTreeScopes); |
visitor->trace(m_activeTreeScopes); |
+ visitor->trace(m_treeBoundaryCrossingScopes); |
+ visitor->trace(m_globalRuleSet); |
visitor->trace(m_fontSelector); |
visitor->trace(m_textToSheetCache); |
visitor->trace(m_sheetToTextCache); |