Title: [253616] trunk
Revision
253616
Author
an...@apple.com
Date
2019-12-17 01:51:54 -0800 (Tue, 17 Dec 2019)

Log Message

Resolve dynamic media queries without reconstructing RuleSets
https://bugs.webkit.org/show_bug.cgi?id=205264

Reviewed by Zalan Bujtas.

Source/WebCore:

We currently do a full style resolver reset whenever a media query result changes. This is very inefficient
as we need to reconstuct all RuleSets and optimization structures. We also lose related caches and are forced
to re-resolve full document style. This may happen frequently, for example when resizing window on a responsive
web site.

With this patch we construct RuleDatas also for non-matching dynamic media queries and simply mark them disabled.
We create a data structure that allows enabling and disabling them efficiently as a response to environment changes
(like view resize). This allows us to avoid throwing away anything during common scenarios.

Test: fast/media/media-query-dynamic-with-font-face.html

* css/MediaQueryEvaluator.cpp:
(WebCore::MediaQueryEvaluator::evaluate const):

Add a mode where dynamic media queries all evaluate to true and only static properties can cause the query to fail.

* css/MediaQueryEvaluator.h:
* style/ElementRuleCollector.cpp:
(WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):

Skip disabled rules during rule collection.

* style/RuleData.cpp:
(WebCore::Style::RuleData::RuleData):
* style/RuleData.h:
(WebCore::Style::RuleData::isEnabled const):
(WebCore::Style::RuleData::setEnabled):

Add a bit.

* style/RuleSet.cpp:
(WebCore::Style::RuleSet::addRule):

Collect positions of rules affected by dynamic media queries.

(WebCore::Style::RuleSet::addPageRule):
(WebCore::Style::RuleSet::addChildRules):
(WebCore::Style::RuleSet::addRulesFromSheet):

First check for a special case where we have style resolver mutating rules (like @font-face) inside a media query.
In this case we fall back to static resolution.

Then collect the rules. Static media queries (print etc) are evaluated right away, dynamic ones are collected by MediaQueryCollector.

(WebCore::Style::RuleSet::addStyleRule):
(WebCore::Style::RuleSet::traverseRuleDatas):
(WebCore::Style::RuleSet::evaluteDynamicMediaQueryRules):

Evaluate media queries for changes and flip the enabled state of the rules if needed.

(WebCore::Style::RuleSet::MediaQueryCollector::pushAndEvaluate):
(WebCore::Style::RuleSet::MediaQueryCollector::pop):
(WebCore::Style::RuleSet::MediaQueryCollector::didMutateResolver):
(WebCore::Style::RuleSet::MediaQueryCollector::addRulePositionIfNeeded):
* style/RuleSet.h:
(WebCore::Style::RuleSet::hasViewportDependentMediaQueries const):
* style/StyleResolver.cpp:
(WebCore::Style::Resolver::hasViewportDependentMediaQueries const):
(WebCore::Style::Resolver::evaluateDynamicMediaQueries):
(WebCore::Style::Resolver::addMediaQueryDynamicResults): Deleted.
(WebCore::Style::Resolver::hasMediaQueriesAffectedByViewportChange const): Deleted.
(WebCore::Style::Resolver::hasMediaQueriesAffectedByAccessibilitySettingsChange const): Deleted.
(WebCore::Style::Resolver::hasMediaQueriesAffectedByAppearanceChange const): Deleted.

Profiling doesn't show any need to handle the cases separately. Replace with single evaluateDynamicMediaQueries path.
We can bring type specific paths back easily if needed.

* style/StyleResolver.h:
(WebCore::Style::Resolver::hasViewportDependentMediaQueries const): Deleted.
(WebCore::Style::Resolver::hasAccessibilitySettingsDependentMediaQueries const): Deleted.
(WebCore::Style::Resolver::hasAppearanceDependentMediaQueries const): Deleted.
* style/StyleScope.cpp:
(WebCore::Style::Scope::evaluateMediaQueriesForViewportChange):
(WebCore::Style::Scope::evaluateMediaQueriesForAccessibilitySettingsChange):
(WebCore::Style::Scope::evaluateMediaQueriesForAppearanceChange):

Call into general evaluateDynamicMediaQueries.

(WebCore::Style::Scope::evaluateMediaQueries):

In normal case we can just invalidate style, not throw everything away.
This can be further improved by adding optimization rule sets.

* style/StyleScopeRuleSets.cpp:
(WebCore::Style::ScopeRuleSets::updateUserAgentMediaQueryStyleIfNeeded const):
(WebCore::Style::ScopeRuleSets::initializeUserStyle):
(WebCore::Style::ScopeRuleSets::collectRulesFromUserStyleSheets):
(WebCore::Style::makeRuleSet):
(WebCore::Style::ScopeRuleSets::hasViewportDependentMediaQueries const):
(WebCore::Style::ScopeRuleSets::evaluteDynamicMediaQueryRules):
(WebCore::Style::ScopeRuleSets::appendAuthorStyleSheets):
(WebCore::Style::ensureInvalidationRuleSets):
* style/StyleScopeRuleSets.h:

LayoutTests:

Add a test verifying that @font-face inside @media works in dynamic scenarios.

* fast/media/media-query-dynamic-with-font-face-expected.html: Added.
* fast/media/media-query-dynamic-with-font-face.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (253615 => 253616)


--- trunk/LayoutTests/ChangeLog	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/LayoutTests/ChangeLog	2019-12-17 09:51:54 UTC (rev 253616)
@@ -1,3 +1,15 @@
+2019-12-17  Antti Koivisto  <an...@apple.com>
+
+        Resolve dynamic media queries without reconstructing RuleSets
+        https://bugs.webkit.org/show_bug.cgi?id=205264
+
+        Reviewed by Zalan Bujtas.
+
+        Add a test verifying that @font-face inside @media works in dynamic scenarios.
+
+        * fast/media/media-query-dynamic-with-font-face-expected.html: Added.
+        * fast/media/media-query-dynamic-with-font-face.html: Added.
+
 2019-12-16  Said Abou-Hallawa  <sabouhall...@apple.com>
 
         WebGLRenderingContext.texImage2D() should respect EXIF orientation

Added: trunk/LayoutTests/fast/media/media-query-dynamic-with-font-face-expected.html (0 => 253616)


