Title: [285486] trunk
Revision
285486
Author
[email protected]
Date
2021-11-09 01:29:43 -0800 (Tue, 09 Nov 2021)

Log Message

[CSS Cascade Layers] Support 'revert-layer' value
https://bugs.webkit.org/show_bug.cgi?id=232236
<rdar://problem/84879369>

Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-cascade/revert-layer-008-expected.txt:

Source/WebCore:

'revert-layer' keyword rolls back the value computed by the cascade to the one coming from the layer below.

https://www.w3.org/TR/css-cascade-5/#revert-layer

* css/CSSPrimitiveValue.h:
* css/CSSValue.cpp:
(WebCore::CSSValue::isRevertLayerValue const):
* css/CSSValue.h:
* css/CSSValueKeywords.in:

Add a 'revert-layer' keyword.

* css/parser/CSSParserIdioms.h:
(WebCore::isCSSWideKeyword):

Make the keyword CSS-wide.

(WebCore::isValidCustomIdentifier):
* style/CascadeLevel.h:
(WebCore::Style::operator--):

Add decrement operator.

(WebCore::Style::allCascadeLevels): Deleted.
* style/ElementRuleCollector.cpp:
(WebCore::Style::ElementRuleCollector::addElementStyleProperties):
(WebCore::Style::ElementRuleCollector::transferMatchedRules):

Pass the casdade layer priority so it is available when resolving the cascade.

(WebCore::Style::ElementRuleCollector::addElementInlineStyleProperties):

Add a bit indicating if the properties came from a style attribute. This is needed for correct resolution of !important with cascade layers.

* style/ElementRuleCollector.h:
* style/PropertyCascade.cpp:
(WebCore::Style::PropertyCascade::PropertyCascade):

Specify cascade levels in terms of the maximum level instead of an OptionSet of levels. This makes things simpler.
Make it a member.
Provide maximum cascade layer priority when constructing rollback cascade.

(WebCore::Style::PropertyCascade::buildCascade):
(WebCore::Style::PropertyCascade::setPropertyInternal):
(WebCore::Style::PropertyCascade::addMatch):

Ignore properties with cascade level higher than the maximum.

(WebCore::Style::PropertyCascade::addImportantMatches):

Take cascade layers into accouny when sorting important matches.

(WebCore::Style::PropertyCascade::propertyCascadeForRollback const): Deleted.

Move rollback cascades to Builder.

* style/PropertyCascade.h:
(WebCore::Style::PropertyCascade::maximumCascadeLevel const):
(WebCore::Style::PropertyCascade::maximumCascadeLayerPriority const):
* style/StyleBuilder.cpp:
(WebCore::Style::Builder::Builder):

Specify cascade levels in terms of the maximum level instead of an OptionSet of levels.

(WebCore::Style::Builder::applyCascadeProperty):
(WebCore::Style::Builder::applyProperty):

Construct rollback cascade for 'revert-layer' case too. This is similar to 'revert'.

(WebCore::Style::Builder::ensureRollbackCascadeForRevert):
(WebCore::Style::Builder::ensureRollbackCascadeForRevertLayer):

Make the rollback cascades and store them into a HashMap.

(WebCore::Style::Builder::makeRollbackCascadeKey):
* style/StyleBuilder.h:
* style/StyleBuilderState.h:
* style/StyleResolver.cpp:
(WebCore::Style::Resolver::styleForKeyframe):
(WebCore::Style::Resolver::styleForPage):
(WebCore::Style::Resolver::applyMatchedProperties):

Adopt to the new interface.

LayoutTests:

* TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (285485 => 285486)


--- trunk/LayoutTests/ChangeLog	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/LayoutTests/ChangeLog	2021-11-09 09:29:43 UTC (rev 285486)
@@ -1,3 +1,13 @@
+2021-11-09  Antti Koivisto  <[email protected]>
+
+        [CSS Cascade Layers] Support 'revert-layer' value
+        https://bugs.webkit.org/show_bug.cgi?id=232236
+        <rdar://problem/84879369>
+
+        Reviewed by Simon Fraser.
+
+        * TestExpectations:
+
 2021-11-09  Arcady Goldmints-Orlov  <[email protected]>
 
         [GLIB] Update test expectations and baselines. Unreviewed test gardening.

Modified: trunk/LayoutTests/TestExpectations (285485 => 285486)


