Changeset 285624 in webkit


Ignore:
Timestamp:
Nov 11, 2021 4:24:18 AM (8 months ago)
Author:
Antti Koivisto
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:
  • web-platform-tests/css/css-will-change/parsing/will-change-invalid:

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:

Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r285623 r285624  
     12021-11-11  Antti Koivisto  <antti@apple.com>
     2
     3        [CSS Cascade Layers] Support 'revert-layer' value
     4        https://bugs.webkit.org/show_bug.cgi?id=232236
     5        <rdar://problem/84879369>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * TestExpectations:
     10
    1112021-11-10  Sergio Villar Senin  <svillar@igalia.com>
    212
  • trunk/LayoutTests/TestExpectations

    r285623 r285624  
    21502150imported/w3c/web-platform-tests/css/css-cascade/important-prop.html [ ImageOnlyFailure ]
    21512151webkit.org/b/187093 [ Debug ] imported/w3c/web-platform-tests/css/css-cascade/all-prop-initial-xml.html [ Skip ]
    2152 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-001.html [ ImageOnlyFailure ]
    2153 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-002.html [ ImageOnlyFailure ]
    2154 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-003.html [ ImageOnlyFailure ]
    2155 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-004.html [ ImageOnlyFailure ]
    2156 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-005.html [ ImageOnlyFailure ]
    2157 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-006.html [ ImageOnlyFailure ]
    2158 webkit.org/b/232236 imported/w3c/web-platform-tests/css/css-cascade/revert-layer-007.html [ ImageOnlyFailure ]
    21592152
    21602153webkit.org/b/148801 imported/w3c/web-platform-tests/css/css-color/t422-rgba-onscreen-b.xht [ ImageOnlyFailure ]
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r285621 r285624  
     12021-11-11  Antti Koivisto  <antti@apple.com>
     2
     3        [CSS Cascade Layers] Support 'revert-layer' value
     4        https://bugs.webkit.org/show_bug.cgi?id=232236
     5        <rdar://problem/84879369>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * web-platform-tests/css/css-cascade/revert-layer-008-expected.txt:
     10        * web-platform-tests/css/css-will-change/parsing/will-change-invalid:
     11
    1122021-11-11  Antoine Quint  <graouts@webkit.org>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-cascade/revert-layer-008-expected.txt

    r285493 r285624  
    11
    2 FAIL 'revert-layer' should revert font-size to 20px and trigger a smooth transition assert_equals: expected "15px" but got "10px"
     2PASS 'revert-layer' should revert font-size to 20px and trigger a smooth transition
    33
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-will-change/parsing/will-change-invalid-expected.txt

    r285499 r285624  
    4848PASS e.style['will-change'] = "revert, none" should not set the property value
    4949PASS e.style['will-change'] = "revert, all" should not set the property value
    50 FAIL e.style['will-change'] = "transform, revert-layer" should not set the property value assert_equals: expected "" but got "transform, revert-layer"
    51 FAIL e.style['will-change'] = "revert-layer, transform" should not set the property value assert_equals: expected "" but got "revert-layer, transform"
     50PASS e.style['will-change'] = "transform, revert-layer" should not set the property value
     51PASS e.style['will-change'] = "revert-layer, transform" should not set the property value
    5252PASS e.style['will-change'] = "revert-layer, initial" should not set the property value
    5353PASS e.style['will-change'] = "revert-layer, inherit" should not set the property value
    5454PASS e.style['will-change'] = "revert-layer, unset" should not set the property value
    5555PASS e.style['will-change'] = "revert-layer, revert" should not set the property value
    56 FAIL e.style['will-change'] = "revert-layer, revert-layer" should not set the property value assert_equals: expected "" but got "revert-layer, revert-layer"
     56PASS e.style['will-change'] = "revert-layer, revert-layer" should not set the property value
    5757PASS e.style['will-change'] = "revert-layer, default" should not set the property value
    5858PASS e.style['will-change'] = "revert-layer, will-change" should not set the property value
  • trunk/Source/WebCore/ChangeLog

    r285623 r285624  
     12021-11-11  Antti Koivisto  <antti@apple.com>
     2
     3        [CSS Cascade Layers] Support 'revert-layer' value
     4        https://bugs.webkit.org/show_bug.cgi?id=232236
     5        <rdar://problem/84879369>
     6
     7        Reviewed by Simon Fraser.
     8
     9        'revert-layer' keyword rolls back the value computed by the cascade to the one coming from the layer below.
     10
     11        https://www.w3.org/TR/css-cascade-5/#revert-layer
     12
     13        * css/CSSPrimitiveValue.h:
     14        * css/CSSValue.cpp:
     15        (WebCore::CSSValue::isRevertLayerValue const):
     16        * css/CSSValue.h:
     17        * css/CSSValueKeywords.in:
     18
     19        Add a 'revert-layer' keyword.
     20
     21        * css/parser/CSSParserIdioms.h:
     22        (WebCore::isCSSWideKeyword):
     23
     24        Make the keyword CSS-wide.
     25
     26        (WebCore::isValidCustomIdentifier):
     27        * style/CascadeLevel.h:
     28        (WebCore::Style::operator--):
     29
     30        Add decrement operator.
     31
     32        (WebCore::Style::allCascadeLevels): Deleted.
     33        * style/ElementRuleCollector.cpp:
     34        (WebCore::Style::ElementRuleCollector::addElementStyleProperties):
     35        (WebCore::Style::ElementRuleCollector::transferMatchedRules):
     36
     37        Pass the casdade layer priority so it is available when resolving the cascade.
     38
     39        (WebCore::Style::ElementRuleCollector::addElementInlineStyleProperties):
     40
     41        Add a bit indicating if the properties came from a style attribute. This is needed for correct resolution of !important with cascade layers.
     42
     43        * style/ElementRuleCollector.h:
     44        * style/PropertyCascade.cpp:
     45        (WebCore::Style::PropertyCascade::PropertyCascade):
     46
     47        Specify cascade levels in terms of the maximum level instead of an OptionSet of levels. This makes things simpler.
     48        Make it a member.
     49        Provide maximum cascade layer priority when constructing rollback cascade.
     50
     51        (WebCore::Style::PropertyCascade::buildCascade):
     52        (WebCore::Style::PropertyCascade::setPropertyInternal):
     53        (WebCore::Style::PropertyCascade::addMatch):
     54
     55        Ignore properties with cascade level higher than the maximum.
     56
     57        (WebCore::Style::PropertyCascade::addImportantMatches):
     58
     59        Take cascade layers into accouny when sorting important matches.
     60
     61        (WebCore::Style::PropertyCascade::propertyCascadeForRollback const): Deleted.
     62
     63        Move rollback cascades to Builder.
     64
     65        * style/PropertyCascade.h:
     66        (WebCore::Style::PropertyCascade::maximumCascadeLevel const):
     67        (WebCore::Style::PropertyCascade::maximumCascadeLayerPriority const):
     68        * style/StyleBuilder.cpp:
     69        (WebCore::Style::Builder::Builder):
     70
     71        Specify cascade levels in terms of the maximum level instead of an OptionSet of levels.
     72
     73        (WebCore::Style::Builder::applyCascadeProperty):
     74        (WebCore::Style::Builder::applyProperty):
     75
     76        Construct rollback cascade for 'revert-layer' case too. This is similar to 'revert'.
     77
     78        (WebCore::Style::Builder::ensureRollbackCascadeForRevert):
     79        (WebCore::Style::Builder::ensureRollbackCascadeForRevertLayer):
     80
     81        Make the rollback cascades and store them into a HashMap.
     82
     83        (WebCore::Style::Builder::makeRollbackCascadeKey):
     84        * style/StyleBuilder.h:
     85        * style/StyleBuilderState.h:
     86        * style/StyleResolver.cpp:
     87        (WebCore::Style::Resolver::styleForKeyframe):
     88        (WebCore::Style::Resolver::styleForPage):
     89        (WebCore::Style::Resolver::applyMatchedProperties):
     90
     91        Adopt to the new interface.
     92
    1932021-11-10  Sergio Villar Senin  <svillar@igalia.com>
    294
  • trunk/Source/WebCore/css/CSSPrimitiveValue.h

    r285493 r285624  
    121121    bool isUnsetValue() const { return valueID() == CSSValueUnset; }
    122122    bool isRevertValue() const { return valueID() == CSSValueRevert; }
     123    bool isRevertLayerValue() const { return valueID() == CSSValueRevertLayer; }
    123124    bool isCSSWideKeyword() const;
    124125
  • trunk/Source/WebCore/css/CSSValue.cpp

    r285493 r285624  
    511511}
    512512
     513bool CSSValue::isRevertLayerValue() const
     514{
     515    return is<CSSPrimitiveValue>(*this) && downcast<CSSPrimitiveValue>(*this).isRevertLayerValue();
     516}
     517
    513518bool CSSValue::isCSSWideKeyword() const
    514519{
  • trunk/Source/WebCore/css/CSSValue.h

    r285493 r285624  
    112112    bool isUnsetValue() const;
    113113    bool isRevertValue() const;
     114    bool isRevertLayerValue() const;
    114115    bool isCSSWideKeyword() const;
    115116    bool treatAsInitialValue(CSSPropertyID) const;
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r285615 r285624  
    66unset
    77revert
     8revert-layer
    89
    910//
  • trunk/Source/WebCore/css/parser/CSSParserIdioms.h

    r285493 r285624  
    6161bool isValueAllowedInMode(unsigned short, CSSParserMode);
    6262
    63 static inline bool isCSSWideKeyword(CSSValueID valueID)
     63inline bool isCSSWideKeyword(CSSValueID valueID)
    6464{
    65     return valueID == CSSValueInitial || valueID == CSSValueInherit || valueID == CSSValueUnset || valueID == CSSValueRevert;
     65    switch (valueID) {
     66    case CSSValueInitial:
     67    case CSSValueInherit:
     68    case CSSValueUnset:
     69    case CSSValueRevert:
     70    case CSSValueRevertLayer:
     71        return true;
     72    default:
     73        return false;
     74    };
    6675}
    6776
    68 static inline bool isValidCustomIdentifier(CSSValueID valueID)
     77inline bool isValidCustomIdentifier(CSSValueID valueID)
    6978{
    7079    // "default" is obsolete as a CSS-wide keyword but is still not allowed as a custom identifier.
  • trunk/Source/WebCore/style/CascadeLevel.h

    r285493 r285624  
    3737};
    3838
    39 static constexpr OptionSet<CascadeLevel> allCascadeLevels() { return { CascadeLevel::UserAgent, CascadeLevel::User, CascadeLevel::Author }; }
     39inline CascadeLevel& operator--(CascadeLevel& level)
     40{
     41    switch (level) {
     42    case CascadeLevel::Author:
     43        return level = CascadeLevel::User;
     44    case CascadeLevel::User:
     45        return level = CascadeLevel::UserAgent;
     46    case CascadeLevel::UserAgent:
     47        ASSERT_NOT_REACHED();
     48        return level;
     49    }
     50}
    4051
    4152}
  • trunk/Source/WebCore/style/ElementRuleCollector.cpp

    r285622 r285624  
    125125}
    126126
    127 inline void ElementRuleCollector::addElementStyleProperties(const StyleProperties* propertySet, bool isCacheable)
     127inline void ElementRuleCollector::addElementStyleProperties(const StyleProperties* propertySet, bool isCacheable, FromStyleAttribute fromStyleAttribute)
    128128{
    129129    if (!propertySet || propertySet->isEmpty())
     
    133133        m_result.isCacheable = false;
    134134
    135     addMatchedProperties({ propertySet }, DeclarationOrigin::Author);
     135    auto matchedProperty = MatchedProperties { propertySet };
     136    matchedProperty.fromStyleAttribute = fromStyleAttribute;
     137    addMatchedProperties(WTFMove(matchedProperty), DeclarationOrigin::Author);
    136138}
    137139
     
    202204        addMatchedProperties({
    203205            &matchedRule.ruleData->styleRule().properties(),
    204             static_cast<uint16_t>(matchedRule.ruleData->linkMatchType()),
     206            static_cast<uint8_t>(matchedRule.ruleData->linkMatchType()),
    205207            matchedRule.ruleData->propertyAllowlist(),
    206             matchedRule.styleScopeOrdinal
     208            matchedRule.styleScopeOrdinal,
     209            FromStyleAttribute::No,
     210            matchedRule.cascadeLayerPriority
    207211        }, declarationOrigin);
    208212    }
     
    567571        // FIXME: Media control shadow trees seem to have problems with caching.
    568572        bool isInlineStyleCacheable = !inlineStyle->isMutable() && !element().isInShadowTree();
    569         addElementStyleProperties(inlineStyle, isInlineStyleCacheable);
     573        addElementStyleProperties(inlineStyle, isInlineStyleCacheable, FromStyleAttribute::Yes);
    570574    }
    571575
  • trunk/Source/WebCore/style/ElementRuleCollector.h

    r285622 r285624  
    9898
    9999private:
    100     void addElementStyleProperties(const StyleProperties*, bool isCacheable = true);
     100    void addElementStyleProperties(const StyleProperties*, bool isCacheable = true, FromStyleAttribute = FromStyleAttribute::No);
    101101
    102102    void matchUARules(const RuleSet&);
  • trunk/Source/WebCore/style/MatchResult.h

    r285574 r285624  
    2626
    2727#include "PropertyAllowlist.h"
     28#include "RuleSet.h"
    2829#include "SelectorChecker.h"
    2930#include "StyleProperties.h"
     
    3334namespace WebCore::Style {
    3435
     36enum class FromStyleAttribute : bool { No, Yes };
     37
    3538struct MatchedProperties {
    3639    RefPtr<const StyleProperties> properties;
    37     uint16_t linkMatchType { SelectorChecker::MatchAll };
     40    uint8_t linkMatchType { SelectorChecker::MatchAll };
    3841    PropertyAllowlist allowlistType { PropertyAllowlist::None };
    3942    ScopeOrdinal styleScopeOrdinal { ScopeOrdinal::Element };
     43    FromStyleAttribute fromStyleAttribute { FromStyleAttribute::No };
     44    CascadeLayerPriority cascadeLayerPriority { RuleSet::cascadeLayerPriorityForUnlayered };
    4045};
    4146
     
    6772        && a.linkMatchType == b.linkMatchType
    6873        && a.allowlistType == b.allowlistType
    69         && a.styleScopeOrdinal == b.styleScopeOrdinal;
     74        && a.styleScopeOrdinal == b.styleScopeOrdinal
     75        && a.fromStyleAttribute == b.fromStyleAttribute
     76        && a.cascadeLayerPriority == b.cascadeLayerPriority;
    7077}
    7178
     
    7784inline void add(Hasher& hasher, const MatchedProperties& matchedProperties)
    7885{
    79     add(hasher, matchedProperties.properties.get(), matchedProperties.linkMatchType, matchedProperties.allowlistType, matchedProperties.styleScopeOrdinal);
     86    add(hasher,
     87        matchedProperties.properties.get(),
     88        matchedProperties.linkMatchType,
     89        matchedProperties.allowlistType,
     90        matchedProperties.styleScopeOrdinal,
     91        matchedProperties.fromStyleAttribute,
     92        matchedProperties.cascadeLayerPriority
     93    );
    8094}
    8195
  • trunk/Source/WebCore/style/PropertyCascade.cpp

    r285493 r285624  
    7272}
    7373
    74 PropertyCascade::PropertyCascade(const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, IncludedProperties includedProperties, Direction direction)
     74PropertyCascade::PropertyCascade(const MatchResult& matchResult, CascadeLevel maximumCascadeLevel, IncludedProperties includedProperties, Direction direction)
    7575    : m_matchResult(matchResult)
    7676    , m_includedProperties(includedProperties)
     77    , m_maximumCascadeLevel(maximumCascadeLevel)
    7778    , m_direction(direction)
    7879{
    79     buildCascade(cascadeLevels);
    80 }
    81 
    82 PropertyCascade::PropertyCascade(const PropertyCascade& parent, OptionSet<CascadeLevel> cascadeLevels)
     80    buildCascade();
     81}
     82
     83PropertyCascade::PropertyCascade(const PropertyCascade& parent, CascadeLevel maximumCascadeLevel, CascadeLayerPriority maximumCascadeLayerPriority)
    8384    : m_matchResult(parent.m_matchResult)
    8485    , m_includedProperties(parent.m_includedProperties)
     86    , m_maximumCascadeLevel(maximumCascadeLevel)
     87    , m_maximumCascadeLayerPriority(maximumCascadeLayerPriority)
    8588    , m_direction(parent.direction())
    8689    , m_directionIsUnresolved(false)
    8790{
    88     buildCascade(cascadeLevels);
     91    buildCascade();
    8992}
    9093
    9194PropertyCascade::~PropertyCascade() = default;
    9295
    93 void PropertyCascade::buildCascade(OptionSet<CascadeLevel> cascadeLevels)
     96void PropertyCascade::buildCascade()
    9497{
    9598    OptionSet<CascadeLevel> cascadeLevelsWithImportant;
    9699
    97     for (auto cascadeLevel : cascadeLevels) {
     100    for (auto cascadeLevel : { CascadeLevel::UserAgent, CascadeLevel::User, CascadeLevel::Author }) {
     101        if (cascadeLevel > m_maximumCascadeLevel)
     102            break;
    98103        bool hasImportant = addNormalMatches(cascadeLevel);
    99104        if (hasImportant)
     
    114119    property.level = cascadeLevel;
    115120    property.styleScopeOrdinal = matchedProperties.styleScopeOrdinal;
     121    property.cascadeLayerPriority = matchedProperties.cascadeLayerPriority;
     122
    116123    if (matchedProperties.linkMatchType == SelectorChecker::MatchAll) {
    117124        property.cssValue[0] = &cssValue;
     
    171178bool PropertyCascade::addMatch(const MatchedProperties& matchedProperties, CascadeLevel cascadeLevel, bool important)
    172179{
     180    if (matchedProperties.cascadeLayerPriority > m_maximumCascadeLayerPriority && cascadeLevel == m_maximumCascadeLevel && matchedProperties.styleScopeOrdinal == ScopeOrdinal::Element)
     181        return false;
     182
    173183    auto& styleProperties = *matchedProperties.properties;
    174184    auto propertyAllowlist = matchedProperties.allowlistType;
     
    238248void PropertyCascade::addImportantMatches(CascadeLevel cascadeLevel)
    239249{
    240     struct IndexAndOrdinal {
     250    struct ImportantMatch {
    241251        unsigned index;
    242252        ScopeOrdinal ordinal;
     253        CascadeLayerPriority layerPriority;
     254        FromStyleAttribute fromStyleAttribute;
    243255    };
    244     Vector<IndexAndOrdinal> importantMatches;
    245     bool hasMatchesFromOtherScopes = false;
     256    Vector<ImportantMatch> importantMatches;
     257    bool hasMatchesFromOtherScopesOrLayers = false;
    246258
    247259    auto& matchedDeclarations = declarationsForCascadeLevel(m_matchResult, cascadeLevel);
     
    253265            continue;
    254266
    255         importantMatches.append({ i, matchedProperties.styleScopeOrdinal });
    256 
    257         if (matchedProperties.styleScopeOrdinal != ScopeOrdinal::Element)
    258             hasMatchesFromOtherScopes = true;
     267        importantMatches.append({ i, matchedProperties.styleScopeOrdinal, matchedProperties.cascadeLayerPriority, matchedProperties.fromStyleAttribute });
     268
     269        if (matchedProperties.styleScopeOrdinal != ScopeOrdinal::Element || matchedProperties.cascadeLayerPriority != RuleSet::cascadeLayerPriorityForUnlayered)
     270            hasMatchesFromOtherScopesOrLayers = true;
    259271    }
    260272
     
    262274        return;
    263275
    264     if (hasMatchesFromOtherScopes) {
    265         // For !important properties a later shadow tree wins.
     276    if (hasMatchesFromOtherScopesOrLayers) {
    266277        // Match results are sorted in reverse tree context order so this is not needed for normal properties.
    267         std::stable_sort(importantMatches.begin(), importantMatches.end(), [] (const IndexAndOrdinal& a, const IndexAndOrdinal& b) {
    268             return a.ordinal < b.ordinal;
     278        std::stable_sort(importantMatches.begin(), importantMatches.end(), [] (auto& a, auto& b) {
     279            // For !important properties a later shadow tree wins.
     280            if (a.ordinal != b.ordinal)
     281                return a.ordinal < b.ordinal;
     282            // Lower priority layer wins, except if style attribute is involved.
     283            if (a.fromStyleAttribute != b.fromStyleAttribute)
     284                return a.fromStyleAttribute == FromStyleAttribute::No;
     285            return a.layerPriority > b.layerPriority;
    269286        });
    270287    }
     
    272289    for (auto& match : importantMatches)
    273290        addMatch(matchedDeclarations[match.index], cascadeLevel, true);
    274 }
    275 
    276 const PropertyCascade* PropertyCascade::propertyCascadeForRollback(CascadeLevel cascadeLevel) const
    277 {
    278     switch (cascadeLevel) {
    279     case CascadeLevel::Author:
    280         if (!m_authorRollbackCascade) {
    281             auto cascadeLevels = OptionSet<CascadeLevel> { CascadeLevel::UserAgent, CascadeLevel::User };
    282             m_authorRollbackCascade = makeUnique<const PropertyCascade>(*this, cascadeLevels);
    283         }
    284         return m_authorRollbackCascade.get();
    285 
    286     case CascadeLevel::User:
    287         if (!m_userRollbackCascade) {
    288             auto cascadeLevels = OptionSet<CascadeLevel> { CascadeLevel::UserAgent };
    289             m_userRollbackCascade = makeUnique<const PropertyCascade>(*this, cascadeLevels);
    290         }
    291         return m_userRollbackCascade.get();
    292 
    293     case CascadeLevel::UserAgent:
    294         return nullptr;
    295     }
    296     ASSERT_NOT_REACHED();
    297     return nullptr;
    298291}
    299292
  • trunk/Source/WebCore/style/PropertyCascade.h

    r285574 r285624  
    4747    };
    4848
    49     PropertyCascade(const MatchResult&, OptionSet<CascadeLevel>, IncludedProperties, Direction);
    50     PropertyCascade(const PropertyCascade&, OptionSet<CascadeLevel>);
     49    PropertyCascade(const MatchResult&, CascadeLevel, IncludedProperties, Direction);
     50    PropertyCascade(const PropertyCascade&, CascadeLevel, CascadeLayerPriority maximumCascadeLayerPriority = RuleSet::cascadeLayerPriorityForUnlayered);
    5151
    5252    ~PropertyCascade();
     
    5656        CascadeLevel level;
    5757        ScopeOrdinal styleScopeOrdinal;
     58        CascadeLayerPriority cascadeLayerPriority;
    5859        CSSValue* cssValue[3]; // Values for link match states MatchDefault, MatchLink and MatchVisited
    5960    };
     
    7071    Direction direction() const;
    7172
    72     const PropertyCascade* propertyCascadeForRollback(CascadeLevel) const;
     73    auto maximumCascadeLevel() const { return m_maximumCascadeLevel; }
     74    auto maximumCascadeLayerPriority() const { return m_maximumCascadeLayerPriority; }
    7375
    7476private:
    75     void buildCascade(OptionSet<CascadeLevel>);
     77    void buildCascade();
    7678    bool addNormalMatches(CascadeLevel);
    7779    void addImportantMatches(CascadeLevel);
     
    8688    const MatchResult& m_matchResult;
    8789    const IncludedProperties m_includedProperties;
     90    const CascadeLevel m_maximumCascadeLevel;
     91    const CascadeLayerPriority m_maximumCascadeLayerPriority { RuleSet::cascadeLayerPriorityForUnlayered };
    8892    mutable Direction m_direction;
    8993    mutable bool m_directionIsUnresolved { true };
     
    9498    Vector<Property, 8> m_deferredProperties;
    9599    HashMap<AtomString, Property> m_customProperties;
    96 
    97     mutable std::unique_ptr<const PropertyCascade> m_authorRollbackCascade;
    98     mutable std::unique_ptr<const PropertyCascade> m_userRollbackCascade;
    99100};
    100101
  • trunk/Source/WebCore/style/StyleBuilder.cpp

    r285493 r285624  
    8181}
    8282
    83 Builder::Builder(RenderStyle& style, BuilderContext&& context, const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, PropertyCascade::IncludedProperties includedProperties)
    84     : m_cascade(matchResult, cascadeLevels, includedProperties, directionFromStyle(style))
     83Builder::Builder(RenderStyle& style, BuilderContext&& context, const MatchResult& matchResult, CascadeLevel cascadeLevel, PropertyCascade::IncludedProperties includedProperties)
     84    : m_cascade(matchResult, cascadeLevel, includedProperties, directionFromStyle(style))
    8585    , m_state(*this, style, WTFMove(context))
    8686{
     
    120120
    121121    ASSERT(!m_state.fontDirty());
    122 }
    123 
    124 void Builder::applyPropertyValue(CSSPropertyID propertyID, CSSValue* value)
    125 {
    126     if (!value)
    127         return;
    128 
    129     applyProperty(propertyID, *value, SelectorChecker::MatchDefault);
    130 
    131     m_state.updateFont();
    132122}
    133123
     
    246236    m_state.m_cascadeLevel = property.level;
    247237    m_state.m_styleScopeOrdinal = property.styleScopeOrdinal;
     238    m_state.m_cascadeLayerPriority = property.cascadeLayerPriority;
    248239
    249240    auto applyWithLinkMatch = [&](SelectorChecker::LinkMatchMask linkMatch) {
     
    296287    bool isUnset = valueToApply->isUnsetValue() || customPropertyValueID == CSSValueUnset;
    297288    bool isRevert = valueToApply->isRevertValue() || customPropertyValueID == CSSValueRevert;
    298 
    299     if (isRevert) {
    300         if (auto* rollback = m_cascade.propertyCascadeForRollback(m_state.m_cascadeLevel)) {
     289    bool isRevertLayer = valueToApply->isRevertLayerValue() || customPropertyValueID == CSSValueRevertLayer;
     290
     291    if (isRevert || isRevertLayer) {
     292        auto* rollbackCascade = isRevert
     293            ? ensureRollbackCascadeForRevert(m_state.m_cascadeLevel)
     294            : ensureRollbackCascadeForRevertLayer(m_state.m_cascadeLevel, m_state.m_cascadeLayerPriority);
     295
     296        if (rollbackCascade) {
    301297            // With the rollback cascade built, we need to obtain the property and apply it. If the property is
    302             // not present, then we behave like "unset." Otherwise we apply the property instead of
    303             // our own.
     298            // not present, then we behave like "unset." Otherwise we apply the property instead of our own.
     299            SetForScope cascadeLevelScope(m_state.m_cascadeLevel, rollbackCascade->maximumCascadeLevel());
     300            SetForScope cascadeLayerPriorityScope(m_state.m_cascadeLayerPriority, rollbackCascade->maximumCascadeLayerPriority());
    304301            if (customPropertyValue) {
    305                 if (customPropertyRegistered && customPropertyRegistered->inherits && rollback->hasCustomProperty(customPropertyValue->name())) {
    306                     auto property = rollback->customProperty(customPropertyValue->name());
     302                if (customPropertyRegistered && customPropertyRegistered->inherits && rollbackCascade->hasCustomProperty(customPropertyValue->name())) {
     303                    auto property = rollbackCascade->customProperty(customPropertyValue->name());
    307304                    if (property.cssValue[linkMatchMask])
    308305                        applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
    309306                    return;
    310307                }
    311             } else if (rollback->hasProperty(id)) {
    312                 auto& property = rollback->property(id);
     308            } else if (rollbackCascade->hasProperty(id)) {
     309                auto& property = rollbackCascade->property(id);
    313310                if (property.cssValue[linkMatchMask])
    314311                    applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
     
    374371}
    375372
    376 }
    377 }
     373const PropertyCascade* Builder::ensureRollbackCascadeForRevert(CascadeLevel rollbackCascadeLevel)
     374{
     375    if (rollbackCascadeLevel == CascadeLevel::UserAgent)
     376        return nullptr;
     377
     378    auto key = makeRollbackCascadeKey(rollbackCascadeLevel, RuleSet::cascadeLayerPriorityForUnlayered);
     379    return m_rollbackCascades.ensure(key, [&] {
     380        return makeUnique<const PropertyCascade>(m_cascade, --rollbackCascadeLevel, RuleSet::cascadeLayerPriorityForUnlayered);
     381    }).iterator->value.get();
     382}
     383
     384const PropertyCascade* Builder::ensureRollbackCascadeForRevertLayer(CascadeLevel cascadeLevel, CascadeLayerPriority rollbackLayerPriority)
     385{
     386    if (!rollbackLayerPriority)
     387        return nullptr;
     388
     389    auto key = makeRollbackCascadeKey(cascadeLevel, rollbackLayerPriority);
     390    return m_rollbackCascades.ensure(key, [&] {
     391        return makeUnique<const PropertyCascade>(m_cascade, cascadeLevel, rollbackLayerPriority - 1);
     392    }).iterator->value.get();
     393}
     394
     395auto Builder::makeRollbackCascadeKey(CascadeLevel cascadeLevel, CascadeLayerPriority cascadeLayerPriority) -> RollbackCascadeKey
     396{
     397    return { static_cast<unsigned>(cascadeLevel), static_cast<unsigned>(cascadeLayerPriority) };
     398}
     399
     400}
     401}
  • trunk/Source/WebCore/style/StyleBuilder.h

    r285493 r285624  
    3636    WTF_MAKE_FAST_ALLOCATED;
    3737public:
    38     Builder(RenderStyle&, BuilderContext&&, const MatchResult&, OptionSet<CascadeLevel>, PropertyCascade::IncludedProperties = PropertyCascade::IncludedProperties::All);
     38    Builder(RenderStyle&, BuilderContext&&, const MatchResult&, CascadeLevel, PropertyCascade::IncludedProperties = PropertyCascade::IncludedProperties::All);
    3939    ~Builder();
    4040
     
    4545    void applyProperty(CSSPropertyID propertyID) { applyProperties(propertyID, propertyID); }
    4646    void applyCustomProperty(const String& name);
    47 
    48     void applyPropertyValue(CSSPropertyID, CSSValue*);
    4947
    5048    BuilderState& state() { return m_state; }
     
    6462    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&);
    6563
     64    const PropertyCascade* ensureRollbackCascadeForRevert(CascadeLevel);
     65    const PropertyCascade* ensureRollbackCascadeForRevertLayer(CascadeLevel, CascadeLayerPriority);
     66
     67    using RollbackCascadeKey = std::pair<unsigned, unsigned>;
     68    RollbackCascadeKey makeRollbackCascadeKey(CascadeLevel, CascadeLayerPriority);
     69
    6670    const PropertyCascade m_cascade;
     71    // Rollback cascades are build on demand to resolve 'revert' and 'revert-layer' keywords.
     72    HashMap<RollbackCascadeKey, std::unique_ptr<const PropertyCascade>> m_rollbackCascades;
     73
    6774    BuilderState m_state;
    6875};
  • trunk/Source/WebCore/style/StyleBuilderState.h

    r285493 r285624  
    3030#include "CascadeLevel.h"
    3131#include "RenderStyle.h"
     32#include "RuleSet.h"
    3233#include "SelectorChecker.h"
    3334#include <wtf/Bitmap.h>
     
    137138    CascadeLevel m_cascadeLevel { };
    138139    ScopeOrdinal m_styleScopeOrdinal { };
     140    CascadeLayerPriority m_cascadeLayerPriority { };
    139141    SelectorChecker::LinkMatchMask m_linkMatch { };
    140142
  • trunk/Source/WebCore/style/StyleResolver.cpp

    r285493 r285624  
    284284    state.setParentStyle(RenderStyle::clonePtr(context.parentStyle ? *context.parentStyle : *elementStyle));
    285285
    286     Builder builder(*state.style(), builderContext(state), result, { CascadeLevel::Author });
     286    Builder builder(*state.style(), builderContext(state), result, CascadeLevel::Author);
    287287    builder.applyAllProperties();
    288288
     
    437437    auto& result = collector.matchResult();
    438438
    439     Builder builder(*state.style(), builderContext(state), result, { CascadeLevel::Author });
     439    Builder builder(*state.style(), builderContext(state), result, CascadeLevel::Author);
    440440    builder.applyAllProperties();
    441441
     
    556556        // can look at them later to figure out if this is a styled form control or not.
    557557        auto userAgentStyle = RenderStyle::clonePtr(style);
    558         Builder builder(*userAgentStyle, builderContext(state), matchResult, { CascadeLevel::UserAgent });
     558        Builder builder(*userAgentStyle, builderContext(state), matchResult, CascadeLevel::UserAgent);
    559559        builder.applyAllProperties();
    560560
     
    562562    }
    563563
    564     Builder builder(*state.style(), builderContext(state), matchResult, allCascadeLevels(), includedProperties);
     564    Builder builder(*state.style(), builderContext(state), matchResult, CascadeLevel::Author, includedProperties);
    565565
    566566    // High priority properties may affect resolution of other properties (they are mostly font related).
Note: See TracChangeset for help on using the changeset viewer.