--- trunk/LayoutTests/fast/media/media-query-dynamic-with-font-face-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/media/media-query-dynamic-with-font-face-expected.html	2019-12-17 09:51:54 UTC (rev 253616)
@@ -0,0 +1,11 @@
+<iframe width=100 srcdoc="
+<style>
+@font-face {
+    font-family: family1;
+    src: local(courier);
+}
+body { background-color: green }
+body { font-family:family1 }
+</style>
+Test frame
+"></iframe>

Added: trunk/LayoutTests/fast/media/media-query-dynamic-with-font-face.html (0 => 253616)


--- trunk/LayoutTests/fast/media/media-query-dynamic-with-font-face.html	                        (rev 0)
+++ trunk/LayoutTests/fast/media/media-query-dynamic-with-font-face.html	2019-12-17 09:51:54 UTC (rev 253616)
@@ -0,0 +1,27 @@
+<iframe id=frame srcdoc="
+<style>
+@media (min-width:200px) {
+    @font-face {
+        font-family: family1;
+        src: local(times);
+    }
+    body { background-color: red }
+}
+
+@media (max-width:200px) {
+    @font-face {
+        font-family: family1;
+        src: local(courier);
+    }
+    body { background-color: green }
+}
+body { font-family:family1 }
+</style>
+Test frame
+"></iframe>
+<script>
+frame._onload_ = () => {
+    frame.contentDocument.offsetWidth;
+    frame.width = 100;
+}
+</script>

Modified: trunk/Source/WebCore/ChangeLog (253615 => 253616)


--- trunk/Source/WebCore/ChangeLog	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/ChangeLog	2019-12-17 09:51:54 UTC (rev 253616)
@@ -1,3 +1,104 @@
+2019-12-17  Antti Koivisto  <an...@apple.com>
+
+        Resolve dynamic media queries without reconstructing RuleSets
+        https://bugs.webkit.org/show_bug.cgi?id=205264
+
+        Reviewed by Zalan Bujtas.
+
+        We currently do a full style resolver reset whenever a media query result changes. This is very inefficient
+        as we need to reconstuct all RuleSets and optimization structures. We also lose related caches and are forced
+        to re-resolve full document style. This may happen frequently, for example when resizing window on a responsive
+        web site.
+
+        With this patch we construct RuleDatas also for non-matching dynamic media queries and simply mark them disabled.
+        We create a data structure that allows enabling and disabling them efficiently as a response to environment changes
+        (like view resize). This allows us to avoid throwing away anything during common scenarios.
+
+        Test: fast/media/media-query-dynamic-with-font-face.html
+
+        * css/MediaQueryEvaluator.cpp:
+        (WebCore::MediaQueryEvaluator::evaluate const):
+
+        Add a mode where dynamic media queries all evaluate to true and only static properties can cause the query to fail.
+
+        * css/MediaQueryEvaluator.h:
+        * style/ElementRuleCollector.cpp:
+        (WebCore::Style::ElementRuleCollector::collectMatchingRulesForList):
+
+        Skip disabled rules during rule collection.
+
+        * style/RuleData.cpp:
+        (WebCore::Style::RuleData::RuleData):
+        * style/RuleData.h:
+        (WebCore::Style::RuleData::isEnabled const):
+        (WebCore::Style::RuleData::setEnabled):
+
+        Add a bit.
+
+        * style/RuleSet.cpp:
+        (WebCore::Style::RuleSet::addRule):
+
+        Collect positions of rules affected by dynamic media queries.
+
+        (WebCore::Style::RuleSet::addPageRule):
+        (WebCore::Style::RuleSet::addChildRules):
+        (WebCore::Style::RuleSet::addRulesFromSheet):
+
+        First check for a special case where we have style resolver mutating rules (like @font-face) inside a media query.
+        In this case we fall back to static resolution.
+
+        Then collect the rules. Static media queries (print etc) are evaluated right away, dynamic ones are collected by MediaQueryCollector.
+
+        (WebCore::Style::RuleSet::addStyleRule):
+        (WebCore::Style::RuleSet::traverseRuleDatas):
+        (WebCore::Style::RuleSet::evaluteDynamicMediaQueryRules):
+
+        Evaluate media queries for changes and flip the enabled state of the rules if needed.
+
+        (WebCore::Style::RuleSet::MediaQueryCollector::pushAndEvaluate):
+        (WebCore::Style::RuleSet::MediaQueryCollector::pop):
+        (WebCore::Style::RuleSet::MediaQueryCollector::didMutateResolver):
+        (WebCore::Style::RuleSet::MediaQueryCollector::addRulePositionIfNeeded):
+        * style/RuleSet.h:
+        (WebCore::Style::RuleSet::hasViewportDependentMediaQueries const):
+        * style/StyleResolver.cpp:
+        (WebCore::Style::Resolver::hasViewportDependentMediaQueries const):
+        (WebCore::Style::Resolver::evaluateDynamicMediaQueries):
+        (WebCore::Style::Resolver::addMediaQueryDynamicResults): Deleted.
+        (WebCore::Style::Resolver::hasMediaQueriesAffectedByViewportChange const): Deleted.
+        (WebCore::Style::Resolver::hasMediaQueriesAffectedByAccessibilitySettingsChange const): Deleted.
+        (WebCore::Style::Resolver::hasMediaQueriesAffectedByAppearanceChange const): Deleted.
+
+        Profiling doesn't show any need to handle the cases separately. Replace with single evaluateDynamicMediaQueries path.
+        We can bring type specific paths back easily if needed.
+
+        * style/StyleResolver.h:
+        (WebCore::Style::Resolver::hasViewportDependentMediaQueries const): Deleted.
+        (WebCore::Style::Resolver::hasAccessibilitySettingsDependentMediaQueries const): Deleted.
+        (WebCore::Style::Resolver::hasAppearanceDependentMediaQueries const): Deleted.
+        * style/StyleScope.cpp:
+        (WebCore::Style::Scope::evaluateMediaQueriesForViewportChange):
+        (WebCore::Style::Scope::evaluateMediaQueriesForAccessibilitySettingsChange):
+        (WebCore::Style::Scope::evaluateMediaQueriesForAppearanceChange):
+
+        Call into general evaluateDynamicMediaQueries.
+
+        (WebCore::Style::Scope::evaluateMediaQueries):
+
+        In normal case we can just invalidate style, not throw everything away.
+        This can be further improved by adding optimization rule sets.
+
+        * style/StyleScopeRuleSets.cpp:
+        (WebCore::Style::ScopeRuleSets::updateUserAgentMediaQueryStyleIfNeeded const):
+        (WebCore::Style::ScopeRuleSets::initializeUserStyle):
+        (WebCore::Style::ScopeRuleSets::collectRulesFromUserStyleSheets):
+        (WebCore::Style::makeRuleSet):
+        (WebCore::Style::ScopeRuleSets::hasViewportDependentMediaQueries const):
+        (WebCore::Style::ScopeRuleSets::evaluteDynamicMediaQueryRules):
+        (WebCore::Style::ScopeRuleSets::appendAuthorStyleSheets):
+        (WebCore::Style::ensureInvalidationRuleSets):
+        * style/StyleScopeRuleSets.h:
+
 2019-12-17  youenn fablet  <you...@apple.com>
 
         FileList should be exposed to workers

