| 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);
|
|
|