--- trunk/LayoutTests/TestExpectations	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/LayoutTests/TestExpectations	2021-11-09 09:29:43 UTC (rev 285486)
@@ -2149,13 +2149,6 @@
 
 imported/w3c/web-platform-tests/css/css-cascade/important-prop.html [ ImageOnlyFailure ]
 webkit.org/b/187093 [ Debug ] imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml.html [ Skip ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-001.html [ ImageOnlyFailure ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-002.html [ ImageOnlyFailure ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-003.html [ ImageOnlyFailure ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-004.html [ ImageOnlyFailure ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-005.html [ ImageOnlyFailure ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-006.html [ ImageOnlyFailure ]
-webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-007.html [ ImageOnlyFailure ]
 
 webkit.org/b/148801 imported/w3c/web-platform-tests/css/css-color/t422-rgba-onscreen-b.xht [ ImageOnlyFailure ]
 webkit.org/b/148801 imported/w3c/web-platform-tests/css/css-color/t422-rgba-onscreen-multiple-boxes-c.xht [ ImageOnlyFailure ]

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (285485 => 285486)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-11-09 09:29:43 UTC (rev 285486)
@@ -1,3 +1,13 @@
+2021-11-09  Antti Koivisto  <[email protected]>
+
+        [CSS Cascade Layers] Support 'revert-layer' value
+        https://bugs.webkit.org/show_bug.cgi?id=232236
+        <rdar://problem/84879369>
+
+        Reviewed by Simon Fraser.
+
+        * web-platform-tests/css/css-cascade/revert-layer-008-expected.txt:
+
 2021-11-09  Arcady Goldmints-Orlov  <[email protected]>
 
         [GLIB] Update test expectations and baselines. Unreviewed test gardening.

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/revert-layer-008-expected.txt (285485 => 285486)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/revert-layer-008-expected.txt	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/revert-layer-008-expected.txt	2021-11-09 09:29:43 UTC (rev 285486)
@@ -1,3 +1,3 @@
 
-FAIL 'revert-layer' should revert font-size to 20px and trigger a smooth transition assert_equals: expected "15px" but got "10px"
+PASS 'revert-layer' should revert font-size to 20px and trigger a smooth transition
 

Modified: trunk/Source/WebCore/ChangeLog (285485 => 285486)


--- trunk/Source/WebCore/ChangeLog	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/ChangeLog	2021-11-09 09:29:43 UTC (rev 285486)
@@ -1,3 +1,95 @@
+2021-11-09  Antti Koivisto  <[email protected]>
+
+        [CSS Cascade Layers] Support 'revert-layer' value
+        https://bugs.webkit.org/show_bug.cgi?id=232236
+        <rdar://problem/84879369>
+
+        Reviewed by Simon Fraser.
+
+        'revert-layer' keyword rolls back the value computed by the cascade to the one coming from the layer below.
+
+        https://www.w3.org/TR/css-cascade-5/#revert-layer
+
+        * css/CSSPrimitiveValue.h:
+        * css/CSSValue.cpp:
+        (WebCore::CSSValue::isRevertLayerValue const):
+        * css/CSSValue.h:
+        * css/CSSValueKeywords.in:
+
+        Add a 'revert-layer' keyword.
+
+        * css/parser/CSSParserIdioms.h:
+        (WebCore::isCSSWideKeyword):
+
+        Make the keyword CSS-wide.
+
+        (WebCore::isValidCustomIdentifier):
+        * style/CascadeLevel.h:
+        (WebCore::Style::operator--):
+
+        Add decrement operator.
+
+        (WebCore::Style::allCascadeLevels): Deleted.
+        * style/ElementRuleCollector.cpp:
+        (WebCore::Style::ElementRuleCollector::addElementStyleProperties):
+        (WebCore::Style::ElementRuleCollector::transferMatchedRules):
+
+        Pass the casdade layer priority so it is available when resolving the cascade.
+
+        (WebCore::Style::ElementRuleCollector::addElementInlineStyleProperties):
+
+        Add a bit indicating if the properties came from a style attribute. This is needed for correct resolution of !important with cascade layers.
+
+        * style/ElementRuleCollector.h:
+        * style/PropertyCascade.cpp:
+        (WebCore::Style::PropertyCascade::PropertyCascade):
+
+        Specify cascade levels in terms of the maximum level instead of an OptionSet of levels. This makes things simpler.
+        Make it a member.
+        Provide maximum cascade layer priority when constructing rollback cascade.
+
+        (WebCore::Style::PropertyCascade::buildCascade):
+        (WebCore::Style::PropertyCascade::setPropertyInternal):
+        (WebCore::Style::PropertyCascade::addMatch):
+
+        Ignore properties with cascade level higher than the maximum.
+
+        (WebCore::Style::PropertyCascade::addImportantMatches):
+
+        Take cascade layers into accouny when sorting important matches.
+
+        (WebCore::Style::PropertyCascade::propertyCascadeForRollback const): Deleted.
+
+        Move rollback cascades to Builder.
+
+        * style/PropertyCascade.h:
+        (WebCore::Style::PropertyCascade::maximumCascadeLevel const):
+        (WebCore::Style::PropertyCascade::maximumCascadeLayerPriority const):
+        * style/StyleBuilder.cpp:
+        (WebCore::Style::Builder::Builder):
+
+        Specify cascade levels in terms of the maximum level instead of an OptionSet of levels.
+
+        (WebCore::Style::Builder::applyCascadeProperty):
+        (WebCore::Style::Builder::applyProperty):
+
+        Construct rollback cascade for 'revert-layer' case too. This is similar to 'revert'.
+
+        (WebCore::Style::Builder::ensureRollbackCascadeForRevert):
+        (WebCore::Style::Builder::ensureRollbackCascadeForRevertLayer):
+
+        Make the rollback cascades and store them into a HashMap.
+
+        (WebCore::Style::Builder::makeRollbackCascadeKey):
+        * style/StyleBuilder.h:
+        * style/StyleBuilderState.h:
+        * style/StyleResolver.cpp:
+        (WebCore::Style::Resolver::styleForKeyframe):
+        (WebCore::Style::Resolver::styleForPage):
+        (WebCore::Style::Resolver::applyMatchedProperties):
+
+        Adopt to the new interface.
+
 2021-11-09  Tim Nguyen  <[email protected]>
 
         Re-use isCSSWideKeyword in CSSVariableParser.cpp & CSSPropertyParser.cpp

Modified: trunk/Source/WebCore/css/CSSPrimitiveValue.h (285485 => 285486)


--- trunk/Source/WebCore/css/CSSPrimitiveValue.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/css/CSSPrimitiveValue.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -120,6 +120,7 @@
     bool isInheritValue() const { return valueID() == CSSValueInherit; }
     bool isUnsetValue() const { return valueID() == CSSValueUnset; }
     bool isRevertValue() const { return valueID() == CSSValueRevert; }
+    bool isRevertLayerValue() const { return valueID() == CSSValueRevertLayer; }
     bool isCSSWideKeyword() const;
 
     static Ref<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) { return adoptRef(*new CSSPrimitiveValue(valueID)); }

Modified: trunk/Source/WebCore/css/CSSValue.cpp (285485 => 285486)


--- trunk/Source/WebCore/css/CSSValue.cpp	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/css/CSSValue.cpp	2021-11-09 09:29:43 UTC (rev 285486)
@@ -510,6 +510,11 @@
     return is<CSSPrimitiveValue>(*this) && downcast<CSSPrimitiveValue>(*this).isRevertValue();
 }
 
+bool CSSValue::isRevertLayerValue() const
+{
+    return is<CSSPrimitiveValue>(*this) && downcast<CSSPrimitiveValue>(*this).isRevertLayerValue();
+}
+
 bool CSSValue::isCSSWideKeyword() const
 {
     return is<CSSPrimitiveValue>(*this) && downcast<CSSPrimitiveValue>(*this).isCSSWideKeyword();

Modified: trunk/Source/WebCore/css/CSSValue.h (285485 => 285486)


--- trunk/Source/WebCore/css/CSSValue.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/css/CSSValue.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -111,6 +111,7 @@
     bool isInitialValue() const;
     bool isUnsetValue() const;
     bool isRevertValue() const;
+    bool isRevertLayerValue() const;
     bool isCSSWideKeyword() const;
     bool treatAsInitialValue(CSSPropertyID) const;
     bool treatAsInheritedValue(CSSPropertyID) const;

Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (285485 => 285486)


--- trunk/Source/WebCore/css/CSSValueKeywords.in	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in	2021-11-09 09:29:43 UTC (rev 285486)
@@ -5,6 +5,7 @@
 initial
 unset
 revert
+revert-layer
 
 //
 // CSS_PROP_OUTLINE_STYLE

Modified: trunk/Source/WebCore/css/parser/CSSParserIdioms.h (285485 => 285486)


--- trunk/Source/WebCore/css/parser/CSSParserIdioms.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/css/parser/CSSParserIdioms.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -60,12 +60,21 @@
 
 bool isValueAllowedInMode(unsigned short, CSSParserMode);
 
-static inline bool isCSSWideKeyword(CSSValueID valueID)
+inline bool isCSSWideKeyword(CSSValueID valueID)
 {
-    return valueID == CSSValueInitial || valueID == CSSValueInherit || valueID == CSSValueUnset || valueID == CSSValueRevert;
+    switch (valueID) {
+    case CSSValueInitial:
+    case CSSValueInherit:
+    case CSSValueUnset:
+    case CSSValueRevert:
+    case CSSValueRevertLayer:
+        return true;
+    default:
+        return false;
+    };
 }
 
-static inline bool isValidCustomIdentifier(CSSValueID valueID)
+inline bool isValidCustomIdentifier(CSSValueID valueID)
 {
     // "default" is obsolete as a CSS-wide keyword but is still not allowed as a custom identifier.
     return !isCSSWideKeyword(valueID) && valueID != CSSValueDefault;

Modified: trunk/Source/WebCore/style/CascadeLevel.h (285485 => 285486)


--- trunk/Source/WebCore/style/CascadeLevel.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/CascadeLevel.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -36,7 +36,18 @@
     Author      = 1 << 2
 };
 
-static constexpr OptionSet<CascadeLevel> allCascadeLevels() { return { CascadeLevel::UserAgent, CascadeLevel::User, CascadeLevel::Author }; }
+inline CascadeLevel& operator--(CascadeLevel& level)
+{
+    switch (level) {
+    case CascadeLevel::Author:
+        return level = CascadeLevel::User;
+    case CascadeLevel::User:
+        return level = CascadeLevel::UserAgent;
+    case CascadeLevel::UserAgent:
+        ASSERT_NOT_REACHED();
+        return level;
+    }
+}
 
 }
 }

Modified: trunk/Source/WebCore/style/ElementRuleCollector.cpp (285485 => 285486)


--- trunk/Source/WebCore/style/ElementRuleCollector.cpp	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/ElementRuleCollector.cpp	2021-11-09 09:29:43 UTC (rev 285486)
@@ -124,7 +124,7 @@
     m_matchedRuleTransferIndex = 0;
 }
 
-inline void ElementRuleCollector::addElementStyleProperties(const StyleProperties* propertySet, bool isCacheable)
+inline void ElementRuleCollector::addElementStyleProperties(const StyleProperties* propertySet, bool isCacheable, FromStyleAttribute fromStyleAttribute)
 {
     if (!propertySet || propertySet->isEmpty())
         return;
@@ -132,7 +132,9 @@
     if (!isCacheable)
         m_result.isCacheable = false;
 
-    addMatchedProperties({ propertySet }, DeclarationOrigin::Author);
+    auto matchedProperty = MatchedProperties { propertySet };
+    matchedProperty.fromStyleAttribute = fromStyleAttribute;
+    addMatchedProperties(WTFMove(matchedProperty), DeclarationOrigin::Author);
 }
 
 void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest)
@@ -203,7 +205,8 @@
             &matchedRule.ruleData->styleRule().properties(),
             static_cast<uint16_t>(matchedRule.ruleData->linkMatchType()),
             matchedRule.ruleData->propertyAllowlist(),
-            matchedRule.styleScopeOrdinal
+            matchedRule.styleScopeOrdinal,
+            matchedRule.cascadeLayerPriority
         }, declarationOrigin);
     }
 }