Modified: trunk/Source/WebCore/css/MediaQueryEvaluator.cpp (253615 => 253616)


--- trunk/Source/WebCore/css/MediaQueryEvaluator.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/css/MediaQueryEvaluator.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -145,7 +145,7 @@
     return r == MediaQuery::Not ? !value : value;
 }
 
-bool MediaQueryEvaluator::evaluate(const MediaQuerySet& querySet, MediaQueryDynamicResults* dynamicResults) const
+bool MediaQueryEvaluator::evaluate(const MediaQuerySet& querySet, MediaQueryDynamicResults* dynamicResults, Mode mode) const
 {
     LOG_WITH_STREAM(MediaQueries, stream << "MediaQueryEvaluator::evaluate on " << (m_document ? m_document->url().string() : emptyString()));
 
@@ -166,22 +166,36 @@
         if (mediaTypeMatch(query.mediaType())) {
             auto& expressions = query.expressions();
             // Iterate through expressions, stop if any of them eval to false (AND semantics).
+            bool isDynamic = false;
             size_t j = 0;
             for (; j < expressions.size(); ++j) {
                 bool expressionResult = evaluate(expressions[j]);
                 if (dynamicResults) {
-                    if (isViewportDependent(expressions[j].mediaFeature()))
+                    if (isViewportDependent(expressions[j].mediaFeature())) {
+                        isDynamic = true;
                         dynamicResults->viewport.append({ expressions[j], expressionResult });
-                    if (isAppearanceDependent(expressions[j].mediaFeature()))
+                    }
+                    if (isAppearanceDependent(expressions[j].mediaFeature())) {
+                        isDynamic = true;
                         dynamicResults->appearance.append({ expressions[j], expressionResult });
-                    if (isAccessibilitySettingsDependent(expressions[j].mediaFeature()))
+                    }
+                    if (isAccessibilitySettingsDependent(expressions[j].mediaFeature())) {
+                        isDynamic = true;
                         dynamicResults->accessibilitySettings.append({ expressions[j], expressionResult });
+                    }
                 }
+                if (mode == Mode::AlwaysMatchDynamic && isDynamic)
+                    continue;
 
                 if (!expressionResult)
                     break;
             }
 
+            if (mode == Mode::AlwaysMatchDynamic && isDynamic) {
+                result = true;
+                continue;
+            }
+
             // Assume true if we are at the end of the list, otherwise assume false.
             result = applyRestrictor(query.restrictor(), expressions.size() == j);
         } else

Modified: trunk/Source/WebCore/css/MediaQueryEvaluator.h (253615 => 253616)


--- trunk/Source/WebCore/css/MediaQueryEvaluator.h	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/css/MediaQueryEvaluator.h	2019-12-17 09:51:54 UTC (rev 253616)
@@ -83,7 +83,8 @@
     bool evaluate(const MediaQueryExpression&) const;
     bool evaluateForChanges(const MediaQueryDynamicResults&) const;
 
-    WEBCORE_EXPORT bool evaluate(const MediaQuerySet&, MediaQueryDynamicResults* = nullptr) const;
+    enum class Mode { Normal, AlwaysMatchDynamic };
+    WEBCORE_EXPORT bool evaluate(const MediaQuerySet&, MediaQueryDynamicResults* = nullptr, Mode = Mode::Normal) const;
 
     static bool mediaAttributeMatches(Document&, const String& attributeValue);
 

Modified: trunk/Source/WebCore/style/ElementRuleCollector.cpp (253615 => 253616)


--- trunk/Source/WebCore/style/ElementRuleCollector.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -524,6 +524,9 @@
     for (unsigned i = 0, size = rules->size(); i < size; ++i) {
         const auto& ruleData = rules->data()[i];
 
+        if (UNLIKELY(!ruleData.isEnabled()))
+            continue;
+
         if (!ruleData.canMatchPseudoElement() && m_pseudoElementRequest.pseudoId != PseudoId::None)
             continue;
 

Modified: trunk/Source/WebCore/style/RuleData.cpp (253615 => 253616)


--- trunk/Source/WebCore/style/RuleData.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/RuleData.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -169,6 +169,7 @@
     , m_containsUncommonAttributeSelector(computeContainsUncommonAttributeSelector(*selector()))
     , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector()))
     , m_propertyWhitelistType(determinePropertyWhitelistType(selector()))
+    , m_isEnabled(true)
     , m_descendantSelectorIdentifierHashes(SelectorFilter::collectHashes(*selector()))
 {
     ASSERT(m_position == position);

Modified: trunk/Source/WebCore/style/RuleData.h (253615 => 253616)


--- trunk/Source/WebCore/style/RuleData.h	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/RuleData.h	2019-12-17 09:51:54 UTC (rev 253616)
@@ -60,6 +60,9 @@
     bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
     unsigned linkMatchType() const { return m_linkMatchType; }
     PropertyWhitelistType propertyWhitelistType() const { return static_cast<PropertyWhitelistType>(m_propertyWhitelistType); }
+    bool isEnabled() const { return m_isEnabled; }
+    void setEnabled(bool value) { m_isEnabled = value; }
+
     const SelectorFilter::Hashes& descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
 
     void disableSelectorFiltering() { m_descendantSelectorIdentifierHashes[0] = 0; }
@@ -76,6 +79,7 @@
     unsigned m_containsUncommonAttributeSelector : 1;
     unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask
     unsigned m_propertyWhitelistType : 2;
+    unsigned m_isEnabled : 1;
     SelectorFilter::Hashes m_descendantSelectorIdentifierHashes;
 };
 