@@ -560,7 +563,7 @@
     if (auto* inlineStyle = downcast<StyledElement>(element()).inlineStyle()) {
         // FIXME: Media control shadow trees seem to have problems with caching.
         bool isInlineStyleCacheable = !inlineStyle->isMutable() && !element().isInShadowTree();
-        addElementStyleProperties(inlineStyle, isInlineStyleCacheable);
+        addElementStyleProperties(inlineStyle, isInlineStyleCacheable, FromStyleAttribute::Yes);
     }
 
     if (includeSMILProperties && is<SVGElement>(element()))

Modified: trunk/Source/WebCore/style/ElementRuleCollector.h (285485 => 285486)


--- trunk/Source/WebCore/style/ElementRuleCollector.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/ElementRuleCollector.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -63,14 +63,18 @@
     const RuleData* ruleData;
     unsigned specificity;
     ScopeOrdinal styleScopeOrdinal;
-    unsigned cascadeLayerPriority;
+    CascadeLayerPriority cascadeLayerPriority;
 };
 
+enum class FromStyleAttribute : bool { No, Yes };
+
 struct MatchedProperties {
     RefPtr<const StyleProperties> properties;
     uint16_t linkMatchType { SelectorChecker::MatchAll };
     PropertyAllowlist allowlistType { PropertyAllowlist::None };
     ScopeOrdinal styleScopeOrdinal { ScopeOrdinal::Element };
+    CascadeLayerPriority cascadeLayerPriority { RuleSet::cascadeLayerPriorityForUnlayered };
+    FromStyleAttribute fromStyleAttribute { FromStyleAttribute::No };
 };
 
 struct MatchResult {
@@ -121,7 +125,7 @@
     bool didMatchUncommonAttributeSelector() const { return m_didMatchUncommonAttributeSelector; }
 
 private:
-    void addElementStyleProperties(const StyleProperties*, bool isCacheable = true);
+    void addElementStyleProperties(const StyleProperties*, bool isCacheable = true, FromStyleAttribute = FromStyleAttribute::No);
 
     void matchUARules(const RuleSet&);
 

Modified: trunk/Source/WebCore/style/PropertyCascade.cpp (285485 => 285486)


--- trunk/Source/WebCore/style/PropertyCascade.cpp	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/PropertyCascade.cpp	2021-11-09 09:29:43 UTC (rev 285486)
@@ -71,30 +71,35 @@
     }
 }
 