Modified: trunk/Source/WebCore/style/RuleSet.cpp (253615 => 253616)


--- trunk/Source/WebCore/style/RuleSet.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/RuleSet.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -88,11 +88,15 @@
     return leftmostSelector->match() == CSSSelector::PseudoClass && leftmostSelector->pseudoClassType() == CSSSelector::PseudoClassHost;
 }
 
-void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, unsigned selectorListIndex)
+void RuleSet::addRule(StyleRule& rule, unsigned selectorIndex, unsigned selectorListIndex, MediaQueryCollector* mediaQueryCollector)
 {
-    RuleData ruleData(rule, selectorIndex, selectorListIndex, m_ruleCount++);
+    RuleData ruleData(&rule, selectorIndex, selectorListIndex, m_ruleCount++);
+
     m_features.collectFeatures(ruleData);
 
+    if (mediaQueryCollector)
+        mediaQueryCollector->addRulePositionIfNeeded(ruleData.position());
+
     unsigned classBucketSize = 0;
     const CSSSelector* idSelector = nullptr;
     const CSSSelector* tagSelector = nullptr;
@@ -260,65 +264,176 @@
     m_universalRules.append(ruleData);
 }
 
-void RuleSet::addPageRule(StyleRulePage* rule)
+void RuleSet::addPageRule(StyleRulePage& rule)
 {
-    m_pageRules.append(rule);
+    m_pageRules.append(&rule);
 }
 
-void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase>>& rules, const MediaQueryEvaluator& medium, Resolver* resolver, MediaQueryDynamicResults& mediaQueryDynamicResults)
+void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase>>& rules, MediaQueryCollector& mediaQueryCollector, Resolver* resolver, AddRulesMode mode)
 {
     for (auto& rule : rules) {
-        if (is<StyleRule>(*rule))
-            addStyleRule(downcast<StyleRule>(rule.get()));
-        else if (is<StyleRulePage>(*rule))
-            addPageRule(downcast<StyleRulePage>(rule.get()));
-        else if (is<StyleRuleMedia>(*rule)) {
+        if (mode == AddRulesMode::ResolverMutationScan && mediaQueryCollector.didMutateResolverWithinDynamicMediaQuery)
+            break;
+
+        if (is<StyleRule>(*rule)) {
+            if (mode == AddRulesMode::Normal)
+                addStyleRule(downcast<StyleRule>(*rule), mediaQueryCollector);
+            continue;
+        }
+        if (is<StyleRulePage>(*rule)) {
+            if (mode == AddRulesMode::Normal)
+                addPageRule(downcast<StyleRulePage>(*rule));
+            continue;
+        }
+        if (is<StyleRuleMedia>(*rule)) {
             auto& mediaRule = downcast<StyleRuleMedia>(*rule);
-            if ((!mediaRule.mediaQueries() || medium.evaluate(*mediaRule.mediaQueries(), &mediaQueryDynamicResults)))
-                addChildRules(mediaRule.childRules(), medium, resolver, mediaQueryDynamicResults);
-        } else if (is<StyleRuleFontFace>(*rule) && resolver) {
+            if (mediaQueryCollector.pushAndEvaluate(mediaRule.mediaQueries())) {
+                addChildRules(mediaRule.childRules(), mediaQueryCollector, resolver, mode);
+                mediaQueryCollector.pop(mediaRule.mediaQueries());
+            }
+            continue;
+        }
+        if (is<StyleRuleFontFace>(*rule)) {
             // Add this font face to our set.
-            resolver->document().fontSelector().addFontFaceRule(downcast<StyleRuleFontFace>(*rule.get()), false);
-            resolver->invalidateMatchedDeclarationsCache();
-        } else if (is<StyleRuleKeyframes>(*rule) && resolver)
-            resolver->addKeyframeStyle(downcast<StyleRuleKeyframes>(*rule));
-        else if (is<StyleRuleSupports>(*rule) && downcast<StyleRuleSupports>(*rule).conditionIsSupported())
-            addChildRules(downcast<StyleRuleSupports>(*rule).childRules(), medium, resolver, mediaQueryDynamicResults);
+            if (resolver) {
+                resolver->document().fontSelector().addFontFaceRule(downcast<StyleRuleFontFace>(*rule.get()), false);
+                resolver->invalidateMatchedDeclarationsCache();
+            }
+            mediaQueryCollector.didMutateResolver();
+            continue;
+        }
+        if (is<StyleRuleKeyframes>(*rule)) {
+            if (resolver)
+                resolver->addKeyframeStyle(downcast<StyleRuleKeyframes>(*rule));
+            mediaQueryCollector.didMutateResolver();
+            continue;
+        }
+        if (is<StyleRuleSupports>(*rule) && downcast<StyleRuleSupports>(*rule).conditionIsSupported()) {
+            addChildRules(downcast<StyleRuleSupports>(*rule).childRules(), mediaQueryCollector, resolver, mode);
+            continue;
+        }
 #if ENABLE(CSS_DEVICE_ADAPTATION)
-        else if (is<StyleRuleViewport>(*rule) && resolver)
-            resolver->viewportStyleResolver()->addViewportRule(downcast<StyleRuleViewport>(rule.get()));
+        if (is<StyleRuleViewport>(*rule)) {
+            if (resolver)
+                resolver->viewportStyleResolver()->addViewportRule(downcast<StyleRuleViewport>(rule.get()));
+            mediaQueryCollector.didMutateResolver();
+            continue;
+        }
 #endif
     }
 }
 
-void RuleSet::addRulesFromSheet(StyleSheetContents& sheet, const MediaQueryEvaluator& mediaQueryEvaluator, Resolver* resolver)
+void RuleSet::addRulesFromSheet(StyleSheetContents& sheet, const MediaQueryEvaluator& evaluator)
 {
-    MediaQueryDynamicResults mediaQueryDynamicResults;
+    auto mediaQueryCollector = MediaQueryCollector { evaluator };
+    addRulesFromSheet(sheet, mediaQueryCollector, nullptr, AddRulesMode::Normal);
+}
 
+void RuleSet::addRulesFromSheet(StyleSheetContents& sheet, MediaQuerySet* sheetQuery, const MediaQueryEvaluator& evaluator, Style::Resolver& resolver)
+{
+    auto canUseDynamicMediaQueryResolution = [&] {
+        auto mediaQueryCollector = MediaQueryCollector { evaluator, true };
+        if (mediaQueryCollector.pushAndEvaluate(sheetQuery))
+            addRulesFromSheet(sheet, mediaQueryCollector, nullptr, AddRulesMode::ResolverMutationScan);
+        return !mediaQueryCollector.didMutateResolverWithinDynamicMediaQuery;
+    }();
+
+    auto mediaQueryCollector = MediaQueryCollector { evaluator, canUseDynamicMediaQueryResolution };
+
+    if (mediaQueryCollector.pushAndEvaluate(sheetQuery)) {
+        addRulesFromSheet(sheet, mediaQueryCollector, &resolver, AddRulesMode::Normal);
+        mediaQueryCollector.pop(sheetQuery);
+    }
+
+    m_hasViewportDependentMediaQueries = mediaQueryCollector.hasViewportDependentMediaQueries;
+    m_dynamicMediaQueryRules.appendVector(WTFMove(mediaQueryCollector.dynamicMediaQueryRules));
+
+    evaluteDynamicMediaQueryRules(evaluator);
+}
+
+void RuleSet::addRulesFromSheet(StyleSheetContents& sheet, MediaQueryCollector& mediaQueryCollector, Resolver* resolver, AddRulesMode mode)
+{
     for (auto& rule : sheet.importRules()) {
         if (!rule->styleSheet())
             continue;
-        if (rule->mediaQueries() && !mediaQueryEvaluator.evaluate(*rule->mediaQueries(), &mediaQueryDynamicResults))
-            continue;
-        addRulesFromSheet(*rule->styleSheet(), mediaQueryEvaluator, resolver);
+
+        if (mediaQueryCollector.pushAndEvaluate(rule->mediaQueries())) {
+            addRulesFromSheet(*rule->styleSheet(), mediaQueryCollector, resolver, mode);
+            mediaQueryCollector.pop(rule->mediaQueries());
+        }
     }
 
-    addChildRules(sheet.childRules(), mediaQueryEvaluator, resolver, mediaQueryDynamicResults);
+    addChildRules(sheet.childRules(), mediaQueryCollector, resolver, mode);
 
-    if (resolver)
-        resolver->addMediaQueryDynamicResults(mediaQueryDynamicResults);
-
-    if (m_autoShrinkToFitEnabled)
+    if (m_autoShrinkToFitEnabled && mode == AddRulesMode::Normal)
         shrinkToFit();
 }
 
-void RuleSet::addStyleRule(StyleRule* rule)
+void RuleSet::addStyleRule(StyleRule& rule, MediaQueryCollector& mediaQueryCollector)
 {
     unsigned selectorListIndex = 0;
-    for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = rule->selectorList().indexOfNextSelectorAfter(selectorIndex))
-        addRule(rule, selectorIndex, selectorListIndex++);
+    for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = rule.selectorList().indexOfNextSelectorAfter(selectorIndex))
+        addRule(rule, selectorIndex, selectorListIndex++, &mediaQueryCollector);
 }
 
+template<typename Function>
+void RuleSet::traverseRuleDatas(Function&& function)
+{
+    auto traverseVector = [&](auto& vector) {
+        for (auto& ruleData : vector)
+            function(ruleData);
+    };
+
+    auto traverseMap = [&](auto& map) {
+        for (auto& ruleDatas : map.values())
+            traverseVector(*ruleDatas);
+    };
+
+    traverseMap(m_idRules);
+    traverseMap(m_classRules);
+    traverseMap(m_tagLocalNameRules);
+    traverseMap(m_tagLowercaseLocalNameRules);
+    traverseMap(m_shadowPseudoElementRules);
+    traverseVector(m_linkPseudoClassRules);
+#if ENABLE(VIDEO_TRACK)
+    traverseVector(m_cuePseudoRules);
+#endif
+    traverseVector(m_hostPseudoClassRules);
+    traverseVector(m_slottedPseudoElementRules);
+    traverseVector(m_partPseudoElementRules);
+    traverseVector(m_focusPseudoClassRules);
+    traverseVector(m_universalRules);
+}
+
+RuleSet::MediaQueryStyleUpdateType RuleSet::evaluteDynamicMediaQueryRules(const MediaQueryEvaluator& evaluator)
+{
+    bool changes = false;
+    for (auto& dynamicRules : m_dynamicMediaQueryRules) {
+        bool result = true;
+        for (auto& set : dynamicRules.mediaQuerySets) {
+            if (!evaluator.evaluate(set.get())) {
+                result = false;
+                break;
+            }
+        }
+
+        if (result != dynamicRules.result) {
+            dynamicRules.result = result;
+            if (dynamicRules.requiresFullReset)
+                return MediaQueryStyleUpdateType::Reset;
+
+            traverseRuleDatas([&](RuleData& ruleData) {
+                if (!dynamicRules.affectedRulePositions.contains(ruleData.position()))
+                    return;
+                ruleData.setEnabled(result);
+                changes = true;
+            });
+        }
+    }
+
+    return changes ? MediaQueryStyleUpdateType::Resolve : MediaQueryStyleUpdateType::None;
+}
+
 bool RuleSet::hasShadowPseudoElementRules() const
 {
     if (!m_shadowPseudoElementRules.isEmpty())
@@ -355,5 +470,67 @@
     m_features.shrinkToFit();
 }
 