-PropertyCascade::PropertyCascade(const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, IncludedProperties includedProperties, Direction direction)
+PropertyCascade::PropertyCascade(const MatchResult& matchResult, CascadeLevel maximumCascadeLevel, IncludedProperties includedProperties, Direction direction)
     : m_matchResult(matchResult)
     , m_includedProperties(includedProperties)
+    , m_maximumCascadeLevel(maximumCascadeLevel)
     , m_direction(direction)
 {
-    buildCascade(cascadeLevels);
+    buildCascade();
 }
 
-PropertyCascade::PropertyCascade(const PropertyCascade& parent, OptionSet<CascadeLevel> cascadeLevels)
+PropertyCascade::PropertyCascade(const PropertyCascade& parent, CascadeLevel maximumCascadeLevel, CascadeLayerPriority maximumCascadeLayerPriority)
     : m_matchResult(parent.m_matchResult)
     , m_includedProperties(parent.m_includedProperties)
+    , m_maximumCascadeLevel(maximumCascadeLevel)
+    , m_maximumCascadeLayerPriority(maximumCascadeLayerPriority)
     , m_direction(parent.direction())
     , m_directionIsUnresolved(false)
 {
-    buildCascade(cascadeLevels);
+    buildCascade();
 }
 
 PropertyCascade::~PropertyCascade() = default;
 