+RuleSet::MediaQueryCollector::~MediaQueryCollector() = default;
+
+bool RuleSet::MediaQueryCollector::pushAndEvaluate(MediaQuerySet* set)
+{
+    if (!set)
+        return true;
+
+    // Only evaluate static expressions that require style rebuild.
+    MediaQueryDynamicResults dynamicResults;
+    auto mode = collectDynamic ? MediaQueryEvaluator::Mode::AlwaysMatchDynamic : MediaQueryEvaluator::Mode::Normal;
+
+    bool result = evaluator.evaluate(*set, &dynamicResults, mode);
+
+    if (!dynamicResults.viewport.isEmpty())
+        hasViewportDependentMediaQueries = true;
+
+    if (!result)
+        return false;
+
+    if (!dynamicResults.isEmpty())
+        dynamicContextStack.append({ *set });
+
+    return true;
+}
+
+void RuleSet::MediaQueryCollector::pop(MediaQuerySet* set)
+{
+    if (!set || dynamicContextStack.isEmpty() || set != &dynamicContextStack.last().set.get())
+        return;
+
+    if (!dynamicContextStack.last().affectedRulePositions.isEmpty()) {
+        DynamicMediaQueryRules rules;
+        for (auto& context : dynamicContextStack)
+            rules.mediaQuerySets.append(context.set.get());
+
+        if (collectDynamic) {
+            auto& toAdd = dynamicContextStack.last().affectedRulePositions;
+            rules.affectedRulePositions.add(toAdd.begin(), toAdd.end());
+        } else
+            rules.requiresFullReset = true;
+
+        dynamicMediaQueryRules.append(WTFMove(rules));
+    }
+
+    dynamicContextStack.removeLast();
+}
+
+void RuleSet::MediaQueryCollector::didMutateResolver()
+{
+    if (dynamicContextStack.isEmpty())
+        return;
+    didMutateResolverWithinDynamicMediaQuery = true;
+}
+
+void RuleSet::MediaQueryCollector::addRulePositionIfNeeded(size_t index)
+{
+    if (dynamicContextStack.isEmpty())
+        return;
+    dynamicContextStack.last().affectedRulePositions.append(index);
+}
+
+
 } // namespace Style
 } // namespace WebCore

Modified: trunk/Source/WebCore/style/RuleSet.h (253615 => 253616)


--- trunk/Source/WebCore/style/RuleSet.h	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/RuleSet.h	2019-12-17 09:51:54 UTC (rev 253616)
@@ -21,6 +21,7 @@
 
 #pragma once
 
+#include "MediaList.h"
 #include "RuleData.h"
 #include "RuleFeature.h"
 #include "SelectorCompiler.h"
@@ -35,7 +36,6 @@
 class CSSSelector;
 class MediaQueryEvaluator;
 class StyleSheetContents;
-struct MediaQueryDynamicResults;
 
 namespace Style {
 
@@ -62,15 +62,50 @@
     typedef Vector<RuleData, 1> RuleDataVector;
     typedef HashMap<AtomString, std::unique_ptr<RuleDataVector>> AtomRuleMap;
 
-    void addRulesFromSheet(StyleSheetContents&, const MediaQueryEvaluator&, Style::Resolver* = nullptr);
+    struct DynamicMediaQueryRules {
+        Vector<Ref<MediaQuerySet>> mediaQuerySets;
+        HashSet<size_t, DefaultHash<size_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<size_t>> affectedRulePositions;
+        bool requiresFullReset { false };
+        bool result { true };
+    };
 
-    void addStyleRule(StyleRule*);
-    void addRule(StyleRule*, unsigned selectorIndex, unsigned selectorListIndex);
-    void addPageRule(StyleRulePage*);
+    struct MediaQueryCollector {
+        ~MediaQueryCollector();
+
+        const MediaQueryEvaluator& evaluator;
+        const bool collectDynamic { false };
+
+        struct DynamicContext {
+            Ref<MediaQuerySet> set;
+            Vector<size_t> affectedRulePositions { };
+        };
+        Vector<DynamicContext> dynamicContextStack { };
+
+        Vector<DynamicMediaQueryRules> dynamicMediaQueryRules { };
+        bool didMutateResolverWithinDynamicMediaQuery { false };
+        bool hasViewportDependentMediaQueries { false };
+
+        bool pushAndEvaluate(MediaQuerySet*);
+        void pop(MediaQuerySet*);
+        void didMutateResolver();
+        void addRulePositionIfNeeded(size_t);
+    };
+
+    void addRulesFromSheet(StyleSheetContents&, const MediaQueryEvaluator&);
+    void addRulesFromSheet(StyleSheetContents&, MediaQuerySet* sheetQuery, const MediaQueryEvaluator&, Style::Resolver&);
+
+    void addStyleRule(StyleRule&, MediaQueryCollector&);
+    void addRule(StyleRule&, unsigned selectorIndex, unsigned selectorListIndex, MediaQueryCollector* = nullptr);
+    void addPageRule(StyleRulePage&);
     void addToRuleSet(const AtomString& key, AtomRuleMap&, const RuleData&);
     void shrinkToFit();
     void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
 
+    bool hasViewportDependentMediaQueries() const { return m_hasViewportDependentMediaQueries; }
+
+    enum class MediaQueryStyleUpdateType { None, Resolve, Reset };
+    MediaQueryStyleUpdateType evaluteDynamicMediaQueryRules(const MediaQueryEvaluator&);
+
     const RuleFeatureSet& features() const { return m_features; }
 
     const RuleDataVector* idRules(const AtomString& key) const { return m_idRules.get(key); }
@@ -95,8 +130,12 @@
     bool hasHostPseudoClassRulesMatchingInShadowTree() const { return m_hasHostPseudoClassRulesMatchingInShadowTree; }
 
 private:
-    void addChildRules(const Vector<RefPtr<StyleRuleBase>>&, const MediaQueryEvaluator& medium, Style::Resolver*, MediaQueryDynamicResults&);
+    enum class AddRulesMode { Normal, ResolverMutationScan };
+    void addRulesFromSheet(StyleSheetContents&, MediaQueryCollector&, Style::Resolver*, AddRulesMode);
+    void addChildRules(const Vector<RefPtr<StyleRuleBase>>&, MediaQueryCollector&, Style::Resolver*, AddRulesMode);
 
+    template<typename Function> void traverseRuleDatas(Function&&);
+
     AtomRuleMap m_idRules;
     AtomRuleMap m_classRules;
     AtomRuleMap m_tagLocalNameRules;
@@ -116,6 +155,8 @@
     bool m_hasHostPseudoClassRulesMatchingInShadowTree { false };
     bool m_autoShrinkToFitEnabled { true };
     RuleFeatureSet m_features;
+    bool m_hasViewportDependentMediaQueries { false };
+    Vector<DynamicMediaQueryRules> m_dynamicMediaQueryRules;
 };
 
 inline const RuleSet::RuleDataVector* RuleSet::tagRules(const AtomString& key, bool isHTMLName) const

Modified: trunk/Source/WebCore/style/StyleResolver.cpp (253615 => 253616)


--- trunk/Source/WebCore/style/StyleResolver.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/StyleResolver.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -602,40 +602,15 @@
         m_matchedDeclarationsCache.add(style, parentStyle, cacheHash, matchResult);
 }
 
-void Resolver::addMediaQueryDynamicResults(const MediaQueryDynamicResults& results)
+bool Resolver::hasViewportDependentMediaQueries() const
 {
-    m_mediaQueryDynamicResults.append(results);
+    return m_ruleSets.hasViewportDependentMediaQueries();
 }
 
-bool Resolver::hasMediaQueriesAffectedByViewportChange() const
+RuleSet::MediaQueryStyleUpdateType Resolver::evaluateDynamicMediaQueries()
 {
-    LOG(MediaQueries, "Style::Resolver::hasMediaQueriesAffectedByViewportChange evaluating queries");
-    for (auto& result : m_mediaQueryDynamicResults.viewport) {
-        if (m_mediaQueryEvaluator.evaluate(result._expression_) != result.result)
-            return true;
-    }
-    return false;
+    return m_ruleSets.evaluteDynamicMediaQueryRules(m_mediaQueryEvaluator);
 }
 
-bool Resolver::hasMediaQueriesAffectedByAccessibilitySettingsChange() const
-{
-    LOG(MediaQueries, "Style::Resolver::hasMediaQueriesAffectedByAccessibilitySettingsChange evaluating queries");
-    for (auto& result : m_mediaQueryDynamicResults.accessibilitySettings) {
-        if (m_mediaQueryEvaluator.evaluate(result._expression_) != result.result)
-            return true;
-    }
-    return false;
-}
-
-bool Resolver::hasMediaQueriesAffectedByAppearanceChange() const
-{
-    LOG(MediaQueries, "Style::Resolver::hasMediaQueriesAffectedByAppearanceChange evaluating queries");
-    for (auto& result : m_mediaQueryDynamicResults.appearance) {
-        if (m_mediaQueryEvaluator.evaluate(result._expression_) != result.result)
-            return true;
-    }
-    return false;
-}
-
 } // namespace Style
 } // namespace WebCore

Modified: trunk/Source/WebCore/style/StyleResolver.h (253615 => 253616)


--- trunk/Source/WebCore/style/StyleResolver.h	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/StyleResolver.h	2019-12-17 09:51:54 UTC (rev 253616)
@@ -131,16 +131,9 @@
     ViewportStyleResolver* viewportStyleResolver() { return m_viewportStyleResolver.get(); }
 #endif
 
-    void addMediaQueryDynamicResults(const MediaQueryDynamicResults&);
-    bool hasViewportDependentMediaQueries() const { return !m_mediaQueryDynamicResults.viewport.isEmpty(); }
-    bool hasMediaQueriesAffectedByViewportChange() const;
+    bool hasViewportDependentMediaQueries() const;
+    RuleSet::MediaQueryStyleUpdateType evaluateDynamicMediaQueries();
 
-    bool hasAccessibilitySettingsDependentMediaQueries() const { return !m_mediaQueryDynamicResults.accessibilitySettings.isEmpty(); }
-    bool hasMediaQueriesAffectedByAccessibilitySettingsChange() const;
-
-    bool hasAppearanceDependentMediaQueries() const { return !m_mediaQueryDynamicResults.appearance.isEmpty(); }
-    bool hasMediaQueriesAffectedByAppearanceChange() const;
-
     void addKeyframeStyle(Ref<StyleRuleKeyframes>&&);
 
     bool usesFirstLineRules() const { return m_ruleSets.features().usesFirstLineRules; }
@@ -200,8 +193,6 @@
 
     RenderStyle* m_overrideDocumentElementStyle { nullptr };
 
-    MediaQueryDynamicResults m_mediaQueryDynamicResults;
-
 #if ENABLE(CSS_DEVICE_ADAPTATION)
     RefPtr<ViewportStyleResolver> m_viewportStyleResolver;
 #endif

Modified: trunk/Source/WebCore/style/StyleScope.cpp (253615 => 253616)


--- trunk/Source/WebCore/style/StyleScope.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/StyleScope.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -622,7 +622,7 @@
 void Scope::evaluateMediaQueriesForViewportChange()
 {
     evaluateMediaQueries([] (Resolver& resolver) {
-        return resolver.hasMediaQueriesAffectedByViewportChange();
+        return resolver.evaluateDynamicMediaQueries();
     });
 }
 
@@ -629,7 +629,7 @@
 void Scope::evaluateMediaQueriesForAccessibilitySettingsChange()
 {
     evaluateMediaQueries([] (Resolver& resolver) {
-        return resolver.hasMediaQueriesAffectedByAccessibilitySettingsChange();
+        return resolver.evaluateDynamicMediaQueries();
     });
 }
 
@@ -636,7 +636,7 @@
 void Scope::evaluateMediaQueriesForAppearanceChange()
 {
     evaluateMediaQueries([] (Resolver& resolver) {
-        return resolver.hasMediaQueriesAffectedByAppearanceChange();
+        return resolver.evaluateDynamicMediaQueries();
     });
 }
 
@@ -650,9 +650,22 @@
     auto* resolver = resolverIfExists();
     if (!resolver)
         return;
-    if (!testFunction(*resolver))
+
+    auto updateType = testFunction(*resolver);
+
+    switch (updateType) {
+    case RuleSet::MediaQueryStyleUpdateType::None:
         return;
-    scheduleUpdate(UpdateType::ContentsOrInterpretation);
+    case RuleSet::MediaQueryStyleUpdateType::Resolve:
+        // FIXME: We could have an invalidation ruleset for rules inside dynamic media queries.
+        if (auto* documentElement = m_document.documentElement())
+            documentElement->invalidateStyleForSubtree();
+        break;
+    case RuleSet::MediaQueryStyleUpdateType::Reset:
+        scheduleUpdate(UpdateType::ContentsOrInterpretation);
+        break;
+    }
+
     InspectorInstrumentation::mediaQueryResultChanged(m_document);
 }
 

Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.cpp (253615 => 253616)


--- trunk/Source/WebCore/style/StyleScopeRuleSets.cpp	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.cpp	2019-12-17 09:51:54 UTC (rev 253616)
@@ -70,18 +70,11 @@
         return;
     m_userAgentMediaQueryRuleCountOnUpdate = ruleCount;
 