-void PropertyCascade::buildCascade(OptionSet<CascadeLevel> cascadeLevels)
+void PropertyCascade::buildCascade()
 {
     OptionSet<CascadeLevel> cascadeLevelsWithImportant;
 
-    for (auto cascadeLevel : cascadeLevels) {
+    for (auto cascadeLevel : { CascadeLevel::UserAgent, CascadeLevel::User, CascadeLevel::Author }) {
+        if (cascadeLevel > m_maximumCascadeLevel)
+            break;
         bool hasImportant = addNormalMatches(cascadeLevel);
         if (hasImportant)
             cascadeLevelsWithImportant.add(cascadeLevel);
@@ -113,6 +118,8 @@
     property.id = id;
     property.level = cascadeLevel;
     property.styleScopeOrdinal = matchedProperties.styleScopeOrdinal;
+    property.cascadeLayerPriority = matchedProperties.cascadeLayerPriority;
+
     if (matchedProperties.linkMatchType == SelectorChecker::MatchAll) {
         property.cssValue[0] = &cssValue;
         property.cssValue[SelectorChecker::MatchLink] = &cssValue;
@@ -170,6 +177,9 @@
 
 bool PropertyCascade::addMatch(const MatchedProperties& matchedProperties, CascadeLevel cascadeLevel, bool important)
 {
+    if (matchedProperties.cascadeLayerPriority > m_maximumCascadeLayerPriority && cascadeLevel == m_maximumCascadeLevel && matchedProperties.styleScopeOrdinal == ScopeOrdinal::Element)
+        return false;
+
     auto& styleProperties = *matchedProperties.properties;
     auto propertyAllowlist = matchedProperties.allowlistType;
     bool hasImportantProperties = false;
@@ -237,12 +247,14 @@
 
 void PropertyCascade::addImportantMatches(CascadeLevel cascadeLevel)
 {
-    struct IndexAndOrdinal {
+    struct ImportantMatch {
         unsigned index;
         ScopeOrdinal ordinal;
+        CascadeLayerPriority layerPriority;
+        FromStyleAttribute fromStyleAttribute;
     };
-    Vector<IndexAndOrdinal> importantMatches;
-    bool hasMatchesFromOtherScopes = false;
+    Vector<ImportantMatch> importantMatches;
+    bool hasMatchesFromOtherScopesOrLayers = false;
 
     auto& matchedDeclarations = declarationsForCascadeLevel(m_matchResult, cascadeLevel);
 
@@ -252,20 +264,25 @@
         if (!hasImportantProperties(*matchedProperties.properties))
             continue;
 
-        importantMatches.append({ i, matchedProperties.styleScopeOrdinal });
+        importantMatches.append({ i, matchedProperties.styleScopeOrdinal, matchedProperties.cascadeLayerPriority, matchedProperties.fromStyleAttribute });
 
-        if (matchedProperties.styleScopeOrdinal != ScopeOrdinal::Element)
-            hasMatchesFromOtherScopes = true;
+        if (matchedProperties.styleScopeOrdinal != ScopeOrdinal::Element || matchedProperties.cascadeLayerPriority != RuleSet::cascadeLayerPriorityForUnlayered)
+            hasMatchesFromOtherScopesOrLayers = true;
     }
 
     if (importantMatches.isEmpty())
         return;
 
-    if (hasMatchesFromOtherScopes) {
-        // For !important properties a later shadow tree wins.
+    if (hasMatchesFromOtherScopesOrLayers) {
         // Match results are sorted in reverse tree context order so this is not needed for normal properties.
-        std::stable_sort(importantMatches.begin(), importantMatches.end(), [] (const IndexAndOrdinal& a, const IndexAndOrdinal& b) {
-            return a.ordinal < b.ordinal;
+        std::stable_sort(importantMatches.begin(), importantMatches.end(), [] (auto& a, auto& b) {
+            // For !important properties a later shadow tree wins.
+            if (a.ordinal != b.ordinal)
+                return a.ordinal < b.ordinal;
+            // Lower priority layer wins, except if style attribute is involved.
+            if (a.fromStyleAttribute != b.fromStyleAttribute)
+                return a.fromStyleAttribute == FromStyleAttribute::No;
+            return a.layerPriority > b.layerPriority;
         });
     }
 
@@ -273,30 +290,6 @@
         addMatch(matchedDeclarations[match.index], cascadeLevel, true);
 }
 
-const PropertyCascade* PropertyCascade::propertyCascadeForRollback(CascadeLevel cascadeLevel) const
-{
-    switch (cascadeLevel) {
-    case CascadeLevel::Author:
-        if (!m_authorRollbackCascade) {
-            auto cascadeLevels = OptionSet<CascadeLevel> { CascadeLevel::UserAgent, CascadeLevel::User };
-            m_authorRollbackCascade = makeUnique<const PropertyCascade>(*this, cascadeLevels);
-        }
-        return m_authorRollbackCascade.get();
-
-    case CascadeLevel::User:
-        if (!m_userRollbackCascade) {
-            auto cascadeLevels = OptionSet<CascadeLevel> { CascadeLevel::UserAgent };
-            m_userRollbackCascade = makeUnique<const PropertyCascade>(*this, cascadeLevels);
-        }
-        return m_userRollbackCascade.get();
-
-    case CascadeLevel::UserAgent:
-        return nullptr;
-    }
-    ASSERT_NOT_REACHED();
-    return nullptr;
-}
-
 PropertyCascade::Direction PropertyCascade::resolveDirectionAndWritingMode(Direction inheritedDirection) const
 {
     Direction result = inheritedDirection;

Modified: trunk/Source/WebCore/style/PropertyCascade.h (285485 => 285486)


--- trunk/Source/WebCore/style/PropertyCascade.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/PropertyCascade.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -46,8 +46,8 @@
         WritingMode writingMode;
     };
 
-    PropertyCascade(const MatchResult&, OptionSet<CascadeLevel>, IncludedProperties, Direction);
-    PropertyCascade(const PropertyCascade&, OptionSet<CascadeLevel>);
+    PropertyCascade(const MatchResult&, CascadeLevel, IncludedProperties, Direction);
+    PropertyCascade(const PropertyCascade&, CascadeLevel, CascadeLayerPriority maximumCascadeLayerPriority = RuleSet::cascadeLayerPriorityForUnlayered);
 
     ~PropertyCascade();
 
@@ -55,6 +55,7 @@
         CSSPropertyID id;
         CascadeLevel level;
         ScopeOrdinal styleScopeOrdinal;
+        CascadeLayerPriority cascadeLayerPriority;
         CSSValue* cssValue[3]; // Values for link match states MatchDefault, MatchLink and MatchVisited
     };
 
@@ -69,10 +70,11 @@
 
     Direction direction() const;
 
-    const PropertyCascade* propertyCascadeForRollback(CascadeLevel) const;
+    auto maximumCascadeLevel() const { return m_maximumCascadeLevel; }
+    auto maximumCascadeLayerPriority() const { return m_maximumCascadeLayerPriority; }
 
 private:
-    void buildCascade(OptionSet<CascadeLevel>);
+    void buildCascade();
     bool addNormalMatches(CascadeLevel);
     void addImportantMatches(CascadeLevel);
     bool addMatch(const MatchedProperties&, CascadeLevel, bool important);
@@ -85,6 +87,8 @@
 
     const MatchResult& m_matchResult;
     const IncludedProperties m_includedProperties;
+    const CascadeLevel m_maximumCascadeLevel;
+    const CascadeLayerPriority m_maximumCascadeLayerPriority { RuleSet::cascadeLayerPriorityForUnlayered };
     mutable Direction m_direction;
     mutable bool m_directionIsUnresolved { true };
 
@@ -93,9 +97,6 @@
 
     Vector<Property, 8> m_deferredProperties;
     HashMap<AtomString, Property> m_customProperties;
-
-    mutable std::unique_ptr<const PropertyCascade> m_authorRollbackCascade;
-    mutable std::unique_ptr<const PropertyCascade> m_userRollbackCascade;
 };
 
 inline bool PropertyCascade::hasProperty(CSSPropertyID id) const

Modified: trunk/Source/WebCore/style/RuleSet.h (285485 => 285486)


--- trunk/Source/WebCore/style/RuleSet.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/RuleSet.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -43,6 +43,8 @@
 class Resolver;
 class RuleSet;
 
+using CascadeLayerPriority = uint32_t;
+
 using InvalidationRuleSetVector = Vector<RefPtr<const RuleSet>, 1>;
 
 struct DynamicMediaQueryEvaluationChanges {
@@ -103,8 +105,8 @@
     bool hasShadowPseudoElementRules() const { return !m_shadowPseudoElementRules.isEmpty(); }
     bool hasHostPseudoClassRulesMatchingInShadowTree() const { return m_hasHostPseudoClassRulesMatchingInShadowTree; }
 
-    static constexpr auto cascadeLayerPriorityForUnlayered = std::numeric_limits<unsigned>::max();
-    unsigned cascadeLayerPriorityFor(const RuleData&) const;
+    static constexpr auto cascadeLayerPriorityForUnlayered = std::numeric_limits<CascadeLayerPriority>::max();
+    CascadeLayerPriority cascadeLayerPriorityFor(const RuleData&) const;
 
 private:
     friend class RuleSetBuilder;
@@ -136,7 +138,7 @@
     };
     CascadeLayer& cascadeLayerForIdentifier(CascadeLayerIdentifier identifier) { return m_cascadeLayers[identifier - 1]; }
     const CascadeLayer& cascadeLayerForIdentifier(CascadeLayerIdentifier identifier) const { return m_cascadeLayers[identifier - 1]; }
-    unsigned cascadeLayerPriorityForIdentifier(CascadeLayerIdentifier) const;
+    CascadeLayerPriority cascadeLayerPriorityForIdentifier(CascadeLayerIdentifier) const;
 
     struct DynamicMediaQueryRules {
         Vector<Ref<const MediaQuerySet>> mediaQuerySets;
@@ -193,7 +195,7 @@
     return tagRules->get(key);
 }
 
-inline unsigned RuleSet::cascadeLayerPriorityForIdentifier(CascadeLayerIdentifier identifier) const
+inline CascadeLayerPriority RuleSet::cascadeLayerPriorityForIdentifier(CascadeLayerIdentifier identifier) const
 {
     if (!identifier)
         return cascadeLayerPriorityForUnlayered;
@@ -200,7 +202,7 @@
     return cascadeLayerForIdentifier(identifier).priority;
 }
 
-inline unsigned RuleSet::cascadeLayerPriorityFor(const RuleData& ruleData) const
+inline CascadeLayerPriority RuleSet::cascadeLayerPriorityFor(const RuleData& ruleData) const
 {
     if (m_cascadeLayerIdentifierForRulePosition.size() <= ruleData.position())
         return cascadeLayerPriorityForUnlayered;

Modified: trunk/Source/WebCore/style/StyleBuilder.cpp (285485 => 285486)


--- trunk/Source/WebCore/style/StyleBuilder.cpp	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/StyleBuilder.cpp	2021-11-09 09:29:43 UTC (rev 285486)
@@ -80,8 +80,8 @@
     return false;
 }
 
-Builder::Builder(RenderStyle& style, BuilderContext&& context, const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, PropertyCascade::IncludedProperties includedProperties)
-    : m_cascade(matchResult, cascadeLevels, includedProperties, directionFromStyle(style))
+Builder::Builder(RenderStyle& style, BuilderContext&& context, const MatchResult& matchResult, CascadeLevel cascadeLevel, PropertyCascade::IncludedProperties includedProperties)
+    : m_cascade(matchResult, cascadeLevel, includedProperties, directionFromStyle(style))
     , m_state(*this, style, WTFMove(context))
 {
 }
@@ -121,16 +121,6 @@
     ASSERT(!m_state.fontDirty());
 }
 
-void Builder::applyPropertyValue(CSSPropertyID propertyID, CSSValue* value)
-{
-    if (!value)
-        return;
-
-    applyProperty(propertyID, *value, SelectorChecker::MatchDefault);
-
-    m_state.updateFont();
-}
-
 void Builder::applyDeferredProperties()
 {
     for (auto& property : m_cascade.deferredProperties())
@@ -245,6 +235,7 @@
 {
     m_state.m_cascadeLevel = property.level;
     m_state.m_styleScopeOrdinal = property.styleScopeOrdinal;
+    m_state.m_cascadeLayerPriority = property.cascadeLayerPriority;
 
     auto applyWithLinkMatch = [&](SelectorChecker::LinkMatchMask linkMatch) {
         if (property.cssValue[linkMatch]) {
@@ -295,21 +286,27 @@
 
     bool isUnset = valueToApply->isUnsetValue() || customPropertyValueID == CSSValueUnset;
     bool isRevert = valueToApply->isRevertValue() || customPropertyValueID == CSSValueRevert;
+    bool isRevertLayer = valueToApply->isRevertLayerValue() || customPropertyValueID == CSSValueRevertLayer;
 
-    if (isRevert) {
-        if (auto* rollback = m_cascade.propertyCascadeForRollback(m_state.m_cascadeLevel)) {
+    if (isRevert || isRevertLayer) {
+        auto* rollbackCascade = isRevert
+            ? ensureRollbackCascadeForRevert(m_state.m_cascadeLevel)
+            : ensureRollbackCascadeForRevertLayer(m_state.m_cascadeLevel, m_state.m_cascadeLayerPriority);
+
+        if (rollbackCascade) {
             // With the rollback cascade built, we need to obtain the property and apply it. If the property is
-            // not present, then we behave like "unset." Otherwise we apply the property instead of
-            // our own.
+            // not present, then we behave like "unset." Otherwise we apply the property instead of our own.
+            SetForScope cascadeLevelScope(m_state.m_cascadeLevel, rollbackCascade->maximumCascadeLevel());
+            SetForScope cascadeLayerPriorityScope(m_state.m_cascadeLayerPriority, rollbackCascade->maximumCascadeLayerPriority());
             if (customPropertyValue) {
-                if (customPropertyRegistered && customPropertyRegistered->inherits && rollback->hasCustomProperty(customPropertyValue->name())) {
-                    auto property = rollback->customProperty(customPropertyValue->name());
+                if (customPropertyRegistered && customPropertyRegistered->inherits && rollbackCascade->hasCustomProperty(customPropertyValue->name())) {
+                    auto property = rollbackCascade->customProperty(customPropertyValue->name());
                     if (property.cssValue[linkMatchMask])
                         applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
                     return;
                 }
-            } else if (rollback->hasProperty(id)) {
-                auto& property = rollback->property(id);
+            } else if (rollbackCascade->hasProperty(id)) {
+                auto& property = rollbackCascade->property(id);
                 if (property.cssValue[linkMatchMask])
                     applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
                 return;
@@ -373,5 +370,32 @@
     return CSSParser(m_state.document()).parseValueWithVariableReferences(propertyID, value, m_state);
 }
 
+const PropertyCascade* Builder::ensureRollbackCascadeForRevert(CascadeLevel rollbackCascadeLevel)
+{
+    if (rollbackCascadeLevel == CascadeLevel::UserAgent)
+        return nullptr;
+
+    auto key = makeRollbackCascadeKey(rollbackCascadeLevel, RuleSet::cascadeLayerPriorityForUnlayered);
+    return m_rollbackCascades.ensure(key, [&] {
+        return makeUnique<const PropertyCascade>(m_cascade, --rollbackCascadeLevel, RuleSet::cascadeLayerPriorityForUnlayered);
+    }).iterator->value.get();
 }
+
+const PropertyCascade* Builder::ensureRollbackCascadeForRevertLayer(CascadeLevel cascadeLevel, CascadeLayerPriority rollbackLayerPriority)
+{
+    if (!rollbackLayerPriority)
+        return nullptr;
+
+    auto key = makeRollbackCascadeKey(cascadeLevel, rollbackLayerPriority);
+    return m_rollbackCascades.ensure(key, [&] {
+        return makeUnique<const PropertyCascade>(m_cascade, cascadeLevel, rollbackLayerPriority - 1);
+    }).iterator->value.get();
 }
+
+auto Builder::makeRollbackCascadeKey(CascadeLevel cascadeLevel, CascadeLayerPriority cascadeLayerPriority) -> RollbackCascadeKey
+{
+    return { static_cast<unsigned>(cascadeLevel), static_cast<unsigned>(cascadeLayerPriority) };
+}
+
+}
+}

Modified: trunk/Source/WebCore/style/StyleBuilder.h (285485 => 285486)


--- trunk/Source/WebCore/style/StyleBuilder.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/StyleBuilder.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -35,7 +35,7 @@
 class Builder {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    Builder(RenderStyle&, BuilderContext&&, const MatchResult&, OptionSet<CascadeLevel>, PropertyCascade::IncludedProperties = PropertyCascade::IncludedProperties::All);
+    Builder(RenderStyle&, BuilderContext&&, const MatchResult&, CascadeLevel, PropertyCascade::IncludedProperties = PropertyCascade::IncludedProperties::All);
     ~Builder();
 
     void applyAllProperties();
@@ -45,8 +45,6 @@
     void applyProperty(CSSPropertyID propertyID) { applyProperties(propertyID, propertyID); }
     void applyCustomProperty(const String& name);
 
-    void applyPropertyValue(CSSPropertyID, CSSValue*);
-
     BuilderState& state() { return m_state; }
 
 private:
@@ -63,7 +61,16 @@
     Ref<CSSValue> resolveValue(CSSPropertyID, CSSValue&);
     RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&);
 
+    const PropertyCascade* ensureRollbackCascadeForRevert(CascadeLevel);
+    const PropertyCascade* ensureRollbackCascadeForRevertLayer(CascadeLevel, CascadeLayerPriority);
+
+    using RollbackCascadeKey = std::pair<unsigned, unsigned>;
+    RollbackCascadeKey makeRollbackCascadeKey(CascadeLevel, CascadeLayerPriority);
+
     const PropertyCascade m_cascade;
+    // Rollback cascades are build on demand to resolve 'revert' and 'revert-layer' keywords.
+    HashMap<RollbackCascadeKey, std::unique_ptr<const PropertyCascade>> m_rollbackCascades;
+
     BuilderState m_state;
 };
 

Modified: trunk/Source/WebCore/style/StyleBuilderState.h (285485 => 285486)


--- trunk/Source/WebCore/style/StyleBuilderState.h	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/StyleBuilderState.h	2021-11-09 09:29:43 UTC (rev 285486)
@@ -29,6 +29,7 @@
 #include "CSSToStyleMap.h"
 #include "CascadeLevel.h"
 #include "RenderStyle.h"
+#include "RuleSet.h"
 #include "SelectorChecker.h"
 #include <wtf/Bitmap.h>
 
@@ -136,6 +137,7 @@
 
     CascadeLevel m_cascadeLevel { };
     ScopeOrdinal m_styleScopeOrdinal { };
+    CascadeLayerPriority m_cascadeLayerPriority { };
     SelectorChecker::LinkMatchMask m_linkMatch { };
 
     bool m_fontDirty { false };

Modified: trunk/Source/WebCore/style/StyleResolver.cpp (285485 => 285486)


--- trunk/Source/WebCore/style/StyleResolver.cpp	2021-11-09 08:37:06 UTC (rev 285485)
+++ trunk/Source/WebCore/style/StyleResolver.cpp	2021-11-09 09:29:43 UTC (rev 285486)
@@ -283,7 +283,7 @@
     state.setStyle(RenderStyle::clonePtr(*elementStyle));
     state.setParentStyle(RenderStyle::clonePtr(context.parentStyle ? *context.parentStyle : *elementStyle));
 
-    Builder builder(*state.style(), builderContext(state), result, { CascadeLevel::Author });
+    Builder builder(*state.style(), builderContext(state), result, CascadeLevel::Author);
     builder.applyAllProperties();
 
     Adjuster adjuster(document(), *state.parentStyle(), nullptr, nullptr);
@@ -436,7 +436,7 @@
 
     auto& result = collector.matchResult();
 
-    Builder builder(*state.style(), builderContext(state), result, { CascadeLevel::Author });
+    Builder builder(*state.style(), builderContext(state), result, CascadeLevel::Author);
     builder.applyAllProperties();
 
     // Now return the style.
@@ -555,13 +555,13 @@
         // If so, we cache the border and background styles so that RenderTheme::adjustStyle()
         // can look at them later to figure out if this is a styled form control or not.
         auto userAgentStyle = RenderStyle::clonePtr(style);
-        Builder builder(*userAgentStyle, builderContext(state), matchResult, { CascadeLevel::UserAgent });
+        Builder builder(*userAgentStyle, builderContext(state), matchResult, CascadeLevel::UserAgent);
         builder.applyAllProperties();
 
         state.setUserAgentAppearanceStyle(WTFMove(userAgentStyle));
     }
 
-    Builder builder(*state.style(), builderContext(state), matchResult, allCascadeLevels(), includedProperties);
+    Builder builder(*state.style(), builderContext(state), matchResult, CascadeLevel::Author, includedProperties);
 
     // High priority properties may affect resolution of other properties (they are mostly font related).
     builder.applyHighPriorityProperties();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to