-#if !ASSERT_DISABLED
-    bool hadViewportDependentMediaQueries = m_styleResolver.hasViewportDependentMediaQueries();
-#endif
-
     // Media queries on user agent sheet need to evaluated in document context. They behave like author sheets in this respect.
     auto& mediaQueryEvaluator = m_styleResolver.mediaQueryEvaluator();
     m_userAgentMediaQueryStyle = makeUnique<RuleSet>();
     
-    m_userAgentMediaQueryStyle->addRulesFromSheet(*UserAgentStyle::mediaQueryStyleSheet, mediaQueryEvaluator, &m_styleResolver);
-
-    // Viewport dependent queries are currently too inefficient to allow on UA sheet.
-    ASSERT(!m_styleResolver.hasViewportDependentMediaQueries() || hadViewportDependentMediaQueries);
+    m_userAgentMediaQueryStyle->addRulesFromSheet(*UserAgentStyle::mediaQueryStyleSheet, nullptr, mediaQueryEvaluator, m_styleResolver);
 }
 
 RuleSet* ScopeRuleSets::userStyle() const
@@ -97,7 +90,7 @@
     auto& mediaQueryEvaluator = m_styleResolver.mediaQueryEvaluator();
     auto tempUserStyle = makeUnique<RuleSet>();
     if (CSSStyleSheet* pageUserSheet = extensionStyleSheets.pageUserSheet())
-        tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), mediaQueryEvaluator, &m_styleResolver);
+        tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), nullptr, mediaQueryEvaluator, m_styleResolver);
     collectRulesFromUserStyleSheets(extensionStyleSheets.injectedUserStyleSheets(), *tempUserStyle, mediaQueryEvaluator);
     collectRulesFromUserStyleSheets(extensionStyleSheets.documentUserStyleSheets(), *tempUserStyle, mediaQueryEvaluator);
     if (tempUserStyle->ruleCount() > 0 || tempUserStyle->pageRules().size() > 0)
@@ -108,7 +101,7 @@
 {
     for (unsigned i = 0; i < userSheets.size(); ++i) {
         ASSERT(userSheets[i]->contents().isUserStyleSheet());
-        userStyle.addRulesFromSheet(userSheets[i]->contents(), medium, &m_styleResolver);
+        userStyle.addRulesFromSheet(userSheets[i]->contents(), nullptr, medium, m_styleResolver);
     }
 }
 
@@ -119,7 +112,7 @@
         return nullptr;
     auto ruleSet = makeUnique<RuleSet>();
     for (size_t i = 0; i < size; ++i)
-        ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].selectorListIndex);
+        ruleSet->addRule(*rules[i].rule, rules[i].selectorIndex, rules[i].selectorListIndex);
     ruleSet->shrinkToFit();
     return ruleSet;
 }
@@ -136,22 +129,49 @@
     m_userAgentMediaQueryStyle = nullptr;
 }
 
+bool ScopeRuleSets::hasViewportDependentMediaQueries() const
+{
+    if (m_authorStyle->hasViewportDependentMediaQueries())
+        return true;
+    if (m_userStyle && m_userStyle->hasViewportDependentMediaQueries())
+        return true;
+    if (m_userAgentMediaQueryStyle && m_userAgentMediaQueryStyle->hasViewportDependentMediaQueries())
+        return true;
+
+    return false;
+}
+
+RuleSet::MediaQueryStyleUpdateType ScopeRuleSets::evaluteDynamicMediaQueryRules(const MediaQueryEvaluator& evaluator)
+{
+    auto updateType = RuleSet::MediaQueryStyleUpdateType::None;
+
+    auto evaluate = [&](auto& ruleSet) {
+        if (!ruleSet)
+            return false;
+        auto newUpdateType = ruleSet->evaluteDynamicMediaQueryRules(evaluator);
+        if (newUpdateType > updateType)
+            updateType = newUpdateType;
+        return updateType == RuleSet::MediaQueryStyleUpdateType::Reset;
+    };
+
+    if (evaluate(m_authorStyle))
+        return updateType;
+
+    if (evaluate(m_userStyle))
+        return updateType;
+
+    evaluate(m_userAgentMediaQueryStyle);
+    return updateType;
+}
+
 void ScopeRuleSets::appendAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet>>& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers)
 {
-    // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
-    // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
-    MediaQueryDynamicResults mediaQueryDynamicResults;
-
     for (auto& cssSheet : styleSheets) {
         ASSERT(!cssSheet->disabled());
-        if (cssSheet->mediaQueries() && !medium->evaluate(*cssSheet->mediaQueries(), &mediaQueryDynamicResults))
-            continue;
-        m_authorStyle->addRulesFromSheet(cssSheet->contents(), *medium, &m_styleResolver);
+        m_authorStyle->addRulesFromSheet(cssSheet->contents(), cssSheet->mediaQueries(), *medium, m_styleResolver);
         inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet.get());
     }
 
-    m_styleResolver.addMediaQueryDynamicResults(mediaQueryDynamicResults);
-
     m_authorStyle->shrinkToFit();
     collectFeatures();
 }
@@ -200,7 +220,7 @@
             auto& ruleSet = matchElementArray[arrayIndex];
             if (!ruleSet)
                 ruleSet = makeUnique<RuleSet>();
-            ruleSet->addRule(feature.rule, feature.selectorIndex, feature.selectorListIndex);
+            ruleSet->addRule(*feature.rule, feature.selectorIndex, feature.selectorListIndex);
             if (feature.invalidationSelector)
                 invalidationSelectorArray[arrayIndex].append(feature.invalidationSelector);
         }

Modified: trunk/Source/WebCore/style/StyleScopeRuleSets.h (253615 => 253616)


--- trunk/Source/WebCore/style/StyleScopeRuleSets.h	2019-12-17 09:32:03 UTC (rev 253615)
+++ trunk/Source/WebCore/style/StyleScopeRuleSets.h	2019-12-17 09:51:54 UTC (rev 253616)
@@ -78,6 +78,9 @@
 
     void resetUserAgentMediaQueryStyle();
 
+    bool hasViewportDependentMediaQueries() const;
+    RuleSet::MediaQueryStyleUpdateType evaluteDynamicMediaQueryRules(const MediaQueryEvaluator&);
+
     RuleFeatureSet& mutableFeatures();
 
     bool& isInvalidatingStyleWithRuleSets() { return m_isInvalidatingStyleWithRuleSets; }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to